Last active
May 22, 2025 17:49
-
-
Save cedricvidal/c4211d0552d2673929fb6555b45f6fb6 to your computer and use it in GitHub Desktop.
Python CLI to create a JSON diff using the patchdiff package
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import rich_click as click | |
import json | |
from pathlib import Path | |
from dotenv import load_dotenv | |
from sys import stdout | |
from patchdiff import diff as patch_diff | |
load_dotenv() | |
def load_jsonl(jsonl_file): | |
return [json.loads(line) for line in jsonl_file] | |
def key(model): | |
return f"{model['model']['name']}-{model['location']}" | |
def index(models): | |
return dict(map(lambda model: (key(model), model), models)) | |
def make_patch(previous, next): | |
ops, _ = patch_diff(previous, next) | |
# Convert Path objects to strings so that they can be JSON dumped | |
for op in ops: | |
op["path"] = str(op["path"]) | |
return ops if len(ops) > 0 else None | |
def diff(previous, next): | |
a = set(previous.keys()) | |
b = set(next.keys()) | |
common = a & b | |
removed = a - b | |
added = b - a | |
common_models = [(key, make_patch(previous[key], next[key]), previous[key]) for key in common] | |
return { | |
'updates': dict([(key, {"previous": prev, "changes": diff}) for (key, diff, prev) in common_models if diff]), | |
'removed': {key: previous[key] for key in removed}, | |
'added': {key: next[key] for key in added} | |
} | |
@click.command() | |
@click.option('--previous-file', '-p', help='Previous file', type=click.File('r')) | |
@click.option('--next-file', '-n', help='Next file', type=click.File('r')) | |
@click.option('--diff-file', '-d', help='Diff file', type=click.File('w'), default=stdout) | |
def report(previous_file, next_file, diff_file): | |
click.echo(f"Creating diff report between {previous_file.name} and {next_file.name}") | |
previous = index(load_jsonl(previous_file)) | |
next = index(load_jsonl(next_file)) | |
d = diff(previous, next) | |
json.dump(d, diff_file, indent=2) | |
if __name__ == '__main__': | |
report() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment