Skip to content

Commit dfe1ea5

Browse files
committed
Adding new_path when the old path and new path don't match
1 parent e559cd3 commit dfe1ea5

File tree

4 files changed

+60
-29
lines changed

4 files changed

+60
-29
lines changed

deepdiff/delta.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -812,19 +812,21 @@ def _get_reverse_diff(self):
812812
elif action == 'values_changed':
813813
r_diff[action] = {}
814814
for path, path_info in info.items():
815-
r_diff[action][path] = {
815+
reverse_path = path_info['new_path'] if path_info.get('new_path') else path
816+
r_diff[action][reverse_path] = {
816817
'new_value': path_info['old_value'], 'old_value': path_info['new_value']
817818
}
818819
elif action == 'type_changes':
819820
r_diff[action] = {}
820821
for path, path_info in info.items():
821-
r_diff[action][path] = {
822+
reverse_path = path_info['new_path'] if path_info.get('new_path') else path
823+
r_diff[action][reverse_path] = {
822824
'old_type': path_info['new_type'], 'new_type': path_info['old_type'],
823825
}
824826
if 'new_value' in path_info:
825-
r_diff[action][path]['old_value'] = path_info['new_value']
827+
r_diff[action][reverse_path]['old_value'] = path_info['new_value']
826828
if 'old_value' in path_info:
827-
r_diff[action][path]['new_value'] = path_info['old_value']
829+
r_diff[action][reverse_path]['new_value'] = path_info['old_value']
828830
elif action == 'iterable_item_moved':
829831
r_diff[action] = {}
830832
for path, path_info in info.items():
@@ -907,6 +909,7 @@ def _from_flat_dicts(flat_dict_list):
907909
action = flat_dict.get("action")
908910
path = flat_dict.get("path")
909911
value = flat_dict.get('value')
912+
new_path = flat_dict.get('new_path')
910913
old_value = flat_dict.get('old_value', UnkownValueCode)
911914
if not action:
912915
raise ValueError("Flat dict need to include the 'action'.")
@@ -920,6 +923,10 @@ def _from_flat_dicts(flat_dict_list):
920923
else:
921924
root_element = ('root', GET)
922925
path_str = stringify_path(path, root_element=root_element) # We need the string path
926+
if new_path and new_path != path:
927+
new_path = stringify_path(new_path, root_element=root_element)
928+
else:
929+
new_path = None
923930
if action not in result:
924931
result[action] = {}
925932
if action in {'iterable_items_added_at_indexes', 'iterable_items_removed_at_indexes'}:
@@ -937,14 +944,14 @@ def _from_flat_dicts(flat_dict_list):
937944
result[action][path_str] = value
938945
elif action == 'values_changed':
939946
if old_value == UnkownValueCode:
940-
result[action][path_str] = {'new_value': value}
947+
result[action][path_str] = {'new_value': value, 'new_path': new_path}
941948
else:
942-
result[action][path_str] = {'new_value': value, 'old_value': old_value}
949+
result[action][path_str] = {'new_value': value, 'old_value': old_value, 'new_path': new_path}
943950
elif action == 'type_changes':
944951
type_ = flat_dict.get('type', UnkownValueCode)
945952
old_type = flat_dict.get('old_type', UnkownValueCode)
946953

947-
result[action][path_str] = {'new_value': value}
954+
result[action][path_str] = {'new_value': value, 'new_path': new_path}
948955
for elem, elem_value in [
949956
('new_type', type_),
950957
('old_type', old_type),

deepdiff/diff.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,12 +1280,14 @@ def get_other_pair(hash_value, in_t1=True):
12801280
other = get_other_pair(hash_value)
12811281
item_id = id(other.item)
12821282
indexes = t2_hashtable[hash_value].indexes if other.item is notpresent else other.indexes
1283+
index2 = t2_hashtable[hash_value].indexes[0]
12831284
for i in indexes:
12841285
change_level = level.branch_deeper(
12851286
other.item,
12861287
t2_hashtable[hash_value].item,
12871288
child_relationship_class=SubscriptableIterableRelationship,
1288-
child_relationship_param=i
1289+
child_relationship_param=i,
1290+
child_relationship_param2=index2,
12891291
)
12901292
if other.item is notpresent:
12911293
self._report_result('iterable_item_added', change_level, local_tree=local_tree)
@@ -1297,12 +1299,15 @@ def get_other_pair(hash_value, in_t1=True):
12971299
return # pragma: no cover. This is already covered for addition.
12981300
other = get_other_pair(hash_value, in_t1=False)
12991301
item_id = id(other.item)
1302+
index2 = None if other.item is notpresent else other.indexes[0]
13001303
for i in t1_hashtable[hash_value].indexes:
13011304
change_level = level.branch_deeper(
13021305
t1_hashtable[hash_value].item,
13031306
other.item,
13041307
child_relationship_class=SubscriptableIterableRelationship,
1305-
child_relationship_param=i)
1308+
child_relationship_param=i,
1309+
child_relationship_param2=index2,
1310+
)
13061311
if other.item is notpresent:
13071312
self._report_result('iterable_item_removed', change_level, local_tree=local_tree)
13081313
else:

deepdiff/model.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ def _from_tree_default(self, tree, report_type, ignore_if_in_iterable_opcodes=Fa
188188
def _from_tree_type_changes(self, tree):
189189
if 'type_changes' in tree:
190190
for change in tree['type_changes']:
191+
path = change.path(force=FORCE_DEFAULT)
192+
new_path = change.path(use_t2=True, force=FORCE_DEFAULT)
191193
if type(change.t1) is type:
192194
include_values = False
193195
old_type = change.t1
@@ -198,19 +200,23 @@ def _from_tree_type_changes(self, tree):
198200
new_type = get_type(change.t2)
199201
remap_dict = RemapDict({
200202
'old_type': old_type,
201-
'new_type': new_type
203+
'new_type': new_type,
202204
})
203-
self['type_changes'][change.path(
204-
force=FORCE_DEFAULT)] = remap_dict
205+
if path != new_path:
206+
remap_dict['new_path'] = new_path
207+
self['type_changes'][path] = remap_dict
205208
if self.verbose_level and include_values:
206209
remap_dict.update(old_value=change.t1, new_value=change.t2)
207210

208211
def _from_tree_value_changed(self, tree):
209212
if 'values_changed' in tree and self.verbose_level > 0:
210213
for change in tree['values_changed']:
214+
path = change.path(force=FORCE_DEFAULT)
215+
new_path = change.path(use_t2=True, force=FORCE_DEFAULT)
211216
the_changed = {'new_value': change.t2, 'old_value': change.t1}
212-
self['values_changed'][change.path(
213-
force=FORCE_DEFAULT)] = the_changed
217+
if path != new_path:
218+
the_changed['new_path'] = new_path
219+
self['values_changed'][path] = the_changed
214220
if 'diff' in change.additional:
215221
the_changed.update({'diff': change.additional['diff']})
216222

@@ -379,21 +385,27 @@ def _from_tree_type_changes(self, tree):
379385
except Exception:
380386
pass
381387

388+
path = change.path(force=FORCE_DEFAULT)
389+
new_path = change.path(use_t2=True, force=FORCE_DEFAULT)
382390
remap_dict = RemapDict({
383391
'old_type': old_type,
384-
'new_type': new_type
392+
'new_type': new_type,
385393
})
386-
self['type_changes'][change.path(
387-
force=FORCE_DEFAULT)] = remap_dict
394+
if path != new_path:
395+
remap_dict['new_path'] = new_path
396+
self['type_changes'][path] = remap_dict
388397
if include_values or self.always_include_values:
389398
remap_dict.update(old_value=change.t1, new_value=change.t2)
390399

391400
def _from_tree_value_changed(self, tree):
392401
if 'values_changed' in tree:
393402
for change in tree['values_changed']:
403+
path = change.path(force=FORCE_DEFAULT)
404+
new_path = change.path(use_t2=True, force=FORCE_DEFAULT)
394405
the_changed = {'new_value': change.t2, 'old_value': change.t1}
395-
self['values_changed'][change.path(
396-
force=FORCE_DEFAULT)] = the_changed
406+
if path != new_path:
407+
the_changed['new_path'] = new_path
408+
self['values_changed'][path] = the_changed
397409
# If we ever want to store the difflib results instead of the new_value
398410
# these lines need to be uncommented and the Delta object needs to be able
399411
# to use them.

tests/test_delta.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -911,8 +911,9 @@ def test_delta_cases(self, test_name, t1, t2, deepdiff_kwargs, to_delta_kwargs,
911911
'expected_delta_dict': {
912912
'values_changed': {
913913
'root[6]': {
914-
'new_value': 5
915-
}
914+
'new_value': 5,
915+
'new_path': 'root[3]',
916+
},
916917
},
917918
'iterable_items_removed_at_indexes': {
918919
'root': {
@@ -935,8 +936,9 @@ def test_delta_cases(self, test_name, t1, t2, deepdiff_kwargs, to_delta_kwargs,
935936
'expected_delta_dict': {
936937
'values_changed': {
937938
'root[3]': {
938-
'new_value': 4
939-
}
939+
'new_value': 4,
940+
'new_path': 'root[6]',
941+
},
940942
},
941943
'iterable_items_added_at_indexes': {
942944
'root': {
@@ -959,10 +961,12 @@ def test_delta_cases(self, test_name, t1, t2, deepdiff_kwargs, to_delta_kwargs,
959961
'expected_delta_dict': {
960962
'values_changed': {
961963
'root[4]': {
962-
'new_value': 7
964+
'new_value': 7,
965+
'new_path': 'root[0]'
963966
},
964967
'root[0]': {
965-
'new_value': 8
968+
'new_value': 8,
969+
'new_path': 'root[4]'
966970
}
967971
}
968972
},
@@ -979,10 +983,12 @@ def test_delta_cases(self, test_name, t1, t2, deepdiff_kwargs, to_delta_kwargs,
979983
'expected_delta_dict': {
980984
'values_changed': {
981985
'root[6]': {
982-
'new_value': 7
986+
'new_value': 7,
987+
'new_path': 'root[0]'
983988
},
984989
'root[0]': {
985-
'new_value': 8
990+
'new_value': 8,
991+
'new_path': 'root[6]'
986992
}
987993
},
988994
'iterable_items_added_at_indexes': {
@@ -2472,7 +2478,6 @@ def test_flat_dict_and_deeply_nested_dict(self):
24722478
pprint(delta._get_reverse_diff())
24732479
print("\nreverse_delta.diff")
24742480
pprint(reverse_delta.diff)
2475-
# import pytest; pytest.set_trace()
24762481
beforeImageAgain = allAfterImage - delta
24772482
diff3 = DeepDiff(beforeImage, beforeImageAgain, ignore_order=True)
24782483
assert not diff3
@@ -2488,6 +2493,8 @@ def test_flat_dict_and_deeply_nested_dict(self):
24882493
raise_errors=False,
24892494
force=True,
24902495
)
2491-
2496+
print("\ndelta from flat dicts")
2497+
pprint(delta2.diff)
2498+
import pytest; pytest.set_trace()
24922499
assert allAfterImage == beforeImage + delta2
24932500
assert beforeImage == allAfterImage - delta2

0 commit comments

Comments
 (0)