from pathlib import Path import re ROOT = Path(__file__).resolve().parents[2] SCAN = [ ROOT / "index.html", ROOT / "research", ROOT / "report", ROOT / "deck", ] # Allow mentions that explicitly retire/forbid the figure ALLOW = re.compile( r"(retir(e|ed|es|ing)|wrong|invalid|never|not .*895|mixed|anti-pattern|RETIRED)", re.I, ) BAD = re.compile( r"895\s*MW(?!\s*\(retir)|delivering 895|895 MW of firm|portfolio.*895|−895 MW|-\s*895 MW", re.I, ) def test_no_active_895_firm_claims(): offenders = [] for base in SCAN: if not base.exists(): continue if base.is_file(): paths = [base] else: paths = list(base.rglob("*.md")) + list(base.rglob("*.html")) for path in paths: # master.md/.html are intermediates the Typst build writes on its way # to the PDF. They re-wrap lines, which can separate a retired figure # from the word retiring it and trip this line-based check. The .typ # source and the published PDF are the surfaces that matter. if path.name in {"master.html", "master.md"}: continue if "__pycache__" in path.parts or "rendered" in path.parts or "dist" in path.parts: continue text = path.read_text(errors="ignore") for i, line in enumerate(text.splitlines(), 1): if BAD.search(line) and not ALLOW.search(line): offenders.append(f"{path.relative_to(ROOT)}:{i}:{line.strip()[:120]}") assert offenders == [], "Retired 895 MW firm claims still active:\n" + "\n".join(offenders)