django-bulk-hooks 0.2.61__py3-none-any.whl → 0.2.62__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.

@@ -47,8 +47,9 @@ class BulkExecutor:
47
47
  self.record_classifier = record_classifier
48
48
  self.model_cls = queryset.model
49
49
 
50
- def _handle_upsert_metadata_tagging(self, result_objects, objs, update_conflicts, unique_fields, existing_record_ids=None, existing_pks_map=None):
51
-
50
+ def _handle_upsert_metadata_tagging(
51
+ self, result_objects, objs, update_conflicts, unique_fields, existing_record_ids=None, existing_pks_map=None
52
+ ):
52
53
  """
53
54
 
54
55
  Handle classification and metadata tagging for upsert operations.
@@ -82,19 +83,13 @@ class BulkExecutor:
82
83
  """
83
84
 
84
85
  if not (update_conflicts and unique_fields):
85
-
86
86
  return
87
87
 
88
-
89
-
90
88
  # Classify records if not already done
91
89
 
92
90
  if existing_record_ids is None or existing_pks_map is None:
93
-
94
91
  existing_record_ids, existing_pks_map = self.record_classifier.classify_for_upsert(objs, unique_fields)
95
92
 
96
-
97
-
98
93
  # Tag the metadata
99
94
  tag_upsert_metadata(result_objects, existing_record_ids, existing_pks_map)
100
95
 
@@ -142,11 +137,13 @@ class BulkExecutor:
142
137
  # This handles the schema migration case where parent exists but child doesn't
143
138
  query_model = self.mti_handler.find_model_with_unique_fields(unique_fields)
144
139
  logger.info(f"MTI upsert: querying {query_model.__name__} for unique fields {unique_fields}")
145
-
140
+
146
141
  existing_record_ids, existing_pks_map = self.record_classifier.classify_for_upsert(
147
142
  objs, unique_fields, query_model=query_model
148
143
  )
149
- logger.info(f"MTI Upsert classification: {len(existing_record_ids)} existing, {len(objs) - len(existing_record_ids)} new")
144
+ logger.info(
145
+ f"MTI Upsert classification: {len(existing_record_ids)} existing, {len(objs) - len(existing_record_ids)} new"
146
+ )
150
147
  logger.info(f"existing_record_ids: {existing_record_ids}")
151
148
  logger.info(f"existing_pks_map: {existing_pks_map}")
152
149
 
@@ -176,10 +173,7 @@ class BulkExecutor:
176
173
  )
177
174
 
178
175
  # Unified upsert metadata handling for both paths
179
- self._handle_upsert_metadata_tagging(
180
- result, objs, update_conflicts, unique_fields,
181
- existing_record_ids, existing_pks_map
182
- )
176
+ self._handle_upsert_metadata_tagging(result, objs, update_conflicts, unique_fields, existing_record_ids, existing_pks_map)
183
177
 
184
178
  return result
185
179
 
@@ -243,9 +237,8 @@ class BulkExecutor:
243
237
 
244
238
  # Use unified auto-now field handling
245
239
  from django_bulk_hooks.operations.field_utils import handle_auto_now_fields_for_inheritance_chain
246
- auto_now_fields = handle_auto_now_fields_for_inheritance_chain(
247
- models_to_check, objs, for_update=True
248
- )
240
+
241
+ auto_now_fields = handle_auto_now_fields_for_inheritance_chain(models_to_check, objs, for_update=True)
249
242
 
250
243
  # Add auto_now fields to the update list if not already present
251
244
  for auto_now_field in auto_now_fields:
@@ -287,7 +280,6 @@ class BulkExecutor:
287
280
  if not plan:
288
281
  return []
289
282
 
290
-
291
283
  with transaction.atomic(using=self.queryset.db, savepoint=False):
292
284
  # Step 1: Upsert all parent objects level by level using Django's native upsert
293
285
  parent_instances_map = {} # Maps original obj id() -> {model: parent_instance}
@@ -295,15 +287,15 @@ class BulkExecutor:
295
287
  for parent_level in plan.parent_levels:
296
288
  # Use base QuerySet to avoid recursion
297
289
  base_qs = BaseQuerySet(model=parent_level.model_class, using=self.queryset.db)
