hat.json.patch

JSON Patch

 1"""JSON Patch"""
 2
 3import jsonpatch
 4
 5from hat.json.data import Data
 6
 7
 8def diff(src: Data,
 9         dst: Data
10         ) -> Data:
11    """Generate JSON Patch diff.
12
13    Example::
14
15        src = [1, {'a': 2}, 3]
16        dst = [1, {'a': 4}, 3]
17        result = diff(src, dst)
18        assert result == [{'op': 'replace', 'path': '/1/a', 'value': 4}]
19
20    """
21    return jsonpatch.JsonPatch.from_diff(src, dst).patch
22
23
24def patch(data: Data,
25          diff: Data
26          ) -> Data:
27    """Apply JSON Patch diff.
28
29    Example::
30
31        data = [1, {'a': 2}, 3]
32        d = [{'op': 'replace', 'path': '/1/a', 'value': 4}]
33        result = patch(data, d)
34        assert result == [1, {'a': 4}, 3]
35
36    """
37    return jsonpatch.apply_patch(data, diff)
38
39
40# check upstream changes in jsonpatch and validate performance impact
41
42# def _monkeypatch_jsonpatch():
43#     """Monkeypatch jsonpatch.
44
45#     Patch incorrect value comparison between ``bool`` and numeric values when
46#     diffing json serializable data.
47
48#     Comparing `False` to `0` or `0.0`; and `True` to `1` or `1.0` incorrectly
49#     results in no change.
50
51#     """
52#     def _compare_values(self, path, key, src, dst):
53
54#         if isinstance(src, jsonpatch.MutableMapping) and \
55#                 isinstance(dst, jsonpatch.MutableMapping):
56#             self._compare_dicts(jsonpatch._path_join(path, key), src, dst)
57
58#         elif isinstance(src, jsonpatch.MutableSequence) and \
59#                 isinstance(dst, jsonpatch.MutableSequence):
60#             self._compare_lists(jsonpatch._path_join(path, key), src, dst)
61
62#         elif isinstance(src, bool) == isinstance(dst, bool) and src == dst:
63#             pass
64
65#         else:
66#             self._item_replaced(path, key, dst)
67
68#     jsonpatch.DiffBuilder._compare_values = _compare_values
69
70
71# _monkeypatch_jsonpatch()
def diff( src: None | bool | int | float | str | list[None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]] | dict[str, None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]], dst: None | bool | int | float | str | list[None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]] | dict[str, None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]]) -> None | bool | int | float | str | list[None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]] | dict[str, None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]]:
 9def diff(src: Data,
10         dst: Data
11         ) -> Data:
12    """Generate JSON Patch diff.
13
14    Example::
15
16        src = [1, {'a': 2}, 3]
17        dst = [1, {'a': 4}, 3]
18        result = diff(src, dst)
19        assert result == [{'op': 'replace', 'path': '/1/a', 'value': 4}]
20
21    """
22    return jsonpatch.JsonPatch.from_diff(src, dst).patch

Generate JSON Patch diff.

Example::

src = [1, {'a': 2}, 3]
dst = [1, {'a': 4}, 3]
result = diff(src, dst)
assert result == [{'op': 'replace', 'path': '/1/a', 'value': 4}]
def patch( data: None | bool | int | float | str | list[None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]] | dict[str, None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]], diff: None | bool | int | float | str | list[None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]] | dict[str, None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]]) -> None | bool | int | float | str | list[None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]] | dict[str, None | bool | int | float | str | list[ForwardRef('Data')] | dict[str, ForwardRef('Data')]]:
25def patch(data: Data,
26          diff: Data
27          ) -> Data:
28    """Apply JSON Patch diff.
29
30    Example::
31
32        data = [1, {'a': 2}, 3]
33        d = [{'op': 'replace', 'path': '/1/a', 'value': 4}]
34        result = patch(data, d)
35        assert result == [1, {'a': 4}, 3]
36
37    """
38    return jsonpatch.apply_patch(data, diff)

Apply JSON Patch diff.

Example::

data = [1, {'a': 2}, 3]
d = [{'op': 'replace', 'path': '/1/a', 'value': 4}]
result = patch(data, d)
assert result == [1, {'a': 4}, 3]