# jaydiff Lightweight JSON diff / patch library for Python. Computes the difference between two dicts and applies it back, with fine-grained control over which kinds of changes (add, update, delete) to track. ## Installation ```bash pip install . ``` ## API ### Diff functions | Function | Description | |---|---| | `jay_diff_add(old, new)` | Keys present in `new` but absent in `old` | | `jay_diff_del(old, new)` | Keys present in `old` but absent in `new` | | `jay_diff_upd(old, new)` | Keys present in both whose values changed | | `jay_diff_upd_add(old, new)` | Combined update + add | | `jay_diff_full(old, new, combine_upd_add=True)` | Full diff; returns a dict with `update_add`/`delete` keys (or `update`/`add`/`delete` when `combine_upd_add=False`) | ### Merge functions | Function | Description | |---|---| | `jay_merge_add(old, delta)` | Apply an add-delta to `old` | | `jay_merge_delete(old, delta)` | Apply a delete-delta to `old` | | `jay_merge_update(old, delta)` | Apply an update-delta to `old` | | `jay_merge_full(old, diff)` | Apply a full diff (output of `jay_diff_full`) to `old` | All operations are recursive — nested dicts are handled at every depth. ## Usage ```python from jaydiff import jay_diff_full, jay_merge_full from copy import deepcopy old = {'soc': 80, 'range': 300, 'status': {'charging': True}} new = {'soc': 75, 'range': 300, 'status': {'charging': False}, 'temp': 22} diff = jay_diff_full(old, new) # {'update_add': {'soc': 75, 'status': {'charging': False}, 'temp': 22}} result = jay_merge_full(deepcopy(old), diff) assert result == new ``` ### Delete semantics When a key whose value is a dict is absent from `new`, the delete delta records `None` to signal "remove the entire key": ```python from jaydiff import jay_diff_del jay_diff_del({'a': 1, 'b': {'x': 1, 'y': 2}}, {'a': 1}) # {'b': None} ``` `jay_merge_full` / `jay_merge_delete` interpret `None` as "delete this key entirely". ## Running tests ```bash pip install pytest pytest ```