Skip to content

Commit 1b8269a

Browse files
committed
chore: Test cases where extension loading or importing fails
1 parent 7ce9993 commit 1b8269a

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

deepnote_toolkit/sql/duckdb_sql.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ def _get_duckdb_connection():
6666
)
6767
_DEEPNOTE_DUCKDB_CONNECTION.load_extension(extension_name)
6868
except Exception as e:
69-
logger.error(f"Failed to load DuckDB {extension_name} extension: {e}")
69+
# Extensions are optional and connection still works, users are able to load
70+
# them manually if needed (pulling them from internet in this case as fallback)
71+
logger.warning(f"Failed to load DuckDB {extension_name} extension: {e}")
7072

7173
_set_sample_size(_DEEPNOTE_DUCKDB_CONNECTION, _DEFAULT_DUCKDB_SAMPLE_SIZE)
7274

tests/unit/test_duckdb_sql.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from contextlib import contextmanager
2+
from unittest import mock
3+
14
import pandas as pd
25
import pytest
36

@@ -8,11 +11,10 @@
811
)
912

1013

11-
@pytest.fixture(scope="function")
12-
def duckdb_connection():
14+
@contextmanager
15+
def fresh_duckdb_connection():
1316
import deepnote_toolkit.sql.duckdb_sql as duckdb_sql_module
1417

15-
# reset the connection to ensure a fresh one is created for each test
1618
duckdb_sql_module._DEEPNOTE_DUCKDB_CONNECTION = None
1719
conn = _get_duckdb_connection()
1820

@@ -23,6 +25,12 @@ def duckdb_connection():
2325
duckdb_sql_module._DEEPNOTE_DUCKDB_CONNECTION = None
2426

2527

28+
@pytest.fixture(scope="function")
29+
def duckdb_connection():
30+
with fresh_duckdb_connection() as conn:
31+
yield conn
32+
33+
2634
@pytest.mark.parametrize("extension_name", ["spatial", "excel"])
2735
def test_extension_installed_and_loadable(duckdb_connection, extension_name):
2836
result = duckdb_connection.execute(
@@ -69,6 +77,38 @@ def test_set_scan_all_frames(duckdb_connection):
6977
assert result[0] == "true"
7078

7179

80+
@mock.patch("deepnote_toolkit.sql.duckdb_sql.import_extension")
81+
def test_connection_returns_successfully_when_import_extension_fails(
82+
mock_import_extension,
83+
):
84+
mock_import_extension.side_effect = Exception("Failed to import extension")
85+
86+
with fresh_duckdb_connection() as conn:
87+
assert conn is not None
88+
result = conn.execute(
89+
"SELECT extension_name, loaded FROM duckdb_extensions()"
90+
).df()
91+
assert result is not None
92+
# check that spatial and excel extensions are not loaded as import extension failed
93+
result = result[result["extension_name"].isin(["spatial", "excel"])]
94+
assert result["loaded"].all() == False
95+
96+
97+
@mock.patch("duckdb.DuckDBPyConnection.load_extension")
98+
def test_connection_returns_successfully_when_load_extension_fails(mock_load_extension):
99+
mock_load_extension.side_effect = Exception("Failed to load extension")
100+
101+
with fresh_duckdb_connection() as conn:
102+
assert conn is not None
103+
result = conn.execute(
104+
"SELECT extension_name, loaded FROM duckdb_extensions()"
105+
).df()
106+
assert result is not None
107+
# check that spatial and excel extensions are not loaded as import extension failed
108+
result = result[result["extension_name"].isin(["spatial", "excel"])]
109+
assert result["loaded"].all() == False
110+
111+
72112
def test_excel_extension_roundtrip(duckdb_connection, tmp_path):
73113
test_data = pd.DataFrame(
74114
{

0 commit comments

Comments
 (0)