from __future__ import annotations import ast import pathlib import tomllib import unittest ROOT = pathlib.Path(__file__).resolve().parents[1] class OptionalTenancyContractTests(unittest.TestCase): def test_access_package_does_not_require_tenancy_to_install(self) -> None: project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))["project"] dependencies = tuple(project["dependencies"]) self.assertIn("govoplan-core>=0.1.6", dependencies) self.assertNotIn("govoplan-tenancy>=0.1.6", dependencies) self.assertFalse(any(item.startswith("govoplan-tenancy") for item in dependencies)) def test_tenancy_is_declared_as_optional_module_integration(self) -> None: manifest_path = ROOT / "src" / "govoplan_access" / "backend" / "manifest.py" tree = ast.parse(manifest_path.read_text(encoding="utf-8")) manifest_call = next( node.value for node in ast.walk(tree) if isinstance(node, ast.Assign) and any(isinstance(target, ast.Name) and target.id == "manifest" for target in node.targets) and isinstance(node.value, ast.Call) ) optional_dependencies = next( keyword.value for keyword in manifest_call.keywords if keyword.arg == "optional_dependencies" ) self.assertIsInstance(optional_dependencies, ast.Tuple) self.assertIn( "tenancy", { item.value for item in optional_dependencies.elts if isinstance(item, ast.Constant) and isinstance(item.value, str) }, ) def test_access_source_does_not_import_tenancy_module_internals(self) -> None: offenders: list[str] = [] for path in (ROOT / "src" / "govoplan_access").rglob("*.py"): source = path.read_text(encoding="utf-8") if "govoplan_tenancy" in source: offenders.append(str(path.relative_to(ROOT))) self.assertEqual([], offenders) if __name__ == "__main__": unittest.main()