Files
openswarm/linter/checks/classes.py
T

62 lines
1.8 KiB
Python

"""Class-level dead code detection with framework awareness.
Pydantic BaseModel subclasses are auto-whitelisted: every annotated field is
part of the serialization schema and therefore intentionally "used".
Non-framework classes are skipped for now (tier 2 — future cross-referencing).
"""
from __future__ import annotations
import ast
from pathlib import Path
from . import is_excepted, is_excluded, is_lintignored
FRAMEWORK_BASES = {"BaseModel"}
def _is_framework_model(cls: ast.ClassDef) -> bool:
return any(
(isinstance(b, ast.Name) and b.id in FRAMEWORK_BASES)
or (isinstance(b, ast.Attribute) and b.attr in FRAMEWORK_BASES)
for b in cls.bases
)
def run_class_check(
root: Path,
exceptions: dict[str, list[str]],
excludes: list[str],
ignores: dict[Path, set[str]] | None = None,
) -> list[str]:
"""Analyse classes in backend Python files and return errors."""
errors: list[str] = []
backend = root / "backend"
if not backend.is_dir():
return errors
for pyfile in sorted(backend.rglob("*.py")):
if is_excluded(pyfile, root, excludes):
continue
rel = str(pyfile.relative_to(root))
if is_excepted(rel, "classes", exceptions):
continue
if ignores and is_lintignored(pyfile, root, "classes", ignores):
continue
try:
source = pyfile.read_text()
tree = ast.parse(source, filename=rel)
except (OSError, SyntaxError):
continue
for node in ast.walk(tree):
if not isinstance(node, ast.ClassDef):
continue
if _is_framework_model(node):
continue
# Tier 2 placeholder: non-framework classes are skipped until
# cross-reference analysis is implemented.
return errors