Files
2026-08-17 07:14:29 +02:00

61 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""Trace Imports — Find broken/missing imports in backend."""
from __future__ import annotations
import ast, sys, json
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent.parent
APP = ROOT / "app"
def find_imports() -> list[dict]:
imports = []
for py in APP.rglob("*.py"):
try: content = py.read_text(); tree = ast.parse(content)
except: continue
rel = str(py.relative_to(ROOT))
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom):
if node.module and node.module.startswith("app."):
for alias in node.names:
imports.append({"file": rel, "module": node.module, "name": alias.name, "line": node.lineno})
return imports
def check_imports_exist(imports: list[dict]) -> list[dict]:
broken = []
for imp in imports:
module_path = imp["module"].replace(".", "/") + ".py"
full_path = ROOT / module_path
if not full_path.exists():
# Try as package
pkg_path = ROOT / module_path.replace(".py", "/__init__.py")
if not pkg_path.exists():
broken.append({**imp, "issue": "Module not found"})
continue
# Check if name exists in module
try:
content = full_path.read_text()
if imp["name"] not in content and imp["name"] != "__init__":
# Could be imported via __init__.py
if not full_path.name == "__init__.py":
broken.append({**imp, "issue": f"Name '{imp['name']}' not found in module"})
except: pass
return broken
def main():
print("=" * 70)
print("TRACE IMPORTS — Broken/Missing Imports")
print("=" * 70)
imports = find_imports()
broken = check_imports_exist(imports)
print(f"\nTotal imports: {len(imports)}")
print(f"Broken imports: {len(broken)}")
if broken:
print("\n--- Broken imports ---")
for b in broken[:30]: print(f" {b['file']}:{b['line']}{b['module']}.{b['name']}{b['issue']}")
results = {"total_imports": len(imports), "broken": broken}
with open(ROOT / "scripts" / "test_suite" / "results_trace_imports.json", "w") as f:
json.dump(results, f, indent=2, default=str)
return len(broken)
if __name__ == "__main__": sys.exit(main())