sqlobjects 1.0.7__tar.gz → 1.0.9__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.9}/PKG-INFO +1 -1
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/pyproject.toml +1 -1
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/database/manager.py +54 -26
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/__init__.py +14 -5
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/core.py +99 -34
- sqlobjects-1.0.9/sqlobjects/fields/proxies.py +486 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/relations/__init__.py +2 -15
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/relations/descriptors.py +26 -15
- sqlobjects-1.0.9/sqlobjects/fields/relations/strategies.py +17 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/relations/utils.py +67 -13
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/mixins.py +39 -8
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/model.py +14 -4
- {sqlobjects-1.0.7 → sqlobjects-1.0.9/sqlobjects.egg-info}/PKG-INFO +1 -1
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/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.9}/LICENSE +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/README.md +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/setup.cfg +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/cascade.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/database/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/database/config.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/exceptions.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/expressions/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/expressions/aggregate.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/expressions/base.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/expressions/function.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/expressions/mixins.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/expressions/scalar.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/expressions/subquery.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/expressions/terminal.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/functions.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/relations/managers.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/relations/prefetch.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/shortcuts.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/types/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/types/base.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/types/comparators.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/types/registry.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/fields/utils.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/internal/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/internal/operations.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/internal/results.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/metadata.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/objects/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/objects/bulk.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/objects/core.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/objects/upsert.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/queries/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/queries/builder.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/queries/dialect.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/queries/executor.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/queryset.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/session.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/signals.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/utils/__init__.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/utils/inspect.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/utils/naming.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/utils/pattern.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects/validators.py +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects.egg-info/dependency_links.txt +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects.egg-info/requires.txt +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/sqlobjects.egg-info/top_level.txt +0 -0
- {sqlobjects-1.0.7 → sqlobjects-1.0.9}/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.9
|
|
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>
|
|
@@ -174,37 +174,49 @@ class Database:
|
|
|
174
174
|
|
|
175
175
|
return event.listens_for(target, event_name)
|
|
176
176
|
|
|
177
|
-
async def create_tables(self, base_class) -> None:
|
|
178
|
-
"""Create
|
|
177
|
+
async def create_tables(self, base_class, tables: list[type] | None = None) -> None:
|
|
178
|
+
"""Create tables defined in the model registry of SQLObjects base class
|
|
179
179
|
|
|
180
|
-
Creates
|
|
180
|
+
Creates tables, indexes, and constraints defined in the provided
|
|
181
181
|
SQLAlchemy metadata object using the database engine.
|
|
182
182
|
|
|
183
183
|
Args:
|
|
184
184
|
base_class: SQLObjects base class containing model registry
|
|
185
|
+
tables: List of model classes to create tables for, creates all if None
|
|
185
186
|
|
|
186
187
|
Examples:
|
|
187
188
|
>>> from sqlobjects.base import ObjectModel
|
|
188
|
-
>>> await db.create_tables(ObjectModel)
|
|
189
|
+
>>> await db.create_tables(ObjectModel) # Create all tables
|
|
190
|
+
>>> await db.create_tables(ObjectModel, [User, Post]) # Create specific tables
|
|
189
191
|
"""
|
|
190
192
|
async with self.engine.begin() as conn:
|
|
191
|
-
|
|
193
|
+
if tables is None:
|
|
194
|
+
await conn.run_sync(base_class.__registry__.create_all)
|
|
195
|
+
else:
|
|
196
|
+
table_objects = [model.__table__ for model in tables]
|
|
197
|
+
await conn.run_sync(base_class.__registry__.create_all, tables=table_objects)
|
|
192
198
|
|
|
193
|
-
async def drop_tables(self, base_class) -> None:
|
|
194
|
-
"""Drop
|
|
199
|
+
async def drop_tables(self, base_class, tables: list[type] | None = None) -> None:
|
|
200
|
+
"""Drop tables defined in the model registry of SQLObjects base class
|
|
195
201
|
|
|
196
|
-
Drops
|
|
202
|
+
Drops tables, indexes, and constraints defined in the provided
|
|
197
203
|
SQLAlchemy metadata object from the database.
|
|
198
204
|
|
|
199
205
|
Args:
|
|
200
206
|
base_class: SQLObjects base class containing model registry
|
|
207
|
+
tables: List of model classes to drop tables for, drops all if None
|
|
201
208
|
|
|
202
209
|
Examples:
|
|
203
210
|
>>> from sqlobjects.base import ObjectModel
|
|
204
|
-
>>> await db.drop_tables(ObjectModel)
|
|
211
|
+
>>> await db.drop_tables(ObjectModel) # Drop all tables
|
|
212
|
+
>>> await db.drop_tables(ObjectModel, [User, Post]) # Drop specific tables
|
|
205
213
|
"""
|
|
206
214
|
async with self.engine.begin() as conn:
|
|
207
|
-
|
|
215
|
+
if tables is None:
|
|
216
|
+
await conn.run_sync(base_class.__registry__.drop_all)
|
|
217
|
+
else:
|
|
218
|
+
table_objects = [model.__table__ for model in tables]
|
|
219
|
+
await conn.run_sync(base_class.__registry__.drop_all, tables=table_objects)
|
|
208
220
|
|
|
209
221
|
async def disconnect(self) -> None:
|
|
210
222
|
"""Disconnect database and clean up resources
|
|
@@ -286,15 +298,16 @@ class _DatabaseManager:
|
|
|
286
298
|
return database.engine
|
|
287
299
|
|
|
288
300
|
@classmethod
|
|
289
|
-
async def create_tables(cls, base_class, db_name: str | None = None) -> None:
|
|
290
|
-
"""Create
|
|
301
|
+
async def create_tables(cls, base_class, db_name: str | None = None, tables: list[type] | None = None) -> None:
|
|
302
|
+
"""Create tables defined in the base class registry
|
|
291
303
|
|
|
292
|
-
Creates
|
|
304
|
+
Creates tables, indexes, and constraints for models registered
|
|
293
305
|
in the base class registry using the specified database connection.
|
|
294
306
|
|
|
295
307
|
Args:
|
|
296
308
|
base_class: SQLObjects base class containing model registry
|
|
297
309
|
db_name: Database name to use, uses default database if None
|
|
310
|
+
tables: List of model classes to create tables for, creates all if None
|
|
298
311
|
|
|
299
312
|
Raises:
|
|
300
313
|
ValueError: When specified database does not exist
|
|
@@ -303,20 +316,22 @@ class _DatabaseManager:
|
|
|
303
316
|
>>> from sqlobjects.base import ObjectModel
|
|
304
317
|
>>> await DatabaseManager.create_tables(ObjectModel)
|
|
305
318
|
>>> await DatabaseManager.create_tables(ObjectModel, "analytics")
|
|
319
|
+
>>> await DatabaseManager.create_tables(ObjectModel, tables=[User, Post])
|
|
306
320
|
"""
|
|
307
321
|
database = cls.get_database(db_name)
|
|
308
|
-
await database.create_tables(base_class)
|
|
322
|
+
await database.create_tables(base_class, tables)
|
|
309
323
|
|
|
310
324
|
@classmethod
|
|
311
|
-
async def drop_tables(cls, base_class, db_name: str | None = None) -> None:
|
|
312
|
-
"""Drop
|
|
325
|
+
async def drop_tables(cls, base_class, db_name: str | None = None, tables: list[type] | None = None) -> None:
|
|
326
|
+
"""Drop tables defined in the base class registry
|
|
313
327
|
|
|
314
|
-
Drops
|
|
328
|
+
Drops tables, indexes, and constraints for models registered
|
|
315
329
|
in the base class registry from the specified database connection.
|
|
316
330
|
|
|
317
331
|
Args:
|
|
318
332
|
base_class: SQLObjects base class containing model registry
|
|
319
333
|
db_name: Database name to use, uses default database if None
|
|
334
|
+
tables: List of model classes to drop tables for, drops all if None
|
|
320
335
|
|
|
321
336
|
Raises:
|
|
322
337
|
ValueError: When specified database does not exist
|
|
@@ -325,9 +340,10 @@ class _DatabaseManager:
|
|
|
325
340
|
>>> from sqlobjects.base import ObjectModel
|
|
326
341
|
>>> await DatabaseManager.drop_tables(ObjectModel)
|
|
327
342
|
>>> await DatabaseManager.drop_tables(ObjectModel, "analytics")
|
|
343
|
+
>>> await DatabaseManager.drop_tables(ObjectModel, tables=[User, Post])
|
|
328
344
|
"""
|
|
329
345
|
database = cls.get_database(db_name)
|
|
330
|
-
await database.drop_tables(base_class)
|
|
346
|
+
await database.drop_tables(base_class, tables)
|
|
331
347
|
|
|
332
348
|
@classmethod
|
|
333
349
|
async def close(cls, db_name: str | None = None, auto_default: bool = False) -> None:
|
|
@@ -476,36 +492,48 @@ async def init_dbs(
|
|
|
476
492
|
return tuple(db_instances)
|
|
477
493
|
|
|
478
494
|
|
|
479
|
-
async def create_tables(base_class, db_name: str | None = None) -> None:
|
|
480
|
-
"""Create
|
|
495
|
+
async def create_tables(base_class, db_name: str | None = None, tables: list[type] | None = None) -> None:
|
|
496
|
+
"""Create tables defined in the base class registry
|
|
481
497
|
|
|
482
|
-
Creates
|
|
498
|
+
Creates tables, indexes, and constraints for models registered
|
|
483
499
|
in the base class registry using the specified database connection.
|
|
484
500
|
|
|
485
501
|
Args:
|
|
486
502
|
base_class: SQLObjects base class containing model registry
|
|
487
503
|
db_name: Name of the database, uses default if None
|
|
504
|
+
tables: List of model classes to create tables for, creates all if None
|
|
488
505
|
|
|
489
506
|
Raises:
|
|
490
507
|
ValueError: When specified database does not exist
|
|
508
|
+
|
|
509
|
+
Examples:
|
|
510
|
+
>>> from sqlobjects.model import ObjectModel
|
|
511
|
+
>>> await create_tables(ObjectModel) # Create all tables
|
|
512
|
+
>>> await create_tables(ObjectModel, tables=[User, Post]) # Create specific tables
|
|
491
513
|
"""
|
|
492
|
-
await _DatabaseManager.create_tables(base_class, db_name)
|
|
514
|
+
await _DatabaseManager.create_tables(base_class, db_name, tables)
|
|
493
515
|
|
|
494
516
|
|
|
495
|
-
async def drop_tables(base_class, db_name: str | None = None) -> None:
|
|
496
|
-
"""Drop
|
|
517
|
+
async def drop_tables(base_class, db_name: str | None = None, tables: list[type] | None = None) -> None:
|
|
518
|
+
"""Drop tables defined in the base class registry
|
|
497
519
|
|
|
498
|
-
Drops
|
|
520
|
+
Drops tables, indexes, and constraints for models registered
|
|
499
521
|
in the base class registry from the specified database connection.
|
|
500
522
|
|
|
501
523
|
Args:
|
|
502
524
|
base_class: SQLObjects base class containing model registry
|
|
503
525
|
db_name: Name of the database, uses default if None
|
|
526
|
+
tables: List of model classes to drop tables for, drops all if None
|
|
504
527
|
|
|
505
528
|
Raises:
|
|
506
529
|
ValueError: When specified database does not exist
|
|
530
|
+
|
|
531
|
+
Examples:
|
|
532
|
+
>>> from sqlobjects.model import ObjectModel
|
|
533
|
+
>>> await drop_tables(ObjectModel) # Drop all tables
|
|
534
|
+
>>> await drop_tables(ObjectModel, tables=[User, Post]) # Drop specific tables
|
|
507
535
|
"""
|
|
508
|
-
await _DatabaseManager.drop_tables(base_class, db_name)
|
|
536
|
+
await _DatabaseManager.drop_tables(base_class, db_name, tables)
|
|
509
537
|
|
|
510
538
|
|
|
511
539
|
async def close_db(db_name: str | None = None, auto_default: bool = False) -> None:
|
|
@@ -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]):
|