diff --git a/checks/env_docs_gate.py b/checks/env_docs_gate.py index 96ccb27..769a57c 100755 --- a/checks/env_docs_gate.py +++ b/checks/env_docs_gate.py @@ -80,11 +80,11 @@ def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description=(__doc__ or "").partition("\n")[0]) parser.parse_args(argv) - if not DOC.exists(): + try: + doc_text = DOC.read_text(encoding="utf-8") + except FileNotFoundError: print(f"ERROR: {DOC.name} does not exist", file=sys.stderr) return 1 - - doc_text = DOC.read_text(encoding="utf-8") documented_rows = set(DOC_ROW.findall(doc_text)) documented_any = documented_rows | set(DOC_INLINE.findall(doc_text)) @@ -95,10 +95,11 @@ def note(name: str, where: str) -> None: declared.setdefault(name, set()).add(where) for path in TEMPLATES: - if not path.exists(): + try: + text = path.read_text(encoding="utf-8") + except FileNotFoundError: print(f"ERROR: template {path} is missing", file=sys.stderr) return 1 - text = path.read_text(encoding="utf-8") rel = path.relative_to(REPO).as_posix() for name in DECL.findall(text): note(name, rel) diff --git a/checks/media_redactions_gate.py b/checks/media_redactions_gate.py index a677993..111aefe 100755 --- a/checks/media_redactions_gate.py +++ b/checks/media_redactions_gate.py @@ -29,10 +29,12 @@ def main(argv: list[str] | None = None) -> int: files = json.loads(MANIFEST.read_text())["files"] failures = [] for name, entry in files.items(): - path = REPO / name - if not path.is_file(): + try: + data = (REPO / name).read_bytes() + except FileNotFoundError: failures.append(f"{name}: missing") - elif hashlib.sha256(path.read_bytes()).hexdigest() != entry.get("result"): + continue + if hashlib.sha256(data).hexdigest() != entry.get("result"): failures.append(f"{name}: not its redacted result") elif declared(entry) != entry.get("declared"): failures.append( diff --git a/checks/text_pii_gate.py b/checks/text_pii_gate.py index b2e35f7..4e18020 100755 --- a/checks/text_pii_gate.py +++ b/checks/text_pii_gate.py @@ -236,10 +236,11 @@ def scan_line(text: str) -> Iterator[tuple[str, str]]: def excluded_prefixes(root: pathlib.Path) -> tuple[str, ...]: """The archive boundary, read the way the prose gate reads it.""" - path = root / EXCLUDES - if not path.is_file(): + try: + text = (root / EXCLUDES).read_text(encoding="utf-8") + except FileNotFoundError: return () - lines = (line.strip() for line in path.read_text(encoding="utf-8").splitlines()) + lines = (line.strip() for line in text.splitlines()) return tuple(line for line in lines if line and not line.startswith("#")) @@ -270,9 +271,11 @@ def findings(root: pathlib.Path) -> list[Finding]: def load_allow(path: pathlib.Path) -> list[dict]: """The declared values, each checked for a known class, one matcher, and a reason.""" - if not path.is_file(): + try: + text = path.read_text(encoding="utf-8") + except FileNotFoundError: return [] - data = json.loads(path.read_text(encoding="utf-8")) + data = json.loads(text) entries = data.get("allow") if isinstance(data, dict) else None if not isinstance(entries, list): raise SystemExit(f"{path}: needs an object with an allow list") diff --git a/checks/url_parity_gate.py b/checks/url_parity_gate.py index a55d74c..f03bdfc 100755 --- a/checks/url_parity_gate.py +++ b/checks/url_parity_gate.py @@ -121,7 +121,11 @@ def check_robots(public): happens, and it catches a sitemap advertised but not built. """ robots = public / "robots.txt" - if not robots.is_file(): + # This uses errors="replace" rather than strict, or invalid UTF-8 raises out of the whole parity run and a gate that exists to report a bad robots.txt stack-traces on one instead. + # A committed static/robots.txt is the file most likely to carry it, and it is the case this check is for. + try: + text = robots.read_text(encoding="utf-8", errors="replace") + except FileNotFoundError: # Naming one cause as the cause sends a reader to check a setting that is already correct. # The likely one is enableRobotsTXT, and a partial build or the wrong output directory reach the same state, which is the same reason the orphan messages name both of their causes. print("robots : missing") @@ -133,9 +137,6 @@ def check_robots(public): ] origin = site_origin(public) - # This uses errors="replace" rather than strict, or invalid UTF-8 raises out of the whole parity run and a gate that exists to report a bad robots.txt stack-traces on one instead. - # A committed static/robots.txt is the file most likely to carry it, and it is the case this check is for. - text = robots.read_text(encoding="utf-8", errors="replace") advertised = re.findall(r"(?mi)^\s*Sitemap:\s*(\S+)\s*$", text) if not advertised: print("robots : built, no Sitemap line") @@ -170,9 +171,10 @@ def site_origin(public): one environment's output against another's and silently match nothing. """ home = public / "index.html" - if not home.is_file(): + try: + text = home.read_text(encoding="utf-8", errors="ignore") + except FileNotFoundError: sys.exit(f"FAIL: {home} is missing - run hugo first") - text = home.read_text(encoding="utf-8", errors="ignore") found = re.search( r'rel=["\']?canonical["\']?\s+href=["\']?(https?://[^/"\'>\s]+)', text )