Skip to content

Commit 8f4a8c2

Browse files
authored
Merge pull request #74 from MJedr/authors
dict merger: dedupe only remove patches
2 parents ad20fcf + e38bc05 commit 8f4a8c2

File tree

5 files changed

+21
-57
lines changed

5 files changed

+21
-57
lines changed

json_merger/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
>>> m = Merger(root, head, update, DictMergerOps.FALLBACK_KEEP_HEAD,
120120
... UnifierOps.KEEP_ONLY_HEAD_ENTITIES)
121121
>>> m.merge() # No conflict here
122-
>>> m.merged_root['badges'] == ['cool', 'nice']
122+
>>> m.merged_root['badges'] == ['cool', 'nice', 'random']
123123
True
124124
>>> m = Merger(root, head, update, DictMergerOps.FALLBACK_KEEP_HEAD,
125125
... UnifierOps.KEEP_ONLY_UPDATE_ENTITIES)
@@ -135,12 +135,12 @@
135135
>>> m = Merger(root, head, update, DictMergerOps.FALLBACK_KEEP_HEAD,
136136
... UnifierOps.KEEP_UPDATE_AND_HEAD_ENTITIES_HEAD_FIRST)
137137
>>> m.merge() # No conflict here
138-
>>> m.merged_root['badges'] == ['cool', 'fun', 'nice', 'healthy']
138+
>>> m.merged_root['badges'] == ['cool', 'fun', 'nice', 'random', 'healthy']
139139
True
140140
>>> m = Merger(root, head, update, DictMergerOps.FALLBACK_KEEP_HEAD,
141141
... UnifierOps.KEEP_UPDATE_AND_HEAD_ENTITIES_UPDATE_FIRST)
142142
>>> m.merge()
143-
>>> m.merged_root['badges'] == ['fun', 'cool', 'nice', 'healthy']
143+
>>> m.merged_root['badges'] == ['fun', 'cool', 'nice', 'healthy', 'random']
144144
True
145145
146146
These options keep the order relations between the entities. For example,

json_merger/dict_merger.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,14 @@ def conflicts(self):
139139
def _merge_base_values(self):
140140
if self.head == self.update:
141141
self.merged_root = self.head
142-
elif self.head == self.root:
143-
self.merged_root = self.update
144-
elif self.update == self.root:
145-
self.merged_root = self.head
146142
elif self.head == NOTHING:
147143
self.merged_root = self.update
148144
elif self.update == NOTHING:
149145
self.merged_root = self.head
146+
elif self.head == self.root:
147+
self.merged_root = self.update
148+
elif self.update == self.root:
149+
self.merged_root = self.head
150150
else:
151151
strategy = self._get_rule_for_field(self.key_path)
152152
self.merged_root, conflict = {
@@ -171,10 +171,19 @@ def _merge_dicts(self):
171171
self._solve_dict_conflicts(non_list_merger, e.content)
172172

173173
self._restore_lists()
174+
remove_patches = []
175+
other_patches = []
176+
for patch_ in non_list_merger.unified_patches:
177+
if patch_[0] == 'remove':
178+
remove_patches.append(patch_)
179+
else:
180+
other_patches.append(patch_)
181+
remove_patches_deduped = dedupe_list(remove_patches)
182+
unified_patches = remove_patches_deduped + other_patches
174183
self.merged_root = patch(
175-
dedupe_list(non_list_merger.unified_patches),
176-
self.root
177-
)
184+
unified_patches,
185+
self.root
186+
)
178187

179188
def _solve_dict_conflicts(self, non_list_merger, conflicts):
180189
strategies = [self._get_custom_strategy(conflict)

json_merger/merger.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
from .dict_merger import SkipListsMerger
3434
from .errors import MergeError
3535
from .list_unify import ListUnifier
36-
from .nothing import NOTHING
3736
from .utils import (
3837
get_conf_set_for_key_path, get_dotted_key_path, get_obj_at_key_path,
3938
set_obj_at_key_path
@@ -262,8 +261,7 @@ def _recursive_merge(self, root, head, update, key_path=()):
262261
)
263262
new_obj = self._recursive_merge(root_obj, head_obj, update_obj,
264263
absolute_key_path + (idx, ))
265-
if new_obj != NOTHING:
266-
new_list.append(new_obj)
264+
new_list.append(new_obj)
267265

268266
root = set_obj_at_key_path(root, list_field, new_list)
269267
self._build_aligned_lists_and_stats(unifier, absolute_key_path)

tests/unit/test_dict_merger.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,18 +87,6 @@ def test_merge_with_nothing():
8787
m.merge()
8888
assert m.merged_root == {'some': 'other object'}
8989

90-
m = SkipListsMerger({'some': 'other object'},
91-
NOTHING, {'some': 'other object'},
92-
DictMergerOps.FALLBACK_KEEP_HEAD)
93-
m.merge()
94-
assert m.merged_root == NOTHING
95-
96-
m = SkipListsMerger({'some': 'other object'},
97-
{'some': 'other object'}, NOTHING,
98-
DictMergerOps.FALLBACK_KEEP_HEAD)
99-
m.merge()
100-
assert m.merged_root == NOTHING
101-
10290

10391
def test_simple_conflicts_keep_head():
10492
r = {}

tests/unit/test_merger.py

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -218,38 +218,7 @@ def test_keep_head_conflict_on_new_update():
218218
with pytest.raises(MergeError):
219219
m.merge()
220220

221-
expected_merge = [2]
221+
expected_merge = [1, 2]
222222
expected_conflict = [('INSERT', (0,), 3)]
223223
assert m.merged_root == expected_merge
224224
assert m.conflicts == expected_conflict
225-
226-
227-
def test_merger_doesnt_add_elements_removed_in_head_when_root_matches_update():
228-
update = {
229-
'ids': [
230-
{'schema': 'INSPIRE ID', 'value': 'INSPIRE-00231894'},
231-
{'schema': 'ORCID', 'value': '0000-0002-0165-6297'}
232-
]
233-
}
234-
head = {
235-
'ids': [
236-
{'value': 'INSPIRE-00231894', 'schema': 'INSPIRE ID'},
237-
{'value': 'V.Nikolaenko.1', 'schema': 'INSPIRE BAI'}
238-
]
239-
}
240-
root = {
241-
'ids': [
242-
{'schema': 'INSPIRE ID', 'value': 'INSPIRE-00231894'},
243-
{'schema': 'ORCID', 'value': '0000-0002-0165-6297'}
244-
]
245-
}
246-
247-
m = Merger(root, head, update,
248-
DictMergerOps.FALLBACK_KEEP_HEAD,
249-
UnifierOps.KEEP_UPDATE_AND_HEAD_ENTITIES_UPDATE_FIRST)
250-
251-
m.merge()
252-
assert m.merged_root['ids'] == [
253-
{'value': 'INSPIRE-00231894', 'schema': 'INSPIRE ID'},
254-
{'value': 'V.Nikolaenko.1', 'schema': 'INSPIRE BAI'}
255-
]

0 commit comments

Comments
 (0)