Skip to content

Commit

Permalink
Merge pull request #60 from ramwin/master
Browse files Browse the repository at this point in the history
add rightonly jsondiff syntax
  • Loading branch information
fzumstein authored Jun 20, 2023
2 parents 66bad55 + 73c7a6a commit c0aab2a
Show file tree
Hide file tree
Showing 5 changed files with 79 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="rightonly")
{"list": [1, 3], delete: ["poplist"]}
# Special handling of sets
>>> diff({'a', 'b', 'c'}, {'a', 'c', 'd'})
{discard: set(['b']), add: set(['d'])}
Expand Down
28 changes: 27 additions & 1 deletion jsondiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,36 @@ def unpatch(self, b, d):
raise Exception("Invalid symmetric diff")


class RightOnlyJsonDiffSyntax(CompactJsonDiffSyntax):
"""
Compare to the CompactJsonDiffSyntax, I will not compare the difference in list,
because in some senario we only care about the right value (in most cases means latest value).
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(),
'rightonly': RightOnlyJsonDiffSyntax(),
}


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


missing = Symbol('missing')
identical = Symbol('identical')
delete = Symbol('delete')
Expand Down Expand Up @@ -55,4 +56,4 @@ def __hash__(self) -> int:
'left',
'right',
'_all_symbols_'
]
]
46 changes: 46 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,39 @@ class TestSpecificIssue:
def test_issue(self, a, b, syntax, expected):
actual = diff(a, b, syntax=syntax)
assert actual == expected


class TestRightOnly(unittest.TestCase):
def test_right_only_syntax(self):
a = {"poplist": [1, 2, 3]}
b = {}
self.assertEqual(
diff(a, b, syntax="rightonly", 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="rightonly", marshal=True),
{
2: 4,
"list": [1, 3],
"$delete": ["poplist"],
}
)
self.assertEqual(
diff(a, b, syntax="rightonly"),
{
2: 4,
"list": [1, 3],
delete: ["poplist"],
}
)
c = [1, 2, 3]
d = [4, 5, 6]
self.assertEqual(
diff(c, d, syntax="rightonly", marshal=True),
[4, 5, 6],
)

0 comments on commit c0aab2a

Please sign in to comment.