ariadne/scripts/check_file_sizes.py

87 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Enforce a ratcheted source file line-budget contract.
The check fails when:
- a file exceeds the configured line budget and is not allowlisted; or
- an allowlist entry is stale (file removed or now within budget).
"""
from __future__ import annotations
import argparse
from pathlib import Path
def _iter_source_files(roots: list[str], exts: set[str]) -> list[Path]:
files: list[Path] = []
for root_text in roots:
root = Path(root_text)
if not root.exists():
continue
for path in root.rglob("*"):
if not path.is_file():
continue
if path.suffix not in exts:
continue
if "__pycache__" in path.parts or ".venv" in path.parts:
continue
files.append(path.resolve())
return sorted(files)
def _load_waivers(path: Path) -> dict[str, str]:
waivers: dict[str, str] = {}
if not path.exists():
return waivers
for raw_line in path.read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
if not line or line.startswith("#"):
continue
parts = line.split("\t")
rel_path = parts[0].strip()
reason = parts[1].strip() if len(parts) > 1 else ""
if rel_path:
waivers[rel_path] = reason
return waivers
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--roots", nargs="+", default=["ariadne", "scripts", "tests"])
parser.add_argument("--max-lines", type=int, default=500)
parser.add_argument("--waivers", default="scripts/loc_hygiene_waivers.tsv")
args = parser.parse_args()
repo_root = Path.cwd().resolve()
waivers = _load_waivers(repo_root / args.waivers)
source_files = _iter_source_files(args.roots, {".py", ".sh"})
violations: dict[str, int] = {}
for path in source_files:
rel = path.relative_to(repo_root).as_posix()
lines = len(path.read_text(encoding="utf-8", errors="ignore").splitlines())
if lines > args.max_lines:
violations[rel] = lines
unexpected = sorted(rel for rel in violations if rel not in waivers)
stale = sorted(rel for rel in waivers if rel not in violations)
if not unexpected and not stale:
print(
f"[hygiene] source line budget check passed (limit={args.max_lines}, over_limit={len(violations)}, waivers={len(waivers)})"
)
return 0
if unexpected:
print("[hygiene] files over budget missing from waiver list:")
for rel in unexpected:
print(f"- {rel}: {violations[rel]} lines (limit {args.max_lines})")
if stale:
print("[hygiene] stale waiver entries (remove from waiver list):")
for rel in stale:
print(f"- {rel}")
return 1
if __name__ == "__main__":
raise SystemExit(main())