Skip to content

Commit

Permalink
add intuitive jsondiff syntax && fix unhashable type error
Browse files Browse the repository at this point in the history
  • Loading branch information
ramwin committed Jun 15, 2023
1 parent 66bad55 commit 83d149c
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ target/
# PyCharm
.idea

.hypothesis/
.hypothesis/
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ Quickstart
>>> diff({'a': 1, 'b': 2}, {'b': 3, 'c': 4}, syntax='symmetric')
{insert: {'c': 4}, 'b': [2, 3], delete: {'a': 1}}
>>> diff({'list': [1, 2, 3], "poplist": [1, 2, 3]}, {'list': [1, 3]}, syntax="intuitive")
{"list": [1, 3], delete: ["poplist"]}
# Special handling of sets
>>> diff({'a', 'b', 'c'}, {'a', 'c', 'd'})
{discard: set(['b']), add: set(['d'])}
Expand Down
26 changes: 25 additions & 1 deletion jsondiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,34 @@ def unpatch(self, b, d):
raise Exception("Invalid symmetric diff")


class IntuitiveJsonDiffSyntax(CompactJsonDiffSyntax):
"""
Compare to the CompactJsonDiffSyntax, I will not compare the difference in list, because { delete : [1] } is not intuitive, instead, I will pop the later list value.
"""

def emit_dict_diff(self, a, b, s, added, changed, removed):
if s == 1.0:
return {}
else:
changed.update(added)
if removed:
changed[delete] = list(removed.keys())
return changed

def emit_list_diff(self, a, b, s, inserted, changed, deleted):
if s == 0.0:
return b
elif s == 1.0:
return {}
else:
return b


builtin_syntaxes = {
'compact': CompactJsonDiffSyntax(),
'symmetric': SymmetricJsonDiffSyntax(),
'explicit': ExplicitJsonDiffSyntax()
'explicit': ExplicitJsonDiffSyntax(),
'intuitive': IntuitiveJsonDiffSyntax(),
}


Expand Down
6 changes: 5 additions & 1 deletion jsondiff/symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ def __eq__(self, other):
def __hash__(self) -> int:
return hash(self.label)

def __hash__(self):
return hash(id(self))


missing = Symbol('missing')
identical = Symbol('identical')
delete = Symbol('delete')
Expand Down Expand Up @@ -55,4 +59,4 @@ def __hash__(self) -> int:
'left',
'right',
'_all_symbols_'
]
]
44 changes: 44 additions & 0 deletions tests/test_jsondiff.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import sys
import unittest
import pytest
Expand All @@ -9,6 +10,15 @@
from hypothesis import given, settings, strategies


logging.basicConfig(
level=logging.INFO,
format=(
'%(asctime)s %(pathname)s[line:%(lineno)d] %(levelname)s %(message)s'
),
)
logging.getLogger("jsondiff").setLevel(logging.DEBUG)


def generate_scenario(rng):
a = generate_random_json(rng, sets=True)
b = perturbate_json(a, rng, sets=True)
Expand Down Expand Up @@ -162,3 +172,37 @@ class TestSpecificIssue:
def test_issue(self, a, b, syntax, expected):
actual = diff(a, b, syntax=syntax)
assert actual == expected

def test_intuitive_syntax(self):
a = {"poplist": [1, 2, 3]}
b = {}
self.assertEqual(
diff(a, b, syntax="intuitive", marshal=True),
{
"$delete": ["poplist"],
}
)
a = {1: 2, 2: 3, 'list': [1, 2, 3], 'samelist': [1, 2, 3], "poplist": [1, 2, 3]}
b = {1: 2, 2: 4, 'list': [1, 3], 'samelist': [1, 2, 3]}
self.assertEqual(
diff(a, b, syntax="intuitive", marshal=True),
{
2: 4,
"list": [1, 3],
"$delete": ["poplist"],
}
)
self.assertEqual(
diff(a, b, syntax="intuitive"),
{
2: 4,
"list": [1, 3],
delete: ["poplist"],
}
)
c = [1, 2, 3]
d = [4, 5, 6]
self.assertEqual(
diff(c, d, syntax="intuitive", marshal=True),
[4, 5, 6],
)

0 comments on commit 83d149c

Please sign in to comment.