Files
troupe-standup/wizard-work/ledger/checkin_inventory_verify.py
T

93 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""Independent verification of checkin-inventory.csv.
Two independent implementations of the same extraction spec:
build : os.listdir() + open/read + re.match() + str.count()
verify: os.scandir() + Path.read_text() + re.fullmatch() + str.count()
Exits 0 only if the CSV's rows equal a fresh recomputation from the source files.
"""
import os
import re
import sys
import csv
SRC = "/root/troupe-standup/checkins"
CSV_PATH = "/root/troupe-standup/wizard-work/ledger/checkin-inventory.csv"
PAT = re.compile(r"^(\d{4}-\d{2}-\d{2})-(.+)$")
FIELDS = ["date", "wizard", "filename", "n_lines", "n_did", "n_blocked", "n_next", "n_ask"]
def build_expected():
rows = []
with os.scandir(SRC) as it:
for entry in it:
if not entry.is_file():
continue
name = entry.name
if not name.endswith(".md"):
continue
m = PAT.fullmatch(name)
if not m:
continue
date, wizard = m.group(1), m.group(2)
with open(entry.path, encoding="utf-8", errors="replace") as fh:
data = fh.read()
rows.append((date, wizard, name, data.count("\n"),
data.count("Did"), data.count("Blocked"),
data.count("Next"), data.count("Ask")))
rows.sort(key=lambda r: (r[0], r[1]))
return rows
def _norm(row):
d = dict(row)
for k in ("n_lines", "n_did", "n_blocked", "n_next", "n_ask"):
d[k] = int(d[k])
return tuple(d[h] for h in FIELDS)
def read_csv():
with open(CSV_PATH, newline="", encoding="utf-8") as fh:
reader = csv.DictReader(fh)
assert reader.fieldnames == FIELDS, f"header mismatch: {reader.fieldnames}"
return [_norm(r) for r in reader]
def main():
ok = True
try:
expected = build_expected()
actual = read_csv()
except Exception as exc: # noqa: BLE001
print("FAIL: could not load source or artifact:", exc)
return 1
if len(expected) != len(actual):
ok = False
print(f"FAIL: row count mismatch: expected {len(expected)}, actual {len(actual)}")
diff = 0
for i in range(max(len(expected), len(actual))):
exp = expected[i] if i < len(expected) else None
act = actual[i] if i < len(actual) else None
if exp != act:
ok = False
diff += 1
print(f"FAIL row {i + 1}: expected={exp} actual={act}")
if ok:
print(f"PASS: {len(actual)} check-in rows match the source files "
f"({len(set(r[0] for r in actual))} distinct dates, "
f"{sorted(set(r[1] for r in actual))})")
else:
print(f"FAIL: {diff} differing rows")
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())