Recursive diff for nested structures
Project description
Nested-Diff.py
Recursive diff and patch for nested structures.
Main features
- Machine-readable diff structure.
- Human-friendly diff visualization, collapsible html diffs.
- All operation tags are optional and may be disabled.
- Extensibility.
Install
pip install nested_diff
For extra formats support (YAML, TOML) in cli tools, use
pip install nested_diff[cli]
Command line tools
$ cat a.json b.json
[0, [1], 3]
[0, [1, 2], 3]
$ nested_diff a.json b.json
[1]
+ [1]
+ 2
$ nested_diff a.json b.json --ofmt json > patch.json
$ nested_patch a.json patch.json
Library usage
>>> from nested_diff import diff, patch
>>>
>>> a = {'one': 1, 'two': 2, 'three': 3}
>>> b = {'one': 1, 'two': 42}
>>>
>>> diff(a, b)
{'D': {'three': {'R': 3}, 'two': {'N': 42, 'O': 2}, 'one': {'U': 1}}}
>>>
>>> diff(a, b, O=False, U=False)
{'D': {'three': {'R': 3}, 'two': {'N': 42}}}
>>>
>>>
>>> c = [0,1,2,3]
>>> d = [ 1,2,4,5]
>>>
>>> c = patch(c, diff(c, d))
>>> assert c == d
>>>
Formatting diffs
>>> from nested_diff import diff, handlers
>>> from nested_diff.formatters import TextFormatter
>>>
>>> a = {'one': 1, 'two': 'some\ntext\ninside'}
>>> b = {'one': 0, 'two': 'some\ntext'}
>>>
>>> d = diff(a, b, U=False, extra_handlers=[handlers.TextHandler(context=3)])
>>> print(TextFormatter().format(d))
{'one'}
- 1
+ 0
{'two'}
# <str>
@@ -1,3 +1,2 @@
some
text
- inside
<BLANKLINE>
>>>
For more examples see Live Demo, HOWTO and tests.
Diff structure
Diff is a dict and may contain status keys:
Astands for 'added', it's value - added item.Dmeans 'different' and contains subdiff.Nis a new value for changed item.Ois a changed item's old value.Rkey used for removed item.Urepresent unchanged item.
and auxiliary keys:
Ccomment; optional, value - arbitrary string.Eextension ID (optional).Iindex for sequence item, used only when prior item was omitted.
Diff metadata alternates with actual data; simple types specified as is, dicts,
lists and tuples contain subdiffs for their items with native for such types
addressing: indexes for lists and tuples, keys for dictionaries. Any status
key, except D may be omitted during diff computation. E key is used with
D when entity unable to contain diff by itself (set, frozenset for example);
D contain a list of subdiffs in this case.
Annotated example:
a: {"one": [5,7]}
b: {"one": [5], "two": 2}
opts: U=False # omit unchanged items
diff:
{"D": {"one": {"D": [{"I": 1, "R": 7}]}, "two": {"A": 2}}}
| | | | | | || | | | | | | | |
| | | | | | || | | | | | | | +- with value 2
| | | | | | || | | | | | | +- key 'two' was added
| | | | | | || | | | | | +- subdiff for it
| | | | | | || | | | | +- another key from top-level
| | | | | | || | | | +- what it was (item's value: 7)
| | | | | | || | | +- what happened to item (removed)
| | | | | | || | +- list item's actual index
| | | | | | || +- prior item was omitted
| | | | | | |+- subdiff for list item
| | | | | | +- it's value - list
| | | | | +- it is deeply changed
| | | | +- subdiff for key 'one'
| | | +- it has key 'one'
| | +- top-level thing is a dict
| +- changes somewhere deeply inside
+- diff is always a dict
License
Licensed under the terms of the Apache License, Version 2.0.
See Also
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nested_diff-1.3.1.tar.gz.
File metadata
- Download URL: nested_diff-1.3.1.tar.gz
- Upload date:
- Size: 25.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3f87f3d4a4170ac77cfb05ac33e11e7b3edb39db28d44a5d0c529cafc76fc9a
|
|
| MD5 |
11db14e3fa48fba67f833ad8780c4056
|
|
| BLAKE2b-256 |
e69027e73fc6b6dd92bc3b44a1c25b46c7ba35cf5aba015bd1a320984a39aab3
|
File details
Details for the file nested_diff-1.3.1-py3-none-any.whl.
File metadata
- Download URL: nested_diff-1.3.1-py3-none-any.whl
- Upload date:
- Size: 25.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5f553e24940c4fbb4f4257b926c217878d86d087d64e57d4752869b08978ef0
|
|
| MD5 |
855db59131f2dc05366700048354caf0
|
|
| BLAKE2b-256 |
6f01891b8a37687e0c37be3774c287877f31d6c93e226fa92055ae086d5a58a0
|