#!/usr/bin/env python3 """Structural verifier for the countries extraction table. Usage: python3 check_countries.py Exits 0 iff the CSV satisfies the contract: - header is exactly the 14-column contract (see HEADERS) - every data row has exactly 14 fields - alpha-2 codes are unique and there are exactly expected_rows rows Exits 1 with a detailed message otherwise. The exit code IS the verdict: 0 = correct, nonzero = wrong. """ import csv import sys EXPECTED_HEADER = [ 'name_common', 'name_official', 'alpha2', 'alpha3', 'numeric', 'region', 'subregion', 'capital', 'population', 'area_km2', 'currencies', 'languages', 'tlds', 'flag', ] def main(): if len(sys.argv) != 3: sys.stderr.write('usage: check_countries.py \n') return 2 csv_path, expected_raw = sys.argv[1], sys.argv[2] try: expected = int(expected_raw) except ValueError: sys.stderr.write('expected_rows must be an integer\n') return 2 try: fh = open(csv_path, encoding='utf-8') except OSError as exc: sys.stderr.write('cannot open %s: %s\n' % (csv_path, exc)) return 1 with fh: reader = csv.reader(fh) try: header = next(reader) except StopIteration: sys.stderr.write('CSV is empty\n') return 1 if header != EXPECTED_HEADER: sys.stderr.write('bad header: %r\n' % header) return 1 rows = list(reader) codes = [] for index, row in enumerate(rows, start=2): if len(row) != len(EXPECTED_HEADER): sys.stderr.write('row %d has %d fields (expected %d)\n' % (index, len(row), len(EXPECTED_HEADER))) return 1 codes.append(row[2]) seen = set() duplicates = [] for code in codes: if code in seen: duplicates.append(code) seen.add(code) ok = True if len(rows) != expected: sys.stderr.write('row count %d != expected %d\n' % (len(rows), expected)) ok = False if duplicates: sys.stderr.write('duplicate alpha-2 codes: %r\n' % sorted(duplicates)) ok = False print('rows=%d fields=%d unique_alpha2=%d header_ok=True' % (len(rows), len(header), len(seen))) return 0 if ok else 1 if __name__ == '__main__': sys.exit(main())