Skip to content

Commit

Permalink
Adding new_path when the old path and new path don't match
Browse files Browse the repository at this point in the history
  • Loading branch information
seperman committed Apr 8, 2024
1 parent e559cd3 commit dfe1ea5
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 29 deletions.
21 changes: 14 additions & 7 deletions deepdiff/delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,19 +812,21 @@ def _get_reverse_diff(self):
elif action == 'values_changed':
r_diff[action] = {}
for path, path_info in info.items():
r_diff[action][path] = {
reverse_path = path_info['new_path'] if path_info.get('new_path') else path
r_diff[action][reverse_path] = {
'new_value': path_info['old_value'], 'old_value': path_info['new_value']
}
elif action == 'type_changes':
r_diff[action] = {}
for path, path_info in info.items():
r_diff[action][path] = {
reverse_path = path_info['new_path'] if path_info.get('new_path') else path
r_diff[action][reverse_path] = {
'old_type': path_info['new_type'], 'new_type': path_info['old_type'],
}
if 'new_value' in path_info:
r_diff[action][path]['old_value'] = path_info['new_value']
r_diff[action][reverse_path]['old_value'] = path_info['new_value']
if 'old_value' in path_info:
r_diff[action][path]['new_value'] = path_info['old_value']
r_diff[action][reverse_path]['new_value'] = path_info['old_value']
elif action == 'iterable_item_moved':
r_diff[action] = {}
for path, path_info in info.items():
Expand Down Expand Up @@ -907,6 +909,7 @@ def _from_flat_dicts(flat_dict_list):
action = flat_dict.get("action")
path = flat_dict.get("path")
value = flat_dict.get('value')
new_path = flat_dict.get('new_path')
old_value = flat_dict.get('old_value', UnkownValueCode)
if not action:
raise ValueError("Flat dict need to include the 'action'.")
Expand All @@ -920,6 +923,10 @@ def _from_flat_dicts(flat_dict_list):
else:
root_element = ('root', GET)
path_str = stringify_path(path, root_element=root_element) # We need the string path
if new_path and new_path != path:
new_path = stringify_path(new_path, root_element=root_element)
else:
new_path = None
if action not in result:
result[action] = {}
if action in {'iterable_items_added_at_indexes', 'iterable_items_removed_at_indexes'}:
Expand All @@ -937,14 +944,14 @@ def _from_flat_dicts(flat_dict_list):
result[action][path_str] = value
elif action == 'values_changed':
if old_value == UnkownValueCode:
result[action][path_str] = {'new_value': value}
result[action][path_str] = {'new_value': value, 'new_path': new_path}
else:
result[action][path_str] = {'new_value': value, 'old_value': old_value}
result[action][path_str] = {'new_value': value, 'old_value': old_value, 'new_path': new_path}
elif action == 'type_changes':
type_ = flat_dict.get('type', UnkownValueCode)
old_type = flat_dict.get('old_type', UnkownValueCode)

result[action][path_str] = {'new_value': value}
result[action][path_str] = {'new_value': value, 'new_path': new_path}
for elem, elem_value in [
('new_type', type_),
('old_type', old_type),
Expand Down
9 changes: 7 additions & 2 deletions deepdiff/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -1280,12 +1280,14 @@ def get_other_pair(hash_value, in_t1=True):
other = get_other_pair(hash_value)
item_id = id(other.item)
indexes = t2_hashtable[hash_value].indexes if other.item is notpresent else other.indexes
index2 = t2_hashtable[hash_value].indexes[0]
for i in indexes:
change_level = level.branch_deeper(
other.item,
t2_hashtable[hash_value].item,
child_relationship_class=SubscriptableIterableRelationship,
child_relationship_param=i
child_relationship_param=i,
child_relationship_param2=index2,
)
if other.item is notpresent:
self._report_result('iterable_item_added', change_level, local_tree=local_tree)
Expand All @@ -1297,12 +1299,15 @@ def get_other_pair(hash_value, in_t1=True):
return # pragma: no cover. This is already covered for addition.
other = get_other_pair(hash_value, in_t1=False)
item_id = id(other.item)
index2 = None if other.item is notpresent else other.indexes[0]
for i in t1_hashtable[hash_value].indexes:
change_level = level.branch_deeper(
t1_hashtable[hash_value].item,
other.item,
child_relationship_class=SubscriptableIterableRelationship,
child_relationship_param=i)
child_relationship_param=i,
child_relationship_param2=index2,
)
if other.item is notpresent:
self._report_result('iterable_item_removed', change_level, local_tree=local_tree)
else:
Expand Down
32 changes: 22 additions & 10 deletions deepdiff/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ def _from_tree_default(self, tree, report_type, ignore_if_in_iterable_opcodes=Fa
def _from_tree_type_changes(self, tree):
if 'type_changes' in tree:
for change in tree['type_changes']:
path = change.path(force=FORCE_DEFAULT)
new_path = change.path(use_t2=True, force=FORCE_DEFAULT)
if type(change.t1) is type:
include_values = False
old_type = change.t1
Expand All @@ -198,19 +200,23 @@ def _from_tree_type_changes(self, tree):
new_type = get_type(change.t2)
remap_dict = RemapDict({
'old_type': old_type,
'new_type': new_type
'new_type': new_type,
})
self['type_changes'][change.path(
force=FORCE_DEFAULT)] = remap_dict
if path != new_path:
remap_dict['new_path'] = new_path
self['type_changes'][path] = remap_dict
if self.verbose_level and include_values:
remap_dict.update(old_value=change.t1, new_value=change.t2)

def _from_tree_value_changed(self, tree):
if 'values_changed' in tree and self.verbose_level > 0:
for change in tree['values_changed']:
path = change.path(force=FORCE_DEFAULT)
new_path = change.path(use_t2=True, force=FORCE_DEFAULT)
the_changed = {'new_value': change.t2, 'old_value': change.t1}
self['values_changed'][change.path(
force=FORCE_DEFAULT)] = the_changed
if path != new_path:
the_changed['new_path'] = new_path
self['values_changed'][path] = the_changed
if 'diff' in change.additional:
the_changed.update({'diff': change.additional['diff']})

Expand Down Expand Up @@ -379,21 +385,27 @@ def _from_tree_type_changes(self, tree):
except Exception:
pass

path = change.path(force=FORCE_DEFAULT)
new_path = change.path(use_t2=True, force=FORCE_DEFAULT)
remap_dict = RemapDict({
'old_type': old_type,
'new_type': new_type
'new_type': new_type,
})
self['type_changes'][change.path(
force=FORCE_DEFAULT)] = remap_dict
if path != new_path:
remap_dict['new_path'] = new_path
self['type_changes'][path] = remap_dict
if include_values or self.always_include_values:
remap_dict.update(old_value=change.t1, new_value=change.t2)

def _from_tree_value_changed(self, tree):
if 'values_changed' in tree:
for change in tree['values_changed']:
path = change.path(force=FORCE_DEFAULT)
new_path = change.path(use_t2=True, force=FORCE_DEFAULT)
the_changed = {'new_value': change.t2, 'old_value': change.t1}
self['values_changed'][change.path(
force=FORCE_DEFAULT)] = the_changed
if path != new_path:
the_changed['new_path'] = new_path
self['values_changed'][path] = the_changed
# If we ever want to store the difflib results instead of the new_value
# these lines need to be uncommented and the Delta object needs to be able
# to use them.
Expand Down
27 changes: 17 additions & 10 deletions tests/test_delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,8 +911,9 @@ def test_delta_cases(self, test_name, t1, t2, deepdiff_kwargs, to_delta_kwargs,
'expected_delta_dict': {
'values_changed': {
'root[6]': {
'new_value': 5
}
'new_value': 5,
'new_path': 'root[3]',
},
},
'iterable_items_removed_at_indexes': {
'root': {
Expand All @@ -935,8 +936,9 @@ def test_delta_cases(self, test_name, t1, t2, deepdiff_kwargs, to_delta_kwargs,
'expected_delta_dict': {
'values_changed': {
'root[3]': {
'new_value': 4
}
'new_value': 4,
'new_path': 'root[6]',
},
},
'iterable_items_added_at_indexes': {
'root': {
Expand All @@ -959,10 +961,12 @@ def test_delta_cases(self, test_name, t1, t2, deepdiff_kwargs, to_delta_kwargs,
'expected_delta_dict': {
'values_changed': {
'root[4]': {
'new_value': 7
'new_value': 7,
'new_path': 'root[0]'
},
'root[0]': {
'new_value': 8
'new_value': 8,
'new_path': 'root[4]'
}
}
},
Expand All @@ -979,10 +983,12 @@ def test_delta_cases(self, test_name, t1, t2, deepdiff_kwargs, to_delta_kwargs,
'expected_delta_dict': {
'values_changed': {
'root[6]': {
'new_value': 7
'new_value': 7,
'new_path': 'root[0]'
},
'root[0]': {
'new_value': 8
'new_value': 8,
'new_path': 'root[6]'
}
},
'iterable_items_added_at_indexes': {
Expand Down Expand Up @@ -2472,7 +2478,6 @@ def test_flat_dict_and_deeply_nested_dict(self):
pprint(delta._get_reverse_diff())
print("\nreverse_delta.diff")
pprint(reverse_delta.diff)
# import pytest; pytest.set_trace()
beforeImageAgain = allAfterImage - delta
diff3 = DeepDiff(beforeImage, beforeImageAgain, ignore_order=True)
assert not diff3
Expand All @@ -2488,6 +2493,8 @@ def test_flat_dict_and_deeply_nested_dict(self):
raise_errors=False,
force=True,
)

print("\ndelta from flat dicts")
pprint(delta2.diff)
import pytest; pytest.set_trace()
assert allAfterImage == beforeImage + delta2
assert beforeImage == allAfterImage - delta2

0 comments on commit dfe1ea5

Please sign in to comment.