#!/usr/bin/env python3 """compare.py [label] Structural, type-aware comparison of two dump files (bool != int != float, str != list). Prints OK or the first few differences; exit 1 on any difference. """ import json import sys MAX_DIFFS = 8 def walk(a, b, path, diffs): if len(diffs) >= MAX_DIFFS: return if type(a) is not type(b): diffs.append(f"{path}: type {type(a).__name__} != {type(b).__name__} ({a!r} vs {b!r})") return if isinstance(a, dict): for k in sorted(set(a) | set(b)): if k not in a: diffs.append(f"{path}.{k}: missing in ours") elif k not in b: diffs.append(f"{path}.{k}: extra in ours") else: walk(a[k], b[k], f"{path}.{k}", diffs) elif isinstance(a, list): if len(a) != len(b): diffs.append(f"{path}: length {len(a)} != {len(b)}") for i, (x, y) in enumerate(zip(a, b)): walk(x, y, f"{path}[{i}]", diffs) elif a != b: diffs.append(f"{path}: {a!r} != {b!r}") def main(argv): ours = json.load(open(argv[1], encoding="ascii")) oracle = json.load(open(argv[2], encoding="ascii")) label = argv[3] if len(argv) > 3 else argv[1] diffs = [] walk(ours, oracle, "$", diffs) if diffs: print(f"DIFF {label}") for d in diffs: print(" ", d) return 1 print(f"OK {label}") return 0 if __name__ == "__main__": sys.exit(main(sys.argv))