Patchdiff 🔍
Bidirectional, JSON-patch-compliant diffs between Python data structures.
📖 Documentation | Quick Start | API Reference
Patchdiff diffs composite structures of dicts, lists, sets and tuples, and gives you both directions in one call: the patches to get from input to output, and the patches to get back. Patches are RFC 6902 JSON-patch style, serializable to JSON, and can be applied in place or to a copy, which makes undo/redo, change synchronization and state auditing one-liners.
from patchdiff import apply, diff, iapply, to_json
input = {"a": [5, 7, 9, {"a", "b", "c"}], "b": 6}
output = {"a": [5, 2, 9, {"b", "c"}], "b": 6, "c": 7}
ops, reverse_ops = diff(input, output)
assert apply(input, ops) == output # patch a copy...
assert apply(output, reverse_ops) == input # ...and it round-trips
iapply(input, ops) # or patch in place
assert input == output
print(to_json(ops, indent=4))
Proxy based patch generation
When your own code makes the changes, produce() (inspired by Immer) skips the comparison entirely: it hands your recipe a draft, records every mutation, and returns the result plus both patch directions. Cost scales with the number of mutations instead of the size of the state:
from patchdiff import produce
base = {"count": 0, "items": [1, 2, 3]}
def recipe(draft):
draft["count"] = 5
draft["items"].append(4)
result, patches, reverse_patches = produce(base, recipe)
assert base == {"count": 0, "items": [1, 2, 3]} # base is untouched
assert result == {"count": 5, "items": [1, 2, 3, 4]}
With in_place=True, mutations (and patches applied with iapply) write straight through proxy-backed state, the natural companion to observ reactive objects, where mutating through the proxy is what triggers watchers. See Observ Integration for reactive state with undo/redo.
Install
pip install patchdiff # or: uv add patchdiff
No dependencies, Python >= 3.9.
Learn more
The documentation covers diffing semantics, applying patches, JSON pointers, proxy-based patch generation, serialization and the gotchas, plus the internals for the curious.
Release files for patchdiff 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| patchdiff-1.0.0.tar.gz | 76.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| patchdiff-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 97.7 kB
Release files / patchdiff-1.0.0.tar.gz
| Download URL | patchdiff-1.0.0.tar.gz |
|---|---|
| Size | 76.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5b79b89d96d15bcbb58ea6df7c86fe91c62daf56837892b8d873800f1718352c
|
|
BLAKE2b-256 checksum How to use checksums |
9719b085b46a112dfcbf915a99197eb6d359842edc5a8383b30fb33bf6668caf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.
Transparency logRelease files / patchdiff-1.0.0-py3-none-any.whl
| Download URL | patchdiff-1.0.0-py3-none-any.whl |
|---|---|
| Size | 21.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e2f9bc78aa262e01900ca03e67a0247ff8a12d51e988ba9b384ec21e34dc56fe
|
|
BLAKE2b-256 checksum How to use checksums |
fd1d0f536221b0c385c417f53858d55a194cc0643fb4e5a77b030fab8025333a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.
Transparency log