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

@@ -55,6 +55,7 @@ class HookQuerySetMixin:
55
55
 
56
56
  @transaction.atomic
57
57
  def update(self, **kwargs):
58
+ logger.debug(f"Entering update method with {len(kwargs)} kwargs")
58
59
  instances = list(self)
59
60
  if not instances:
60
61
  return 0
@@ -70,13 +71,29 @@ class HookQuerySetMixin:
70
71
  originals = [original_map.get(obj.pk) for obj in instances]
71
72
 
72
73
  # Check if any of the update values are Subquery objects
73
- from django.db.models import Subquery
74
- has_subquery = any(
75
- isinstance(value, Subquery)
76
- for value in kwargs.values()
77
- )
74
+ try:
75
+ from django.db.models import Subquery
76
+ logger.debug(f"Successfully imported Subquery from django.db.models")
77
+ except ImportError as e:
78
+ logger.error(f"Failed to import Subquery: {e}")
79
+ raise
80
+
81
+ logger.debug(f"Checking for Subquery objects in {len(kwargs)} kwargs")
82
+
83
+ subquery_detected = []
84
+ for key, value in kwargs.items():
85
+ is_subquery = isinstance(value, Subquery)
86
+ logger.debug(f"Key '{key}': type={type(value).__name__}, is_subquery={is_subquery}")
87
+ if is_subquery:
88
+ subquery_detected.append(key)
89
+
90
+ has_subquery = len(subquery_detected) > 0
91
+ logger.debug(f"Subquery detection result: {has_subquery}, detected keys: {subquery_detected}")
78
92
 
79
93
  # Debug logging for Subquery detection
94
+ logger.debug(f"Update kwargs: {list(kwargs.keys())}")
95
+ logger.debug(f"Update kwargs types: {[(k, type(v).__name__) for k, v in kwargs.items()]}")
96
+
80
97
  if has_subquery:
81
98
  logger.debug(f"Detected Subquery in update: {[k for k, v in kwargs.items() if isinstance(v, Subquery)]}")
82
99
  else:
@@ -84,6 +101,8 @@ class HookQuerySetMixin:
84
101
  for k, v in kwargs.items():
85
102
  if hasattr(v, 'query') and hasattr(v, 'resolve_expression'):
86
103
  logger.warning(f"Potential Subquery-like object detected but not recognized: {k}={type(v).__name__}")
104
+ logger.warning(f"Object attributes: query={hasattr(v, 'query')}, resolve_expression={hasattr(v, 'resolve_expression')}")
105
+ logger.warning(f"Object dir: {[attr for attr in dir(v) if not attr.startswith('_')][:10]}")
87
106
 
88
107
  # Apply field updates to instances
89
108
  # If a per-object value map exists (from bulk_update), prefer it over kwargs
@@ -145,11 +164,24 @@ class HookQuerySetMixin:
145
164
  output_field = field_obj
146
165
  target_name = field_name
147
166
 
