sqlobjects 1.0.7__tar.gz → 1.0.8__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.0.7/sqlobjects.egg-info → sqlobjects-1.0.8}/PKG-INFO +1 -1
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/pyproject.toml +1 -1
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/__init__.py +14 -5
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/core.py +99 -34
- sqlobjects-1.0.8/sqlobjects/fields/proxies.py +486 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/relations/__init__.py +2 -15
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/relations/descriptors.py +26 -15
- sqlobjects-1.0.8/sqlobjects/fields/relations/strategies.py +17 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/relations/utils.py +67 -13
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/mixins.py +39 -8
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/model.py +14 -4
- {sqlobjects-1.0.7 → sqlobjects-1.0.8/sqlobjects.egg-info}/PKG-INFO +1 -1
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects.egg-info/SOURCES.txt +1 -1
- sqlobjects-1.0.7/sqlobjects/fields/proxies.py +0 -147
- sqlobjects-1.0.7/sqlobjects/fields/relations/proxies.py +0 -419
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/LICENSE +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/README.md +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/setup.cfg +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/cascade.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/database/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/database/config.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/database/manager.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/exceptions.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/expressions/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/expressions/aggregate.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/expressions/base.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/expressions/function.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/expressions/mixins.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/expressions/scalar.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/expressions/subquery.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/expressions/terminal.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/functions.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/relations/managers.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/relations/prefetch.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/shortcuts.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/types/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/types/base.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/types/comparators.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/types/registry.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/fields/utils.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/internal/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/internal/operations.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/internal/results.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/metadata.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/objects/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/objects/bulk.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/objects/core.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/objects/upsert.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/queries/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/queries/builder.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/queries/dialect.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/queries/executor.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/queryset.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/session.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/signals.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/utils/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/utils/inspect.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/utils/naming.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/utils/pattern.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects/validators.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects.egg-info/dependency_links.txt +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects.egg-info/requires.txt +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/sqlobjects.egg-info/top_level.txt +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.8}/tests/test_config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlobjects
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
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>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
from .core import Column, ColumnAttribute, column
|
|
1
|
+
from .core import Column, ColumnAttribute, Related, column
|
|
2
2
|
from .functions import computed, foreign_key, identity
|
|
3
|
-
from .proxies import
|
|
3
|
+
from .proxies import (
|
|
4
|
+
# Backward compatibility aliases
|
|
5
|
+
DeferredObject,
|
|
6
|
+
ManyToManyRelation,
|
|
7
|
+
OneToManyRelation,
|
|
8
|
+
RelatedObject,
|
|
9
|
+
)
|
|
4
10
|
from .relations import M2MTable, relationship
|
|
5
11
|
from .shortcuts import (
|
|
6
12
|
ArrayColumn,
|
|
@@ -25,6 +31,7 @@ __all__ = [
|
|
|
25
31
|
# Core field system
|
|
26
32
|
"Column",
|
|
27
33
|
"ColumnAttribute",
|
|
34
|
+
"Related",
|
|
28
35
|
"column",
|
|
29
36
|
# Shortcut field classes
|
|
30
37
|
"StringColumn",
|
|
@@ -48,9 +55,11 @@ __all__ = [
|
|
|
48
55
|
# Relationship system
|
|
49
56
|
"M2MTable",
|
|
50
57
|
"relationship",
|
|
51
|
-
#
|
|
52
|
-
"
|
|
53
|
-
"
|
|
58
|
+
# Public proxy interfaces
|
|
59
|
+
"DeferredObject",
|
|
60
|
+
"RelatedObject",
|
|
61
|
+
"OneToManyRelation",
|
|
62
|
+
"ManyToManyRelation",
|
|
54
63
|
# Utility functions
|
|
55
64
|
"extract_field_metadata",
|
|
56
65
|
"get_deferred_fields",
|
|
@@ -1,21 +1,112 @@
|
|
|
1
1
|
"""Core field classes for SQLObjects"""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
-
from typing import Any, Generic, TypeVar, Union, cast, get_args, get_origin, overload
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar, Union, cast, get_args, get_origin, overload
|
|
5
5
|
|
|
6
6
|
from sqlalchemy import Column as CoreColumn
|
|
7
7
|
from sqlalchemy import ForeignKey
|
|
8
8
|
from sqlalchemy.sql.elements import ColumnElement
|
|
9
9
|
|
|
10
|
+
from sqlobjects.fields.proxies import RelatedCollection, RelatedObject
|
|
11
|
+
|
|
10
12
|
from ..cascade import OnDelete
|
|
11
13
|
from ..expressions.mixins import ColumnAttributeFunctionMixin
|
|
12
14
|
from .types import create_type_instance
|
|
13
15
|
|
|
14
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
15
21
|
T = TypeVar("T")
|
|
16
22
|
NullableT = TypeVar("NullableT")
|
|
17
23
|
|
|
18
24
|
|
|
25
|
+
class Related(Generic[T]):
|
|
26
|
+
"""Relationship field container - returns appropriate relationship proxy.
|
|
27
|
+
|
|
28
|
+
This class serves as a type container for relationship fields, providing
|
|
29
|
+
clear type hints while delegating actual behavior to RelationshipDescriptor.
|
|
30
|
+
|
|
31
|
+
Type Parameters:
|
|
32
|
+
T: The related model type (single object or list)
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
>>> class User(ObjectModel):
|
|
36
|
+
... posts: Related[list["Post"]] = relationship("Post")
|
|
37
|
+
... profile: Related["Profile"] = relationship("Profile", uselist=False)
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(self, **params):
|
|
41
|
+
"""Initialize relationship field container.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
**params: Relationship configuration parameters
|
|
45
|
+
"""
|
|
46
|
+
self._params = params
|
|
47
|
+
self._is_relationship = True
|
|
48
|
+
self._relationship_descriptor = None
|
|
49
|
+
self.name = None
|
|
50
|
+
|
|
51
|
+
def __set_name__(self, owner, name):
|
|
52
|
+
"""Set field name and create relationship descriptor.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
owner: The model class that owns this field
|
|
56
|
+
name: The field name
|
|
57
|
+
"""
|
|
58
|
+
self.name = name
|
|
59
|
+
self._setup_relationship(owner, name)
|
|
60
|
+
|
|
61
|
+
def _setup_relationship(self, owner, name):
|
|
62
|
+
"""Set up relationship field descriptor.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
owner: The model class that owns this field
|
|
66
|
+
name: The field name
|
|
67
|
+
"""
|
|
68
|
+
from .relations.descriptors import RelationshipDescriptor
|
|
69
|
+
|
|
70
|
+
relationship_property = self._params.get("relationship_property")
|
|
71
|
+
if relationship_property:
|
|
72
|
+
# Set M2M definition if provided
|
|
73
|
+
m2m_def = self._params.get("m2m_definition")
|
|
74
|
+
if m2m_def:
|
|
75
|
+
relationship_property.m2m_definition = m2m_def
|
|
76
|
+
relationship_property.is_many_to_many = True
|
|
77
|
+
|
|
78
|
+
self._relationship_descriptor = RelationshipDescriptor(relationship_property)
|
|
79
|
+
self._relationship_descriptor.__set_name__(owner, name)
|
|
80
|
+
|
|
81
|
+
@overload
|
|
82
|
+
def __get__(self, instance: None, owner: type) -> "Related[T]": ...
|
|
83
|
+
|
|
84
|
+
@overload
|
|
85
|
+
def __get__(self: "Related[list[Any]]", instance: Any, owner: type) -> "RelatedCollection[Any]": ...
|
|
86
|
+
|
|
87
|
+
@overload
|
|
88
|
+
def __get__(self, instance: Any, owner: type) -> "RelatedObject[T]": ...
|
|
89
|
+
|
|
90
|
+
def __get__(self, instance, owner) -> "Related[T] | RelatedCollection[Any] | RelatedObject[T] | None":
|
|
91
|
+
"""Fallback descriptor - should not be called in normal usage.
|
|
92
|
+
|
|
93
|
+
ModelProcessor metaclass extracts RelationshipDescriptor and replaces
|
|
94
|
+
this Related instance, so this method is only called if setup fails.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
instance: Model instance or None for class access
|
|
98
|
+
owner: The model class
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
RelationshipDescriptor or None as fallback
|
|
102
|
+
"""
|
|
103
|
+
if self._relationship_descriptor:
|
|
104
|
+
return self._relationship_descriptor.__get__(instance, owner)
|
|
105
|
+
if instance is None:
|
|
106
|
+
return self
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
|
|
19
110
|
class Column(Generic[T]):
|
|
20
111
|
"""Field descriptor for parameter collection and ColumnAttribute creation.
|
|
21
112
|
|
|
@@ -56,11 +147,10 @@ class Column(Generic[T]):
|
|
|
56
147
|
self._private_name = None
|
|
57
148
|
|
|
58
149
|
def __set_name__(self, owner, name):
|
|
59
|
-
"""Set field name and initialize
|
|
150
|
+
"""Set field name and initialize column descriptor.
|
|
60
151
|
|
|
61
152
|
Called automatically by Python when the field is assigned to a class.
|
|
62
|
-
Creates
|
|
63
|
-
descriptor for relationship fields.
|
|
153
|
+
Creates ColumnAttribute for database fields.
|
|
64
154
|
|
|
65
155
|
Args:
|
|
66
156
|
owner: The model class that owns this field
|
|
@@ -68,25 +158,7 @@ class Column(Generic[T]):
|
|
|
68
158
|
"""
|
|
69
159
|
self.name = name
|
|
70
160
|
self._private_name = f"_{name}"
|
|
71
|
-
|
|
72
|
-
if self._is_relationship:
|
|
73
|
-
self._setup_relationship(owner, name)
|
|
74
|
-
else:
|
|
75
|
-
self._setup_column(owner, name)
|
|
76
|
-
|
|
77
|
-
def _setup_relationship(self, owner, name):
|
|
78
|
-
"""Set up relationship field descriptor.
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
owner: The model class that owns this field
|
|
82
|
-
name: The field name
|
|
83
|
-
"""
|
|
84
|
-
from .relations.descriptors import RelationshipDescriptor
|
|
85
|
-
|
|
86
|
-
relationship_property = self._params.get("relationship_property")
|
|
87
|
-
if relationship_property:
|
|
88
|
-
self._relationship_descriptor = RelationshipDescriptor(relationship_property)
|
|
89
|
-
self._relationship_descriptor.__set_name__(owner, name)
|
|
161
|
+
self._setup_column(owner, name)
|
|
90
162
|
|
|
91
163
|
def _setup_column(self, owner, name):
|
|
92
164
|
"""Set up database column field.
|
|
@@ -197,9 +269,6 @@ class Column(Generic[T]):
|
|
|
197
269
|
Returns:
|
|
198
270
|
ColumnAttribute when accessed on class, field value when accessed on instance
|
|
199
271
|
"""
|
|
200
|
-
if self._is_relationship and self._relationship_descriptor:
|
|
201
|
-
return self._relationship_descriptor.__get__(instance, owner)
|
|
202
|
-
|
|
203
272
|
if instance is None:
|
|
204
273
|
return self._column_attribute
|
|
205
274
|
else:
|
|
@@ -221,14 +290,10 @@ class Column(Generic[T]):
|
|
|
221
290
|
Raises:
|
|
222
291
|
AttributeError: If trying to set value on class rather than instance
|
|
223
292
|
"""
|
|
224
|
-
if
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if instance is None:
|
|
229
|
-
raise AttributeError("Cannot set attribute on class")
|
|
230
|
-
private_name = self._private_name or f"_{self.name}"
|
|
231
|
-
setattr(instance, private_name, value)
|
|
293
|
+
if instance is None:
|
|
294
|
+
raise AttributeError("Cannot set attribute on class")
|
|
295
|
+
private_name = self._private_name or f"_{self.name}"
|
|
296
|
+
setattr(instance, private_name, value)
|
|
232
297
|
|
|
233
298
|
|
|
234
299
|
class ColumnAttribute(ColumnAttributeFunctionMixin, Generic[T]):
|