By default, objects of the same type are stored in a dictionary, meaning the processing order during diff or sync operations is not guaranteed. To enforce a specific order (e.g., for top-level objects or children of a specific object), you must implement ordering methods within a subclass of Diff.
Ordering Logic
When the core engine iterates over a list of objects, it looks for specific class methods to determine order:
- Type-specific ordering: It looks for a method named
order_children_<type>, where <type> is the name of the object type (e.g., order_children_device for device objects). - Fallback ordering: If no type-specific method is found, it calls
order_children_default.
Requirements:
- Both
order_children_default and any type-specific methods you implement must be @classmethod. - These methods must accept
children (a dictionary of names to DiffElement objects) and must yield an Iterator of DiffElement objects.
from collections import defaultdict
from diff import Diff
class MixedOrderingDiff(Diff):
"""Alternate diff class to list children in alphabetical order,
except devices to be ordered by CRUD action."""
@classmethod
def order_children_default(cls, children):
"""Simple diff to return all children in alphabetical order."""
for child_name, child in sorted(children.items()):
yield children[child_name]
@classmethod
def order_children_device(cls, children):
"""Return a list of device sorted by CRUD action and alphabetically."""
children_by_type = defaultdict(list)
# Organize the children's name by action create, update or delete
for child_name, child in children.items():
action = child.action or "skip"
children_by_type[action].append(child_name)
# Create a global list, organized per action
sorted_children = sorted(children_by_type["create"])
sorted_children += sorted(children_by_type["update"])
sorted_children += sorted(children_by_type["delete"])
sorted_children += sorted(children_by_type["skip"])
for name in sorted_children:
yield children[name]