SQLAlchemy 2.0.47__cp313-cp313t-win_amd64.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.
- sqlalchemy/__init__.py +283 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +184 -0
- sqlalchemy/connectors/asyncio.py +429 -0
- sqlalchemy/connectors/pyodbc.py +250 -0
- sqlalchemy/cyextension/__init__.py +6 -0
- sqlalchemy/cyextension/collections.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/collections.pyx +409 -0
- sqlalchemy/cyextension/immutabledict.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/immutabledict.pxd +8 -0
- sqlalchemy/cyextension/immutabledict.pyx +133 -0
- sqlalchemy/cyextension/processors.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/processors.pyx +68 -0
- sqlalchemy/cyextension/resultproxy.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/resultproxy.pyx +102 -0
- sqlalchemy/cyextension/util.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/util.pyx +90 -0
- sqlalchemy/dialects/__init__.py +62 -0
- sqlalchemy/dialects/_typing.py +30 -0
- sqlalchemy/dialects/mssql/__init__.py +88 -0
- sqlalchemy/dialects/mssql/aioodbc.py +63 -0
- sqlalchemy/dialects/mssql/base.py +4093 -0
- sqlalchemy/dialects/mssql/information_schema.py +285 -0
- sqlalchemy/dialects/mssql/json.py +129 -0
- sqlalchemy/dialects/mssql/provision.py +185 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +760 -0
- sqlalchemy/dialects/mysql/__init__.py +104 -0
- sqlalchemy/dialects/mysql/aiomysql.py +250 -0
- sqlalchemy/dialects/mysql/asyncmy.py +231 -0
- sqlalchemy/dialects/mysql/base.py +3949 -0
- sqlalchemy/dialects/mysql/cymysql.py +106 -0
- sqlalchemy/dialects/mysql/dml.py +225 -0
- sqlalchemy/dialects/mysql/enumerated.py +282 -0
- sqlalchemy/dialects/mysql/expression.py +146 -0
- sqlalchemy/dialects/mysql/json.py +91 -0
- sqlalchemy/dialects/mysql/mariadb.py +72 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +322 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +302 -0
- sqlalchemy/dialects/mysql/mysqldb.py +314 -0
- sqlalchemy/dialects/mysql/provision.py +153 -0
- sqlalchemy/dialects/mysql/pymysql.py +158 -0
- sqlalchemy/dialects/mysql/pyodbc.py +157 -0
- sqlalchemy/dialects/mysql/reflection.py +727 -0
- sqlalchemy/dialects/mysql/reserved_words.py +570 -0
- sqlalchemy/dialects/mysql/types.py +835 -0
- sqlalchemy/dialects/oracle/__init__.py +81 -0
- sqlalchemy/dialects/oracle/base.py +3802 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1555 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/oracledb.py +941 -0
- sqlalchemy/dialects/oracle/provision.py +297 -0
- sqlalchemy/dialects/oracle/types.py +316 -0
- sqlalchemy/dialects/oracle/vector.py +365 -0
- sqlalchemy/dialects/postgresql/__init__.py +167 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +189 -0
- sqlalchemy/dialects/postgresql/array.py +519 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1284 -0
- sqlalchemy/dialects/postgresql/base.py +5378 -0
- sqlalchemy/dialects/postgresql/dml.py +339 -0
- sqlalchemy/dialects/postgresql/ext.py +540 -0
- sqlalchemy/dialects/postgresql/hstore.py +406 -0
- sqlalchemy/dialects/postgresql/json.py +404 -0
- sqlalchemy/dialects/postgresql/named_types.py +524 -0
- sqlalchemy/dialects/postgresql/operators.py +129 -0
- sqlalchemy/dialects/postgresql/pg8000.py +669 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +326 -0
- sqlalchemy/dialects/postgresql/provision.py +183 -0
- sqlalchemy/dialects/postgresql/psycopg.py +862 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +892 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1031 -0
- sqlalchemy/dialects/postgresql/types.py +313 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +482 -0
- sqlalchemy/dialects/sqlite/base.py +3056 -0
- sqlalchemy/dialects/sqlite/dml.py +263 -0
- sqlalchemy/dialects/sqlite/json.py +92 -0
- sqlalchemy/dialects/sqlite/provision.py +229 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +157 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_py_processors.py +136 -0
- sqlalchemy/engine/_py_row.py +128 -0
- sqlalchemy/engine/_py_util.py +74 -0
- sqlalchemy/engine/base.py +3390 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +893 -0
- sqlalchemy/engine/cursor.py +2298 -0
- sqlalchemy/engine/default.py +2394 -0
- sqlalchemy/engine/events.py +965 -0
- sqlalchemy/engine/interfaces.py +3471 -0
- sqlalchemy/engine/mock.py +134 -0
- sqlalchemy/engine/processors.py +61 -0
- sqlalchemy/engine/reflection.py +2102 -0
- sqlalchemy/engine/result.py +2399 -0
- sqlalchemy/engine/row.py +400 -0
- sqlalchemy/engine/strategies.py +16 -0
- sqlalchemy/engine/url.py +924 -0
- sqlalchemy/engine/util.py +167 -0
- sqlalchemy/event/__init__.py +26 -0
- sqlalchemy/event/api.py +220 -0
- sqlalchemy/event/attr.py +676 -0
- sqlalchemy/event/base.py +472 -0
- sqlalchemy/event/legacy.py +258 -0
- sqlalchemy/event/registry.py +390 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +832 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2027 -0
- sqlalchemy/ext/asyncio/__init__.py +25 -0
- sqlalchemy/ext/asyncio/base.py +281 -0
- sqlalchemy/ext/asyncio/engine.py +1471 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +965 -0
- sqlalchemy/ext/asyncio/scoping.py +1599 -0
- sqlalchemy/ext/asyncio/session.py +1947 -0
- sqlalchemy/ext/automap.py +1701 -0
- sqlalchemy/ext/baked.py +570 -0
- sqlalchemy/ext/compiler.py +600 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +564 -0
- sqlalchemy/ext/horizontal_shard.py +478 -0
- sqlalchemy/ext/hybrid.py +1535 -0
- sqlalchemy/ext/indexable.py +364 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1085 -0
- sqlalchemy/ext/mypy/__init__.py +6 -0
- sqlalchemy/ext/mypy/apply.py +324 -0
- sqlalchemy/ext/mypy/decl_class.py +515 -0
- sqlalchemy/ext/mypy/infer.py +590 -0
- sqlalchemy/ext/mypy/names.py +335 -0
- sqlalchemy/ext/mypy/plugin.py +303 -0
- sqlalchemy/ext/mypy/util.py +357 -0
- sqlalchemy/ext/orderinglist.py +439 -0
- sqlalchemy/ext/serializer.py +185 -0
- sqlalchemy/future/__init__.py +16 -0
- sqlalchemy/future/engine.py +15 -0
- sqlalchemy/inspection.py +174 -0
- sqlalchemy/log.py +288 -0
- sqlalchemy/orm/__init__.py +171 -0
- sqlalchemy/orm/_orm_constructors.py +2661 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2845 -0
- sqlalchemy/orm/base.py +971 -0
- sqlalchemy/orm/bulk_persistence.py +2135 -0
- sqlalchemy/orm/clsregistry.py +571 -0
- sqlalchemy/orm/collections.py +1627 -0
- sqlalchemy/orm/context.py +3334 -0
- sqlalchemy/orm/decl_api.py +2004 -0
- sqlalchemy/orm/decl_base.py +2192 -0
- sqlalchemy/orm/dependency.py +1302 -0
- sqlalchemy/orm/descriptor_props.py +1092 -0
- sqlalchemy/orm/dynamic.py +300 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3252 -0
- sqlalchemy/orm/exc.py +237 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +754 -0
- sqlalchemy/orm/interfaces.py +1496 -0
- sqlalchemy/orm/loading.py +1686 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4444 -0
- sqlalchemy/orm/path_registry.py +809 -0
- sqlalchemy/orm/persistence.py +1788 -0
- sqlalchemy/orm/properties.py +935 -0
- sqlalchemy/orm/query.py +3459 -0
- sqlalchemy/orm/relationships.py +3508 -0
- sqlalchemy/orm/scoping.py +2148 -0
- sqlalchemy/orm/session.py +5280 -0
- sqlalchemy/orm/state.py +1168 -0
- sqlalchemy/orm/state_changes.py +196 -0
- sqlalchemy/orm/strategies.py +3470 -0
- sqlalchemy/orm/strategy_options.py +2568 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +796 -0
- sqlalchemy/orm/util.py +2403 -0
- sqlalchemy/orm/writeonly.py +674 -0
- sqlalchemy/pool/__init__.py +44 -0
- sqlalchemy/pool/base.py +1524 -0
- sqlalchemy/pool/events.py +375 -0
- sqlalchemy/pool/impl.py +588 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +69 -0
- sqlalchemy/sql/__init__.py +145 -0
- sqlalchemy/sql/_dml_constructors.py +132 -0
- sqlalchemy/sql/_elements_constructors.py +1872 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_py_util.py +75 -0
- sqlalchemy/sql/_selectable_constructors.py +763 -0
- sqlalchemy/sql/_typing.py +482 -0
- sqlalchemy/sql/annotation.py +587 -0
- sqlalchemy/sql/base.py +2293 -0
- sqlalchemy/sql/cache_key.py +1057 -0
- sqlalchemy/sql/coercions.py +1404 -0
- sqlalchemy/sql/compiler.py +8081 -0
- sqlalchemy/sql/crud.py +1752 -0
- sqlalchemy/sql/ddl.py +1444 -0
- sqlalchemy/sql/default_comparator.py +551 -0
- sqlalchemy/sql/dml.py +1850 -0
- sqlalchemy/sql/elements.py +5589 -0
- sqlalchemy/sql/events.py +458 -0
- sqlalchemy/sql/expression.py +159 -0
- sqlalchemy/sql/functions.py +2158 -0
- sqlalchemy/sql/lambdas.py +1442 -0
- sqlalchemy/sql/naming.py +209 -0
- sqlalchemy/sql/operators.py +2623 -0
- sqlalchemy/sql/roles.py +323 -0
- sqlalchemy/sql/schema.py +6222 -0
- sqlalchemy/sql/selectable.py +7265 -0
- sqlalchemy/sql/sqltypes.py +3930 -0
- sqlalchemy/sql/traversals.py +1024 -0
- sqlalchemy/sql/type_api.py +2368 -0
- sqlalchemy/sql/util.py +1485 -0
- sqlalchemy/sql/visitors.py +1164 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +994 -0
- sqlalchemy/testing/assertsql.py +520 -0
- sqlalchemy/testing/asyncio.py +135 -0
- sqlalchemy/testing/config.py +434 -0
- sqlalchemy/testing/engines.py +483 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +476 -0
- sqlalchemy/testing/fixtures/__init__.py +28 -0
- sqlalchemy/testing/fixtures/base.py +384 -0
- sqlalchemy/testing/fixtures/mypy.py +332 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +482 -0
- sqlalchemy/testing/pickleable.py +155 -0
- sqlalchemy/testing/plugin/__init__.py +6 -0
- sqlalchemy/testing/plugin/bootstrap.py +51 -0
- sqlalchemy/testing/plugin/plugin_base.py +828 -0
- sqlalchemy/testing/plugin/pytestplugin.py +892 -0
- sqlalchemy/testing/profiling.py +329 -0
- sqlalchemy/testing/provision.py +603 -0
- sqlalchemy/testing/requirements.py +1945 -0
- sqlalchemy/testing/schema.py +198 -0
- sqlalchemy/testing/suite/__init__.py +19 -0
- sqlalchemy/testing/suite/test_cte.py +237 -0
- sqlalchemy/testing/suite/test_ddl.py +389 -0
- sqlalchemy/testing/suite/test_deprecations.py +153 -0
- sqlalchemy/testing/suite/test_dialect.py +776 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3557 -0
- sqlalchemy/testing/suite/test_results.py +504 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +2010 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_types.py +2147 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +535 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +74 -0
- sqlalchemy/util/__init__.py +162 -0
- sqlalchemy/util/_collections.py +712 -0
- sqlalchemy/util/_concurrency_py3k.py +288 -0
- sqlalchemy/util/_has_cy.py +40 -0
- sqlalchemy/util/_py_collections.py +541 -0
- sqlalchemy/util/compat.py +421 -0
- sqlalchemy/util/concurrency.py +110 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2203 -0
- sqlalchemy/util/preloaded.py +150 -0
- sqlalchemy/util/queue.py +322 -0
- sqlalchemy/util/tool_support.py +201 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +734 -0
- sqlalchemy-2.0.47.dist-info/METADATA +243 -0
- sqlalchemy-2.0.47.dist-info/RECORD +274 -0
- sqlalchemy-2.0.47.dist-info/WHEEL +5 -0
- sqlalchemy-2.0.47.dist-info/licenses/LICENSE +19 -0
- sqlalchemy-2.0.47.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,935 @@
|
|
|
1
|
+
# orm/properties.py
|
|
2
|
+
# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
|
|
3
|
+
# <see AUTHORS file>
|
|
4
|
+
#
|
|
5
|
+
# This module is part of SQLAlchemy and is released under
|
|
6
|
+
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
|
7
|
+
|
|
8
|
+
"""MapperProperty implementations.
|
|
9
|
+
|
|
10
|
+
This is a private module which defines the behavior of individual ORM-
|
|
11
|
+
mapped attributes.
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import Any
|
|
18
|
+
from typing import cast
|
|
19
|
+
from typing import Dict
|
|
20
|
+
from typing import List
|
|
21
|
+
from typing import Optional
|
|
22
|
+
from typing import Sequence
|
|
23
|
+
from typing import Set
|
|
24
|
+
from typing import Tuple
|
|
25
|
+
from typing import Type
|
|
26
|
+
from typing import TYPE_CHECKING
|
|
27
|
+
from typing import TypeVar
|
|
28
|
+
from typing import Union
|
|
29
|
+
|
|
30
|
+
from . import attributes
|
|
31
|
+
from . import exc as orm_exc
|
|
32
|
+
from . import strategy_options
|
|
33
|
+
from .base import _DeclarativeMapped
|
|
34
|
+
from .base import class_mapper
|
|
35
|
+
from .descriptor_props import CompositeProperty
|
|
36
|
+
from .descriptor_props import ConcreteInheritedProperty
|
|
37
|
+
from .descriptor_props import SynonymProperty
|
|
38
|
+
from .interfaces import _AttributeOptions
|
|
39
|
+
from .interfaces import _DEFAULT_ATTRIBUTE_OPTIONS
|
|
40
|
+
from .interfaces import _IntrospectsAnnotations
|
|
41
|
+
from .interfaces import _MapsColumns
|
|
42
|
+
from .interfaces import MapperProperty
|
|
43
|
+
from .interfaces import PropComparator
|
|
44
|
+
from .interfaces import StrategizedProperty
|
|
45
|
+
from .relationships import RelationshipProperty
|
|
46
|
+
from .util import de_stringify_annotation
|
|
47
|
+
from .. import exc as sa_exc
|
|
48
|
+
from .. import ForeignKey
|
|
49
|
+
from .. import log
|
|
50
|
+
from .. import util
|
|
51
|
+
from ..sql import coercions
|
|
52
|
+
from ..sql import roles
|
|
53
|
+
from ..sql.base import _NoArg
|
|
54
|
+
from ..sql.schema import Column
|
|
55
|
+
from ..sql.schema import SchemaConst
|
|
56
|
+
from ..sql.type_api import TypeEngine
|
|
57
|
+
from ..util.typing import de_optionalize_union_types
|
|
58
|
+
from ..util.typing import get_args
|
|
59
|
+
from ..util.typing import includes_none
|
|
60
|
+
from ..util.typing import is_a_type
|
|
61
|
+
from ..util.typing import is_fwd_ref
|
|
62
|
+
from ..util.typing import is_pep593
|
|
63
|
+
from ..util.typing import is_pep695
|
|
64
|
+
from ..util.typing import Self
|
|
65
|
+
|
|
66
|
+
if TYPE_CHECKING:
|
|
67
|
+
from ._typing import _IdentityKeyType
|
|
68
|
+
from ._typing import _InstanceDict
|
|
69
|
+
from ._typing import _ORMColumnExprArgument
|
|
70
|
+
from ._typing import _RegistryType
|
|
71
|
+
from .base import Mapped
|
|
72
|
+
from .decl_base import _ClassScanMapperConfig
|
|
73
|
+
from .mapper import Mapper
|
|
74
|
+
from .session import Session
|
|
75
|
+
from .state import _InstallLoaderCallableProto
|
|
76
|
+
from .state import InstanceState
|
|
77
|
+
from ..sql._typing import _InfoType
|
|
78
|
+
from ..sql.elements import ColumnElement
|
|
79
|
+
from ..sql.elements import NamedColumn
|
|
80
|
+
from ..sql.operators import OperatorType
|
|
81
|
+
from ..util.typing import _AnnotationScanType
|
|
82
|
+
from ..util.typing import RODescriptorReference
|
|
83
|
+
|
|
84
|
+
_T = TypeVar("_T", bound=Any)
|
|
85
|
+
_PT = TypeVar("_PT", bound=Any)
|
|
86
|
+
_NC = TypeVar("_NC", bound="NamedColumn[Any]")
|
|
87
|
+
|
|
88
|
+
__all__ = [
|
|
89
|
+
"ColumnProperty",
|
|
90
|
+
"CompositeProperty",
|
|
91
|
+
"ConcreteInheritedProperty",
|
|
92
|
+
"RelationshipProperty",
|
|
93
|
+
"SynonymProperty",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@log.class_logger
|
|
98
|
+
class ColumnProperty(
|
|
99
|
+
_MapsColumns[_T],
|
|
100
|
+
StrategizedProperty[_T],
|
|
101
|
+
_IntrospectsAnnotations,
|
|
102
|
+
log.Identified,
|
|
103
|
+
):
|
|
104
|
+
"""Describes an object attribute that corresponds to a table column
|
|
105
|
+
or other column expression.
|
|
106
|
+
|
|
107
|
+
Public constructor is the :func:`_orm.column_property` function.
|
|
108
|
+
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
strategy_wildcard_key = strategy_options._COLUMN_TOKEN
|
|
112
|
+
inherit_cache = True
|
|
113
|
+
""":meta private:"""
|
|
114
|
+
|
|
115
|
+
_links_to_entity = False
|
|
116
|
+
|
|
117
|
+
columns: List[NamedColumn[Any]]
|
|
118
|
+
|
|
119
|
+
_is_polymorphic_discriminator: bool
|
|
120
|
+
|
|
121
|
+
_mapped_by_synonym: Optional[str]
|
|
122
|
+
|
|
123
|
+
comparator_factory: Type[PropComparator[_T]]
|
|
124
|
+
|
|
125
|
+
__slots__ = (
|
|
126
|
+
"columns",
|
|
127
|
+
"group",
|
|
128
|
+
"deferred",
|
|
129
|
+
"instrument",
|
|
130
|
+
"comparator_factory",
|
|
131
|
+
"active_history",
|
|
132
|
+
"expire_on_flush",
|
|
133
|
+
"_creation_order",
|
|
134
|
+
"_is_polymorphic_discriminator",
|
|
135
|
+
"_mapped_by_synonym",
|
|
136
|
+
"_deferred_column_loader",
|
|
137
|
+
"_raise_column_loader",
|
|
138
|
+
"_renders_in_subqueries",
|
|
139
|
+
"raiseload",
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def __init__(
|
|
143
|
+
self,
|
|
144
|
+
column: _ORMColumnExprArgument[_T],
|
|
145
|
+
*additional_columns: _ORMColumnExprArgument[Any],
|
|
146
|
+
attribute_options: Optional[_AttributeOptions] = None,
|
|
147
|
+
group: Optional[str] = None,
|
|
148
|
+
deferred: bool = False,
|
|
149
|
+
raiseload: bool = False,
|
|
150
|
+
comparator_factory: Optional[Type[PropComparator[_T]]] = None,
|
|
151
|
+
active_history: bool = False,
|
|
152
|
+
expire_on_flush: bool = True,
|
|
153
|
+
info: Optional[_InfoType] = None,
|
|
154
|
+
doc: Optional[str] = None,
|
|
155
|
+
_instrument: bool = True,
|
|
156
|
+
_assume_readonly_dc_attributes: bool = False,
|
|
157
|
+
):
|
|
158
|
+
super().__init__(
|
|
159
|
+
attribute_options=attribute_options,
|
|
160
|
+
_assume_readonly_dc_attributes=_assume_readonly_dc_attributes,
|
|
161
|
+
)
|
|
162
|
+
columns = (column,) + additional_columns
|
|
163
|
+
self.columns = [
|
|
164
|
+
coercions.expect(roles.LabeledColumnExprRole, c) for c in columns
|
|
165
|
+
]
|
|
166
|
+
self.group = group
|
|
167
|
+
self.deferred = deferred
|
|
168
|
+
self.raiseload = raiseload
|
|
169
|
+
self.instrument = _instrument
|
|
170
|
+
self.comparator_factory = (
|
|
171
|
+
comparator_factory
|
|
172
|
+
if comparator_factory is not None
|
|
173
|
+
else self.__class__.Comparator
|
|
174
|
+
)
|
|
175
|
+
self.active_history = active_history
|
|
176
|
+
self.expire_on_flush = expire_on_flush
|
|
177
|
+
|
|
178
|
+
if info is not None:
|
|
179
|
+
self.info.update(info)
|
|
180
|
+
|
|
181
|
+
if doc is not None:
|
|
182
|
+
self.doc = doc
|
|
183
|
+
else:
|
|
184
|
+
for col in reversed(self.columns):
|
|
185
|
+
doc = getattr(col, "doc", None)
|
|
186
|
+
if doc is not None:
|
|
187
|
+
self.doc = doc
|
|
188
|
+
break
|
|
189
|
+
else:
|
|
190
|
+
self.doc = None
|
|
191
|
+
|
|
192
|
+
util.set_creation_order(self)
|
|
193
|
+
|
|
194
|
+
self.strategy_key = (
|
|
195
|
+
("deferred", self.deferred),
|
|
196
|
+
("instrument", self.instrument),
|
|
197
|
+
)
|
|
198
|
+
if self.raiseload:
|
|
199
|
+
self.strategy_key += (("raiseload", True),)
|
|
200
|
+
|
|
201
|
+
def declarative_scan(
|
|
202
|
+
self,
|
|
203
|
+
decl_scan: _ClassScanMapperConfig,
|
|
204
|
+
registry: _RegistryType,
|
|
205
|
+
cls: Type[Any],
|
|
206
|
+
originating_module: Optional[str],
|
|
207
|
+
key: str,
|
|
208
|
+
mapped_container: Optional[Type[Mapped[Any]]],
|
|
209
|
+
annotation: Optional[_AnnotationScanType],
|
|
210
|
+
extracted_mapped_annotation: Optional[_AnnotationScanType],
|
|
211
|
+
is_dataclass_field: bool,
|
|
212
|
+
) -> None:
|
|
213
|
+
column = self.columns[0]
|
|
214
|
+
if column.key is None:
|
|
215
|
+
column.key = key
|
|
216
|
+
if column.name is None:
|
|
217
|
+
column.name = key
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def mapper_property_to_assign(self) -> Optional[MapperProperty[_T]]:
|
|
221
|
+
return self
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def columns_to_assign(self) -> List[Tuple[Column[Any], int]]:
|
|
225
|
+
# mypy doesn't care about the isinstance here
|
|
226
|
+
return [
|
|
227
|
+
(c, 0) # type: ignore
|
|
228
|
+
for c in self.columns
|
|
229
|
+
if isinstance(c, Column) and c.table is None
|
|
230
|
+
]
|
|
231
|
+
|
|
232
|
+
def _memoized_attr__renders_in_subqueries(self) -> bool:
|
|
233
|
+
if ("query_expression", True) in self.strategy_key:
|
|
234
|
+
return self.strategy._have_default_expression # type: ignore
|
|
235
|
+
|
|
236
|
+
return ("deferred", True) not in self.strategy_key or (
|
|
237
|
+
self not in self.parent._readonly_props
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
@util.preload_module("sqlalchemy.orm.state", "sqlalchemy.orm.strategies")
|
|
241
|
+
def _memoized_attr__deferred_column_loader(
|
|
242
|
+
self,
|
|
243
|
+
) -> _InstallLoaderCallableProto[Any]:
|
|
244
|
+
state = util.preloaded.orm_state
|
|
245
|
+
strategies = util.preloaded.orm_strategies
|
|
246
|
+
return state.InstanceState._instance_level_callable_processor(
|
|
247
|
+
self.parent.class_manager,
|
|
248
|
+
strategies.LoadDeferredColumns(self.key),
|
|
249
|
+
self.key,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
@util.preload_module("sqlalchemy.orm.state", "sqlalchemy.orm.strategies")
|
|
253
|
+
def _memoized_attr__raise_column_loader(
|
|
254
|
+
self,
|
|
255
|
+
) -> _InstallLoaderCallableProto[Any]:
|
|
256
|
+
state = util.preloaded.orm_state
|
|
257
|
+
strategies = util.preloaded.orm_strategies
|
|
258
|
+
return state.InstanceState._instance_level_callable_processor(
|
|
259
|
+
self.parent.class_manager,
|
|
260
|
+
strategies.LoadDeferredColumns(self.key, True),
|
|
261
|
+
self.key,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def __clause_element__(self) -> roles.ColumnsClauseRole:
|
|
265
|
+
"""Allow the ColumnProperty to work in expression before it is turned
|
|
266
|
+
into an instrumented attribute.
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
return self.expression
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def expression(self) -> roles.ColumnsClauseRole:
|
|
273
|
+
"""Return the primary column or expression for this ColumnProperty.
|
|
274
|
+
|
|
275
|
+
E.g.::
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class File(Base):
|
|
279
|
+
# ...
|
|
280
|
+
|
|
281
|
+
name = Column(String(64))
|
|
282
|
+
extension = Column(String(8))
|
|
283
|
+
filename = column_property(name + "." + extension)
|
|
284
|
+
path = column_property("C:/" + filename.expression)
|
|
285
|
+
|
|
286
|
+
.. seealso::
|
|
287
|
+
|
|
288
|
+
:ref:`mapper_column_property_sql_expressions_composed`
|
|
289
|
+
|
|
290
|
+
"""
|
|
291
|
+
return self.columns[0]
|
|
292
|
+
|
|
293
|
+
def instrument_class(self, mapper: Mapper[Any]) -> None:
|
|
294
|
+
if not self.instrument:
|
|
295
|
+
return
|
|
296
|
+
|
|
297
|
+
attributes.register_descriptor(
|
|
298
|
+
mapper.class_,
|
|
299
|
+
self.key,
|
|
300
|
+
comparator=self.comparator_factory(self, mapper),
|
|
301
|
+
parententity=mapper,
|
|
302
|
+
doc=self.doc,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
def do_init(self) -> None:
|
|
306
|
+
super().do_init()
|
|
307
|
+
|
|
308
|
+
if len(self.columns) > 1 and set(self.parent.primary_key).issuperset(
|
|
309
|
+
self.columns
|
|
310
|
+
):
|
|
311
|
+
util.warn(
|
|
312
|
+
(
|
|
313
|
+
"On mapper %s, primary key column '%s' is being combined "
|
|
314
|
+
"with distinct primary key column '%s' in attribute '%s'. "
|
|
315
|
+
"Use explicit properties to give each column its own "
|
|
316
|
+
"mapped attribute name."
|
|
317
|
+
)
|
|
318
|
+
% (self.parent, self.columns[1], self.columns[0], self.key)
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
def copy(self) -> ColumnProperty[_T]:
|
|
322
|
+
return ColumnProperty(
|
|
323
|
+
*self.columns,
|
|
324
|
+
deferred=self.deferred,
|
|
325
|
+
group=self.group,
|
|
326
|
+
active_history=self.active_history,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
def merge(
|
|
330
|
+
self,
|
|
331
|
+
session: Session,
|
|
332
|
+
source_state: InstanceState[Any],
|
|
333
|
+
source_dict: _InstanceDict,
|
|
334
|
+
dest_state: InstanceState[Any],
|
|
335
|
+
dest_dict: _InstanceDict,
|
|
336
|
+
load: bool,
|
|
337
|
+
_recursive: Dict[Any, object],
|
|
338
|
+
_resolve_conflict_map: Dict[_IdentityKeyType[Any], object],
|
|
339
|
+
) -> None:
|
|
340
|
+
if not self.instrument:
|
|
341
|
+
return
|
|
342
|
+
elif self.key in source_dict:
|
|
343
|
+
value = source_dict[self.key]
|
|
344
|
+
|
|
345
|
+
if not load:
|
|
346
|
+
dest_dict[self.key] = value
|
|
347
|
+
else:
|
|
348
|
+
impl = dest_state.get_impl(self.key)
|
|
349
|
+
impl.set(dest_state, dest_dict, value, None)
|
|
350
|
+
elif dest_state.has_identity and self.key not in dest_dict:
|
|
351
|
+
dest_state._expire_attributes(
|
|
352
|
+
dest_dict, [self.key], no_loader=True
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
class Comparator(util.MemoizedSlots, PropComparator[_PT]):
|
|
356
|
+
"""Produce boolean, comparison, and other operators for
|
|
357
|
+
:class:`.ColumnProperty` attributes.
|
|
358
|
+
|
|
359
|
+
See the documentation for :class:`.PropComparator` for a brief
|
|
360
|
+
overview.
|
|
361
|
+
|
|
362
|
+
.. seealso::
|
|
363
|
+
|
|
364
|
+
:class:`.PropComparator`
|
|
365
|
+
|
|
366
|
+
:class:`.ColumnOperators`
|
|
367
|
+
|
|
368
|
+
:ref:`types_operators`
|
|
369
|
+
|
|
370
|
+
:attr:`.TypeEngine.comparator_factory`
|
|
371
|
+
|
|
372
|
+
"""
|
|
373
|
+
|
|
374
|
+
if not TYPE_CHECKING:
|
|
375
|
+
# prevent pylance from being clever about slots
|
|
376
|
+
__slots__ = "__clause_element__", "info", "expressions"
|
|
377
|
+
|
|
378
|
+
prop: RODescriptorReference[ColumnProperty[_PT]]
|
|
379
|
+
|
|
380
|
+
expressions: Sequence[NamedColumn[Any]]
|
|
381
|
+
"""The full sequence of columns referenced by this
|
|
382
|
+
attribute, adjusted for any aliasing in progress.
|
|
383
|
+
|
|
384
|
+
.. versionadded:: 1.3.17
|
|
385
|
+
|
|
386
|
+
.. seealso::
|
|
387
|
+
|
|
388
|
+
:ref:`maptojoin` - usage example
|
|
389
|
+
"""
|
|
390
|
+
|
|
391
|
+
def _orm_annotate_column(self, column: _NC) -> _NC:
|
|
392
|
+
"""annotate and possibly adapt a column to be returned
|
|
393
|
+
as the mapped-attribute exposed version of the column.
|
|
394
|
+
|
|
395
|
+
The column in this context needs to act as much like the
|
|
396
|
+
column in an ORM mapped context as possible, so includes
|
|
397
|
+
annotations to give hints to various ORM functions as to
|
|
398
|
+
the source entity of this column. It also adapts it
|
|
399
|
+
to the mapper's with_polymorphic selectable if one is
|
|
400
|
+
present.
|
|
401
|
+
|
|
402
|
+
"""
|
|
403
|
+
|
|
404
|
+
pe = self._parententity
|
|
405
|
+
annotations: Dict[str, Any] = {
|
|
406
|
+
"entity_namespace": pe,
|
|
407
|
+
"parententity": pe,
|
|
408
|
+
"parentmapper": pe,
|
|
409
|
+
"proxy_key": self.prop.key,
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
col = column
|
|
413
|
+
|
|
414
|
+
# for a mapper with polymorphic_on and an adapter, return
|
|
415
|
+
# the column against the polymorphic selectable.
|
|
416
|
+
# see also orm.util._orm_downgrade_polymorphic_columns
|
|
417
|
+
# for the reverse operation.
|
|
418
|
+
if self._parentmapper._polymorphic_adapter:
|
|
419
|
+
mapper_local_col = col
|
|
420
|
+
col = self._parentmapper._polymorphic_adapter.traverse(col)
|
|
421
|
+
|
|
422
|
+
# this is a clue to the ORM Query etc. that this column
|
|
423
|
+
# was adapted to the mapper's polymorphic_adapter. the
|
|
424
|
+
# ORM uses this hint to know which column its adapting.
|
|
425
|
+
annotations["adapt_column"] = mapper_local_col
|
|
426
|
+
|
|
427
|
+
return col._annotate(annotations)._set_propagate_attrs(
|
|
428
|
+
{"compile_state_plugin": "orm", "plugin_subject": pe}
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
if TYPE_CHECKING:
|
|
432
|
+
|
|
433
|
+
def __clause_element__(self) -> NamedColumn[_PT]: ...
|
|
434
|
+
|
|
435
|
+
def _memoized_method___clause_element__(
|
|
436
|
+
self,
|
|
437
|
+
) -> NamedColumn[_PT]:
|
|
438
|
+
if self.adapter:
|
|
439
|
+
return self.adapter(self.prop.columns[0], self.prop.key)
|
|
440
|
+
else:
|
|
441
|
+
return self._orm_annotate_column(self.prop.columns[0])
|
|
442
|
+
|
|
443
|
+
def _memoized_attr_info(self) -> _InfoType:
|
|
444
|
+
"""The .info dictionary for this attribute."""
|
|
445
|
+
|
|
446
|
+
ce = self.__clause_element__()
|
|
447
|
+
try:
|
|
448
|
+
return ce.info # type: ignore
|
|
449
|
+
except AttributeError:
|
|
450
|
+
return self.prop.info
|
|
451
|
+
|
|
452
|
+
def _memoized_attr_expressions(self) -> Sequence[NamedColumn[Any]]:
|
|
453
|
+
"""The full sequence of columns referenced by this
|
|
454
|
+
attribute, adjusted for any aliasing in progress.
|
|
455
|
+
|
|
456
|
+
.. versionadded:: 1.3.17
|
|
457
|
+
|
|
458
|
+
"""
|
|
459
|
+
if self.adapter:
|
|
460
|
+
return [
|
|
461
|
+
self.adapter(col, self.prop.key)
|
|
462
|
+
for col in self.prop.columns
|
|
463
|
+
]
|
|
464
|
+
else:
|
|
465
|
+
return [
|
|
466
|
+
self._orm_annotate_column(col) for col in self.prop.columns
|
|
467
|
+
]
|
|
468
|
+
|
|
469
|
+
def _fallback_getattr(self, key: str) -> Any:
|
|
470
|
+
"""proxy attribute access down to the mapped column.
|
|
471
|
+
|
|
472
|
+
this allows user-defined comparison methods to be accessed.
|
|
473
|
+
"""
|
|
474
|
+
return getattr(self.__clause_element__(), key)
|
|
475
|
+
|
|
476
|
+
def operate(
|
|
477
|
+
self, op: OperatorType, *other: Any, **kwargs: Any
|
|
478
|
+
) -> ColumnElement[Any]:
|
|
479
|
+
return op(self.__clause_element__(), *other, **kwargs) # type: ignore[no-any-return] # noqa: E501
|
|
480
|
+
|
|
481
|
+
def reverse_operate(
|
|
482
|
+
self, op: OperatorType, other: Any, **kwargs: Any
|
|
483
|
+
) -> ColumnElement[Any]:
|
|
484
|
+
col = self.__clause_element__()
|
|
485
|
+
return op(col._bind_param(op, other), col, **kwargs) # type: ignore[no-any-return] # noqa: E501
|
|
486
|
+
|
|
487
|
+
def __str__(self) -> str:
|
|
488
|
+
if not self.parent or not self.key:
|
|
489
|
+
return object.__repr__(self)
|
|
490
|
+
return str(self.parent.class_.__name__) + "." + self.key
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
class MappedSQLExpression(ColumnProperty[_T], _DeclarativeMapped[_T]):
|
|
494
|
+
"""Declarative front-end for the :class:`.ColumnProperty` class.
|
|
495
|
+
|
|
496
|
+
Public constructor is the :func:`_orm.column_property` function.
|
|
497
|
+
|
|
498
|
+
.. versionchanged:: 2.0 Added :class:`_orm.MappedSQLExpression` as
|
|
499
|
+
a Declarative compatible subclass for :class:`_orm.ColumnProperty`.
|
|
500
|
+
|
|
501
|
+
.. seealso::
|
|
502
|
+
|
|
503
|
+
:class:`.MappedColumn`
|
|
504
|
+
|
|
505
|
+
"""
|
|
506
|
+
|
|
507
|
+
inherit_cache = True
|
|
508
|
+
""":meta private:"""
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
class MappedColumn(
|
|
512
|
+
_IntrospectsAnnotations,
|
|
513
|
+
_MapsColumns[_T],
|
|
514
|
+
_DeclarativeMapped[_T],
|
|
515
|
+
):
|
|
516
|
+
"""Maps a single :class:`_schema.Column` on a class.
|
|
517
|
+
|
|
518
|
+
:class:`_orm.MappedColumn` is a specialization of the
|
|
519
|
+
:class:`_orm.ColumnProperty` class and is oriented towards declarative
|
|
520
|
+
configuration.
|
|
521
|
+
|
|
522
|
+
To construct :class:`_orm.MappedColumn` objects, use the
|
|
523
|
+
:func:`_orm.mapped_column` constructor function.
|
|
524
|
+
|
|
525
|
+
.. versionadded:: 2.0
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
"""
|
|
529
|
+
|
|
530
|
+
__slots__ = (
|
|
531
|
+
"column",
|
|
532
|
+
"_creation_order",
|
|
533
|
+
"_sort_order",
|
|
534
|
+
"foreign_keys",
|
|
535
|
+
"_has_nullable",
|
|
536
|
+
"_has_insert_default",
|
|
537
|
+
"deferred",
|
|
538
|
+
"deferred_group",
|
|
539
|
+
"deferred_raiseload",
|
|
540
|
+
"active_history",
|
|
541
|
+
"_attribute_options",
|
|
542
|
+
"_has_dataclass_arguments",
|
|
543
|
+
"_use_existing_column",
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
deferred: Union[_NoArg, bool]
|
|
547
|
+
deferred_raiseload: bool
|
|
548
|
+
deferred_group: Optional[str]
|
|
549
|
+
|
|
550
|
+
column: Column[_T]
|
|
551
|
+
foreign_keys: Optional[Set[ForeignKey]]
|
|
552
|
+
_attribute_options: _AttributeOptions
|
|
553
|
+
|
|
554
|
+
def __init__(self, *arg: Any, **kw: Any):
|
|
555
|
+
self._attribute_options = attr_opts = kw.pop(
|
|
556
|
+
"attribute_options", _DEFAULT_ATTRIBUTE_OPTIONS
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
self._use_existing_column = kw.pop("use_existing_column", False)
|
|
560
|
+
|
|
561
|
+
self._has_dataclass_arguments = (
|
|
562
|
+
attr_opts is not None
|
|
563
|
+
and attr_opts != _DEFAULT_ATTRIBUTE_OPTIONS
|
|
564
|
+
and any(
|
|
565
|
+
attr_opts[i] is not _NoArg.NO_ARG
|
|
566
|
+
for i, attr in enumerate(attr_opts._fields)
|
|
567
|
+
if attr != "dataclasses_default"
|
|
568
|
+
)
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
insert_default = kw.pop("insert_default", _NoArg.NO_ARG)
|
|
572
|
+
self._has_insert_default = insert_default is not _NoArg.NO_ARG
|
|
573
|
+
|
|
574
|
+
if self._has_insert_default:
|
|
575
|
+
kw["default"] = insert_default
|
|
576
|
+
elif attr_opts.dataclasses_default is not _NoArg.NO_ARG:
|
|
577
|
+
kw["default"] = attr_opts.dataclasses_default
|
|
578
|
+
|
|
579
|
+
self.deferred_group = kw.pop("deferred_group", None)
|
|
580
|
+
self.deferred_raiseload = kw.pop("deferred_raiseload", None)
|
|
581
|
+
self.deferred = kw.pop("deferred", _NoArg.NO_ARG)
|
|
582
|
+
self.active_history = kw.pop("active_history", False)
|
|
583
|
+
|
|
584
|
+
self._sort_order = kw.pop("sort_order", _NoArg.NO_ARG)
|
|
585
|
+
self.column = cast("Column[_T]", Column(*arg, **kw))
|
|
586
|
+
self.foreign_keys = self.column.foreign_keys
|
|
587
|
+
self._has_nullable = "nullable" in kw and kw.get("nullable") not in (
|
|
588
|
+
None,
|
|
589
|
+
SchemaConst.NULL_UNSPECIFIED,
|
|
590
|
+
)
|
|
591
|
+
util.set_creation_order(self)
|
|
592
|
+
|
|
593
|
+
def _copy(self, **kw: Any) -> Self:
|
|
594
|
+
new = self.__class__.__new__(self.__class__)
|
|
595
|
+
new.column = self.column._copy(**kw)
|
|
596
|
+
new.deferred = self.deferred
|
|
597
|
+
new.deferred_group = self.deferred_group
|
|
598
|
+
new.deferred_raiseload = self.deferred_raiseload
|
|
599
|
+
new.foreign_keys = new.column.foreign_keys
|
|
600
|
+
new.active_history = self.active_history
|
|
601
|
+
new._has_nullable = self._has_nullable
|
|
602
|
+
new._attribute_options = self._attribute_options
|
|
603
|
+
new._has_insert_default = self._has_insert_default
|
|
604
|
+
new._has_dataclass_arguments = self._has_dataclass_arguments
|
|
605
|
+
new._use_existing_column = self._use_existing_column
|
|
606
|
+
new._sort_order = self._sort_order
|
|
607
|
+
util.set_creation_order(new)
|
|
608
|
+
return new
|
|
609
|
+
|
|
610
|
+
@property
|
|
611
|
+
def name(self) -> str:
|
|
612
|
+
return self.column.name
|
|
613
|
+
|
|
614
|
+
@property
|
|
615
|
+
def mapper_property_to_assign(self) -> Optional[MapperProperty[_T]]:
|
|
616
|
+
effective_deferred = self.deferred
|
|
617
|
+
if effective_deferred is _NoArg.NO_ARG:
|
|
618
|
+
effective_deferred = bool(
|
|
619
|
+
self.deferred_group or self.deferred_raiseload
|
|
620
|
+
)
|
|
621
|
+
|
|
622
|
+
if effective_deferred or self.active_history:
|
|
623
|
+
return ColumnProperty(
|
|
624
|
+
self.column,
|
|
625
|
+
deferred=effective_deferred,
|
|
626
|
+
group=self.deferred_group,
|
|
627
|
+
raiseload=self.deferred_raiseload,
|
|
628
|
+
attribute_options=self._attribute_options,
|
|
629
|
+
active_history=self.active_history,
|
|
630
|
+
)
|
|
631
|
+
else:
|
|
632
|
+
return None
|
|
633
|
+
|
|
634
|
+
@property
|
|
635
|
+
def columns_to_assign(self) -> List[Tuple[Column[Any], int]]:
|
|
636
|
+
return [
|
|
637
|
+
(
|
|
638
|
+
self.column,
|
|
639
|
+
(
|
|
640
|
+
self._sort_order
|
|
641
|
+
if self._sort_order is not _NoArg.NO_ARG
|
|
642
|
+
else 0
|
|
643
|
+
),
|
|
644
|
+
)
|
|
645
|
+
]
|
|
646
|
+
|
|
647
|
+
def __clause_element__(self) -> Column[_T]:
|
|
648
|
+
return self.column
|
|
649
|
+
|
|
650
|
+
def operate(
|
|
651
|
+
self, op: OperatorType, *other: Any, **kwargs: Any
|
|
652
|
+
) -> ColumnElement[Any]:
|
|
653
|
+
return op(self.__clause_element__(), *other, **kwargs) # type: ignore[no-any-return] # noqa: E501
|
|
654
|
+
|
|
655
|
+
def reverse_operate(
|
|
656
|
+
self, op: OperatorType, other: Any, **kwargs: Any
|
|
657
|
+
) -> ColumnElement[Any]:
|
|
658
|
+
col = self.__clause_element__()
|
|
659
|
+
return op(col._bind_param(op, other), col, **kwargs) # type: ignore[no-any-return] # noqa: E501
|
|
660
|
+
|
|
661
|
+
def found_in_pep593_annotated(self) -> Any:
|
|
662
|
+
# return a blank mapped_column(). This mapped_column()'s
|
|
663
|
+
# Column will be merged into it in _init_column_for_annotation().
|
|
664
|
+
return MappedColumn()
|
|
665
|
+
|
|
666
|
+
def _adjust_for_existing_column(
|
|
667
|
+
self,
|
|
668
|
+
decl_scan: _ClassScanMapperConfig,
|
|
669
|
+
key: str,
|
|
670
|
+
given_column: Column[_T],
|
|
671
|
+
) -> Column[_T]:
|
|
672
|
+
if (
|
|
673
|
+
self._use_existing_column
|
|
674
|
+
and decl_scan.inherits
|
|
675
|
+
and decl_scan.single
|
|
676
|
+
):
|
|
677
|
+
if decl_scan.is_deferred:
|
|
678
|
+
raise sa_exc.ArgumentError(
|
|
679
|
+
"Can't use use_existing_column with deferred mappers"
|
|
680
|
+
)
|
|
681
|
+
supercls_mapper = class_mapper(decl_scan.inherits, False)
|
|
682
|
+
|
|
683
|
+
colname = (
|
|
684
|
+
given_column.name if given_column.name is not None else key
|
|
685
|
+
)
|
|
686
|
+
given_column = supercls_mapper.local_table.c.get( # type: ignore[assignment] # noqa: E501
|
|
687
|
+
colname, given_column
|
|
688
|
+
)
|
|
689
|
+
return given_column
|
|
690
|
+
|
|
691
|
+
def declarative_scan(
|
|
692
|
+
self,
|
|
693
|
+
decl_scan: _ClassScanMapperConfig,
|
|
694
|
+
registry: _RegistryType,
|
|
695
|
+
cls: Type[Any],
|
|
696
|
+
originating_module: Optional[str],
|
|
697
|
+
key: str,
|
|
698
|
+
mapped_container: Optional[Type[Mapped[Any]]],
|
|
699
|
+
annotation: Optional[_AnnotationScanType],
|
|
700
|
+
extracted_mapped_annotation: Optional[_AnnotationScanType],
|
|
701
|
+
is_dataclass_field: bool,
|
|
702
|
+
) -> None:
|
|
703
|
+
column = self.column
|
|
704
|
+
|
|
705
|
+
column = self.column = self._adjust_for_existing_column(
|
|
706
|
+
decl_scan, key, self.column
|
|
707
|
+
)
|
|
708
|
+
|
|
709
|
+
if column.key is None:
|
|
710
|
+
column.key = key
|
|
711
|
+
if column.name is None:
|
|
712
|
+
column.name = key
|
|
713
|
+
|
|
714
|
+
sqltype = column.type
|
|
715
|
+
|
|
716
|
+
if extracted_mapped_annotation is None:
|
|
717
|
+
if sqltype._isnull and not self.column.foreign_keys:
|
|
718
|
+
self._raise_for_required(key, cls)
|
|
719
|
+
else:
|
|
720
|
+
return
|
|
721
|
+
|
|
722
|
+
self._init_column_for_annotation(
|
|
723
|
+
cls,
|
|
724
|
+
decl_scan,
|
|
725
|
+
key,
|
|
726
|
+
registry,
|
|
727
|
+
extracted_mapped_annotation,
|
|
728
|
+
originating_module,
|
|
729
|
+
)
|
|
730
|
+
|
|
731
|
+
@util.preload_module("sqlalchemy.orm.decl_base")
|
|
732
|
+
def declarative_scan_for_composite(
|
|
733
|
+
self,
|
|
734
|
+
decl_scan: _ClassScanMapperConfig,
|
|
735
|
+
registry: _RegistryType,
|
|
736
|
+
cls: Type[Any],
|
|
737
|
+
originating_module: Optional[str],
|
|
738
|
+
key: str,
|
|
739
|
+
param_name: str,
|
|
740
|
+
param_annotation: _AnnotationScanType,
|
|
741
|
+
) -> None:
|
|
742
|
+
decl_base = util.preloaded.orm_decl_base
|
|
743
|
+
decl_base._undefer_column_name(param_name, self.column)
|
|
744
|
+
self._init_column_for_annotation(
|
|
745
|
+
cls, decl_scan, key, registry, param_annotation, originating_module
|
|
746
|
+
)
|
|
747
|
+
|
|
748
|
+
def _init_column_for_annotation(
|
|
749
|
+
self,
|
|
750
|
+
cls: Type[Any],
|
|
751
|
+
decl_scan: _ClassScanMapperConfig,
|
|
752
|
+
key: str,
|
|
753
|
+
registry: _RegistryType,
|
|
754
|
+
argument: _AnnotationScanType,
|
|
755
|
+
originating_module: Optional[str],
|
|
756
|
+
) -> None:
|
|
757
|
+
sqltype = self.column.type
|
|
758
|
+
|
|
759
|
+
if is_fwd_ref(
|
|
760
|
+
argument, check_generic=True, check_for_plain_string=True
|
|
761
|
+
):
|
|
762
|
+
assert originating_module is not None
|
|
763
|
+
argument = de_stringify_annotation(
|
|
764
|
+
cls, argument, originating_module, include_generic=True
|
|
765
|
+
)
|
|
766
|
+
|
|
767
|
+
nullable = includes_none(argument)
|
|
768
|
+
|
|
769
|
+
if not self._has_nullable:
|
|
770
|
+
self.column.nullable = nullable
|
|
771
|
+
|
|
772
|
+
find_mapped_in: Tuple[Any, ...] = ()
|
|
773
|
+
our_type_is_pep593 = False
|
|
774
|
+
raw_pep_593_type = None
|
|
775
|
+
raw_pep_695_type = None
|
|
776
|
+
|
|
777
|
+
our_type: Any = de_optionalize_union_types(argument)
|
|
778
|
+
|
|
779
|
+
if is_pep695(our_type):
|
|
780
|
+
raw_pep_695_type = our_type
|
|
781
|
+
our_type = de_optionalize_union_types(raw_pep_695_type.__value__)
|
|
782
|
+
our_args = get_args(raw_pep_695_type)
|
|
783
|
+
if our_args:
|
|
784
|
+
our_type = our_type[our_args]
|
|
785
|
+
|
|
786
|
+
if is_pep593(our_type):
|
|
787
|
+
our_type_is_pep593 = True
|
|
788
|
+
|
|
789
|
+
pep_593_components = get_args(our_type)
|
|
790
|
+
raw_pep_593_type = pep_593_components[0]
|
|
791
|
+
if nullable:
|
|
792
|
+
raw_pep_593_type = de_optionalize_union_types(raw_pep_593_type)
|
|
793
|
+
find_mapped_in = pep_593_components[1:]
|
|
794
|
+
|
|
795
|
+
use_args_from: Optional[MappedColumn[Any]]
|
|
796
|
+
for elem in find_mapped_in:
|
|
797
|
+
if isinstance(elem, MappedColumn):
|
|
798
|
+
use_args_from = elem
|
|
799
|
+
break
|
|
800
|
+
else:
|
|
801
|
+
use_args_from = None
|
|
802
|
+
|
|
803
|
+
if use_args_from is not None:
|
|
804
|
+
|
|
805
|
+
self.column = use_args_from._adjust_for_existing_column(
|
|
806
|
+
decl_scan, key, self.column
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
if (
|
|
810
|
+
not self._has_insert_default
|
|
811
|
+
and use_args_from.column.default is not None
|
|
812
|
+
):
|
|
813
|
+
self.column.default = None
|
|
814
|
+
|
|
815
|
+
use_args_from.column._merge(self.column)
|
|
816
|
+
sqltype = self.column.type
|
|
817
|
+
|
|
818
|
+
if (
|
|
819
|
+
use_args_from.deferred is not _NoArg.NO_ARG
|
|
820
|
+
and self.deferred is _NoArg.NO_ARG
|
|
821
|
+
):
|
|
822
|
+
self.deferred = use_args_from.deferred
|
|
823
|
+
|
|
824
|
+
if (
|
|
825
|
+
use_args_from.deferred_group is not None
|
|
826
|
+
and self.deferred_group is None
|
|
827
|
+
):
|
|
828
|
+
self.deferred_group = use_args_from.deferred_group
|
|
829
|
+
|
|
830
|
+
if (
|
|
831
|
+
use_args_from.deferred_raiseload is not None
|
|
832
|
+
and self.deferred_raiseload is None
|
|
833
|
+
):
|
|
834
|
+
self.deferred_raiseload = use_args_from.deferred_raiseload
|
|
835
|
+
|
|
836
|
+
if (
|
|
837
|
+
use_args_from._use_existing_column
|
|
838
|
+
and not self._use_existing_column
|
|
839
|
+
):
|
|
840
|
+
self._use_existing_column = True
|
|
841
|
+
|
|
842
|
+
if use_args_from.active_history:
|
|
843
|
+
self.active_history = use_args_from.active_history
|
|
844
|
+
|
|
845
|
+
if (
|
|
846
|
+
use_args_from._sort_order is not None
|
|
847
|
+
and self._sort_order is _NoArg.NO_ARG
|
|
848
|
+
):
|
|
849
|
+
self._sort_order = use_args_from._sort_order
|
|
850
|
+
|
|
851
|
+
if (
|
|
852
|
+
use_args_from.column.key is not None
|
|
853
|
+
or use_args_from.column.name is not None
|
|
854
|
+
):
|
|
855
|
+
util.warn_deprecated(
|
|
856
|
+
"Can't use the 'key' or 'name' arguments in "
|
|
857
|
+
"Annotated with mapped_column(); this will be ignored",
|
|
858
|
+
"2.0.22",
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
if use_args_from._has_dataclass_arguments:
|
|
862
|
+
for idx, arg in enumerate(
|
|
863
|
+
use_args_from._attribute_options._fields
|
|
864
|
+
):
|
|
865
|
+
if (
|
|
866
|
+
use_args_from._attribute_options[idx]
|
|
867
|
+
is not _NoArg.NO_ARG
|
|
868
|
+
):
|
|
869
|
+
arg = arg.replace("dataclasses_", "")
|
|
870
|
+
util.warn_deprecated(
|
|
871
|
+
f"Argument '{arg}' is a dataclass argument and "
|
|
872
|
+
"cannot be specified within a mapped_column() "
|
|
873
|
+
"bundled inside of an Annotated object",
|
|
874
|
+
"2.0.22",
|
|
875
|
+
)
|
|
876
|
+
|
|
877
|
+
if sqltype._isnull and not self.column.foreign_keys:
|
|
878
|
+
checks: List[Any]
|
|
879
|
+
if our_type_is_pep593:
|
|
880
|
+
checks = [our_type, raw_pep_593_type]
|
|
881
|
+
else:
|
|
882
|
+
checks = [our_type]
|
|
883
|
+
|
|
884
|
+
if raw_pep_695_type is not None:
|
|
885
|
+
checks.insert(0, raw_pep_695_type)
|
|
886
|
+
|
|
887
|
+
for check_type in checks:
|
|
888
|
+
new_sqltype = registry._resolve_type(
|
|
889
|
+
check_type, _do_fallbacks=check_type is our_type
|
|
890
|
+
)
|
|
891
|
+
if new_sqltype is not None:
|
|
892
|
+
break
|
|
893
|
+
else:
|
|
894
|
+
if isinstance(our_type, TypeEngine) or (
|
|
895
|
+
isinstance(our_type, type)
|
|
896
|
+
and issubclass(our_type, TypeEngine)
|
|
897
|
+
):
|
|
898
|
+
raise orm_exc.MappedAnnotationError(
|
|
899
|
+
f"The type provided inside the {self.column.key!r} "
|
|
900
|
+
"attribute Mapped annotation is the SQLAlchemy type "
|
|
901
|
+
f"{our_type}. Expected a Python type instead"
|
|
902
|
+
)
|
|
903
|
+
elif is_a_type(checks[0]):
|
|
904
|
+
if len(checks) == 1:
|
|
905
|
+
detail = (
|
|
906
|
+
"the type object is not resolvable by the registry"
|
|
907
|
+
)
|
|
908
|
+
elif len(checks) == 2:
|
|
909
|
+
detail = (
|
|
910
|
+
f"neither '{checks[0]}' nor '{checks[1]}' "
|
|
911
|
+
"are resolvable by the registry"
|
|
912
|
+
)
|
|
913
|
+
else:
|
|
914
|
+
detail = (
|
|
915
|
+
f"""none of {
|
|
916
|
+
", ".join(f"'{t}'" for t in checks)
|
|
917
|
+
} """
|
|
918
|
+
"are resolvable by the registry"
|
|
919
|
+
)
|
|
920
|
+
raise orm_exc.MappedAnnotationError(
|
|
921
|
+
"Could not locate SQLAlchemy Core type when resolving "
|
|
922
|
+
f"for Python type indicated by '{checks[0]}' inside "
|
|
923
|
+
"the "
|
|
924
|
+
f"Mapped[] annotation for the {self.column.key!r} "
|
|
925
|
+
f"attribute; {detail}"
|
|
926
|
+
)
|
|
927
|
+
else:
|
|
928
|
+
raise orm_exc.MappedAnnotationError(
|
|
929
|
+
f"The object provided inside the {self.column.key!r} "
|
|
930
|
+
"attribute Mapped annotation is not a Python type, "
|
|
931
|
+
f"it's the object {argument!r}. Expected a Python "
|
|
932
|
+
"type."
|
|
933
|
+
)
|
|
934
|
+
|
|
935
|
+
self.column._set_type(new_sqltype)
|