django-bulk-hooks 0.2.103__tar.gz → 0.3.3__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.
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/PKG-INFO +25 -1
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/README.md +24 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/__init__.py +18 -7
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/conditions.py +297 -230
- django_bulk_hooks-0.3.3/django_bulk_hooks/decorators.py +499 -0
- django_bulk_hooks-0.3.3/django_bulk_hooks/dispatcher.py +353 -0
- django_bulk_hooks-0.3.3/django_bulk_hooks/dispatcher_executor.py +271 -0
- django_bulk_hooks-0.3.3/django_bulk_hooks/dispatcher_preloader.py +214 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/factory.py +91 -10
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/helpers.py +66 -15
- django_bulk_hooks-0.3.3/django_bulk_hooks/models.py +218 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/operations/__init__.py +0 -2
- django_bulk_hooks-0.3.3/django_bulk_hooks/operations/auto_fields.py +11 -0
- django_bulk_hooks-0.3.3/django_bulk_hooks/operations/bulk_executor.py +303 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/operations/coordinator.py +1162 -928
- django_bulk_hooks-0.3.3/django_bulk_hooks/operations/field_utils.py +600 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/operations/record_classifier.py +2 -2
- django_bulk_hooks-0.3.3/django_bulk_hooks/operations/value_prep.py +12 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/registry.py +37 -0
- django_bulk_hooks-0.3.3/django_bulk_hooks/utils/__init__.py +2 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/pyproject.toml +4 -1
- django_bulk_hooks-0.2.103/django_bulk_hooks/decorators.py +0 -304
- django_bulk_hooks-0.2.103/django_bulk_hooks/dispatcher.py +0 -612
- django_bulk_hooks-0.2.103/django_bulk_hooks/models.py +0 -89
- django_bulk_hooks-0.2.103/django_bulk_hooks/operations/bulk_executor.py +0 -765
- django_bulk_hooks-0.2.103/django_bulk_hooks/operations/field_utils.py +0 -341
- django_bulk_hooks-0.2.103/django_bulk_hooks/operations/mti_handler.py +0 -705
- django_bulk_hooks-0.2.103/django_bulk_hooks/operations/mti_plans.py +0 -103
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/LICENSE +0 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/changeset.py +0 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/context.py +0 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/operations/analyzer.py +0 -0
- {django_bulk_hooks-0.2.103 → django_bulk_hooks-0.3.3}/django_bulk_hooks/queryset.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: django-bulk-hooks
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.3
|
|
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
|
|
@@ -32,6 +32,7 @@ Description-Content-Type: text/markdown
|
|
|
32
32
|
- **NEW**: `HookModelMixin` for individual model lifecycle events
|
|
33
33
|
- Hook chaining, hook deduplication, and atomicity
|
|
34
34
|
- Class-based hook handlers with DI support
|
|
35
|
+
- Register hooks against abstract models; they apply to all concrete subclasses
|
|
35
36
|
- Support for both bulk and individual model operations
|
|
36
37
|
|
|
37
38
|
## 🚀 Quickstart
|
|
@@ -178,6 +179,7 @@ Django's `bulk_` methods bypass signals and `save()`. This package fills that ga
|
|
|
178
179
|
|
|
179
180
|
- Hooks that behave consistently across creates/updates/deletes
|
|
180
181
|
- **NEW**: Individual model lifecycle hooks that work with `save()` and `delete()`
|
|
182
|
+
- **NEW**: Abstract-base hook registration; MTI support removed for simplicity and stability
|
|
181
183
|
- Scalable performance via chunking (default 200)
|
|
182
184
|
- Support for `@hook` decorators and centralized hook classes
|
|
183
185
|
- **NEW**: Automatic hook hooking for admin operations and other Django features
|
|
@@ -314,6 +316,28 @@ Execute them in priority order
|
|
|
314
316
|
Pass ChangeSet to them
|
|
315
317
|
Handle errors (rollback on failure)
|
|
316
318
|
|
|
319
|
+
## 🔄 Migration (1.0.0)
|
|
320
|
+
|
|
321
|
+
- MTI (Multi-Table Inheritance) support has been removed.
|
|
322
|
+
- Register hooks against abstract base models to have them apply to all concrete subclasses.
|
|
323
|
+
- Example:
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
class AbstractBusiness(models.Model):
|
|
327
|
+
class Meta:
|
|
328
|
+
abstract = True
|
|
329
|
+
|
|
330
|
+
class Business(AbstractBusiness):
|
|
331
|
+
name = models.CharField(max_length=100)
|
|
332
|
+
|
|
333
|
+
class BusinessHook(Hook):
|
|
334
|
+
@hook(AFTER_UPDATE, model=AbstractBusiness)
|
|
335
|
+
def on_update(self, new_records, old_records, **kwargs):
|
|
336
|
+
...
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
If any model inherits from a concrete parent (true MTI), an error is raised at import time. Convert parents to abstract models instead.
|
|
340
|
+
|
|
317
341
|
## 📝 License
|
|
318
342
|
|
|
319
343
|
MIT © 2024 Augend / Konrad Beck
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
- **NEW**: `HookModelMixin` for individual model lifecycle events
|
|
14
14
|
- Hook chaining, hook deduplication, and atomicity
|
|
15
15
|
- Class-based hook handlers with DI support
|
|
16
|
+
- Register hooks against abstract models; they apply to all concrete subclasses
|
|
16
17
|
- Support for both bulk and individual model operations
|
|
17
18
|
|
|
18
19
|
## 🚀 Quickstart
|
|
@@ -159,6 +160,7 @@ Django's `bulk_` methods bypass signals and `save()`. This package fills that ga
|
|
|
159
160
|
|
|
160
161
|
- Hooks that behave consistently across creates/updates/deletes
|
|
161
162
|
- **NEW**: Individual model lifecycle hooks that work with `save()` and `delete()`
|
|
163
|
+
- **NEW**: Abstract-base hook registration; MTI support removed for simplicity and stability
|
|
162
164
|
- Scalable performance via chunking (default 200)
|
|
163
165
|
- Support for `@hook` decorators and centralized hook classes
|
|
164
166
|
- **NEW**: Automatic hook hooking for admin operations and other Django features
|
|
@@ -295,6 +297,28 @@ Execute them in priority order
|
|
|
295
297
|
Pass ChangeSet to them
|
|
296
298
|
Handle errors (rollback on failure)
|
|
297
299
|
|
|
300
|
+
## 🔄 Migration (1.0.0)
|
|
301
|
+
|
|
302
|
+
- MTI (Multi-Table Inheritance) support has been removed.
|
|
303
|
+
- Register hooks against abstract base models to have them apply to all concrete subclasses.
|
|
304
|
+
- Example:
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
class AbstractBusiness(models.Model):
|
|
308
|
+
class Meta:
|
|
309
|
+
abstract = True
|
|
310
|
+
|
|
311
|
+
class Business(AbstractBusiness):
|
|
312
|
+
name = models.CharField(max_length=100)
|
|
313
|
+
|
|
314
|
+
class BusinessHook(Hook):
|
|
315
|
+
@hook(AFTER_UPDATE, model=AbstractBusiness)
|
|
316
|
+
def on_update(self, new_records, old_records, **kwargs):
|
|
317
|
+
...
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
If any model inherits from a concrete parent (true MTI), an error is raised at import time. Convert parents to abstract models instead.
|
|
321
|
+
|
|
298
322
|
## 📝 License
|
|
299
323
|
|
|
300
324
|
MIT © 2024 Augend / Konrad Beck
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Django Bulk Hooks - Salesforce-style hooks for Django bulk operations.
|
|
3
|
+
|
|
4
|
+
Architecture:
|
|
5
|
+
Following Salesforce's trigger context pattern, each bulk operation
|
|
6
|
+
gets an isolated dispatcher context that's automatically cleaned up.
|
|
7
|
+
This prevents memory leaks in long-lived processes (web servers).
|
|
8
|
+
"""
|
|
9
|
+
|
|
1
10
|
import logging
|
|
2
11
|
|
|
3
12
|
from django_bulk_hooks.changeset import ChangeSet
|
|
4
13
|
from django_bulk_hooks.changeset import RecordChange
|
|
5
14
|
from django_bulk_hooks.constants import DEFAULT_BULK_UPDATE_BATCH_SIZE
|
|
6
15
|
from django_bulk_hooks.dispatcher import HookDispatcher
|
|
7
|
-
from django_bulk_hooks.dispatcher import get_dispatcher
|
|
8
16
|
from django_bulk_hooks.factory import clear_hook_factories
|
|
9
17
|
from django_bulk_hooks.factory import configure_hook_container
|
|
10
18
|
from django_bulk_hooks.factory import configure_nested_container
|
|
11
19
|
from django_bulk_hooks.factory import create_hook_instance
|
|
20
|
+
from django_bulk_hooks.factory import dishka_hook_resolver
|
|
12
21
|
from django_bulk_hooks.factory import is_container_configured
|
|
13
22
|
from django_bulk_hooks.factory import set_default_hook_factory
|
|
14
23
|
from django_bulk_hooks.factory import set_hook_factory
|
|
@@ -20,34 +29,36 @@ from django_bulk_hooks.helpers import dispatch_hooks_for_operation
|
|
|
20
29
|
from django_bulk_hooks.manager import BulkHookManager
|
|
21
30
|
from django_bulk_hooks.operations import BulkExecutor
|
|
22
31
|
|
|
23
|
-
# Service layer (
|
|
32
|
+
# Service layer (composition-based architecture)
|
|
24
33
|
from django_bulk_hooks.operations import BulkOperationCoordinator
|
|
25
34
|
from django_bulk_hooks.operations import ModelAnalyzer
|
|
26
|
-
from django_bulk_hooks.operations import MTIHandler
|
|
27
35
|
|
|
28
36
|
__all__ = [
|
|
37
|
+
# Manager and Hook base class
|
|
29
38
|
"BulkHookManager",
|
|
30
39
|
"HookClass",
|
|
40
|
+
# Dependency injection
|
|
31
41
|
"set_hook_factory",
|
|
32
42
|
"set_default_hook_factory",
|
|
33
43
|
"configure_hook_container",
|
|
34
44
|
"configure_nested_container",
|
|
45
|
+
"dishka_hook_resolver",
|
|
35
46
|
"clear_hook_factories",
|
|
36
47
|
"create_hook_instance",
|
|
37
48
|
"is_container_configured",
|
|
49
|
+
# Constants
|
|
38
50
|
"DEFAULT_BULK_UPDATE_BATCH_SIZE",
|
|
39
|
-
#
|
|
51
|
+
# Changeset (Salesforce-style context)
|
|
40
52
|
"ChangeSet",
|
|
41
53
|
"RecordChange",
|
|
42
|
-
"get_dispatcher",
|
|
43
|
-
"HookDispatcher",
|
|
44
54
|
"build_changeset_for_create",
|
|
45
55
|
"build_changeset_for_update",
|
|
46
56
|
"build_changeset_for_delete",
|
|
57
|
+
# Dispatcher (per-operation context)
|
|
58
|
+
"HookDispatcher",
|
|
47
59
|
"dispatch_hooks_for_operation",
|
|
48
60
|
# Service layer (composition-based architecture)
|
|
49
61
|
"BulkOperationCoordinator",
|
|
50
62
|
"ModelAnalyzer",
|
|
51
63
|
"BulkExecutor",
|
|
52
|
-
"MTIHandler",
|
|
53
64
|
]
|