import ast import unittest from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] ADMIN_ROOT = REPO_ROOT / "admin_app" PRODUCT_ROOT = REPO_ROOT / "app" FORBIDDEN_ADMIN_IMPORT_PREFIXES = ( "app.repositories.user_repository", "app.services.user", ) FORBIDDEN_ADMIN_MODULE_IMPORTS = { ("app.db.mock_models", "User"), } def _iter_python_files(root: Path): for path in root.rglob("*.py"): if "__pycache__" in path.parts: continue yield path def _iter_imports(path: Path): source = path.read_text(encoding="utf-8-sig") tree = ast.parse(source, filename=str(path)) for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: yield ("import", alias.name, None) elif isinstance(node, ast.ImportFrom): module = node.module or "" for alias in node.names: yield ("from", module, alias.name) class AdminIdentityIsolationTests(unittest.TestCase): def test_admin_app_does_not_depend_on_product_user_identity_modules(self): violations: list[str] = [] for path in _iter_python_files(ADMIN_ROOT): for import_kind, module, imported_name in _iter_imports(path): if import_kind == "import" and module.startswith(FORBIDDEN_ADMIN_IMPORT_PREFIXES): violations.append(f"{path.relative_to(REPO_ROOT)} imports {module}") if import_kind == "from" and module.startswith(FORBIDDEN_ADMIN_IMPORT_PREFIXES): violations.append(f"{path.relative_to(REPO_ROOT)} imports from {module}") if import_kind == "from" and (module, imported_name) in FORBIDDEN_ADMIN_MODULE_IMPORTS: violations.append(f"{path.relative_to(REPO_ROOT)} imports {imported_name} from {module}") self.assertEqual(violations, [], "\n".join(violations)) def test_product_runtime_does_not_depend_on_admin_app_modules(self): violations: list[str] = [] for path in _iter_python_files(PRODUCT_ROOT): for _, module, _ in _iter_imports(path): if module.startswith("admin_app"): violations.append(f"{path.relative_to(REPO_ROOT)} imports {module}") self.assertEqual(violations, [], "\n".join(violations)) if __name__ == "__main__": unittest.main()