84 lines
2.5 KiB
Python
Executable File
84 lines
2.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Independent verifier for the extension census.
|
|
|
|
Re-derives the census from the SOURCE file `repo_files.tsv` (rank<TAB>path,
|
|
CRLF) with a standalone loop -- it never imports extract_extension_census --
|
|
normalizes CRLF line endings, and asserts the resulting ranked (extension,
|
|
count) table byte-matches `extension-census.csv` produced by that script.
|
|
|
|
Exit code 0 = artifact matches re-derivation; 1 = mismatch; 2 = misuse.
|
|
"""
|
|
import csv
|
|
import os
|
|
import sys
|
|
|
|
REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
SRC = os.path.join(REPO, "repo_files.tsv")
|
|
ART = os.path.join(REPO, "wizard-work", "ledger", "extension-census.csv")
|
|
|
|
PASS = 0
|
|
|
|
|
|
def clean_path(raw):
|
|
s = raw.strip()
|
|
if len(s) >= 2 and s[0] == '"' and s[-1] == '"':
|
|
s = s[1:-1]
|
|
return s.encode("latin-1", "replace").decode("unicode_escape", "replace")
|
|
|
|
|
|
def ext_of(path):
|
|
base = os.path.basename(path.rstrip("/"))
|
|
if not base or base in (".", ".."):
|
|
return "(none)"
|
|
if "." in base:
|
|
return "." + base.rsplit(".", 1)[1].lower()
|
|
return "(none)"
|
|
|
|
|
|
def re_derivation():
|
|
counts = {}
|
|
total = 0
|
|
with open(SRC, "r", encoding="utf-8", errors="replace") as f:
|
|
for line in f:
|
|
line = line.rstrip("\n").rstrip("\r")
|
|
if "\t" not in line:
|
|
continue
|
|
path = clean_path(line.split("\t", 1)[1])
|
|
total += 1
|
|
ext = ext_of(path)
|
|
counts[ext] = counts.get(ext, 0) + 1
|
|
return sorted(counts.items(), key=lambda kv: (-kv[1], kv[0]))
|
|
|
|
|
|
def read_artifact():
|
|
rows = []
|
|
with open(ART, newline="", encoding="utf-8") as f:
|
|
for row in csv.reader(f):
|
|
rows.append(row)
|
|
return rows[0], rows[1:]
|
|
|
|
|
|
def main():
|
|
global PASS
|
|
header, rows = read_artifact()
|
|
if header != ["rank", "extension", "file_count"]:
|
|
print("FAIL: bad header %r" % (header,))
|
|
return 1
|
|
expected = re_derivation()
|
|
if len(rows) != len(expected):
|
|
print("FAIL: row count artifact=%d rederivation=%d"
|
|
% (len(rows), len(expected)))
|
|
return 1
|
|
for i, ((ext, cnt), row) in enumerate(zip(expected, rows), 1):
|
|
if row != [str(i), ext, str(cnt)]:
|
|
print("FAIL: row %d artifact=%r expected=%r"
|
|
% (i, row, [str(i), ext, str(cnt)]))
|
|
return 1
|
|
print("OK: %d rows byte-match re-derivation from repo_files.tsv; header=%r"
|
|
% (len(rows), header))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|