Skip to main content

Recursive diff and patch for nested structures.

Project description

Nested-Diff.py

Recursive diff and patch for nested structures.

PyPi Tests Coverage Supported Python versions License

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.

See Live Demo!

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

HOWTO

deepdiff, jsondiff, jsonpatch, json-delta

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nested_diff-1.6.0.tar.gz (22.3 kB view details)

Uploaded Source

Built Distribution

nested_diff-1.6.0-py3-none-any.whl (26.0 kB view details)

Uploaded Python 3

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

Hashes for nested_diff-1.6.0.tar.gz
Algorithm Hash digest
SHA256 2d9eea19595d69380ac51686627bb54cc2bdb6f72fbca2d7fd6dd8838f31d1df
MD5 8557cd9756bfb4c0c1f34664b2e336b5
BLAKE2b-256 6526a2fdfc6596dbd944005505593dfe10b505ece7bfa62362fe1706374ca2b0

See more details on using hashes here.

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

Hashes for nested_diff-1.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 236895d56d64b39123034321bd819bf77006632fd96d0095b02e5183fce1f8ba
MD5 b29d1288ff9884662fc3f449919ee302
BLAKE2b-256 567214133a8c18fa4fe1b4be4b206244a8d83d9c3a5a2d6f1d4b3a541aae4165

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page