2222from .diff import Diff , DiffElement
2323from .enum import DiffSyncModelFlags , DiffSyncFlags , DiffSyncStatus
2424from .exceptions import ObjectNotFound , ObjectNotCreated , ObjectNotUpdated , ObjectNotDeleted , ObjectCrudException
25- from .utils import intersection
25+ from .utils import intersection , symmetric_difference
2626
2727if TYPE_CHECKING : # pragma: no cover
2828 # For type annotation purposes, we have a circular import loop between __init__.py and this file.
@@ -41,7 +41,7 @@ def __init__( # pylint: disable=too-many-arguments
4141 dst_diffsync : "DiffSync" ,
4242 flags : DiffSyncFlags ,
4343 diff_class : Type [Diff ] = Diff ,
44- callback : Optional [Callable [[int , int ], None ]] = None ,
44+ callback : Optional [Callable [[str , int , int ], None ]] = None ,
4545 ):
4646 """Create a DiffSyncDiffer for calculating diffs between the provided DiffSync instances."""
4747 self .src_diffsync = src_diffsync
@@ -62,7 +62,7 @@ def incr_models_processed(self, delta: int = 1):
6262 if delta :
6363 self .models_processed += delta
6464 if self .callback :
65- self .callback (self .models_processed , self .total_models )
65+ self .callback ("diff" , self .models_processed , self .total_models )
6666
6767 def calculate_diffs (self ) -> Diff :
6868 """Calculate diffs between the src and dst DiffSync objects and return the resulting Diff."""
@@ -73,6 +73,16 @@ def calculate_diffs(self) -> Diff:
7373
7474 self .logger .info ("Beginning diff calculation" )
7575 self .diff = self .diff_class ()
76+
77+ skipped_types = symmetric_difference (self .dst_diffsync .top_level , self .src_diffsync .top_level )
78+ # This won't count everything, since these top-level types may have child types which are
79+ # implicitly also skipped as well, but we don't want to waste too much time on this calculation.
80+ for skipped_type in skipped_types :
81+ if skipped_type in self .dst_diffsync .top_level :
82+ self .incr_models_processed (len (self .dst_diffsync .get_all (skipped_type )))
83+ elif skipped_type in self .src_diffsync .top_level :
84+ self .incr_models_processed (len (self .src_diffsync .get_all (skipped_type )))
85+
7686 for obj_type in intersection (self .dst_diffsync .top_level , self .src_diffsync .top_level ):
7787 diff_elements = self .diff_object_list (
7888 src = self .src_diffsync .get_all (obj_type ), dst = self .dst_diffsync .get_all (obj_type ),
@@ -170,15 +180,19 @@ def diff_object_pair(
170180 log = self .logger .bind (model = model , unique_id = unique_id )
171181 if self .flags & DiffSyncFlags .SKIP_UNMATCHED_SRC and not dst_obj :
172182 log .debug ("Skipping unmatched source object" )
183+ self .incr_models_processed ()
173184 return None
174185 if self .flags & DiffSyncFlags .SKIP_UNMATCHED_DST and not src_obj :
175186 log .debug ("Skipping unmatched dest object" )
187+ self .incr_models_processed ()
176188 return None
177189 if src_obj and src_obj .model_flags & DiffSyncModelFlags .IGNORE :
178190 log .debug ("Skipping due to IGNORE flag on source object" )
191+ self .incr_models_processed ()
179192 return None
180193 if dst_obj and dst_obj .model_flags & DiffSyncModelFlags .IGNORE :
181194 log .debug ("Skipping due to IGNORE flag on dest object" )
195+ self .incr_models_processed ()
182196 return None
183197
184198 diff_element = DiffElement (
@@ -224,6 +238,11 @@ def diff_child_objects(
224238 for child_type , child_fieldname in src_mapping .items ():
225239 if child_type in dst_mapping :
226240 children_mapping [child_type ] = child_fieldname
241+ else :
242+ self .incr_models_processed (len (getattr (src_obj , child_fieldname )))
243+ for child_type , child_fieldname in dst_mapping .items ():
244+ if child_type not in src_mapping :
245+ self .incr_models_processed (len (getattr (dst_obj , child_fieldname )))
227246 elif src_obj :
228247 children_mapping = src_obj .get_children_mapping ()
229248 elif dst_obj :
@@ -257,7 +276,7 @@ def __init__( # pylint: disable=too-many-arguments
257276 src_diffsync : "DiffSync" ,
258277 dst_diffsync : "DiffSync" ,
259278 flags : DiffSyncFlags ,
260- callback : Optional [Callable [[int , int ], None ]] = None ,
279+ callback : Optional [Callable [[str , int , int ], None ]] = None ,
261280 ):
262281 """Create a DiffSyncSyncer instance, ready to call `perform_sync()` against."""
263282 self .diff = diff
@@ -280,7 +299,7 @@ def incr_elements_processed(self, delta: int = 1):
280299 if delta :
281300 self .elements_processed += delta
282301 if self .callback :
283- self .callback (self .elements_processed , self .total_elements )
302+ self .callback ("sync" , self .elements_processed , self .total_elements )
284303
285304 def perform_sync (self ) -> bool :
286305 """Perform data synchronization based on the provided diff.
0 commit comments