#!/usr/bin/env python3 """Fail closed unless a selected Python wheel directory obeys its runtime profile.""" from __future__ import annotations import argparse import hashlib import json import re from pathlib import Path def sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as stream: for chunk in iter(lambda: stream.read(1024 * 1024), b""): digest.update(chunk) return digest.hexdigest() def validate(contract: dict, profile_name: str, wheel_dir: Path) -> list[str]: errors: list[str] = [] profiles = contract.get("profiles", {}) if profile_name not in profiles: return [f"unknown profile: {profile_name}"] profile = profiles[profile_name] wheels = {path.name: path for path in wheel_dir.glob("*.whl") if path.is_file()} if not wheels: errors.append("selected wheel directory is empty") for pattern in profile.get("forbidden_filename_patterns", []): matches = sorted(name for name in wheels if re.search(pattern, name, re.IGNORECASE)) if matches: errors.append(f"forbidden pattern {pattern!r}: {', '.join(matches)}") for name, expected in profile.get("required", {}).items(): path = wheels.get(name) if path is None: errors.append(f"missing required wheel: {name}") elif sha256(path) != expected: errors.append(f"digest mismatch: {name}") return errors def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("contract", type=Path) parser.add_argument("profile") parser.add_argument("wheel_dir", type=Path) args = parser.parse_args() contract = json.loads(args.contract.read_text(encoding="utf-8")) errors = validate(contract, args.profile, args.wheel_dir) if errors: for error in errors: print(f"ERROR: {error}") return 1 print(f"profile valid: {args.profile}; wheels={len(list(args.wheel_dir.glob('*.whl')))}") return 0 if __name__ == "__main__": raise SystemExit(main())