298
-
290
+
299
291
  # Build bulk_create kwargs
300
292
  bulk_kwargs = {"batch_size": len(parent_level.objects)}
301
-
293
+
302
294
  if parent_level.update_conflicts:
303
295
  # Let Django handle the upsert - it will INSERT or UPDATE as needed
304
296
  bulk_kwargs["update_conflicts"] = True
305
297
  bulk_kwargs["unique_fields"] = parent_level.unique_fields
306
-
298
+
307
299
  # Filter update fields to only those that exist in this parent model
308
300
  parent_model_fields = {field.name for field in parent_level.model_class._meta.local_fields}
309
301
  filtered_update_fields = [field for field in parent_level.update_fields if field in parent_model_fields]
@@ -368,9 +360,7 @@ class BulkExecutor:
368
360
 
369
361
  existing_child_pks = set()
370
362
  if parent_pks_to_check:
371
- existing_child_pks = set(
372
- base_qs.filter(pk__in=parent_pks_to_check).values_list('pk', flat=True)
373
- )
363
+ existing_child_pks = set(base_qs.filter(pk__in=parent_pks_to_check).values_list("pk", flat=True))
374
364
 
375
365
  # Split based on whether child record exists
376
366
  for child_obj in plan.child_objects:
@@ -430,15 +420,17 @@ class BulkExecutor:
430
420
 
431
421
  # Build kwargs for _batched_insert call
432
422
  kwargs = {
433
- 'batch_size': len(objs_without_pk),
423
+ "batch_size": len(objs_without_pk),
434
424
  }
435
425
  # Only pass conflict resolution parameters if we have unique fields for this table
436
426
  if batched_unique_fields:
437
- kwargs.update({
438
- 'on_conflict': on_conflict,
439
- 'update_fields': batched_update_fields,
440
- 'unique_fields': batched_unique_fields,
441
- })
427
+ kwargs.update(
428
+ {
429
+ "on_conflict": on_conflict,
430
+ "update_fields": batched_update_fields,
431
+ "unique_fields": batched_unique_fields,
432
+ }
433
+ )
442
434
 
