Skip to content

Commit f3e5af9

Browse files
author
Leo Kirchner
committed
fixes natural deletion order flag
Prior to this change, if natural deletion order was set on a parent model and that model had no changes, children would not be recursed through.
1 parent 94b5500 commit f3e5af9

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

diffsync/helpers.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,13 @@ def sync_diff_element(self, element: DiffElement, parent_model: Optional["DiffSy
369369
natural_deletion_order = bool(dst_model.model_flags & DiffSyncModelFlags.NATURAL_DELETION_ORDER)
370370
skip_children = bool(dst_model.model_flags & DiffSyncModelFlags.SKIP_CHILDREN_ON_DELETE)
371371

372+
# Recurse through children to delete if we are supposed to delete the current diff element
372373
changed = False
373374
if natural_deletion_order and self.action == DiffSyncActions.DELETE and not skip_children:
374375
for child in element.get_children():
375376
changed |= self.sync_diff_element(child, parent_model=dst_model)
376377

378+
# Sync the current model - this will delete the current model if self.action is DELETE
377379
changed, modified_model = self.sync_model(src_model=src_model, dst_model=dst_model, ids=ids, attrs=attrs)
378380
dst_model = modified_model or dst_model
379381

@@ -396,7 +398,7 @@ def sync_diff_element(self, element: DiffElement, parent_model: Optional["DiffSy
396398

397399
self.incr_elements_processed()
398400

399-
if not natural_deletion_order:
401+
if not natural_deletion_order or self.action is None:
400402
for child in element.get_children():
401403
changed |= self.sync_diff_element(child, parent_model=dst_model)
402404

tests/unit/test_diffsync_model_flags.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,64 @@ def load(self):
162162
source.remove(source.get("parent", {"name": "Test-Parent"}), remove_children=True)
163163
source.sync_to(destination)
164164
assert call_order == ["Test-Child", "Test-Parent"]
165+
166+
167+
def test_natural_deletion_order_with_noop_parent():
168+
"""Test whether children are recursed through when natural deletion order is set and the parent has no changes."""
169+
call_order = []
170+
171+
class ChildModel(DiffSyncModel):
172+
"""Test child model that reports when its update method is called."""
173+
_modelname = "child"
174+
_identifiers = ("name",)
175+
_attributes = ("attribute",)
176+
177+
name: str
178+
attribute: str
179+
180+
def update(self, attrs):
181+
call_order.append("Update on child")
182+
return super().update(attrs)
183+
184+
class ParentModel(DiffSyncModel):
185+
"""Test parent model."""
186+
_modelname = "parent"
187+
_identifiers = ("name",)
188+
_attributes = ("attribute",)
189+
_children = {"child": "children"}
190+
191+
name: str
192+
attribute: str
193+
children: List[ChildModel] = []
194+
195+
class Adapter(DiffSync):
196+
"""Test adapter."""
197+
top_level = ["parent"]
198+
199+
parent = ParentModel
200+
child = ChildModel
201+
202+
def load(self, is_source=False) -> None:
203+
"""Test load method. Generate a difference with the is_source parameter."""
204+
parent = self.parent(name="Test Parent", attribute="This doesn't change")
205+
parent.model_flags |= DiffSyncModelFlags.NATURAL_DELETION_ORDER
206+
self.add(parent)
207+
if is_source:
208+
child = self.child(name="Test Child", attribute="Attribute from source")
209+
child.model_flags |= DiffSyncModelFlags.NATURAL_DELETION_ORDER
210+
parent.add_child(child)
211+
self.add(child)
212+
else:
213+
child = self.child(name="Test Child", attribute="Attribute from destination")
214+
child.model_flags |= DiffSyncModelFlags.NATURAL_DELETION_ORDER
215+
parent.add_child(child)
216+
self.add(child)
217+
218+
source_adapter = Adapter()
219+
source_adapter.load(is_source=True)
220+
destination_adapter = Adapter()
221+
destination_adapter.load()
222+
223+
source_adapter.sync_to(destination_adapter)
224+
225+
assert "Update on child" in call_order

0 commit comments

Comments
 (0)