generated from john/python-template
Enforce the four unenforced reviewer checks with guard tests
The reviewer skill recorded four deterministic checks as unenforced or partial. Add tests so they fail the build instead of relying on a reviewer noticing. tests/test_model_contract_guards.py: - Status vocabulary: flags string literals compared against or assigned to status/purpose attributes, plus a narrower sweep that requires every status-valued literal in the package to be a known non-status use. - Relationship loading: every Relationship must declare lazy='raise' except documented exceptions, and the exception set must match the Relationship Loading Contract in docs/schema.md. - Schema fidelity: the Field-Accurate Table Contracts tables must match db/models.py on table coverage, field names, and declaration order, and the Authoritative Enumerations section must match the enum members. tests/test_orphan_sweep.py: - Locks the set of unreferenced public definitions. Route handlers registered by decorator are exempt, string entrypoint references count, and tests/ and tools/ count as consumers. KNOWN_ORPHANS records the four current orphans with rationale; a new one fails the build. Each guard was mutation-tested: reverting the fix below, dropping a documented field, widening a lazy strategy, and adding a stranded function each fail their respective test. Also fix the one violation the status guard found: sources_page.py compared attempt.status.value to the literal 'transcribed' instead of JobSourceStatus.TRANSCRIBED, which would survive an enum rename. Co-authored-by: Copilot App <[email protected]>
This commit is contained in:
co-authored by
Copilot App
parent
5566f48fc0
commit
c6ed3126e0
@@ -0,0 +1,146 @@
|
||||
"""Deterministic orphan sweep for the `transcription` package.
|
||||
|
||||
`.github/skills/python-code-reviewer/skill.md` requires every review to report
|
||||
orphaned code as removed, retained-with-justification, or uncertain-follow-up. This
|
||||
guard makes that sweep reproducible: it locks the current set of unreferenced public
|
||||
definitions, so a newly stranded function fails the build instead of accumulating
|
||||
silently, and deleting a known orphan requires deleting its entry here.
|
||||
|
||||
The sweep is intentionally conservative. It only considers module-level public
|
||||
definitions, and it honours the dynamic-wiring exceptions the skill calls out:
|
||||
framework route registration, string-based entrypoint references, and use from
|
||||
`tests/` or `tools/`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
from pathlib import Path
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
SOURCE_DIR = PROJECT_ROOT / "src" / "transcription"
|
||||
|
||||
# Every tree that may legitimately consume package API.
|
||||
REFERENCE_ROOTS = (SOURCE_DIR, PROJECT_ROOT / "tests", PROJECT_ROOT / "tools")
|
||||
|
||||
# Decorators that hand a callable to a framework registry, making the definition
|
||||
# reachable without any in-repo reference to its name.
|
||||
REGISTRATION_DECORATOR_PREFIXES = ("router.", "app.", "ui.page")
|
||||
|
||||
# Confirmed orphans, retained by decision rather than by reference. Each entry needs a
|
||||
# rationale. Removing the code means removing the entry; adding an entry means an
|
||||
# explicit decision to keep unreferenced code.
|
||||
KNOWN_ORPHANS: dict[str, str] = {
|
||||
"BenchmarkManifest": (
|
||||
"Benchmark manifest model in benchmarking.py with no current caller. "
|
||||
"Uncertain - follow-up: confirm whether the benchmarking entrypoint is still "
|
||||
"intended before removing."
|
||||
),
|
||||
"dispose_all_engines": (
|
||||
"Engine lifecycle helper in db/engine.py. Uncertain - follow-up: operational "
|
||||
"teardown utility with no runtime or test caller."
|
||||
),
|
||||
"refresh_engine": (
|
||||
"Engine lifecycle helper in db/engine.py. Uncertain - follow-up: paired with "
|
||||
"dispose_all_engines and equally unreferenced."
|
||||
),
|
||||
"summarize_error": (
|
||||
"Error-presentation helper in ui/components/error_presenter.py that no page or "
|
||||
"component calls. Uncertain - follow-up: superseded by the presenter's other "
|
||||
"entrypoints."
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _source_files() -> list[Path]:
|
||||
return sorted(SOURCE_DIR.rglob("*.py"))
|
||||
|
||||
|
||||
def _is_registered_with_framework(node: ast.FunctionDef | ast.AsyncFunctionDef | ast.ClassDef) -> bool:
|
||||
return any(
|
||||
ast.unparse(decorator).startswith(REGISTRATION_DECORATOR_PREFIXES) for decorator in node.decorator_list
|
||||
)
|
||||
|
||||
|
||||
def _public_definitions() -> dict[str, str]:
|
||||
"""Public module-level definitions, mapped to `path:line`."""
|
||||
definitions: dict[str, str] = {}
|
||||
for path in _source_files():
|
||||
tree = ast.parse(path.read_text(encoding="utf-8"))
|
||||
for node in tree.body:
|
||||
if not isinstance(node, ast.FunctionDef | ast.AsyncFunctionDef | ast.ClassDef):
|
||||
continue
|
||||
if node.name.startswith("_") or _is_registered_with_framework(node):
|
||||
continue
|
||||
definitions[node.name] = f"{path.relative_to(PROJECT_ROOT).as_posix()}:{node.lineno}"
|
||||
return definitions
|
||||
|
||||
|
||||
def _referenced_names() -> tuple[set[str], str]:
|
||||
"""Names referenced anywhere, plus every string literal joined for dotted lookups."""
|
||||
names: set[str] = set()
|
||||
literals: list[str] = []
|
||||
for root in REFERENCE_ROOTS:
|
||||
for path in sorted(root.rglob("*.py")):
|
||||
# This module names every known orphan in `KNOWN_ORPHANS`; counting those
|
||||
# strings as references would make the allowlist self-satisfying.
|
||||
if path == Path(__file__).resolve():
|
||||
continue
|
||||
tree = ast.parse(path.read_text(encoding="utf-8"))
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Name):
|
||||
names.add(node.id)
|
||||
elif isinstance(node, ast.Attribute):
|
||||
names.add(node.attr)
|
||||
elif isinstance(node, ast.ImportFrom):
|
||||
for alias in node.names:
|
||||
names.add(alias.name)
|
||||
names.add(alias.asname or alias.name)
|
||||
elif isinstance(node, ast.Constant) and isinstance(node.value, str):
|
||||
literals.append(node.value)
|
||||
return names, "\n".join(literals)
|
||||
|
||||
|
||||
def _orphans() -> dict[str, str]:
|
||||
definitions = _public_definitions()
|
||||
names, literal_blob = _referenced_names()
|
||||
return {
|
||||
name: location
|
||||
for name, location in definitions.items()
|
||||
# A definition is referenced if its name is used directly, or appears inside a
|
||||
# string such as "transcription.__main__:create_cli_app".
|
||||
if name not in names and name not in literal_blob
|
||||
}
|
||||
|
||||
|
||||
def test_public_definitions_are_discovered():
|
||||
"""Guard the guard: the sweep is meaningless if nothing is scanned."""
|
||||
definitions = _public_definitions()
|
||||
assert len(definitions) >= 200
|
||||
assert "create_app" in definitions
|
||||
|
||||
|
||||
def test_framework_registered_routes_are_exempt():
|
||||
"""Route handlers are reachable via decorator registration, not by name."""
|
||||
definitions = _public_definitions()
|
||||
assert "healthz_route" not in definitions
|
||||
assert "read_document_source_media" not in definitions
|
||||
|
||||
|
||||
def test_no_unexpected_orphaned_definitions():
|
||||
"""Check 10: no public definition becomes unreferenced without a recorded decision."""
|
||||
unexpected = {name: location for name, location in _orphans().items() if name not in KNOWN_ORPHANS}
|
||||
assert unexpected == {}
|
||||
|
||||
|
||||
def test_known_orphans_are_still_orphaned():
|
||||
"""Keep the allowlist honest: an entry that regained callers must be removed."""
|
||||
current = set(_orphans())
|
||||
stale = sorted(name for name in KNOWN_ORPHANS if name not in current)
|
||||
assert stale == [], "these definitions are referenced again; drop them from KNOWN_ORPHANS"
|
||||
|
||||
|
||||
def test_known_orphans_document_a_rationale():
|
||||
"""An allowlist without reasons is just suppressed output."""
|
||||
missing = sorted(name for name, reason in KNOWN_ORPHANS.items() if len(reason.strip()) < 40)
|
||||
assert missing == []
|
||||
Reference in New Issue
Block a user