#!/usr/bin/env python3 """ Run the complete verifier suite against the versions pinned in requirements.txt. This is the repository's Tier 2 baseline gate. It refuses to run individual verifiers when the active Python environment does not contain the exact pinned RNS and LXMF versions, then runs every tools/verify_*.py script in isolation. Exit code 0 means every verifier passed. Exit code 1 means the environment does not match the pins or at least one verifier failed. """ from __future__ import annotations import importlib.metadata import pathlib import re import subprocess import sys TOOLS_DIR = pathlib.Path(__file__).resolve().parent REQUIREMENTS_PATH = TOOLS_DIR / "requirements.txt" PIN_PATTERN = re.compile(r"^(rns|lxmf)==([A-Za-z0-9_.+-]+)$", re.IGNORECASE) def load_pins() -> dict[str, str]: pins: dict[str, str] = {} for raw_line in REQUIREMENTS_PATH.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() match = PIN_PATTERN.match(line) if match: pins[match.group(1).lower()] = match.group(2) missing = {"rns", "lxmf"} - pins.keys() if missing: names = ", ".join(sorted(missing)) raise RuntimeError(f"missing required pins in {REQUIREMENTS_PATH}: {names}") return pins def installed_versions(names: list[str]) -> dict[str, str]: versions: dict[str, str] = {} for name in names: try: versions[name] = importlib.metadata.version(name) except importlib.metadata.PackageNotFoundError: versions[name] = "" return versions def verifier_paths() -> list[pathlib.Path]: return sorted( path for path in TOOLS_DIR.glob("verify_*.py") if path.name != pathlib.Path(__file__).name ) def main() -> int: try: pins = load_pins() except (OSError, RuntimeError) as exc: print(f"FAIL baseline configuration: {exc}") return 1 installed = installed_versions(sorted(pins)) mismatches = [ f"{name}: installed {installed[name]}, pinned {pins[name]}" for name in sorted(pins) if installed[name] != pins[name] ] print(f"Python: {sys.executable}") print("Pinned environment: " + ", ".join( f"{name}=={pins[name]}" for name in sorted(pins) )) if mismatches: print("FAIL environment does not match tools/requirements.txt:") for mismatch in mismatches: print(f" - {mismatch}") return 1 verifiers = verifier_paths() if not verifiers: print("FAIL no verifier scripts found") return 1 failures: list[tuple[str, int]] = [] for index, path in enumerate(verifiers, start=1): print(f"\n=== [{index}/{len(verifiers)}] {path.name} ===", flush=True) result = subprocess.run([sys.executable, str(path)], cwd=TOOLS_DIR.parent) if result.returncode != 0: failures.append((path.name, result.returncode)) print("\n=== Verification summary ===") print(f"Passed: {len(verifiers) - len(failures)}") print(f"Failed: {len(failures)}") if failures: for name, returncode in failures: print(f" - {name}: exit {returncode}") return 1 print("ALL VERIFIERS PASS") return 0 if __name__ == "__main__": raise SystemExit(main())