"""Tests that src/app_controller.py has NO top-level fastapi imports. Per spec.md:2.2 Layer 1, the main thread's import chain must not include heavy modules. FastAPI is heavy (~470ms) and is only needed when `--enable-test-hooks` or `--web-host` is passed. The warmup loads it on the AppController's _io_pool; functions that need it call `_require_warmed("fastapi")` to get the module from sys.modules. These tests run in a fresh subprocess to ensure no warmup state leaks from the test runner. We assert: - `fastapi` is NOT in `sys.modules` after `import src.app_controller` - `fastapi.security.api_key` is NOT in `sys.modules` either - The static audit script reports NO new violation from app_controller.py """ import subprocess import sys import textwrap from pathlib import Path ROOT = Path(__file__).resolve().parent.parent def _run_in_subprocess(snippet: str) -> subprocess.CompletedProcess: script = textwrap.dedent(snippet) return subprocess.run( [sys.executable, "-c", script], capture_output=True, text=True, cwd=str(ROOT), timeout=30, ) def test_app_controller_does_not_import_fastapi_at_module_level() -> None: res = _run_in_subprocess(""" import sys import src.app_controller print('fastapi' in sys.modules) """) assert res.returncode == 0, f"stderr: {res.stderr}" assert res.stdout.strip() == "False", f"app_controller triggered fastapi import: {res.stdout}" def test_app_controller_does_not_import_fastapi_security_at_module_level() -> None: res = _run_in_subprocess(""" import sys import src.app_controller print('fastapi.security.api_key' in sys.modules) """) assert res.returncode == 0, f"stderr: {res.stderr}" assert res.stdout.strip() == "False", f"app_controller triggered fastapi.security.api_key import: {res.stdout}" def test_app_controller_create_api_still_resolvable() -> None: """Even without fastapi in sys.modules, the function reference must be importable (it just returns a lazy FastAPI app on call).""" res = _run_in_subprocess(""" import src.app_controller print(hasattr(src.app_controller.AppController, 'create_api')) print(callable(src.app_controller.AppController.create_api)) """) assert res.returncode == 0, f"stderr: {res.stderr}" assert res.stdout.strip() == "True\nTrue" def test_audit_main_thread_imports_sees_no_new_violation_from_app_controller() -> None: """Run the static audit and check that src/app_controller.py contributes no new fastapi violations (any remaining violations are pre-existing in OTHER files; this just verifies app_controller is clean). """ res = _run_in_subprocess(""" import ast from pathlib import Path root = Path('.').resolve() app_controller_path = root / 'src' / 'app_controller.py' tree = ast.parse(app_controller_path.read_text(encoding='utf-8')) heavy = ['fastapi', 'fastapi.security', 'fastapi.security.api_key'] for node in tree.body: if isinstance(node, ast.Import): for alias in node.names: for h in heavy: if alias.name == h or alias.name.startswith(h + '.'): print('VIOLATION:', alias.name) elif isinstance(node, ast.ImportFrom): if node.module: for h in heavy: if node.module == h or node.module.startswith(h + '.'): print('VIOLATION:', node.module) print('OK') """) assert res.returncode == 0, f"stderr: {res.stderr}" assert "OK" in res.stdout assert "VIOLATION" not in res.stdout