"""Tests that src/theme_2.py has NO top-level NERV theme imports. Per spec.md:2.2 Layer 1, the main thread's import chain must not include heavy feature-gated modules. The NERV theme modules (src.theme_nerv, src.theme_nerv_fx) are warmed on AppController's _io_pool and accessed via _require_warmed at use sites. NERV is only active when the user explicitly chooses it; the default theme path should be lean. src/theme_2.py uses these NERV symbols at three sites: - ai_text_color() uses DATA_GREEN (only when is_nerv_active() is True) - apply() uses theme_nerv.apply_nerv() (only when palette == 'NERV') - render_post_fx() creates CRTFilter/AlertPulsing/StatusFlicker instances All three sites are now lazy: the modules are looked up via _require_warmed inside the function body, and the FX objects are created locally per-call. These tests run in a fresh subprocess to ensure no warmup state leaks from the test runner. """ 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_theme_2_does_not_import_theme_nerv_at_module_level() -> None: res = _run_in_subprocess(""" import sys import src.theme_2 print('src.theme_nerv' in sys.modules) """) assert res.returncode == 0, f"stderr: {res.stderr}" assert res.stdout.strip() == "False", f"theme_2 triggered src.theme_nerv import: {res.stdout}" def test_theme_2_does_not_import_theme_nerv_fx_at_module_level() -> None: res = _run_in_subprocess(""" import sys import src.theme_2 print('src.theme_nerv_fx' in sys.modules) """) assert res.returncode == 0, f"stderr: {res.stderr}" assert res.stdout.strip() == "False", f"theme_2 triggered src.theme_nerv_fx import: {res.stdout}" def test_theme_2_ai_text_color_source_does_not_import_theme_nerv() -> None: """The ai_text_color function's body uses _require_warmed; verify the file no longer has DATA_GREEN as a top-level import. (Cannot call the function outside a real imgui context, but AST inspection is sufficient.)""" res = _run_in_subprocess(""" import ast from pathlib import Path root = Path('.').resolve() theme_path = root / 'src' / 'theme_2.py' tree = ast.parse(theme_path.read_text(encoding='utf-8')) # Look for any top-level ImportFrom that imports DATA_GREEN directly has_top_level_data_green = False for node in tree.body: if isinstance(node, ast.ImportFrom): for alias in node.names: if alias.name == 'DATA_GREEN': has_top_level_data_green = True print('HAS_TOP_LEVEL_DATA_GREEN:', has_top_level_data_green) """) assert res.returncode == 0, f"stderr: {res.stderr}" assert "HAS_TOP_LEVEL_DATA_GREEN: False" in res.stdout def test_audit_main_thread_imports_sees_no_new_violation_from_theme_2() -> None: """Run the static audit and check that src/theme_2.py contributes no new NERV violations.""" res = _run_in_subprocess(""" import ast from pathlib import Path root = Path('.').resolve() theme_path = root / 'src' / 'theme_2.py' tree = ast.parse(theme_path.read_text(encoding='utf-8')) heavy = ['src.theme_nerv', 'src.theme_nerv_fx', 'theme_nerv', 'theme_nerv_fx'] 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