sqlobjects 1.4.0__tar.gz → 1.5.0__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.
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/CHANGELOG.md +6 -0
- {sqlobjects-1.4.0/sqlobjects.egg-info → sqlobjects-1.5.0}/PKG-INFO +1 -1
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/pyproject.toml +1 -1
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/cascade.py +37 -2
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/model.py +9 -2
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/queryset.py +3 -2
- {sqlobjects-1.4.0 → sqlobjects-1.5.0/sqlobjects.egg-info}/PKG-INFO +1 -1
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/LICENSE +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/README.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/docs/rules/01-database-session-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/docs/rules/02-model-definition-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/docs/rules/03-query-operations-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/docs/rules/04-crud-operations-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/docs/rules/05-relationships-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/docs/rules/06-validation-signals-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/docs/rules/07-performance-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/docs/rules/README.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/setup.cfg +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/_install_rules.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/contrib/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/contrib/asgi.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/contrib/fastapi.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/database/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/database/config.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/database/manager.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/exceptions.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/aggregate.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/base.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/cte.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/explain.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/function.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/mixins.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/scalar.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/subquery.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/terminal.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/expressions/window.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/core.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/functions.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/proxies.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/relations/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/relations/descriptors.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/relations/managers.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/relations/prefetch.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/relations/strategies.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/relations/utils.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/shortcuts.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/types/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/types/base.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/types/comparators.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/types/registry.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/fields/utils.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/internal/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/internal/operations.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/internal/results.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/metadata.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/mixins.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/objects/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/objects/bulk.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/objects/core.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/objects/upsert.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/queries/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/queries/builder.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/queries/dialect.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/queries/executor.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/session.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/signals.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/utils/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/utils/inspect.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/utils/naming.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/utils/pattern.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects/validators.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects.egg-info/SOURCES.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects.egg-info/dependency_links.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects.egg-info/entry_points.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects.egg-info/requires.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/sqlobjects.egg-info/top_level.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.5.0}/tests/test_config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlobjects
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Django-style async ORM library based on SQLAlchemy with chainable queries, Q objects, and relationship loading
|
|
5
5
|
Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
6
6
|
Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
@@ -28,6 +28,7 @@ __all__ = [
|
|
|
28
28
|
"normalize_onupdate",
|
|
29
29
|
"normalize_cascade",
|
|
30
30
|
"has_cascade_delete_relations",
|
|
31
|
+
"has_delete_signals",
|
|
31
32
|
]
|
|
32
33
|
|
|
33
34
|
|
|
@@ -130,6 +131,30 @@ def has_cascade_delete_relations(model_class) -> bool:
|
|
|
130
131
|
return False
|
|
131
132
|
|
|
132
133
|
|
|
134
|
+
def has_delete_signals(model_class) -> bool:
|
|
135
|
+
"""Check if model class has delete signal handlers defined.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
model_class: Model class to check
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
True if model has before_delete/after_delete handlers, False otherwise
|
|
142
|
+
"""
|
|
143
|
+
from .signals import SignalMixin
|
|
144
|
+
|
|
145
|
+
if not issubclass(model_class, SignalMixin):
|
|
146
|
+
return False
|
|
147
|
+
|
|
148
|
+
for method_name in ("before_delete", "after_delete"):
|
|
149
|
+
method = getattr(model_class, method_name, None)
|
|
150
|
+
if method is None:
|
|
151
|
+
continue
|
|
152
|
+
# Must be defined on the model itself, not inherited from SignalMixin
|
|
153
|
+
if method_name in model_class.__dict__:
|
|
154
|
+
return True
|
|
155
|
+
return False
|
|
156
|
+
|
|
157
|
+
|
|
133
158
|
def normalize_cascade(cascade: CascadeType) -> str:
|
|
134
159
|
"""Normalize cascade parameter to SQLAlchemy string format."""
|
|
135
160
|
if cascade is None:
|
|
@@ -344,7 +369,7 @@ class CascadeExecutor:
|
|
|
344
369
|
return instance
|
|
345
370
|
|
|
346
371
|
async def execute_delete_operation(
|
|
347
|
-
self, target, cascade_strategy: str = "
|
|
372
|
+
self, target, cascade_strategy: str = "auto", session: "AsyncSession | None" = None
|
|
348
373
|
) -> int:
|
|
349
374
|
"""Execute delete operation with cascade handling."""
|
|
350
375
|
if session is None:
|
|
@@ -355,7 +380,8 @@ class CascadeExecutor:
|
|
|
355
380
|
return await self._execute_queryset_delete(target, cascade_strategy, session)
|
|
356
381
|
|
|
357
382
|
# Handle single instance deletion
|
|
358
|
-
|
|
383
|
+
if has_cascade_delete_relations(target.__class__):
|
|
384
|
+
await self._delete_related_objects(target, session)
|
|
359
385
|
await target._delete_internal(session=session) # noqa
|
|
360
386
|
return 1
|
|
361
387
|
|
|
@@ -478,6 +504,15 @@ class CascadeExecutor:
|
|
|
478
504
|
|
|
479
505
|
async def _execute_queryset_delete(self, queryset, cascade_strategy: str, session: "AsyncSession") -> int:
|
|
480
506
|
"""Execute QuerySet delete with different cascade strategies."""
|
|
507
|
+
if cascade_strategy == "auto":
|
|
508
|
+
model_class = queryset._model_class
|
|
509
|
+
if has_delete_signals(model_class):
|
|
510
|
+
cascade_strategy = "full"
|
|
511
|
+
elif has_cascade_delete_relations(model_class):
|
|
512
|
+
cascade_strategy = "fast"
|
|
513
|
+
else:
|
|
514
|
+
cascade_strategy = "none"
|
|
515
|
+
|
|
481
516
|
if cascade_strategy == "full":
|
|
482
517
|
return await self._delete_with_full_cascade(queryset, session)
|
|
483
518
|
elif cascade_strategy == "fast":
|
|
@@ -278,11 +278,14 @@ class ModelMixin(DataConversionMixin, SignalMixin):
|
|
|
278
278
|
return await self._save_internal(validate=validate, session=session)
|
|
279
279
|
|
|
280
280
|
@emit_signals(Operation.DELETE)
|
|
281
|
-
async def delete(self, cascade: bool =
|
|
281
|
+
async def delete(self, cascade: bool | None = None):
|
|
282
282
|
"""Delete this model instance from the database with cascade support.
|
|
283
283
|
|
|
284
284
|
Args:
|
|
285
|
-
cascade: Whether to handle cascade deletion
|
|
285
|
+
cascade: Whether to handle cascade deletion.
|
|
286
|
+
None (default): auto-detect based on model relationships
|
|
287
|
+
True: force cascade handling
|
|
288
|
+
False: skip cascade, direct delete
|
|
286
289
|
|
|
287
290
|
Raises:
|
|
288
291
|
PrimaryKeyError: If instance has no primary key values or delete fails
|
|
@@ -292,6 +295,10 @@ class ModelMixin(DataConversionMixin, SignalMixin):
|
|
|
292
295
|
|
|
293
296
|
session = self.get_session()
|
|
294
297
|
|
|
298
|
+
# Auto-detect cascade need when not explicitly specified
|
|
299
|
+
if cascade is None:
|
|
300
|
+
cascade = self._has_on_delete_relations()
|
|
301
|
+
|
|
295
302
|
# Use cascade executor for cascade operations
|
|
296
303
|
if cascade:
|
|
297
304
|
executor = CascadeExecutor()
|
|
@@ -1221,12 +1221,13 @@ class QuerySet(Generic[T]):
|
|
|
1221
1221
|
return await executor.execute_update_operation(self, values)
|
|
1222
1222
|
|
|
1223
1223
|
@emit_signals(Operation.DELETE, is_bulk=True)
|
|
1224
|
-
async def delete(self, cascade: str = "
|
|
1224
|
+
async def delete(self, cascade: str = "auto") -> int:
|
|
1225
1225
|
"""Perform bulk delete on objects matching query conditions.
|
|
1226
1226
|
|
|
1227
1227
|
Args:
|
|
1228
1228
|
cascade: Cascade deletion strategy
|
|
1229
|
-
- "
|
|
1229
|
+
- "auto" (default): Automatically choose based on model relationships
|
|
1230
|
+
- "full": Complete cascade deletion with full ORM functionality
|
|
1230
1231
|
- "fast": Fast cascade deletion with minimal ORM processing
|
|
1231
1232
|
- "none": Direct SQL deletion without ORM cascade processing
|
|
1232
1233
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlobjects
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Django-style async ORM library based on SQLAlchemy with chainable queries, Q objects, and relationship loading
|
|
5
5
|
Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
6
6
|
Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|