author | Alan Dipert
<alan@dipert.org> 2025-10-08 06:26:33 UTC |
committer | Alan Dipert
<alan@dipert.org> 2025-10-08 06:26:33 UTC |
parent | b6ea70c4d5763a38be974b32f18645b81c31365f |
tools/check_links.py | +12 | -6 |
diff --git a/tools/check_links.py b/tools/check_links.py index d8f2695..55bec55 100755 --- a/tools/check_links.py +++ b/tools/check_links.py @@ -18,7 +18,7 @@ def collect_links(md_path: pathlib.Path) -> set[str]: return set(URL_RE.findall(text)) -def check_url(url: str) -> tuple[bool, str]: +def check_url(url: str) -> tuple[bool, str, str]: try: proc = subprocess.run( [ @@ -35,19 +35,23 @@ def check_url(url: str) -> tuple[bool, str]: check=False, ) except Exception as exc: # pragma: no cover - defensive - return False, f"error: {exc}" + return False, "error", f"error: {exc}" status_lines = [line for line in proc.stdout.splitlines() if line.startswith("HTTP/")] status_line = status_lines[0] if status_lines else "" if not status_line: detail = proc.stderr.strip() or "no response" - return False, detail + return False, "error", detail ok_prefixes = (" 200 ", " 301 ", " 302 ", " 303 ", " 307 ", " 308 ") if any(code in status_line for code in ok_prefixes): - return True, status_line.strip() + parts = status_line.split() + code = parts[1] if len(parts) > 1 else "200" + return True, code, status_line.strip() - return False, status_line.strip() + parts = status_line.split() + code = parts[1] if len(parts) > 1 else "error" + return False, code, status_line.strip() def main() -> int: @@ -56,7 +60,9 @@ def main() -> int: for md_file in sorted(MD_DIR.glob("*.md")): links = collect_links(md_file) for url in sorted(links): - ok, detail = check_url(url) + ok, code, detail = check_url(url) + print(f"{code}\t{md_file}\t{url}") + sys.stdout.flush() if not ok: broken[str(md_file)].append((url, detail))