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.
Files changed (274) hide show
  1. sqlalchemy/__init__.py +283 -0
  2. sqlalchemy/connectors/__init__.py +18 -0
  3. sqlalchemy/connectors/aioodbc.py +184 -0
  4. sqlalchemy/connectors/asyncio.py +429 -0
  5. sqlalchemy/connectors/pyodbc.py +250 -0
  6. sqlalchemy/cyextension/__init__.py +6 -0
  7. sqlalchemy/cyextension/collections.cp313t-win_amd64.pyd +0 -0
  8. sqlalchemy/cyextension/collections.pyx +409 -0
  9. sqlalchemy/cyextension/immutabledict.cp313t-win_amd64.pyd +0 -0
  10. sqlalchemy/cyextension/immutabledict.pxd +8 -0
  11. sqlalchemy/cyextension/immutabledict.pyx +133 -0
  12. sqlalchemy/cyextension/processors.cp313t-win_amd64.pyd +0 -0
  13. sqlalchemy/cyextension/processors.pyx +68 -0
  14. sqlalchemy/cyextension/resultproxy.cp313t-win_amd64.pyd +0 -0
  15. sqlalchemy/cyextension/resultproxy.pyx +102 -0
  16. sqlalchemy/cyextension/util.cp313t-win_amd64.pyd +0 -0
  17. sqlalchemy/cyextension/util.pyx +90 -0
  18. sqlalchemy/dialects/__init__.py +62 -0
  19. sqlalchemy/dialects/_typing.py +30 -0
  20. sqlalchemy/dialects/mssql/__init__.py +88 -0
  21. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  22. sqlalchemy/dialects/mssql/base.py +4093 -0
  23. sqlalchemy/dialects/mssql/information_schema.py +285 -0
  24. sqlalchemy/dialects/mssql/json.py +129 -0
  25. sqlalchemy/dialects/mssql/provision.py +185 -0
  26. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  27. sqlalchemy/dialects/mssql/pyodbc.py +760 -0
  28. sqlalchemy/dialects/mysql/__init__.py +104 -0
  29. sqlalchemy/dialects/mysql/aiomysql.py +250 -0
  30. sqlalchemy/dialects/mysql/asyncmy.py +231 -0
  31. sqlalchemy/dialects/mysql/base.py +3949 -0
  32. sqlalchemy/dialects/mysql/cymysql.py +106 -0
  33. sqlalchemy/dialects/mysql/dml.py +225 -0
  34. sqlalchemy/dialects/mysql/enumerated.py +282 -0
  35. sqlalchemy/dialects/mysql/expression.py +146 -0
  36. sqlalchemy/dialects/mysql/json.py +91 -0
  37. sqlalchemy/dialects/mysql/mariadb.py +72 -0
  38. sqlalchemy/dialects/mysql/mariadbconnector.py +322 -0
  39. sqlalchemy/dialects/mysql/mysqlconnector.py +302 -0
  40. sqlalchemy/dialects/mysql/mysqldb.py +314 -0
  41. sqlalchemy/dialects/mysql/provision.py +153 -0
  42. sqlalchemy/dialects/mysql/pymysql.py +158 -0
  43. sqlalchemy/dialects/mysql/pyodbc.py +157 -0
  44. sqlalchemy/dialects/mysql/reflection.py +727 -0
  45. sqlalchemy/dialects/mysql/reserved_words.py +570 -0
  46. sqlalchemy/dialects/mysql/types.py +835 -0
  47. sqlalchemy/dialects/oracle/__init__.py +81 -0
  48. sqlalchemy/dialects/oracle/base.py +3802 -0
  49. sqlalchemy/dialects/oracle/cx_oracle.py +1555 -0
  50. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  51. sqlalchemy/dialects/oracle/oracledb.py +941 -0
  52. sqlalchemy/dialects/oracle/provision.py +297 -0
  53. sqlalchemy/dialects/oracle/types.py +316 -0
  54. sqlalchemy/dialects/oracle/vector.py +365 -0
  55. sqlalchemy/dialects/postgresql/__init__.py +167 -0
  56. sqlalchemy/dialects/postgresql/_psycopg_common.py +189 -0
  57. sqlalchemy/dialects/postgresql/array.py +519 -0
  58. sqlalchemy/dialects/postgresql/asyncpg.py +1284 -0
  59. sqlalchemy/dialects/postgresql/base.py +5378 -0
  60. sqlalchemy/dialects/postgresql/dml.py +339 -0
  61. sqlalchemy/dialects/postgresql/ext.py +540 -0
  62. sqlalchemy/dialects/postgresql/hstore.py +406 -0
  63. sqlalchemy/dialects/postgresql/json.py +404 -0
  64. sqlalchemy/dialects/postgresql/named_types.py +524 -0
  65. sqlalchemy/dialects/postgresql/operators.py +129 -0
  66. sqlalchemy/dialects/postgresql/pg8000.py +669 -0
  67. sqlalchemy/dialects/postgresql/pg_catalog.py +326 -0
  68. sqlalchemy/dialects/postgresql/provision.py +183 -0
  69. sqlalchemy/dialects/postgresql/psycopg.py +862 -0
  70. sqlalchemy/dialects/postgresql/psycopg2.py +892 -0
  71. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  72. sqlalchemy/dialects/postgresql/ranges.py +1031 -0
  73. sqlalchemy/dialects/postgresql/types.py +313 -0
  74. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  75. sqlalchemy/dialects/sqlite/aiosqlite.py +482 -0
  76. sqlalchemy/dialects/sqlite/base.py +3056 -0
  77. sqlalchemy/dialects/sqlite/dml.py +263 -0
  78. sqlalchemy/dialects/sqlite/json.py +92 -0
  79. sqlalchemy/dialects/sqlite/provision.py +229 -0
  80. sqlalchemy/dialects/sqlite/pysqlcipher.py +157 -0
  81. sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
  82. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  83. sqlalchemy/engine/__init__.py +62 -0
  84. sqlalchemy/engine/_py_processors.py +136 -0
  85. sqlalchemy/engine/_py_row.py +128 -0
  86. sqlalchemy/engine/_py_util.py +74 -0
  87. sqlalchemy/engine/base.py +3390 -0
  88. sqlalchemy/engine/characteristics.py +155 -0
  89. sqlalchemy/engine/create.py +893 -0
  90. sqlalchemy/engine/cursor.py +2298 -0
  91. sqlalchemy/engine/default.py +2394 -0
  92. sqlalchemy/engine/events.py +965 -0
  93. sqlalchemy/engine/interfaces.py +3471 -0
  94. sqlalchemy/engine/mock.py +134 -0
  95. sqlalchemy/engine/processors.py +61 -0
  96. sqlalchemy/engine/reflection.py +2102 -0
  97. sqlalchemy/engine/result.py +2399 -0
  98. sqlalchemy/engine/row.py +400 -0
  99. sqlalchemy/engine/strategies.py +16 -0
  100. sqlalchemy/engine/url.py +924 -0
  101. sqlalchemy/engine/util.py +167 -0
  102. sqlalchemy/event/__init__.py +26 -0
  103. sqlalchemy/event/api.py +220 -0
  104. sqlalchemy/event/attr.py +676 -0
  105. sqlalchemy/event/base.py +472 -0
  106. sqlalchemy/event/legacy.py +258 -0
  107. sqlalchemy/event/registry.py +390 -0
  108. sqlalchemy/events.py +17 -0
  109. sqlalchemy/exc.py +832 -0
  110. sqlalchemy/ext/__init__.py +11 -0
  111. sqlalchemy/ext/associationproxy.py +2027 -0
  112. sqlalchemy/ext/asyncio/__init__.py +25 -0
  113. sqlalchemy/ext/asyncio/base.py +281 -0
  114. sqlalchemy/ext/asyncio/engine.py +1471 -0
  115. sqlalchemy/ext/asyncio/exc.py +21 -0
  116. sqlalchemy/ext/asyncio/result.py +965 -0
  117. sqlalchemy/ext/asyncio/scoping.py +1599 -0
  118. sqlalchemy/ext/asyncio/session.py +1947 -0
  119. sqlalchemy/ext/automap.py +1701 -0
  120. sqlalchemy/ext/baked.py +570 -0
  121. sqlalchemy/ext/compiler.py +600 -0
  122. sqlalchemy/ext/declarative/__init__.py +65 -0
  123. sqlalchemy/ext/declarative/extensions.py +564 -0
  124. sqlalchemy/ext/horizontal_shard.py +478 -0
  125. sqlalchemy/ext/hybrid.py +1535 -0
  126. sqlalchemy/ext/indexable.py +364 -0
  127. sqlalchemy/ext/instrumentation.py +450 -0
  128. sqlalchemy/ext/mutable.py +1085 -0
  129. sqlalchemy/ext/mypy/__init__.py +6 -0
  130. sqlalchemy/ext/mypy/apply.py +324 -0
  131. sqlalchemy/ext/mypy/decl_class.py +515 -0
  132. sqlalchemy/ext/mypy/infer.py +590 -0
  133. sqlalchemy/ext/mypy/names.py +335 -0
  134. sqlalchemy/ext/mypy/plugin.py +303 -0
  135. sqlalchemy/ext/mypy/util.py +357 -0
  136. sqlalchemy/ext/orderinglist.py +439 -0
  137. sqlalchemy/ext/serializer.py +185 -0
  138. sqlalchemy/future/__init__.py +16 -0
  139. sqlalchemy/future/engine.py +15 -0
  140. sqlalchemy/inspection.py +174 -0
  141. sqlalchemy/log.py +288 -0
  142. sqlalchemy/orm/__init__.py +171 -0
  143. sqlalchemy/orm/_orm_constructors.py +2661 -0
  144. sqlalchemy/orm/_typing.py +179 -0
  145. sqlalchemy/orm/attributes.py +2845 -0
  146. sqlalchemy/orm/base.py +971 -0
  147. sqlalchemy/orm/bulk_persistence.py +2135 -0
  148. sqlalchemy/orm/clsregistry.py +571 -0
  149. sqlalchemy/orm/collections.py +1627 -0
  150. sqlalchemy/orm/context.py +3334 -0
  151. sqlalchemy/orm/decl_api.py +2004 -0
  152. sqlalchemy/orm/decl_base.py +2192 -0
  153. sqlalchemy/orm/dependency.py +1302 -0
  154. sqlalchemy/orm/descriptor_props.py +1092 -0
  155. sqlalchemy/orm/dynamic.py +300 -0
  156. sqlalchemy/orm/evaluator.py +379 -0
  157. sqlalchemy/orm/events.py +3252 -0
  158. sqlalchemy/orm/exc.py +237 -0
  159. sqlalchemy/orm/identity.py +302 -0
  160. sqlalchemy/orm/instrumentation.py +754 -0
  161. sqlalchemy/orm/interfaces.py +1496 -0
  162. sqlalchemy/orm/loading.py +1686 -0
  163. sqlalchemy/orm/mapped_collection.py +557 -0
  164. sqlalchemy/orm/mapper.py +4444 -0
  165. sqlalchemy/orm/path_registry.py +809 -0
  166. sqlalchemy/orm/persistence.py +1788 -0
  167. sqlalchemy/orm/properties.py +935 -0
  168. sqlalchemy/orm/query.py +3459 -0
  169. sqlalchemy/orm/relationships.py +3508 -0
  170. sqlalchemy/orm/scoping.py +2148 -0
  171. sqlalchemy/orm/session.py +5280 -0
  172. sqlalchemy/orm/state.py +1168 -0
  173. sqlalchemy/orm/state_changes.py +196 -0
  174. sqlalchemy/orm/strategies.py +3470 -0
  175. sqlalchemy/orm/strategy_options.py +2568 -0
  176. sqlalchemy/orm/sync.py +164 -0
  177. sqlalchemy/orm/unitofwork.py +796 -0
  178. sqlalchemy/orm/util.py +2403 -0
  179. sqlalchemy/orm/writeonly.py +674 -0
  180. sqlalchemy/pool/__init__.py +44 -0
  181. sqlalchemy/pool/base.py +1524 -0
  182. sqlalchemy/pool/events.py +375 -0
  183. sqlalchemy/pool/impl.py +588 -0
  184. sqlalchemy/py.typed +0 -0
  185. sqlalchemy/schema.py +69 -0
  186. sqlalchemy/sql/__init__.py +145 -0
  187. sqlalchemy/sql/_dml_constructors.py +132 -0
  188. sqlalchemy/sql/_elements_constructors.py +1872 -0
  189. sqlalchemy/sql/_orm_types.py +20 -0
  190. sqlalchemy/sql/_py_util.py +75 -0
  191. sqlalchemy/sql/_selectable_constructors.py +763 -0
  192. sqlalchemy/sql/_typing.py +482 -0
  193. sqlalchemy/sql/annotation.py +587 -0
  194. sqlalchemy/sql/base.py +2293 -0
  195. sqlalchemy/sql/cache_key.py +1057 -0
  196. sqlalchemy/sql/coercions.py +1404 -0
  197. sqlalchemy/sql/compiler.py +8081 -0
  198. sqlalchemy/sql/crud.py +1752 -0
  199. sqlalchemy/sql/ddl.py +1444 -0
  200. sqlalchemy/sql/default_comparator.py +551 -0
  201. sqlalchemy/sql/dml.py +1850 -0
  202. sqlalchemy/sql/elements.py +5589 -0
  203. sqlalchemy/sql/events.py +458 -0
  204. sqlalchemy/sql/expression.py +159 -0
  205. sqlalchemy/sql/functions.py +2158 -0
  206. sqlalchemy/sql/lambdas.py +1442 -0
  207. sqlalchemy/sql/naming.py +209 -0
  208. sqlalchemy/sql/operators.py +2623 -0
  209. sqlalchemy/sql/roles.py +323 -0
  210. sqlalchemy/sql/schema.py +6222 -0
  211. sqlalchemy/sql/selectable.py +7265 -0
  212. sqlalchemy/sql/sqltypes.py +3930 -0
  213. sqlalchemy/sql/traversals.py +1024 -0
  214. sqlalchemy/sql/type_api.py +2368 -0
  215. sqlalchemy/sql/util.py +1485 -0
  216. sqlalchemy/sql/visitors.py +1164 -0
  217. sqlalchemy/testing/__init__.py +96 -0
  218. sqlalchemy/testing/assertions.py +994 -0
  219. sqlalchemy/testing/assertsql.py +520 -0
  220. sqlalchemy/testing/asyncio.py +135 -0
  221. sqlalchemy/testing/config.py +434 -0
  222. sqlalchemy/testing/engines.py +483 -0
  223. sqlalchemy/testing/entities.py +117 -0
  224. sqlalchemy/testing/exclusions.py +476 -0
  225. sqlalchemy/testing/fixtures/__init__.py +28 -0
  226. sqlalchemy/testing/fixtures/base.py +384 -0
  227. sqlalchemy/testing/fixtures/mypy.py +332 -0
  228. sqlalchemy/testing/fixtures/orm.py +227 -0
  229. sqlalchemy/testing/fixtures/sql.py +482 -0
  230. sqlalchemy/testing/pickleable.py +155 -0
  231. sqlalchemy/testing/plugin/__init__.py +6 -0
  232. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  233. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  234. sqlalchemy/testing/plugin/pytestplugin.py +892 -0
  235. sqlalchemy/testing/profiling.py +329 -0
  236. sqlalchemy/testing/provision.py +603 -0
  237. sqlalchemy/testing/requirements.py +1945 -0
  238. sqlalchemy/testing/schema.py +198 -0
  239. sqlalchemy/testing/suite/__init__.py +19 -0
  240. sqlalchemy/testing/suite/test_cte.py +237 -0
  241. sqlalchemy/testing/suite/test_ddl.py +389 -0
  242. sqlalchemy/testing/suite/test_deprecations.py +153 -0
  243. sqlalchemy/testing/suite/test_dialect.py +776 -0
  244. sqlalchemy/testing/suite/test_insert.py +630 -0
  245. sqlalchemy/testing/suite/test_reflection.py +3557 -0
  246. sqlalchemy/testing/suite/test_results.py +504 -0
  247. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  248. sqlalchemy/testing/suite/test_select.py +2010 -0
  249. sqlalchemy/testing/suite/test_sequence.py +317 -0
  250. sqlalchemy/testing/suite/test_types.py +2147 -0
  251. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  252. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  253. sqlalchemy/testing/util.py +535 -0
  254. sqlalchemy/testing/warnings.py +52 -0
  255. sqlalchemy/types.py +74 -0
  256. sqlalchemy/util/__init__.py +162 -0
  257. sqlalchemy/util/_collections.py +712 -0
  258. sqlalchemy/util/_concurrency_py3k.py +288 -0
  259. sqlalchemy/util/_has_cy.py +40 -0
  260. sqlalchemy/util/_py_collections.py +541 -0
  261. sqlalchemy/util/compat.py +421 -0
  262. sqlalchemy/util/concurrency.py +110 -0
  263. sqlalchemy/util/deprecations.py +401 -0
  264. sqlalchemy/util/langhelpers.py +2203 -0
  265. sqlalchemy/util/preloaded.py +150 -0
  266. sqlalchemy/util/queue.py +322 -0
  267. sqlalchemy/util/tool_support.py +201 -0
  268. sqlalchemy/util/topological.py +120 -0
  269. sqlalchemy/util/typing.py +734 -0
  270. sqlalchemy-2.0.47.dist-info/METADATA +243 -0
  271. sqlalchemy-2.0.47.dist-info/RECORD +274 -0
  272. sqlalchemy-2.0.47.dist-info/WHEEL +5 -0
  273. sqlalchemy-2.0.47.dist-info/licenses/LICENSE +19 -0
  274. 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)