django-bulk-hooks 0.2.9__py3-none-any.whl → 0.2.93__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.
- django_bulk_hooks/__init__.py +20 -27
- django_bulk_hooks/changeset.py +214 -230
- django_bulk_hooks/conditions.py +12 -12
- django_bulk_hooks/decorators.py +68 -26
- django_bulk_hooks/dispatcher.py +369 -58
- django_bulk_hooks/factory.py +541 -565
- django_bulk_hooks/handler.py +106 -115
- django_bulk_hooks/helpers.py +258 -99
- django_bulk_hooks/manager.py +134 -130
- django_bulk_hooks/models.py +89 -76
- django_bulk_hooks/operations/__init__.py +5 -5
- django_bulk_hooks/operations/analyzer.py +299 -172
- django_bulk_hooks/operations/bulk_executor.py +742 -437
- django_bulk_hooks/operations/coordinator.py +928 -472
- django_bulk_hooks/operations/field_utils.py +335 -0
- django_bulk_hooks/operations/mti_handler.py +696 -473
- django_bulk_hooks/operations/mti_plans.py +103 -87
- django_bulk_hooks/operations/record_classifier.py +196 -0
- django_bulk_hooks/queryset.py +233 -189
- django_bulk_hooks/registry.py +276 -288
- {django_bulk_hooks-0.2.9.dist-info → django_bulk_hooks-0.2.93.dist-info}/METADATA +55 -4
- django_bulk_hooks-0.2.93.dist-info/RECORD +27 -0
- django_bulk_hooks/debug_utils.py +0 -145
- django_bulk_hooks-0.2.9.dist-info/RECORD +0 -26
- {django_bulk_hooks-0.2.9.dist-info → django_bulk_hooks-0.2.93.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.2.9.dist-info → django_bulk_hooks-0.2.93.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
django_bulk_hooks/__init__.py,sha256=ZKjEi9Sj3lRr3hcEfknXAr1UXXwERzUCNgMkNXhW0mk,2119
|
|
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=IjRAEQmWIiTqyan3hWlnV3rnjM0CYSVRmXc1xNUWWU8,24085
|
|
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=3rH9TJkdCPF7Vu--0tDaZzJg9Yxcv7yoSF1K1_-0psQ,8048
|
|
12
|
+
django_bulk_hooks/manager.py,sha256=sn4ALCuxRydjIJ91kB81Dhj4PitwytGa4wzxPos4I2Q,4096
|
|
13
|
+
django_bulk_hooks/models.py,sha256=H16AuIiRjkwTD-YDA9S_sMYfAzAFoBgKqiq4TvJuJ9M,3325
|
|
14
|
+
django_bulk_hooks/operations/__init__.py,sha256=BtJYjmRhe_sScivLsniDaZmBkm0ZLvcmzXFKL7QY2Xg,550
|
|
15
|
+
django_bulk_hooks/operations/analyzer.py,sha256=Fw4rjkhpfT8b2A4c7CSMfFRtLUFVimCCz_eGIBtcNiI,15126
|
|
16
|
+
django_bulk_hooks/operations/bulk_executor.py,sha256=FEhC8IsjvPcTXMMNvxc3w3CB1c49mKqQ-Jq02QY5yLM,28263
|
|
17
|
+
django_bulk_hooks/operations/coordinator.py,sha256=3n9bKpcn3_X-zos0tYX6JWS77JleeYMVawZu2DZ1LC4,34973
|
|
18
|
+
django_bulk_hooks/operations/field_utils.py,sha256=EM7y3Vs_4zn-ejgHee6MaenYEhL5txN13kB5cqFHIN0,14109
|
|
19
|
+
django_bulk_hooks/operations/mti_handler.py,sha256=00djtjfZ0rrOfiEii8TS1aBarC0qDpCBsFfWGrljvsc,26946
|
|
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=tPIkNESb47fTIpTrR6xUtc-k3gCFR15W0Xt2-HmvlJo,6811
|
|
23
|
+
django_bulk_hooks/registry.py,sha256=4HxP1mVK2z4VzvlohbEw2359wM21UJZJYagJJ1komM0,7947
|
|
24
|
+
django_bulk_hooks-0.2.93.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
25
|
+
django_bulk_hooks-0.2.93.dist-info/METADATA,sha256=ewuQ9Igpa9y-NNo3UFbmPtu2lDRFO1cUndjdQQD3FR4,10555
|
|
26
|
+
django_bulk_hooks-0.2.93.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
27
|
+
django_bulk_hooks-0.2.93.dist-info/RECORD,,
|
django_bulk_hooks/debug_utils.py
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Debug utilities for tracking N+1 queries and database performance.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import logging
|
|
6
|
-
import time
|
|
7
|
-
from functools import wraps
|
|
8
|
-
from django.db import connection
|
|
9
|
-
from django.conf import settings
|
|
10
|
-
|
|
11
|
-
logger = logging.getLogger(__name__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def track_queries(func):
|
|
15
|
-
"""
|
|
16
|
-
Decorator to track database queries during function execution.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
@wraps(func)
|
|
20
|
-
def wrapper(*args, **kwargs):
|
|
21
|
-
# Reset query count
|
|
22
|
-
initial_queries = len(connection.queries)
|
|
23
|
-
initial_time = time.time()
|
|
24
|
-
|
|
25
|
-
logger.debug(
|
|
26
|
-
f"QUERY DEBUG: Starting {func.__name__} - initial query count: {initial_queries}"
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
try:
|
|
30
|
-
result = func(*args, **kwargs)
|
|
31
|
-
|
|
32
|
-
final_queries = len(connection.queries)
|
|
33
|
-
final_time = time.time()
|
|
34
|
-
query_count = final_queries - initial_queries
|
|
35
|
-
duration = final_time - initial_time
|
|
36
|
-
|
|
37
|
-
logger.debug(
|
|
38
|
-
f"QUERY DEBUG: Completed {func.__name__} - queries executed: {query_count}, duration: {duration:.4f}s"
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
# Log all queries executed during this function
|
|
42
|
-
if query_count > 0:
|
|
43
|
-
logger.debug(f"QUERY DEBUG: Queries executed in {func.__name__}:")
|
|
44
|
-
for i, query in enumerate(connection.queries[initial_queries:], 1):
|
|
45
|
-
logger.debug(
|
|
46
|
-
f"QUERY DEBUG: {i}. {query['sql'][:100]}... (time: {query['time']})"
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
return result
|
|
50
|
-
|
|
51
|
-
except Exception as e:
|
|
52
|
-
final_queries = len(connection.queries)
|
|
53
|
-
query_count = final_queries - initial_queries
|
|
54
|
-
logger.debug(
|
|
55
|
-
f"QUERY DEBUG: Exception in {func.__name__} - queries executed: {query_count}"
|
|
56
|
-
)
|
|
57
|
-
raise
|
|
58
|
-
|
|
59
|
-
return wrapper
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def log_query_count(context=""):
|
|
63
|
-
"""
|
|
64
|
-
Log the current query count with optional context.
|
|
65
|
-
"""
|
|
66
|
-
query_count = len(connection.queries)
|
|
67
|
-
logger.debug(f"QUERY DEBUG: Query count at {context}: {query_count}")
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def log_recent_queries(count=5, context=""):
|
|
71
|
-
"""
|
|
72
|
-
Log the most recent database queries.
|
|
73
|
-
"""
|
|
74
|
-
recent_queries = connection.queries[-count:] if connection.queries else []
|
|
75
|
-
logger.debug(f"QUERY DEBUG: Recent {len(recent_queries)} queries at {context}:")
|
|
76
|
-
for i, query in enumerate(recent_queries, 1):
|
|
77
|
-
logger.debug(
|
|
78
|
-
f"QUERY DEBUG: {i}. {query['sql'][:100]}... (time: {query['time']})"
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
class QueryTracker:
|
|
83
|
-
"""
|
|
84
|
-
Context manager for tracking database queries.
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
def __init__(self, context_name="QueryTracker"):
|
|
88
|
-
self.context_name = context_name
|
|
89
|
-
self.initial_queries = 0
|
|
90
|
-
self.start_time = 0
|
|
91
|
-
|
|
92
|
-
def __enter__(self):
|
|
93
|
-
self.initial_queries = len(connection.queries)
|
|
94
|
-
self.start_time = time.time()
|
|
95
|
-
logger.debug(
|
|
96
|
-
f"QUERY DEBUG: Starting {self.context_name} - initial query count: {self.initial_queries}"
|
|
97
|
-
)
|
|
98
|
-
return self
|
|
99
|
-
|
|
100
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
101
|
-
final_queries = len(connection.queries)
|
|
102
|
-
final_time = time.time()
|
|
103
|
-
query_count = final_queries - self.initial_queries
|
|
104
|
-
duration = final_time - self.start_time
|
|
105
|
-
|
|
106
|
-
logger.debug(
|
|
107
|
-
f"QUERY DEBUG: Completed {self.context_name} - queries executed: {query_count}, duration: {duration:.4f}s"
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
if query_count > 0:
|
|
111
|
-
logger.debug(f"QUERY DEBUG: Queries executed in {self.context_name}:")
|
|
112
|
-
for i, query in enumerate(connection.queries[self.initial_queries :], 1):
|
|
113
|
-
logger.debug(
|
|
114
|
-
f"QUERY DEBUG: {i}. {query['sql'][:100]}... (time: {query['time']})"
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
return False # Don't suppress exceptions
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def enable_django_query_logging():
|
|
121
|
-
"""
|
|
122
|
-
Enable Django's built-in query logging.
|
|
123
|
-
"""
|
|
124
|
-
if not settings.DEBUG:
|
|
125
|
-
logger.warning("Django query logging can only be enabled in DEBUG mode")
|
|
126
|
-
return
|
|
127
|
-
|
|
128
|
-
# Enable query logging
|
|
129
|
-
settings.LOGGING = {
|
|
130
|
-
"version": 1,
|
|
131
|
-
"disable_existing_loggers": False,
|
|
132
|
-
"handlers": {
|
|
133
|
-
"console": {
|
|
134
|
-
"class": "logging.StreamHandler",
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
"loggers": {
|
|
138
|
-
"django.db.backends": {
|
|
139
|
-
"level": "DEBUG",
|
|
140
|
-
"handlers": ["console"],
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
logger.info("Django query logging enabled")
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
django_bulk_hooks/__init__.py,sha256=4QlWY5rqR9o2ddrNB-ypM4s1GtNJ1ZvL2ABhybaPpio,1823
|
|
2
|
-
django_bulk_hooks/changeset.py,sha256=WALeiWDcjOBNdCKeidVKOPKAySKj9ZOvUJ-kWaVZYhM,7444
|
|
3
|
-
django_bulk_hooks/conditions.py,sha256=qtGjToKXC8FPUPK31Mib-GMzc9GSdrH90M2pT3CIsh8,8111
|
|
4
|
-
django_bulk_hooks/constants.py,sha256=PxpEETaO6gdENcTPoXS586lerGKVP3nmjpDvOkmhYxI,509
|
|
5
|
-
django_bulk_hooks/context.py,sha256=mqaC5-yESDTA5ruI7fuXlt8qSgKuOFp0mjq7h1-4HdQ,1926
|
|
6
|
-
django_bulk_hooks/debug_utils.py,sha256=6T32E_Pms6gbCl94A55fJAe_ynFsK_CJBTaPcsG8tik,4578
|
|
7
|
-
django_bulk_hooks/decorators.py,sha256=B1mzXjVx9XWB8kwvJ97ZvBsgnVcpvtQWBpDHytVRtYo,9611
|
|
8
|
-
django_bulk_hooks/dispatcher.py,sha256=L5_hSqENuKXDftJOdMetfjdZkiakUgkheqU8HpWKaOI,8214
|
|
9
|
-
django_bulk_hooks/enums.py,sha256=Zo8_tJzuzZ2IKfVc7gZ-0tWPT8q1QhqZbAyoh9ZVJbs,381
|
|
10
|
-
django_bulk_hooks/factory.py,sha256=JmjQiJPfAnytXrO6r6qOadX5yX0-sfpbZ9V8nwX3MAg,20013
|
|
11
|
-
django_bulk_hooks/handler.py,sha256=2-k0GPWGSQ6acfvV0qJgDH8aa0z51DqdpX5vSJ6Uawk,4759
|
|
12
|
-
django_bulk_hooks/helpers.py,sha256=Yopvl588VbKOi2kHEsQcEcI5jw5jiNA2MuF6Ce1VP0c,3174
|
|
13
|
-
django_bulk_hooks/manager.py,sha256=3mFzB0ZzHHeXWdKGObZD_H0NlskHJc8uYBF69KKdAXU,4068
|
|
14
|
-
django_bulk_hooks/models.py,sha256=62tn5wL55EjJVOsZofMluhEJB8bH7CzBvH0vd214_RY,2570
|
|
15
|
-
django_bulk_hooks/operations/__init__.py,sha256=5L5NnwiFw8Yn5WO6-38eGdCYBkA0URpwyDcAdeYfc5w,550
|
|
16
|
-
django_bulk_hooks/operations/analyzer.py,sha256=wmlO5RnITmo7JPFHpERObpAts_5TfHWMjwP1RQss7lM,11753
|
|
17
|
-
django_bulk_hooks/operations/bulk_executor.py,sha256=7VJgeTFcMQ9ZELvCV6WR6udUPJNL6Kf-w9iEva6pIPA,18271
|
|
18
|
-
django_bulk_hooks/operations/coordinator.py,sha256=XH84Vl8pLVOWXzpUuTNf6bX6Zm0__no02TFfr6DW6Jg,16599
|
|
19
|
-
django_bulk_hooks/operations/mti_handler.py,sha256=eIH-tImMqcWR5lLQr6Ca-HeVYta-UkXk5X5fcpS885Y,18245
|
|
20
|
-
django_bulk_hooks/operations/mti_plans.py,sha256=fHUYbrUAHq8UXqxgAD43oHdTxOnEkmpxoOD4Qrzfqk8,2878
|
|
21
|
-
django_bulk_hooks/queryset.py,sha256=ody4MXrRREL27Ts2ey1UpS0tb5Dxnw-6kN3unxPQ3zY,5860
|
|
22
|
-
django_bulk_hooks/registry.py,sha256=UPerNhtVz_9tKZqrYSZD2LhjAcs4F6hVUuk8L5oOeHc,8821
|
|
23
|
-
django_bulk_hooks-0.2.9.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
24
|
-
django_bulk_hooks-0.2.9.dist-info/METADATA,sha256=zklF13vbEibe1zzHXzNDrQVFGXorKSbJmpAZcLmL4Pw,9264
|
|
25
|
-
django_bulk_hooks-0.2.9.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
26
|
-
django_bulk_hooks-0.2.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|