#!/usr/bin/env python3 # Import-free verifier for top-python-repos-2026-10-26. # Exit code 0 = artifact correct, nonzero = wrong. import csv import json import sys BASE = "/root/troupe-standup/wizard-work/ledger" CSV_PATH = BASE + "/top-python-repos-2026-10-26.csv" JSON_PATH = BASE + "/top-python-repos-2026-10-26.json" HEADER = ["rank", "name", "owner", "description", "stars", "forks", "html_url", "language"] def fail(msg): print("CHECK FAIL: " + msg) sys.exit(1) try: with open(JSON_PATH) as f: payload = json.load(f) except Exception as e: fail("cannot read json: %r" % e) items = payload.get("items") if not items: fail("json has no items") # Expected order: stars desc, name asc expected = sorted(items, key=lambda r: (-int(r.get("stargazers_count") or 0), r.get("name", ""))) expected_rows = [] for i, r in enumerate(expected, 1): owner = r.get("owner") or {} expected_rows.append({ "rank": str(i), "name": r.get("name", ""), "owner": owner.get("login", "") if isinstance(owner, dict) else "", "description": r.get("description") or "", "stars": str(int(r.get("stargazers_count") or 0)), "forks": str(int(r.get("forks_count") or 0)), "html_url": r.get("html_url", ""), "language": r.get("language") or "", }) try: with open(CSV_PATH, newline="") as f: rows = list(csv.DictReader(f)) except Exception as e: fail("cannot read csv: %r" % e) if not rows: fail("csv is empty") if list(rows[0].keys()) != HEADER: fail("header mismatch: %r" % list(rows[0].keys())) if len(rows) != 50: fail("row count %d != 50" % len(rows)) for i, (act, exp) in enumerate(zip(rows, expected_rows), 1): if act != exp: fail("row %d mismatch: %r != %r" % (i, act, exp)) stars = [int(r["stars"]) for r in rows] if any(a < b for a, b in zip(stars, stars[1:])): fail("stars not non-increasing") ranks = [int(r["rank"]) for r in rows] if ranks != list(range(1, 51)): fail("ranks not 1..50") print("CHECK PASS: %d rows | top=%s/%s stars=%s" % ( len(rows), rows[0]["owner"], rows[0]["name"], rows[0]["stars"]))