Coverage for tests/test_optional_dependencies.py: 100%
29 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-01 20:15 +0300
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-01 20:15 +0300
1"""Optional backend dependency contract tests."""
3from __future__ import annotations
5import subprocess
6import sys
7from importlib.metadata import metadata
9from snektest import assert_eq, assert_in, test
12def _run_python(script: str) -> subprocess.CompletedProcess[str]:
13 """Run an import-isolated Python snippet in the current test environment."""
15 return subprocess.run(
16 [sys.executable, "-c", script],
17 check=False,
18 capture_output=True,
19 text=True,
20 )
23@test()
24def package_metadata_declares_backend_driver_extras() -> None:
25 """SQLite and MariaDB drivers are optional backend extras."""
27 package_metadata = metadata("snekql")
28 extras = package_metadata.get_all("Provides-Extra") or []
29 requirements = package_metadata.get_all("Requires-Dist") or []
31 assert_in("aiosqlite", extras)
32 assert_in("aiomysql", extras)
33 assert any(
34 requirement.startswith("aiosqlite") and "extra == 'aiosqlite'" in requirement
35 for requirement in requirements
36 )
37 assert any(
38 requirement.startswith("aiomysql") and "extra == 'aiomysql'" in requirement
39 for requirement in requirements
40 )
41 assert not any(
42 requirement.startswith(("aiosqlite", "aiomysql"))
43 and "extra ==" not in requirement
44 for requirement in requirements
45 )
48@test()
49def public_imports_do_not_import_optional_drivers() -> None:
50 """Root and backend namespace imports do not load optional database drivers."""
52 script = """
53import sys
54import snekql
55from tests.logging_helpers import NULL_LOGGER
56from snekql import mariadb, sqlite
58if "aiosqlite" in sys.modules:
59 raise AssertionError("aiosqlite was imported")
60if "aiomysql" in sys.modules:
61 raise AssertionError("aiomysql was imported")
62if "snekql._pool" in sys.modules:
63 raise AssertionError("SQLite pool was imported")
64if "snekql.schema" in sys.modules:
65 raise AssertionError("SQLite schema was imported")
66_ = sqlite.Config(database=":memory:")
67_ = mariadb.Config(database="app", user="snekql")
68print("ok")
69"""
71 result = _run_python(script)
73 assert_eq(result.returncode, 0)
74 assert_eq(result.stdout.strip(), "ok")
77@test(mark="medium")
78def sqlite_initialization_without_extra_reports_install_hint() -> None:
79 """Runtime initialization explains how to install a missing SQLite driver."""
81 script = """
82from __future__ import annotations
84import asyncio
85import builtins
87import snekql
88from snekql import Database, sqlite
89from tests.logging_helpers import NULL_LOGGER
91original_import = builtins.__import__
94def block_aiosqlite(name, globals=None, locals=None, fromlist=(), level=0):
95 if name == "aiosqlite" or name.startswith("aiosqlite."):
96 raise ModuleNotFoundError("No module named 'aiosqlite'", name="aiosqlite")
97 return original_import(name, globals, locals, fromlist, level)
100async def main() -> None:
101 builtins.__import__ = block_aiosqlite
102 try:
103 try:
104 _ = await Database.initialize(NULL_LOGGER, sqlite.Config(database=":memory:"))
105 except snekql.DatabaseRuntimeError as error:
106 print(error)
107 return
108 raise AssertionError("SQLite initialization unexpectedly succeeded")
109 finally:
110 builtins.__import__ = original_import
113asyncio.run(main())
114"""
116 result = _run_python(script)
118 assert_eq(result.returncode, 0)
119 assert_in("snekql[aiosqlite]", result.stdout)