Skip to content

Commit

Permalink
bugfix: Differ now produce correct diff for nested derivatives
Browse files Browse the repository at this point in the history
example: dict derivative placed in another dict vs. same structure and data
with just dicts are now considered different
  • Loading branch information
mr-mixas committed Sep 6, 2020
1 parent d584b72 commit b146741
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
18 changes: 9 additions & 9 deletions nested_diff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ def diff(self, a, b):
This method is a dispatcher and calls registered diff method for each
diffed values pair according to their type. `diff__default` called for
non-registered types. Args and kwargs passed to called method as is.
unequal and not registered types. Args and kwargs passed to called
method as is.
:param a: First object to diff.
:param b: Second object to diff.
Expand All @@ -156,8 +157,11 @@ def diff(self, a, b):
)

if a.__class__ is b.__class__:
if a == b:
# it's faster to compare pickled dumps and dig differences
# afterwards than recursively diff each pair of objects
if a is b or dumps(a, -1) == dumps(b, -1):
return {'U': a} if self.op_u else {}

return self.get_differ(a.__class__)(a, b)

return self.diff__default(a, b)
Expand Down Expand Up @@ -207,13 +211,9 @@ def diff_dict(self, a, b):
dif[key] = {'A': b[key]}
continue

if old == new:
if self.op_u:
dif[key] = {'U': old}
else:
subdiff = self.diff(old, new)
if subdiff:
dif[key] = subdiff
subdiff = self.diff(old, new)
if subdiff:
dif[key] = subdiff

if dif:
return {'D': dif}
Expand Down
38 changes: 38 additions & 0 deletions tests/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,41 @@ def test_diff(name):
got = diff(a, b, **opts)

assert expected == got


def test_local_objects():
def local_function_cant_be_pickled():
pass

a = [local_function_cant_be_pickled]
b = []

with pytest.raises(Exception): # Can't pickle local object
diff(a, b)


class SubclassedDict(dict):
# can't be declared inside test (Can't pickle local object)
pass


def test_nested_derivatives():
original = {}
a = {'k': original}
derivative = SubclassedDict()
b = {'k': derivative}

d = diff(a, b)

assert {'D': {'k': {'N': derivative, 'O': original}}} == d


def test_different_object_attributes():
a = SubclassedDict()
a.arbitrary_attr = True
b = SubclassedDict()
b.arbitrary_attr = False

d = diff(a, b)

assert {'N': b, 'O': a} == d

0 comments on commit b146741

Please sign in to comment.