django-bulk-hooks 0.1.218__tar.gz → 0.1.220__tar.gz

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.

Files changed (17) hide show
  1. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/PKG-INFO +1 -1
  2. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/conditions.py +9 -4
  3. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/engine.py +5 -5
  4. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/models.py +6 -7
  5. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/queryset.py +15 -12
  6. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/registry.py +5 -2
  7. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/pyproject.toml +1 -1
  8. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/LICENSE +0 -0
  9. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/README.md +0 -0
  10. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/__init__.py +0 -0
  11. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/constants.py +0 -0
  12. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/context.py +0 -0
  13. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/decorators.py +0 -0
  14. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/enums.py +0 -0
  15. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/handler.py +0 -0
  16. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/manager.py +0 -0
  17. {django_bulk_hooks-0.1.218 → django_bulk_hooks-0.1.220}/django_bulk_hooks/priority.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.218
3
+ Version: 0.1.220
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
@@ -1,3 +1,8 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger(__name__)
4
+
5
+
1
6
  def resolve_dotted_attr(instance, dotted_path):
2
7
  """
3
8
  Recursively resolve a dotted attribute path, e.g., "type.category".
@@ -66,11 +71,11 @@ class HasChanged(HookCondition):
66
71
  self.has_changed = has_changed
67
72
 
68
73
  def check(self, instance, original_instance=None):
69
- print(f"DEBUG: HasChanged.check called for field '{self.field}' on instance {getattr(instance, 'pk', 'No PK')}")
70
- print(f"DEBUG: Original instance: {getattr(original_instance, 'pk', 'No PK') if original_instance else 'None'}")
74
+ logger.debug(f"HasChanged.check called for field '{self.field}' on instance {getattr(instance, 'pk', 'No PK')}")
75
+ logger.debug(f"Original instance: {getattr(original_instance, 'pk', 'No PK') if original_instance else 'None'}")
71
76
 
72
77
  if not original_instance:
73
- print(f"DEBUG: No original instance, returning False")
78
+ logger.debug("No original instance, returning False")
74
79
  return False
75
80
 
76
81
  current = resolve_dotted_attr(instance, self.field)
@@ -78,7 +83,7 @@ class HasChanged(HookCondition):
78
83
 
79
84
  # Add more detailed debugging
80
85
  result = (current != previous) == self.has_changed
81
- print(f"DEBUG: HasChanged {self.field} result={result}")
86
+ logger.debug(f"HasChanged {self.field} result={result}")
82
87
  return result
83
88
 
84
89
 
@@ -23,11 +23,11 @@ def run(model_cls, event, new_records, old_records=None, ctx=None):
23
23
  import traceback
24
24
 
25
25
  stack = traceback.format_stack()
26
- print(f"DEBUG: engine.run {model_cls.__name__}.{event} {len(new_records)} records")
26
+ logger.debug(f"engine.run {model_cls.__name__}.{event} {len(new_records)} records")
27
27
 
28
28
  # Check if we're in a bypass context
29
29
  if ctx and hasattr(ctx, 'bypass_hooks') and ctx.bypass_hooks:
30
- print(f"DEBUG: engine.run bypassed")
30
+ logger.debug("engine.run bypassed")
31
31
  return
32
32
 
33
33
  # For BEFORE_* events, run model.clean() first for validation
@@ -41,7 +41,7 @@ def run(model_cls, event, new_records, old_records=None, ctx=None):
41
41
 
42
42
  # Process hooks
43
43
  for handler_cls, method_name, condition, priority in hooks:
44
- print(f"DEBUG: Processing {handler_cls.__name__}.{method_name}")
44
+ logger.debug(f"Processing {handler_cls.__name__}.{method_name}")
45
45
  handler_instance = handler_cls()
46
46
  func = getattr(handler_instance, method_name)
47
47
 
@@ -63,12 +63,12 @@ def run(model_cls, event, new_records, old_records=None, ctx=None):
63
63
  to_process_old.append(original)
64
64
 
65
65
  if to_process_new:
66
- print(f"DEBUG: Executing {handler_cls.__name__}.{method_name} for {len(to_process_new)} records")
66
+ logger.debug(f"Executing {handler_cls.__name__}.{method_name} for {len(to_process_new)} records")
67
67
  try:
68
68
  func(
69
69
  new_records=to_process_new,
70
70
  old_records=to_process_old if any(to_process_old) else None,
71
71
  )
72
72
  except Exception as e:
73
- print(f"DEBUG: Hook execution failed: {e}")
73
+ logger.debug(f"Hook execution failed: {e}")
74
74
  raise
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from django.db import models
2
3
 
3
4
  from django_bulk_hooks.constants import (
@@ -15,6 +16,8 @@ from django_bulk_hooks.context import HookContext
15
16
  from django_bulk_hooks.engine import run
16
17
  from django_bulk_hooks.manager import BulkHookManager
17
18
 
19
+ logger = logging.getLogger(__name__)
20
+
18
21
 
19
22
  class HookModelMixin(models.Model):
20
23
  objects = BulkHookManager()
@@ -56,15 +59,13 @@ class HookModelMixin(models.Model):
56
59
  def save(self, *args, bypass_hooks=False, **kwargs):
57
60
  # If bypass_hooks is True, use base manager to avoid triggering hooks
58
61
  if bypass_hooks:
59
- print(
60
- f"DEBUG: save() called with bypass_hooks=True for {self.__class__.__name__} pk={self.pk}"
61
- )
62
+ logger.debug(f"save() called with bypass_hooks=True for {self.__class__.__name__} pk={self.pk}")
62
63
  return self._base_manager.save(self, *args, **kwargs)
63
64
 
64
65
  is_create = self.pk is None
65
66
 
66
67
  if is_create:
67
- print(f"DEBUG: save() creating new {self.__class__.__name__} instance")
68
+ logger.debug(f"save() creating new {self.__class__.__name__} instance")
68
69
  # For create operations, we don't have old records
69
70
  ctx = HookContext(self.__class__)
70
71
  run(self.__class__, BEFORE_CREATE, [self], ctx=ctx)
@@ -73,9 +74,7 @@ class HookModelMixin(models.Model):
73
74
 
74
75
  run(self.__class__, AFTER_CREATE, [self], ctx=ctx)
75
76
  else:
76
- print(
77
- f"DEBUG: save() updating existing {self.__class__.__name__} instance pk={self.pk}"
78
- )
77
+ logger.debug(f"save() updating existing {self.__class__.__name__} instance pk={self.pk}")
79
78
  # For update operations, we need to get the old record
80
79
  try:
81
80
  # Use _base_manager to avoid triggering hooks recursively
@@ -1,7 +1,10 @@
1
+ import logging
1
2
  from django.db import models, transaction
2
3
  from django.db.models import AutoField, Case, Field, Value, When
3
4
 
4
5
  from django_bulk_hooks import engine
6
+
7
+ logger = logging.getLogger(__name__)
5
8
  from django_bulk_hooks.constants import (
6
9
  AFTER_CREATE,
7
10
  AFTER_DELETE,
@@ -78,10 +81,10 @@ class HookQuerySetMixin:
78
81
 
79
82
  # If we're in a bulk operation context, skip hooks to prevent double execution
80
83
  if current_bypass_hooks:
81
- print(f"DEBUG: update skipping hooks (bulk context)")
84
+ logger.debug("update skipping hooks (bulk context)")
82
85
  ctx = HookContext(model_cls, bypass_hooks=True)
83
86
  else:
84
- print(f"DEBUG: update running hooks (standalone)")
87
+ logger.debug("update running hooks (standalone)")
85
88
  ctx = HookContext(model_cls, bypass_hooks=False)
86
89
  # Run validation hooks first
87
90
  engine.run(model_cls, VALIDATE_UPDATE, instances, originals, ctx=ctx)
@@ -115,10 +118,10 @@ class HookQuerySetMixin:
115
118
 
116
119
  # Run AFTER_UPDATE hooks only for standalone updates
117
120
  if not current_bypass_hooks:
118
- print(f"DEBUG: update running AFTER_UPDATE")
121
+ logger.debug("update running AFTER_UPDATE")
119
122
  engine.run(model_cls, AFTER_UPDATE, instances, originals, ctx=ctx)
120
123
  else:
121
- print(f"DEBUG: update skipping AFTER_UPDATE (bulk context)")
124
+ logger.debug("update skipping AFTER_UPDATE (bulk context)")
122
125
 
123
126
  return update_count
124
127
 
@@ -183,7 +186,7 @@ class HookQuerySetMixin:
183
186
  engine.run(model_cls, BEFORE_CREATE, objs, ctx=ctx)
184
187
  else:
185
188
  ctx = HookContext(model_cls, bypass_hooks=True) # Pass bypass_hooks
186
- print(f"DEBUG: bulk_create bypassed hooks")
189
+ logger.debug("bulk_create bypassed hooks")
187
190
 
188
191
  # For MTI models, we need to handle them specially
189
192
  if is_mti:
@@ -238,7 +241,7 @@ class HookQuerySetMixin:
238
241
  f"bulk_update expected instances of {model_cls.__name__}, but got {set(type(obj).__name__ for obj in objs)}"
239
242
  )
240
243
 
241
- print(f"DEBUG: bulk_update {model_cls.__name__} bypass_hooks={bypass_hooks} objs={len(objs)}")
244
+ logger.debug(f"bulk_update {model_cls.__name__} bypass_hooks={bypass_hooks} objs={len(objs)}")
242
245
 
243
246
  # Check for MTI
244
247
  is_mti = False
@@ -248,11 +251,11 @@ class HookQuerySetMixin:
248
251
  break
249
252
 
250
253
  if not bypass_hooks:
251
- print(f"DEBUG: bulk_update setting bypass_hooks=False (hooks will run in update())")
254
+ logger.debug("bulk_update setting bypass_hooks=False (hooks will run in update())")
252
255
  ctx = HookContext(model_cls, bypass_hooks=False)
253
256
  originals = [None] * len(objs) # Placeholder for after_update call
254
257
  else:
255
- print(f"DEBUG: bulk_update setting bypass_hooks=True (no hooks)")
258
+ logger.debug("bulk_update setting bypass_hooks=True (no hooks)")
256
259
  ctx = HookContext(model_cls, bypass_hooks=True)
257
260
  originals = [None] * len(objs) # Ensure originals is defined for after_update call
258
261
 
@@ -279,16 +282,16 @@ class HookQuerySetMixin:
279
282
  for k, v in kwargs.items()
280
283
  if k not in ["bypass_hooks", "bypass_validation"]
281
284
  }
282
- print(f"DEBUG: Calling Django bulk_update")
285
+ logger.debug("Calling Django bulk_update")
283
286
  result = super().bulk_update(objs, fields, **django_kwargs)
284
- print(f"DEBUG: Django bulk_update done: {result}")
287
+ logger.debug(f"Django bulk_update done: {result}")
285
288
 
286
289
  # Note: We don't run AFTER_UPDATE hooks here to prevent double execution
287
290
  # The update() method will handle all hook execution based on thread-local state
288
291
  if not bypass_hooks:
289
- print(f"DEBUG: bulk_update skipping AFTER_UPDATE (update() will handle)")
292
+ logger.debug("bulk_update skipping AFTER_UPDATE (update() will handle)")
290
293
  else:
291
- print(f"DEBUG: bulk_update bypassed hooks")
294
+ logger.debug("bulk_update bypassed hooks")
292
295
 
293
296
  return result
294
297
 
@@ -1,8 +1,11 @@
1
+ import logging
1
2
  from collections.abc import Callable
2
3
  from typing import Union
3
4
 
4
5
  from django_bulk_hooks.priority import Priority
5
6
 
7
+ logger = logging.getLogger(__name__)
8
+
6
9
  _hooks: dict[tuple[type, str], list[tuple[type, str, Callable, int]]] = {}
7
10
 
8
11
 
@@ -14,13 +17,13 @@ def register_hook(
14
17
  hooks.append((handler_cls, method_name, condition, priority))
15
18
  # keep sorted by priority
16
19
  hooks.sort(key=lambda x: x[3])
17
- print(f"DEBUG: Registered {handler_cls.__name__}.{method_name} for {model.__name__}.{event}")
20
+ logger.debug(f"Registered {handler_cls.__name__}.{method_name} for {model.__name__}.{event}")
18
21
 
19
22
 
20
23
  def get_hooks(model, event):
21
24
  key = (model, event)
22
25
  hooks = _hooks.get(key, [])
23
- print(f"DEBUG: get_hooks {model.__name__}.{event} found {len(hooks)} hooks")
26
+ logger.debug(f"get_hooks {model.__name__}.{event} found {len(hooks)} hooks")
24
27
  return hooks
25
28
 
26
29
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-bulk-hooks"
3
- version = "0.1.218"
3
+ version = "0.1.220"
4
4
  description = "Hook-style hooks for Django bulk operations like bulk_create and bulk_update."
5
5
  authors = ["Konrad Beck <konrad.beck@merchantcapital.co.za>"]
6
6
  readme = "README.md"