89 lines
2.8 KiB
Python
89 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Verify the ISO 3166-1 extraction CSV.
|
|
|
|
Usage: python3 verify_ledger_iso3166.py <csv_path>
|
|
Exit 0 = artifact correct; nonzero = wrong.
|
|
"""
|
|
import csv
|
|
import re
|
|
import sys
|
|
|
|
EXPECTED_HEADER = ["country", "alpha2", "alpha3", "numeric", "independent"]
|
|
# (country, alpha2, alpha3, numeric) spot checks against the ISO 3166-1 standard.
|
|
KNOWN = {
|
|
"Afghanistan": ("AF", "AFG", "004"),
|
|
"United States": ("US", "USA", "840"),
|
|
"United Kingdom": ("GB", "GBR", "826"),
|
|
"China": ("CN", "CHN", "156"),
|
|
"Åland Islands": ("AX", "ALA", "248"),
|
|
"South Korea": ("KR", "KOR", "410"),
|
|
"Czechia": ("CZ", "CZE", "203"),
|
|
"Iran": ("IR", "IRN", "364"),
|
|
"Russia": ("RU", "RUS", "643"),
|
|
"Vietnam": ("VN", "VNM", "704"),
|
|
}
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) != 2:
|
|
print("usage: verify_ledger_iso3166.py <csv>")
|
|
sys.exit(2)
|
|
path = sys.argv[1]
|
|
with open(path, newline="", encoding="utf-8") as f:
|
|
reader = csv.DictReader(f)
|
|
header = reader.fieldnames
|
|
rows = list(reader)
|
|
|
|
errors = []
|
|
|
|
if header != EXPECTED_HEADER:
|
|
errors.append("header mismatch: %r" % header)
|
|
|
|
if len(rows) != 249:
|
|
errors.append("row count %d != 249" % len(rows))
|
|
|
|
seen = set()
|
|
for i, r in enumerate(rows, start=2):
|
|
c = r.get("country", "")
|
|
a2 = r.get("alpha2", "")
|
|
a3 = r.get("alpha3", "")
|
|
num = r.get("numeric", "")
|
|
ind = r.get("independent", "")
|
|
|
|
if re.search(r"\[[^\]]*\]", c):
|
|
errors.append("row %d: footnote marker in country %r" % (i, c))
|
|
if re.search(r"\[[^\]]*\]", ind):
|
|
errors.append("row %d: footnote marker in independent %r" % (i, ind))
|
|
if not c or not a2 or not a3 or not num or not ind:
|
|
errors.append("row %d: empty field %r" % (i, r))
|
|
if not re.fullmatch(r"[A-Za-z]{2}", a2):
|
|
errors.append("row %d: bad alpha2 %r" % (i, a2))
|
|
if not re.fullmatch(r"[A-Za-z]{3}", a3):
|
|
errors.append("row %d: bad alpha3 %r" % (i, a3))
|
|
if not re.fullmatch(r"\d{3}", num):
|
|
errors.append("row %d: bad numeric %r" % (i, num))
|
|
if ind not in ("Yes", "No"):
|
|
errors.append("row %d: bad independent %r" % (i, ind))
|
|
key = (a2, a3)
|
|
if key in seen:
|
|
errors.append("row %d: duplicate alpha3 %s" % (i, a3))
|
|
seen.add(key)
|
|
|
|
if c in KNOWN:
|
|
exp = KNOWN[c]
|
|
if (a2, a3, num) != exp:
|
|
errors.append("row %d: %r got (%s,%s,%s) want %s" % (i, c, a2, a3, num, exp))
|
|
|
|
if errors:
|
|
print("VERIFY FAILED (%d errors)" % len(errors))
|
|
for e in errors[:20]:
|
|
print(" -", e)
|
|
sys.exit(1)
|
|
|
|
print("OK: %d rows verified, header=%s" % (len(rows), header))
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|