"""Enforce branch-aware coverage for every eligible backend module.""" import argparse import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] EXCLUDED_NAMES = {"__init__.py", "apps.py"} EXCLUDED_CONFIG = { "config/asgi.py", "config/wsgi.py", "config/services/location.py", "config/services/notifications.py", "config/services/zarinpal.py", } def eligible_modules(): for source in ("apps", "core", "config"): for path in (ROOT / source).rglob("*.py"): relative = path.relative_to(ROOT).as_posix() if path.name in EXCLUDED_NAMES or relative in EXCLUDED_CONFIG: continue if any(part in {"tests", "migrations"} for part in path.parts): continue if relative.startswith("config/settings/"): continue yield relative def main(): parser = argparse.ArgumentParser() parser.add_argument("coverage_json", type=Path) parser.add_argument("--minimum", type=float, default=80.0) args = parser.parse_args() report = json.loads(args.coverage_json.read_text(encoding="utf-8")) files = {name.replace("\\", "/"): data for name, data in report["files"].items()} failures = [] for module in sorted(eligible_modules()): data = files.get(module) if data is None: failures.append(f"{module}: absent from coverage report") continue summary = data["summary"] total = summary["num_statements"] + summary["num_branches"] if total == 0: continue covered = total - summary["missing_lines"] - summary["missing_branches"] percent = covered * 100 / total print(f"{percent:6.2f}% {module}") if percent < args.minimum: failures.append(f"{module}: {percent:.2f}% < {args.minimum:.2f}%") if failures: print("Coverage gate failed:") for failure in failures: print(f" {failure}") raise SystemExit(1) if __name__ == "__main__": main()