148
- when_statements.append(
149
- When(
150
- pk=obj_pk, then=Value(value, output_field=output_field)
167
+ # Special handling for Subquery values in CASE statements
168
+ if isinstance(value, Subquery):
169
+ logger.debug(f"Creating When statement with Subquery for {field_name}")
170
+ # Ensure the Subquery has proper output_field
171
+ if not hasattr(value, 'output_field') or value.output_field is None:
172
+ value.output_field = output_field
173
+ logger.debug(f"Set output_field for Subquery in When statement to {output_field}")
174
+ when_statements.append(
175
+ When(
176
+ pk=obj_pk, then=value
177
+ )
178
+ )
179
+ else:
180
+ when_statements.append(
181
+ When(
182
+ pk=obj_pk, then=Value(value, output_field=output_field)
183
+ )
151
184
  )
152
- )
153
185
 
154
186
  if when_statements:
155
187
  case_statements[target_name] = Case(
@@ -158,11 +190,103 @@ class HookQuerySetMixin:
158
190
 
159
191
  # Merge extra CASE updates into kwargs for DB update
160
192
  if case_statements:
193
+ logger.debug(f"Adding case statements to kwargs: {list(case_statements.keys())}")
194
+ for field_name, case_stmt in case_statements.items():
195
+ logger.debug(f"Case statement for {field_name}: {type(case_stmt).__name__}")
196
+ # Check if the case statement contains Subquery objects
197
+ if hasattr(case_stmt, 'get_source_expressions'):
198
+ source_exprs = case_stmt.get_source_expressions()
199
+ for expr in source_exprs:
200
+ if isinstance(expr, Subquery):
201
+ logger.debug(f"Case statement for {field_name} contains Subquery")
202
+ elif hasattr(expr, 'get_source_expressions'):
203
+ # Check nested expressions (like Value objects)
204
+ nested_exprs = expr.get_source_expressions()
205
+ for nested_expr in nested_exprs:
206
+ if isinstance(nested_expr, Subquery):
207
+ logger.debug(f"Case statement for {field_name} contains nested Subquery")
208
+
161
209
  kwargs = {**kwargs, **case_statements}
162
210
 
163
211
  # Use Django's built-in update logic directly
164
212
  # Call the base QuerySet implementation to avoid recursion
165
- update_count = super().update(**kwargs)
213
+
214
+ # Additional safety check: ensure Subquery objects are properly handled
215
+ # This prevents the "cannot adapt type 'Subquery'" error
216
+ safe_kwargs = {}
217
+ logger.debug(f"Processing {len(kwargs)} kwargs for safety check")
218
+
219
+ for key, value in kwargs.items():
220
+ logger.debug(f"Processing key '{key}' with value type {type(value).__name__}")
221
+
222
+ if isinstance(value, Subquery):
223
+ logger.debug(f"Found Subquery for field {key}")
224
+ # Ensure Subquery has proper output_field
225
+ if not hasattr(value, 'output_field') or value.output_field is None:
226
+ logger.warning(f"Subquery for field {key} missing output_field, attempting to infer")
227
+ # Try to infer from the model field
228
+ try:
229
+ field = model_cls._meta.get_field(key)
230
+ logger.debug(f"Inferred field type: {type(field).__name__}")
231
+ value = value.resolve_expression(None, None)
232
+ value.output_field = field
233
+ logger.debug(f"Set output_field to {field}")
234
+ except Exception as e:
235
+ logger.error(f"Failed to infer output_field for Subquery on {key}: {e}")
236
+ raise
237
+ else:
238
+ logger.debug(f"Subquery for field {key} already has output_field: {value.output_field}")
239
+ safe_kwargs[key] = value
240
+ elif hasattr(value, 'get_source_expressions') and hasattr(value, 'resolve_expression'):
241
+ # Handle Case statements and other complex expressions
242
+ logger.debug(f"Found complex expression for field {key}: {type(value).__name__}")
243
+
244
+ # Check if this expression contains any Subquery objects
245
+ source_expressions = value.get_source_expressions()
246
+ has_nested_subquery = False
247
+
248
+ for expr in source_expressions:
249
+ if isinstance(expr, Subquery):
250
+ has_nested_subquery = True
251
+ logger.debug(f"Found nested Subquery in {type(value).__name__}")
252
+ # Ensure the nested Subquery has proper output_field
253
+ if not hasattr(expr, 'output_field') or expr.output_field is None:
254
+ try:
255
+ field = model_cls._meta.get_field(key)
256
+ expr.output_field = field
257
+ logger.debug(f"Set output_field for nested Subquery to {field}")
258
+ except Exception as e:
259
+ logger.error(f"Failed to set output_field for nested Subquery: {e}")
260
+ raise
261
+
262
+ if has_nested_subquery:
263
+ logger.debug(f"Expression contains Subquery, ensuring proper output_field")
264
+ # Try to resolve the expression to ensure it's properly formatted
265
+ try:
266
+ resolved_value = value.resolve_expression(None, None)
267
+ safe_kwargs[key] = resolved_value
268
+ logger.debug(f"Successfully resolved expression for {key}")
269
+ except Exception as e:
270
+ logger.error(f"Failed to resolve expression for {key}: {e}")
271
+ raise
272
+ else:
273
+ safe_kwargs[key] = value
274
+ else:
275
+ logger.debug(f"Non-Subquery value for field {key}: {type(value).__name__}")
276
+ safe_kwargs[key] = value
277
+
278
+ logger.debug(f"Safe kwargs keys: {list(safe_kwargs.keys())}")
279
+ logger.debug(f"Safe kwargs types: {[(k, type(v).__name__) for k, v in safe_kwargs.items()]}")
280
+
281
+ logger.debug(f"Calling super().update() with {len(safe_kwargs)} kwargs")
282
+ try:
283
+ update_count = super().update(**safe_kwargs)
284
+ logger.debug(f"Super update successful, count: {update_count}")
285
+ except Exception as e:
286
+ logger.error(f"Super update failed: {e}")
287
+ logger.error(f"Exception type: {type(e).__name__}")
288
+ logger.error(f"Safe kwargs that caused failure: {safe_kwargs}")
289
+ raise
166
290
 
167
291
  # If we used Subquery objects, refresh the instances to get computed values
168
292
  if has_subquery and instances:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.239
3
+ Version: 0.1.241
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
@@ -9,9 +9,9 @@ django_bulk_hooks/handler.py,sha256=Bx-W6yyiciKMyy-BRxUt3CmRPCrX9_LhQgU-5LaJTjg,
9
9
  django_bulk_hooks/manager.py,sha256=nfWiwU5-yAoxdnQsUMohxtyCpkV0MBv6X3wmipr9eQY,3697
10
10
  django_bulk_hooks/models.py,sha256=exnXYVKEVbYAXhChCP8VdWTnKCnm9DiTcokEIBee1I0,4350
11
11
  django_bulk_hooks/priority.py,sha256=HG_2D35nga68lBCZmSXTcplXrjFoRgZFRDOy4ROKonY,376
12
- django_bulk_hooks/queryset.py,sha256=38BvCf_FgKMCAOxEoSYMSkNnmpO2bvUqaPcJkf_6gMc,38561
12
+ django_bulk_hooks/queryset.py,sha256=kUmV4izYquYsvtcR3PH8TkY3PBm-Kt8c8B4HO4ck0uo,46280
13
13
  django_bulk_hooks/registry.py,sha256=GRUTGVQEO2sdkC9OaZ9Q3U7mM-3Ix83uTyvrlTtpatw,1317
14
- django_bulk_hooks-0.1.239.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
15
- django_bulk_hooks-0.1.239.dist-info/METADATA,sha256=CDwXkK4tvZenRQrbIHkpYE75r2hZRwI8S8NDzmT5IgI,9061
16
- django_bulk_hooks-0.1.239.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
17
- django_bulk_hooks-0.1.239.dist-info/RECORD,,
14
+ django_bulk_hooks-0.1.241.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
15
+ django_bulk_hooks-0.1.241.dist-info/METADATA,sha256=DUraAu1YHa04565ngESG8QnmmUwrcvrD1-4oqoOnBhY,9061
16
+ django_bulk_hooks-0.1.241.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
17
+ django_bulk_hooks-0.1.241.dist-info/RECORD,,