Recursive diff and patch 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 ops (added/removed/changed/unchanged) are optional and may be disabled.
- Any data types support may be added by external handlers.
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
>>> from nested_diff.formatters import TextFormatter
>>>
>>> a = {'one': 1, 'two': 2, 'three': 3}
>>> b = {'one': 1, 'two': 42}
>>>
>>>
>>> full_diff = diff(a, b)
>>> full_diff
{'D': {'three': {'R': 3}, 'two': {'N': 42, 'O': 2}, 'one': {'U': 1}}}
>>>
>>> short_diff = diff(a, b, O=False, U=False) # omit old and unchanged items
>>> short_diff
{'D': {'three': {'R': 3}, 'two': {'N': 42}}}
>>>
>>>
>>> a = patch(a, short_diff)
>>> assert a == b
>>>
>>>
>>> human_readable = TextFormatter().format(full_diff)
>>> print(human_readable)
{'one'}
1
- {'three'}
- 3
{'two'}
- 2
+ 42
<BLANKLINE>
>>>
HTML and ANSI colored terminal formatters also available out of the box.
See Live Demo,
HOWTO and
nested_diff.formatters.
Diff structure
Diff is a dict and may contain status keys:
A
stands for 'added', it's value - added item.D
means 'different' and contains subdiff.N
is a new value for changed item.O
is a changed item's old value.R
key used for removed item.U
represent unchanged item.
and auxiliary keys:
C
comment; optional, value - arbitrary string.E
extension ID (optional).I
index 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
File details
Details for the file nested_diff-1.6.0.tar.gz
.
File metadata
- Download URL: nested_diff-1.6.0.tar.gz
- Upload date:
- Size: 22.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2d9eea19595d69380ac51686627bb54cc2bdb6f72fbca2d7fd6dd8838f31d1df |
|
MD5 | 8557cd9756bfb4c0c1f34664b2e336b5 |
|
BLAKE2b-256 | 6526a2fdfc6596dbd944005505593dfe10b505ece7bfa62362fe1706374ca2b0 |
File details
Details for the file nested_diff-1.6.0-py3-none-any.whl
.
File metadata
- Download URL: nested_diff-1.6.0-py3-none-any.whl
- Upload date:
- Size: 26.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 236895d56d64b39123034321bd819bf77006632fd96d0095b02e5183fce1f8ba |
|
MD5 | b29d1288ff9884662fc3f449919ee302 |
|
BLAKE2b-256 | 567214133a8c18fa4fe1b4be4b206244a8d83d9c3a5a2d6f1d4b3a541aae4165 |