61 lines
2.3 KiB
Python
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())
|