443
435
  returned_columns = base_qs._batched_insert(
444
436
  objs_without_pk,
@@ -623,4 +615,3 @@ class BulkExecutor:
623
615
  from django.db.models import QuerySet
624
616
 
625
617
  return QuerySet.delete(self.queryset)
626
-
@@ -68,24 +68,28 @@ class BulkOperationCoordinator:
68
68
  def analyzer(self):
69
69
  """Get or create ModelAnalyzer"""
70
70
  from django_bulk_hooks.operations.analyzer import ModelAnalyzer
71
+
71
72
  return self._get_or_create_service("analyzer", ModelAnalyzer, self.model_cls)
72
73
 
73
74
  @property
74
75
  def mti_handler(self):
75
76
  """Get or create MTIHandler"""
76
77
  from django_bulk_hooks.operations.mti_handler import MTIHandler
78
+
77
79
  return self._get_or_create_service("mti_handler", MTIHandler, self.model_cls)
78
80
 
79
81
  @property
80
82
  def record_classifier(self):
81
83
  """Get or create RecordClassifier"""
82
84
  from django_bulk_hooks.operations.record_classifier import RecordClassifier
85
+
83
86
  return self._get_or_create_service("record_classifier", RecordClassifier, self.model_cls)
84
87
 
85
88
  @property
86
89
  def executor(self):
87
90
  """Get or create BulkExecutor"""
88
91
  from django_bulk_hooks.operations.bulk_executor import BulkExecutor
92
+
89
93
  return self._get_or_create_service(
90
94
  "executor",
91
95
  BulkExecutor,
@@ -99,6 +103,7 @@ class BulkOperationCoordinator:
99
103
  def dispatcher(self):
100
104
  """Get or create Dispatcher"""
101
105
  from django_bulk_hooks.dispatcher import get_dispatcher
106
+
102
107
  return self._get_or_create_service("dispatcher", get_dispatcher)
103
108
 
104
109
  @property
@@ -171,7 +176,7 @@ class BulkOperationCoordinator:
171
176
  Returns:
172
177
  List of created objects
173
178
  """
174
- empty_result = self._validate_objects_for_operation(objs, 'create')
179
+ empty_result = self._validate_objects_for_operation(objs, "create")
175
180
  if empty_result is not None:
176
181
  return empty_result
177
182
 
@@ -188,9 +193,7 @@ class BulkOperationCoordinator:
188
193
  query_model = self.mti_handler.find_model_with_unique_fields(unique_fields)
189
194
  logger.info(f"MTI model detected: querying {query_model.__name__} for unique fields {unique_fields}")
190
195
 
191
- existing_record_ids, existing_pks_map = self.record_classifier.classify_for_upsert(
192
- objs, unique_fields, query_model=query_model
193
- )
196
+ existing_record_ids, existing_pks_map = self.record_classifier.classify_for_upsert(objs, unique_fields, query_model=query_model)
194
197
  logger.info(f"Upsert operation: {len(existing_record_ids)} existing, {len(objs) - len(existing_record_ids)} new records")
195
198
  logger.debug(f"Existing record IDs: {existing_record_ids}")
196
199
  logger.debug(f"Existing PKs map: {existing_pks_map}")
@@ -249,7 +252,7 @@ class BulkOperationCoordinator:
249
252
  Returns:
250
253
  Number of objects updated
251
254
  """
252
- empty_result = self._validate_objects_for_operation(objs, 'update')
255
+ empty_result = self._validate_objects_for_operation(objs, "update")
253
256
  if empty_result is not None:
254
257
  return empty_result
255
258
 
@@ -544,7 +547,7 @@ class BulkOperationCoordinator:
544
547
  """
545
548
  # Get objects
546
549
  objs = list(self.queryset)
547
- empty_result = self._validate_objects_for_operation(objs, 'delete')
550
+ empty_result = self._validate_objects_for_operation(objs, "delete")
548
551
  if empty_result is not None:
549
552
  return empty_result
550
553
 
@@ -581,7 +584,7 @@ class BulkOperationCoordinator:
581
584
  Returns:
582
585
  None
583
586
  """
584
- empty_result = self._validate_objects_for_operation(objs, 'validate')
587
+ empty_result = self._validate_objects_for_operation(objs, "validate")
585
588
  if empty_result is not None:
586
589
  return
587
590
 
@@ -65,10 +65,7 @@ def get_field_values_for_db(obj, field_names, model_cls=None):
65
65
  if model_cls is None:
66
66
  model_cls = obj.__class__
67
67
 
68
- return {
69
- field_name: get_field_value_for_db(obj, field_name, model_cls)
70
- for field_name in field_names
71
- }
68
+ return {field_name: get_field_value_for_db(obj, field_name, model_cls) for field_name in field_names}
72
69
 
73
70
 
74
71
  def normalize_field_name_to_db(field_name, model_cls):
@@ -152,9 +149,7 @@ def get_auto_fields(model_cls, include_auto_now_add=True):
152
149
  """
153
150
  fields = []
154
151
  for field in model_cls._meta.fields:
155
- if getattr(field, "auto_now", False) or (
156
- include_auto_now_add and getattr(field, "auto_now_add", False)
157
- ):
152
+ if getattr(field, "auto_now", False) or (include_auto_now_add and getattr(field, "auto_now_add", False)):
158
153
  fields.append(field.name)
159
154
  return fields
160
155
 
@@ -166,8 +161,7 @@ def get_auto_now_only_fields(model_cls):
166
161
 
167
162
  def get_fk_fields(model_cls):
168
163
  """Get foreign key field names for a model."""
169
- return [field.name for field in model_cls._meta.concrete_fields
170
- if field.is_relation and not field.many_to_many]
164
+ return [field.name for field in model_cls._meta.concrete_fields if field.is_relation and not field.many_to_many]
171
165
 
172
166
 
173
167
  def collect_auto_now_fields_for_inheritance_chain(inheritance_chain):
@@ -199,9 +193,7 @@ def handle_auto_now_fields_for_inheritance_chain(models, instances, for_update=T
199
193
  for field in model_cls._meta.local_fields:
200
194
  # For updates, only include auto_now (not auto_now_add)
201
195
  # For creates, include both
202
- if getattr(field, "auto_now", False) or (
203
- not for_update and getattr(field, "auto_now_add", False)
204
- ):
196
+ if getattr(field, "auto_now", False) or (not for_update and getattr(field, "auto_now_add", False)):
205
197
  all_auto_now_fields.add(field.name)
206
198
 
207
199
  # Pre-save the field on instances
@@ -231,4 +223,4 @@ def pre_save_auto_now_fields(objects, inheritance_chain):
231
223
  field.pre_save(obj, add=False)
232
224
  break
233
225
  except Exception:
234
- continue
226
+ continue
@@ -219,6 +219,7 @@ class MTIHandler:
219
219
 
220
220
  # Pre-compute child-specific fields for execution efficiency
221
221
  from django_bulk_hooks.helpers import get_fields_for_model, filter_field_names_for_model
222
+
222
223
  child_unique_fields = get_fields_for_model(inheritance_chain[-1], unique_fields or [])
223
224
  child_update_fields = get_fields_for_model(inheritance_chain[-1], update_fields or [])
224
225
 
@@ -373,14 +374,14 @@ class MTIHandler:
373
374
  def _get_auto_now_fields_for_model(self, model_class, model_fields_by_name):
374
375
  """
375
376
  Get auto_now (not auto_now_add) fields for a specific model.
376
-
377
+
377
378
  Only includes fields that exist in model_fields_by_name to ensure
378
379
  they're valid local fields for this model level.
379
-
380
+
380
381
  Args:
381
382
  model_class: Model class to get fields for
382
383
  model_fields_by_name: Dict of valid field names for this model level
383
-
384
+
384
385
  Returns:
385
386
  List of auto_now field names (excluding auto_now_add)
386
387
  """
@@ -470,7 +471,9 @@ class MTIHandler:
470
471
 
471
472
  # Handle auto fields for this single parent model
472
473
  handle_auto_now_fields_for_inheritance_chain(
473
- [parent_model], [parent_obj], for_update=False, # MTI create is like insert
474
+ [parent_model],
475
+ [parent_obj],
476
+ for_update=False, # MTI create is like insert
474
477
  )
475
478
 
476
479
  return parent_obj
@@ -527,7 +530,9 @@ class MTIHandler:
527
530
 
528
531
  # Handle auto fields for this single child model
529
532
  handle_auto_now_fields_for_inheritance_chain(
530
- [child_model], [child_obj], for_update=False, # MTI create is like insert
533
+ [child_model],
534
+ [child_obj],
535
+ for_update=False, # MTI create is like insert
531
536
  )
532
537
 
533
538
  return child_obj
@@ -1,103 +1,103 @@
1
- """
2
- MTI operation plans - Data structures for multi-table inheritance operations.
3
-
4
- These are pure data structures returned by MTIHandler to be executed by BulkExecutor.
5
- This separates planning (logic) from execution (database operations).
6
- """
7
-
8
- from dataclasses import dataclass
9
- from dataclasses import field
10
- from typing import Any
11
-
12
-
13
- @dataclass
14
- class ParentLevel:
15
- """
16
- Represents one level in the parent hierarchy for MTI bulk create.
17
-
18
- Attributes:
19
- model_class: The parent model class for this level
20
- objects: List of parent instances to create
21
- original_object_map: Maps parent instance id() -> original object id()
22
- update_conflicts: Whether to enable UPSERT for this level
23
- unique_fields: Fields for conflict detection (if update_conflicts=True)
24
- update_fields: Fields to update on conflict (if update_conflicts=True)
25
- """
26
-
27
- model_class: Any
28
- objects: list[Any]
29
- original_object_map: dict[int, int] = field(default_factory=dict)
30
- update_conflicts: bool = False
31
- unique_fields: list[str] = field(default_factory=list)
32
- update_fields: list[str] = field(default_factory=list)
33
-
34
-
35
- @dataclass
36
- class MTICreatePlan:
37
- """
38
- Plan for executing bulk_create on an MTI model.
39
-
40
- This plan describes WHAT to create, not HOW to create it.
41
- The executor is responsible for executing this plan.
42
-
43
- Attributes:
44
- inheritance_chain: List of model classes from root to child
45
- parent_levels: List of ParentLevel objects, one per parent model
46
- child_objects: List of child instances to create (not yet with parent links)
47
- child_model: The child model class
48
- original_objects: Original objects provided by user
49
- batch_size: Batch size for operations
50
- existing_record_ids: Set of id() of original objects that represent existing DB records
51
- update_conflicts: Whether this is an upsert operation
52
- unique_fields: Fields used for conflict detection (original, unfiltered)
53
- update_fields: Fields to update on conflict (original, unfiltered)
54
- child_unique_fields: Pre-filtered field objects for child table conflict detection
55
- child_update_fields: Pre-filtered field objects for child table updates
56
- """
57
-
58
- inheritance_chain: list[Any]
59
- parent_levels: list[ParentLevel]
60
- child_objects: list[Any]
61
- child_model: Any
62
- original_objects: list[Any]
63
- batch_size: int = None
64
- existing_record_ids: set = field(default_factory=set)
65
- update_conflicts: bool = False
66
- unique_fields: list[str] = field(default_factory=list)
67
- update_fields: list[str] = field(default_factory=list)
68
- child_unique_fields: list = field(default_factory=list) # Field objects for child table
69
- child_update_fields: list = field(default_factory=list) # Field objects for child table
70
-
71
-
72
- @dataclass
73
- class ModelFieldGroup:
74
- """
75
- Represents fields to update for one model in the inheritance chain.
76
-
77
- Attributes:
78
- model_class: The model class
79
- fields: List of field names to update on this model
80
- filter_field: Field to use for filtering (e.g., 'pk' or parent link attname)
81
- """
82
-
83
- model_class: Any
84
- fields: list[str]
85
- filter_field: str = "pk"
86
-
87
-
88
- @dataclass
89
- class MTIUpdatePlan:
90
- """
91
- Plan for executing bulk_update on an MTI model.
92
-
93
- Attributes:
94
- inheritance_chain: List of model classes from root to child
95
- field_groups: List of ModelFieldGroup objects
96
- objects: Objects to update
97
- batch_size: Batch size for operations
98
- """
99
-
100
- inheritance_chain: list[Any]
101
- field_groups: list[ModelFieldGroup]
102
- objects: list[Any]
103
- batch_size: int = None
1
+ """
2
+ MTI operation plans - Data structures for multi-table inheritance operations.
3
+
4
+ These are pure data structures returned by MTIHandler to be executed by BulkExecutor.
5
+ This separates planning (logic) from execution (database operations).
6
+ """
7
+
8
+ from dataclasses import dataclass
9
+ from dataclasses import field
10
+ from typing import Any
11
+
12
+
13
+ @dataclass
14
+ class ParentLevel:
15
+ """
16
+ Represents one level in the parent hierarchy for MTI bulk create.
17
+
18
+ Attributes:
19
+ model_class: The parent model class for this level
20
+ objects: List of parent instances to create
21
+ original_object_map: Maps parent instance id() -> original object id()
22
+ update_conflicts: Whether to enable UPSERT for this level
23
+ unique_fields: Fields for conflict detection (if update_conflicts=True)
24
+ update_fields: Fields to update on conflict (if update_conflicts=True)
25
+ """
26
+
27
+ model_class: Any
28
+ objects: list[Any]
29
+ original_object_map: dict[int, int] = field(default_factory=dict)
30
+ update_conflicts: bool = False
31
+ unique_fields: list[str] = field(default_factory=list)
32
+ update_fields: list[str] = field(default_factory=list)
33
+
34
+
35
+ @dataclass
36
+ class MTICreatePlan:
37
+ """
38
+ Plan for executing bulk_create on an MTI model.
39
+
40
+ This plan describes WHAT to create, not HOW to create it.
41
+ The executor is responsible for executing this plan.
42
+
43
+ Attributes:
44
+ inheritance_chain: List of model classes from root to child
45
+ parent_levels: List of ParentLevel objects, one per parent model
46
+ child_objects: List of child instances to create (not yet with parent links)
47
+ child_model: The child model class
48
+ original_objects: Original objects provided by user
49
+ batch_size: Batch size for operations
50
+ existing_record_ids: Set of id() of original objects that represent existing DB records
51
+ update_conflicts: Whether this is an upsert operation
52
+ unique_fields: Fields used for conflict detection (original, unfiltered)
53
+ update_fields: Fields to update on conflict (original, unfiltered)
54
+ child_unique_fields: Pre-filtered field objects for child table conflict detection
55
+ child_update_fields: Pre-filtered field objects for child table updates
56
+ """
57
+
58
+ inheritance_chain: list[Any]
59
+ parent_levels: list[ParentLevel]
60
+ child_objects: list[Any]
61
+ child_model: Any
62
+ original_objects: list[Any]
63
+ batch_size: int = None
64
+ existing_record_ids: set = field(default_factory=set)
65
+ update_conflicts: bool = False
66
+ unique_fields: list[str] = field(default_factory=list)
67
+ update_fields: list[str] = field(default_factory=list)
68
+ child_unique_fields: list = field(default_factory=list) # Field objects for child table
69
+ child_update_fields: list = field(default_factory=list) # Field objects for child table
70
+
71
+
72
+ @dataclass
73
+ class ModelFieldGroup:
74
+ """
75
+ Represents fields to update for one model in the inheritance chain.
76
+
77
+ Attributes:
78
+ model_class: The model class
79
+ fields: List of field names to update on this model
80
+ filter_field: Field to use for filtering (e.g., 'pk' or parent link attname)
81
+ """
82
+
83
+ model_class: Any
84
+ fields: list[str]
85
+ filter_field: str = "pk"
86
+
87
+
88
+ @dataclass
89
+ class MTIUpdatePlan:
90
+ """
91
+ Plan for executing bulk_update on an MTI model.
92
+
93
+ Attributes:
94
+ inheritance_chain: List of model classes from root to child
95
+ field_groups: List of ModelFieldGroup objects
96
+ objects: Objects to update
97
+ batch_size: Batch size for operations
98
+ """
99
+
100
+ inheritance_chain: list[Any]
101
+ field_groups: list[ModelFieldGroup]
102
+ objects: list[Any]
103
+ batch_size: int = None
@@ -64,7 +64,7 @@ class RecordClassifier:
64
64
  # Build lookup dict for this object's unique fields
65
65
  lookup = {}
66
66
  normalized_values = []
67
-
67
+
68
68
  for field_name in unique_fields:
69
69
  # Use centralized field value extraction for consistent FK handling
70
70
  value = get_field_value_for_db(obj, field_name, query_model)
@@ -134,7 +134,11 @@ class HookQuerySet(models.QuerySet):
134
134
 
135
135
  @transaction.atomic
136
136
  def bulk_delete(
137
- self, objs, bypass_hooks=False, bypass_validation=False, **kwargs,
137
+ self,
138
+ objs,
139
+ bypass_hooks=False,
140
+ bypass_validation=False,
141
+ **kwargs,
138
142
  ):
139
143
  """
140
144
  Delete multiple objects with hook support.
@@ -116,7 +116,6 @@ class HookRegistry:
116
116
  if not self._hooks[key]:
117
117
  del self._hooks[key]
118
118
 
119
-
120
119
  def clear(self) -> None:
121
120
  """
122
121
  Clear all registered hooks.
@@ -132,7 +131,6 @@ class HookRegistry:
132
131
  HookMeta._registered.clear()
133
132
  HookMeta._class_hook_map.clear()
134
133
 
135
-
136
134
  def list_all(self) -> dict[tuple[type, str], list[HookInfo]]:
137
135
  """
138
136
  Get all registered hooks for debugging.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-bulk-hooks
3
- Version: 0.2.61
3
+ Version: 0.2.62
4
4
  Summary: Hook-style hooks for Django bulk operations like bulk_create and bulk_update.
5
5
  License: MIT
6
6
  Keywords: django,bulk,hooks
@@ -0,0 +1,27 @@
1
+ django_bulk_hooks/__init__.py,sha256=ujBvX-GY4Pg4ACBh7RXm_MOmi2eAowf5s7pG2SXWdpo,2276
2
+ django_bulk_hooks/changeset.py,sha256=qnMD3bR2cNh8ZM8J6ASR5ly5Rjx-tPzXBYkqIjKGW98,6568
3
+ django_bulk_hooks/conditions.py,sha256=ar4pGjtxLKmgSIlO4S6aZFKmaBNchLtxMmWpkn4g9RU,8114
4
+ django_bulk_hooks/constants.py,sha256=PxpEETaO6gdENcTPoXS586lerGKVP3nmjpDvOkmhYxI,509
5
+ django_bulk_hooks/context.py,sha256=mqaC5-yESDTA5ruI7fuXlt8qSgKuOFp0mjq7h1-4HdQ,1926
6
+ django_bulk_hooks/decorators.py,sha256=TdkO4FJyFrVU2zqK6Y_6JjEJ4v3nbKkk7aa22jN10sk,11994
7
+ django_bulk_hooks/dispatcher.py,sha256=yHfmAWChj9rsZwO4jhYDVtJde_Z8bPe9WHRjkYBMfEo,8151
8
+ django_bulk_hooks/enums.py,sha256=Zo8_tJzuzZ2IKfVc7gZ-0tWPT8q1QhqZbAyoh9ZVJbs,381
9
+ django_bulk_hooks/factory.py,sha256=ezrVM5U023KZqOBbJXb6lYUP-pE7WJmi8Olh2Ew-7RA,18085
10
+ django_bulk_hooks/handler.py,sha256=SRCrMzgolrruTkvMnYBFmXLR-ABiw0JiH3605PEdCZM,4207
11
+ django_bulk_hooks/helpers.py,sha256=tMxUI5oWhbtWByzCCR0Qcj1CgZ6iP5Jfx03EqVmEhxU,7597
12
+ django_bulk_hooks/manager.py,sha256=aDuP87DZLWWbDK2qeA7usl3pxoIjHFIWnQNi_jEq6z0,4446
13
+ django_bulk_hooks/models.py,sha256=TWN_F-SsLGPx9jrkNT9pmJFR5VsZ0Z_QaVOZOmt7bpw,2434
14
+ django_bulk_hooks/operations/__init__.py,sha256=BtJYjmRhe_sScivLsniDaZmBkm0ZLvcmzXFKL7QY2Xg,550
15
+ django_bulk_hooks/operations/analyzer.py,sha256=Pz8mc-EL8KDOfLQFYiRuN-r0OmINW3nIBhRJJCma-yo,10360
16
+ django_bulk_hooks/operations/bulk_executor.py,sha256=po8V_2H3ULiE0RYJ-wbaRIz52SKhss81UHwuQjlz3H8,26214
17
+ django_bulk_hooks/operations/coordinator.py,sha256=NPPkiEIMgbJXEIOtBqvy3OH4l0pOK_NL5jwT7Og9I4o,33765
18
+ django_bulk_hooks/operations/field_utils.py,sha256=cQ9w4xdk-z3PrMLFvRzVV07Wc0D2qbpSepwoupqwQH8,7888
19
+ django_bulk_hooks/operations/mti_handler.py,sha256=Vmz0C0gtYDvbybmb4cDzIaGglSaQK4DQVkaBK-WuQeE,25855
20
+ django_bulk_hooks/operations/mti_plans.py,sha256=HIRJgogHPpm6MV7nZZ-sZhMLUnozpZPV2SzwQHLRzYc,3667
21
+ django_bulk_hooks/operations/record_classifier.py,sha256=It85hJC2K-UsEOLbTR-QBdY5UPV-acQIJ91TSGa7pYo,7053
22
+ django_bulk_hooks/queryset.py,sha256=g_9OtOTC8FXY0hBwYr2FCqQ3mYXbfJTFPLlFV3SHmWQ,5600
23
+ django_bulk_hooks/registry.py,sha256=4HxP1mVK2z4VzvlohbEw2359wM21UJZJYagJJ1komM0,7947
24
+ django_bulk_hooks-0.2.62.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
25
+ django_bulk_hooks-0.2.62.dist-info/METADATA,sha256=Ib--glZc6N4AtvIcIGqMAQUTdAk0AeCmrV2wv6u8iWQ,9265
26
+ django_bulk_hooks-0.2.62.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
+ django_bulk_hooks-0.2.62.dist-info/RECORD,,
@@ -1,27 +0,0 @@
1
- django_bulk_hooks/__init__.py,sha256=ujBvX-GY4Pg4ACBh7RXm_MOmi2eAowf5s7pG2SXWdpo,2276
2
- django_bulk_hooks/changeset.py,sha256=opWqb_x-_9KaMsUJc7lI3wScWLHn2Yhe7hB-ngFCBp0,6731
3
- django_bulk_hooks/conditions.py,sha256=v2DMFmWI7bppBQw5qdbO5CmQRN_QtUwnBjcyKBJLLbw,8030
4
- django_bulk_hooks/constants.py,sha256=PxpEETaO6gdENcTPoXS586lerGKVP3nmjpDvOkmhYxI,509
5
- django_bulk_hooks/context.py,sha256=mqaC5-yESDTA5ruI7fuXlt8qSgKuOFp0mjq7h1-4HdQ,1926
6
- django_bulk_hooks/decorators.py,sha256=P7cvzFgORJRW-YQHNAxNXqQOP9OywBmA7Rz9kiJoxUk,12237
7
- django_bulk_hooks/dispatcher.py,sha256=CiKYe5ecUPu5TYUZq8ToaRT40TkLc5l5mczgf5XDzGA,8217
8
- django_bulk_hooks/enums.py,sha256=Zo8_tJzuzZ2IKfVc7gZ-0tWPT8q1QhqZbAyoh9ZVJbs,381
9
- django_bulk_hooks/factory.py,sha256=ezrVM5U023KZqOBbJXb6lYUP-pE7WJmi8Olh2Ew-7RA,18085
10
- django_bulk_hooks/handler.py,sha256=38ejMdQ9reYA07_XQ9tC8xv0lW3amO-m8gPzuRNOyj0,4200
11
- django_bulk_hooks/helpers.py,sha256=e14aYE1lKaj8-krFclY_WfJF2uWQpblfsl5hqsW-dxY,7800
12
- django_bulk_hooks/manager.py,sha256=g11g1MZ4DJGIM4prYLpYLejTsz0YkYPWeoxWA4dcgYk,4596
13
- django_bulk_hooks/models.py,sha256=9uh7leV3EEnTWkNKNqT1xevamPTczRhW7KbnIHraBlk,2969
14
- django_bulk_hooks/operations/__init__.py,sha256=BtJYjmRhe_sScivLsniDaZmBkm0ZLvcmzXFKL7QY2Xg,550
15
- django_bulk_hooks/operations/analyzer.py,sha256=wO-LUgGExE8y3fb25kdfpbj_KdSIW8fd4QFp0Os8Muk,10679
16
- django_bulk_hooks/operations/bulk_executor.py,sha256=byo09_65qQI_Z-7HvIoeWh-fRAFnI6qrWFjDr2Ar8LA,26275
17
- django_bulk_hooks/operations/coordinator.py,sha256=d7DD_CMUA4yeUJeJueBOQ9LrJFFj3emVx56hG1Ju5Xg,33787
18
- django_bulk_hooks/operations/field_utils.py,sha256=M1HfBj5EK5c6SbOmkVT9s6u_SEOh_N4bheytm5jBD4o,7980
19
- django_bulk_hooks/operations/mti_handler.py,sha256=LbmbAzowfaQePWjjryHJxogvyDZ4GTL176gc6ezKVYA,25829
20
- django_bulk_hooks/operations/mti_plans.py,sha256=Vl0lV7AuhmovI0_qcD73KairyPy73l36fJYk8wRBh2g,3770
21
- django_bulk_hooks/operations/record_classifier.py,sha256=kqML4aO11X9K3SSJ5DUlUukwI172j_Tk12Kr77ee8q8,7065
22
- django_bulk_hooks/queryset.py,sha256=8xdA3jV6SeEGzW-av346I85Kq1N1uqt178aEh8vm8v8,5568
23
- django_bulk_hooks/registry.py,sha256=uum5jhGI3TPaoiXuA1MdBdu4gbE3rQGGwQ5YDjiMcjk,7949
24
- django_bulk_hooks-0.2.61.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
25
- django_bulk_hooks-0.2.61.dist-info/METADATA,sha256=UxXjcApyuPWulCJWCm9LJGeI6Krh7bwb8mdOsVMfmc0,9265
26
- django_bulk_hooks-0.2.61.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
- django_bulk_hooks-0.2.61.dist-info/RECORD,,