django-bulk-hooks 0.2.71__py3-none-any.whl → 0.2.72__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of django-bulk-hooks might be problematic. Click here for more details.
- django_bulk_hooks/dispatcher.py +12 -0
- django_bulk_hooks/operations/coordinator.py +9 -1
- django_bulk_hooks/operations/mti_handler.py +3 -0
- {django_bulk_hooks-0.2.71.dist-info → django_bulk_hooks-0.2.72.dist-info}/METADATA +1 -1
- {django_bulk_hooks-0.2.71.dist-info → django_bulk_hooks-0.2.72.dist-info}/RECORD +7 -7
- {django_bulk_hooks-0.2.71.dist-info → django_bulk_hooks-0.2.72.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.2.71.dist-info → django_bulk_hooks-0.2.72.dist-info}/WHEEL +0 -0
django_bulk_hooks/dispatcher.py
CHANGED
|
@@ -103,6 +103,9 @@ class HookDispatcher:
|
|
|
103
103
|
# Get hooks sorted by priority (deterministic order)
|
|
104
104
|
hooks = self.registry.get_hooks(changeset.model_cls, event)
|
|
105
105
|
|
|
106
|
+
logger.debug(f"🧵 DISPATCH: changeset.model_cls={changeset.model_cls.__name__}, event={event}")
|
|
107
|
+
logger.debug(f"🎣 HOOKS_FOUND: {len(hooks)} hooks for {changeset.model_cls.__name__}.{event}: {[f'{h[0].__name__}.{h[1]}' for h in hooks]}")
|
|
108
|
+
|
|
106
109
|
if not hooks:
|
|
107
110
|
return
|
|
108
111
|
|
|
@@ -148,12 +151,21 @@ class HookDispatcher:
|
|
|
148
151
|
|
|
149
152
|
# Filter out hooks that have already been executed for this operation
|
|
150
153
|
unique_hooks = []
|
|
154
|
+
skipped_hooks = []
|
|
151
155
|
for handler_cls, method_name, condition, priority in hooks:
|
|
152
156
|
hook_key = (handler_cls, method_name, operation_key)
|
|
153
157
|
if hook_key not in self._executed_hooks:
|
|
154
158
|
unique_hooks.append((handler_cls, method_name, condition, priority))
|
|
155
159
|
self._executed_hooks.add(hook_key)
|
|
160
|
+
else:
|
|
161
|
+
skipped_hooks.append((handler_cls.__name__, method_name))
|
|
162
|
+
|
|
163
|
+
# Debug logging for hook deduplication
|
|
164
|
+
if skipped_hooks:
|
|
165
|
+
logger.debug(f"⏭️ SKIPPED_DUPS: {len(skipped_hooks)} duplicate hooks: {[f'{cls}.{method}' for cls, method in skipped_hooks]}")
|
|
156
166
|
|
|
167
|
+
if unique_hooks:
|
|
168
|
+
logger.debug(f"✅ EXECUTING_UNIQUE: {len(unique_hooks)} unique hooks: {[f'{h[0].__name__}.{h[1]}' for h in unique_hooks]}")
|
|
157
169
|
|
|
158
170
|
if not unique_hooks:
|
|
159
171
|
return
|
|
@@ -142,8 +142,11 @@ class BulkOperationCoordinator:
|
|
|
142
142
|
event_suffix: Event name suffix (e.g., 'before_create', 'validate_update')
|
|
143
143
|
bypass_hooks: Whether to skip hook execution
|
|
144
144
|
"""
|
|
145
|
-
for
|
|
145
|
+
logger.debug(f"🔄 DISPATCH_MODELS: Iterating through {len(models_in_chain)} models for {event_suffix}: {[m.__name__ for m in models_in_chain]}")
|
|
146
|
+
for i, model_cls in enumerate(models_in_chain):
|
|
147
|
+
logger.debug(f"🔄 DISPATCH_ITERATION: {i+1}/{len(models_in_chain)} - Dispatching to {model_cls.__name__} for {event_suffix}")
|
|
146
148
|
model_changeset = self._build_changeset_for_model(changeset, model_cls)
|
|
149
|
+
logger.debug(f"🔄 CHANGESET_MODEL: Created changeset with model_cls={model_changeset.model_cls.__name__}")
|
|
147
150
|
self.dispatcher.dispatch(model_changeset, event_suffix, bypass_hooks=bypass_hooks)
|
|
148
151
|
|
|
149
152
|
# ==================== PUBLIC API ====================
|
|
@@ -702,9 +705,11 @@ class BulkOperationCoordinator:
|
|
|
702
705
|
|
|
703
706
|
# Reset hook execution tracking for this new operation
|
|
704
707
|
self.dispatcher._reset_executed_hooks()
|
|
708
|
+
logger.debug(f"🚀 MTI_OPERATION_START: {event_prefix} operation for {changeset.model_cls.__name__}")
|
|
705
709
|
|
|
706
710
|
# Get all models in inheritance chain
|
|
707
711
|
models_in_chain = self._get_models_in_chain(changeset.model_cls)
|
|
712
|
+
logger.debug(f"🔗 MTI_CHAIN_START: {len(models_in_chain)} models in chain for {changeset.model_cls.__name__}")
|
|
708
713
|
|
|
709
714
|
# VALIDATE phase - for all models in chain
|
|
710
715
|
if not bypass_validation:
|
|
@@ -799,6 +804,7 @@ class BulkOperationCoordinator:
|
|
|
799
804
|
result_objects: List of objects returned from the operation
|
|
800
805
|
models_in_chain: List of model classes in the MTI inheritance chain
|
|
801
806
|
"""
|
|
807
|
+
logger.debug(f"🔀 UPSERT_AFTER_START: Processing {len(result_objects)} result objects with {len(models_in_chain)} models in chain")
|
|
802
808
|
# Split objects based on metadata set by the executor
|
|
803
809
|
created_objects = []
|
|
804
810
|
updated_objects = []
|
|
@@ -868,6 +874,7 @@ class BulkOperationCoordinator:
|
|
|
868
874
|
|
|
869
875
|
# Dispatch after_create hooks for created objects
|
|
870
876
|
if created_objects:
|
|
877
|
+
logger.debug(f"🔀 UPSERT_DISPATCH_CREATE: Dispatching after_create for {len(created_objects)} created objects")
|
|
871
878
|
from django_bulk_hooks.helpers import build_changeset_for_create
|
|
872
879
|
|
|
873
880
|
create_changeset = build_changeset_for_create(self.model_cls, created_objects)
|
|
@@ -876,6 +883,7 @@ class BulkOperationCoordinator:
|
|
|
876
883
|
|
|
877
884
|
# Dispatch after_update hooks for updated objects
|
|
878
885
|
if updated_objects:
|
|
886
|
+
logger.debug(f"🔀 UPSERT_DISPATCH_UPDATE: Dispatching after_update for {len(updated_objects)} updated objects")
|
|
879
887
|
# Fetch old records for proper change detection
|
|
880
888
|
old_records_map = self.analyzer.fetch_old_records_map(updated_objects)
|
|
881
889
|
|
|
@@ -78,14 +78,17 @@ class MTIHandler:
|
|
|
78
78
|
while current_model:
|
|
79
79
|
if not current_model._meta.proxy and not current_model._meta.abstract:
|
|
80
80
|
chain.append(current_model)
|
|
81
|
+
logger.debug(f"🔗 MTI_CHAIN_ADD: Added {current_model.__name__} (abstract: {current_model._meta.abstract}, proxy: {current_model._meta.proxy})")
|
|
81
82
|
|
|
82
83
|
# Get concrete parent models (not abstract, not proxy)
|
|
83
84
|
parents = [parent for parent in current_model._meta.parents.keys() if not parent._meta.proxy and not parent._meta.abstract]
|
|
85
|
+
logger.debug(f"🔗 MTI_PARENTS: {current_model.__name__} has concrete parents: {[p.__name__ for p in parents]}")
|
|
84
86
|
|
|
85
87
|
current_model = parents[0] if parents else None
|
|
86
88
|
|
|
87
89
|
# Reverse to get root-to-child order
|
|
88
90
|
chain.reverse()
|
|
91
|
+
logger.debug(f"🔗 MTI_CHAIN_FINAL: {[m.__name__ for m in chain]} (length: {len(chain)})")
|
|
89
92
|
return chain
|
|
90
93
|
|
|
91
94
|
def get_parent_models(self):
|
|
@@ -4,7 +4,7 @@ django_bulk_hooks/conditions.py,sha256=ar4pGjtxLKmgSIlO4S6aZFKmaBNchLtxMmWpkn4g9
|
|
|
4
4
|
django_bulk_hooks/constants.py,sha256=PxpEETaO6gdENcTPoXS586lerGKVP3nmjpDvOkmhYxI,509
|
|
5
5
|
django_bulk_hooks/context.py,sha256=mqaC5-yESDTA5ruI7fuXlt8qSgKuOFp0mjq7h1-4HdQ,1926
|
|
6
6
|
django_bulk_hooks/decorators.py,sha256=TdkO4FJyFrVU2zqK6Y_6JjEJ4v3nbKkk7aa22jN10sk,11994
|
|
7
|
-
django_bulk_hooks/dispatcher.py,sha256=
|
|
7
|
+
django_bulk_hooks/dispatcher.py,sha256=AJJFpP5zvstF1VfKyduetDlor9Dskk-7VbwHkGHRMYM,22352
|
|
8
8
|
django_bulk_hooks/enums.py,sha256=Zo8_tJzuzZ2IKfVc7gZ-0tWPT8q1QhqZbAyoh9ZVJbs,381
|
|
9
9
|
django_bulk_hooks/factory.py,sha256=ezrVM5U023KZqOBbJXb6lYUP-pE7WJmi8Olh2Ew-7RA,18085
|
|
10
10
|
django_bulk_hooks/handler.py,sha256=SRCrMzgolrruTkvMnYBFmXLR-ABiw0JiH3605PEdCZM,4207
|
|
@@ -14,14 +14,14 @@ django_bulk_hooks/models.py,sha256=TWN_F-SsLGPx9jrkNT9pmJFR5VsZ0Z_QaVOZOmt7bpw,2
|
|
|
14
14
|
django_bulk_hooks/operations/__init__.py,sha256=BtJYjmRhe_sScivLsniDaZmBkm0ZLvcmzXFKL7QY2Xg,550
|
|
15
15
|
django_bulk_hooks/operations/analyzer.py,sha256=Pz8mc-EL8KDOfLQFYiRuN-r0OmINW3nIBhRJJCma-yo,10360
|
|
16
16
|
django_bulk_hooks/operations/bulk_executor.py,sha256=po8V_2H3ULiE0RYJ-wbaRIz52SKhss81UHwuQjlz3H8,26214
|
|
17
|
-
django_bulk_hooks/operations/coordinator.py,sha256=
|
|
17
|
+
django_bulk_hooks/operations/coordinator.py,sha256=Gq2vqjlIyyfV8OSoipoED2hC2kb2czaHuy2Cs3gtmGI,39751
|
|
18
18
|
django_bulk_hooks/operations/field_utils.py,sha256=cQ9w4xdk-z3PrMLFvRzVV07Wc0D2qbpSepwoupqwQH8,7888
|
|
19
|
-
django_bulk_hooks/operations/mti_handler.py,sha256=
|
|
19
|
+
django_bulk_hooks/operations/mti_handler.py,sha256=x1uNvP8MkidifPp_AMp4nffsdW3dz3izV6SeaLJ0DaA,26247
|
|
20
20
|
django_bulk_hooks/operations/mti_plans.py,sha256=HIRJgogHPpm6MV7nZZ-sZhMLUnozpZPV2SzwQHLRzYc,3667
|
|
21
21
|
django_bulk_hooks/operations/record_classifier.py,sha256=It85hJC2K-UsEOLbTR-QBdY5UPV-acQIJ91TSGa7pYo,7053
|
|
22
22
|
django_bulk_hooks/queryset.py,sha256=tHt1U2O9Hvozg9sdn5MjzAk_I6wDU-LupuKFTfv1SiQ,7449
|
|
23
23
|
django_bulk_hooks/registry.py,sha256=4HxP1mVK2z4VzvlohbEw2359wM21UJZJYagJJ1komM0,7947
|
|
24
|
-
django_bulk_hooks-0.2.
|
|
25
|
-
django_bulk_hooks-0.2.
|
|
26
|
-
django_bulk_hooks-0.2.
|
|
27
|
-
django_bulk_hooks-0.2.
|
|
24
|
+
django_bulk_hooks-0.2.72.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
25
|
+
django_bulk_hooks-0.2.72.dist-info/METADATA,sha256=QkD3zT88vaJBu79C5vYBSORg0LBh4nCzVpwObeLwpko,10555
|
|
26
|
+
django_bulk_hooks-0.2.72.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
27
|
+
django_bulk_hooks-0.2.72.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|