SQLAlchemy 2.0.47__cp313-cp313t-win32.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-win32.pyd +0 -0
  8. sqlalchemy/cyextension/collections.pyx +409 -0
  9. sqlalchemy/cyextension/immutabledict.cp313t-win32.pyd +0 -0
  10. sqlalchemy/cyextension/immutabledict.pxd +8 -0
  11. sqlalchemy/cyextension/immutabledict.pyx +133 -0
  12. sqlalchemy/cyextension/processors.cp313t-win32.pyd +0 -0
  13. sqlalchemy/cyextension/processors.pyx +68 -0
  14. sqlalchemy/cyextension/resultproxy.cp313t-win32.pyd +0 -0
  15. sqlalchemy/cyextension/resultproxy.pyx +102 -0
  16. sqlalchemy/cyextension/util.cp313t-win32.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,2004 @@
1
+ # orm/decl_api.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
+ """Public API functions and helpers for declarative."""
9
+
10
+ from __future__ import annotations
11
+
12
+ import itertools
13
+ import re
14
+ import typing
15
+ from typing import Any
16
+ from typing import Callable
17
+ from typing import ClassVar
18
+ from typing import Dict
19
+ from typing import FrozenSet
20
+ from typing import Generic
21
+ from typing import Iterable
22
+ from typing import Iterator
23
+ from typing import Mapping
24
+ from typing import Optional
25
+ from typing import overload
26
+ from typing import Set
27
+ from typing import Tuple
28
+ from typing import Type
29
+ from typing import TYPE_CHECKING
30
+ from typing import TypeVar
31
+ from typing import Union
32
+ import weakref
33
+
34
+ from . import attributes
35
+ from . import clsregistry
36
+ from . import instrumentation
37
+ from . import interfaces
38
+ from . import mapperlib
39
+ from ._orm_constructors import composite
40
+ from ._orm_constructors import deferred
41
+ from ._orm_constructors import mapped_column
42
+ from ._orm_constructors import relationship
43
+ from ._orm_constructors import synonym
44
+ from .attributes import InstrumentedAttribute
45
+ from .base import _inspect_mapped_class
46
+ from .base import _is_mapped_class
47
+ from .base import Mapped
48
+ from .base import ORMDescriptor
49
+ from .decl_base import _add_attribute
50
+ from .decl_base import _as_declarative
51
+ from .decl_base import _ClassScanMapperConfig
52
+ from .decl_base import _declarative_constructor
53
+ from .decl_base import _DeferredMapperConfig
54
+ from .decl_base import _del_attribute
55
+ from .decl_base import _mapper
56
+ from .descriptor_props import Composite
57
+ from .descriptor_props import Synonym
58
+ from .descriptor_props import Synonym as _orm_synonym
59
+ from .mapper import Mapper
60
+ from .properties import MappedColumn
61
+ from .relationships import RelationshipProperty
62
+ from .state import InstanceState
63
+ from .. import exc
64
+ from .. import inspection
65
+ from .. import util
66
+ from ..sql import sqltypes
67
+ from ..sql.base import _NoArg
68
+ from ..sql.elements import SQLCoreOperations
69
+ from ..sql.schema import MetaData
70
+ from ..sql.selectable import FromClause
71
+ from ..util import hybridmethod
72
+ from ..util import hybridproperty
73
+ from ..util import typing as compat_typing
74
+ from ..util import warn_deprecated
75
+ from ..util.typing import CallableReference
76
+ from ..util.typing import de_optionalize_union_types
77
+ from ..util.typing import flatten_newtype
78
+ from ..util.typing import is_generic
79
+ from ..util.typing import is_literal
80
+ from ..util.typing import is_newtype
81
+ from ..util.typing import is_pep593
82
+ from ..util.typing import is_pep695
83
+ from ..util.typing import Literal
84
+ from ..util.typing import LITERAL_TYPES
85
+ from ..util.typing import Self
86
+
87
+ if TYPE_CHECKING:
88
+ from ._typing import _O
89
+ from ._typing import _RegistryType
90
+ from .decl_base import _DataclassArguments
91
+ from .instrumentation import ClassManager
92
+ from .interfaces import MapperProperty
93
+ from .state import InstanceState # noqa
94
+ from ..sql._typing import _TypeEngineArgument
95
+ from ..sql.type_api import _MatchedOnType
96
+
97
+ _T = TypeVar("_T", bound=Any)
98
+
99
+ _TT = TypeVar("_TT", bound=Any)
100
+
101
+ # it's not clear how to have Annotated, Union objects etc. as keys here
102
+ # from a typing perspective so just leave it open ended for now
103
+ _TypeAnnotationMapType = Mapping[Any, "_TypeEngineArgument[Any]"]
104
+ _MutableTypeAnnotationMapType = Dict[Any, "_TypeEngineArgument[Any]"]
105
+
106
+ _DeclaredAttrDecorated = Callable[
107
+ ..., Union[Mapped[_T], ORMDescriptor[_T], SQLCoreOperations[_T]]
108
+ ]
109
+
110
+
111
+ def has_inherited_table(cls: Type[_O]) -> bool:
112
+ """Given a class, return True if any of the classes it inherits from has a
113
+ mapped table, otherwise return False.
114
+
115
+ This is used in declarative mixins to build attributes that behave
116
+ differently for the base class vs. a subclass in an inheritance
117
+ hierarchy.
118
+
119
+ .. seealso::
120
+
121
+ :ref:`decl_mixin_inheritance`
122
+
123
+ """
124
+ for class_ in cls.__mro__[1:]:
125
+ if getattr(class_, "__table__", None) is not None:
126
+ return True
127
+ return False
128
+
129
+
130
+ class _DynamicAttributesType(type):
131
+ def __setattr__(cls, key: str, value: Any) -> None:
132
+ if "__mapper__" in cls.__dict__:
133
+ _add_attribute(cls, key, value)
134
+ else:
135
+ type.__setattr__(cls, key, value)
136
+
137
+ def __delattr__(cls, key: str) -> None:
138
+ if "__mapper__" in cls.__dict__:
139
+ _del_attribute(cls, key)
140
+ else:
141
+ type.__delattr__(cls, key)
142
+
143
+
144
+ class DeclarativeAttributeIntercept(
145
+ _DynamicAttributesType,
146
+ # Inspectable is used only by the mypy plugin
147
+ inspection.Inspectable[Mapper[Any]],
148
+ ):
149
+ """Metaclass that may be used in conjunction with the
150
+ :class:`_orm.DeclarativeBase` class to support addition of class
151
+ attributes dynamically.
152
+
153
+ """
154
+
155
+
156
+ @compat_typing.dataclass_transform(
157
+ field_specifiers=(
158
+ MappedColumn,
159
+ RelationshipProperty,
160
+ Composite,
161
+ Synonym,
162
+ mapped_column,
163
+ relationship,
164
+ composite,
165
+ synonym,
166
+ deferred,
167
+ ),
168
+ )
169
+ class DCTransformDeclarative(DeclarativeAttributeIntercept):
170
+ """metaclass that includes @dataclass_transforms"""
171
+
172
+
173
+ class DeclarativeMeta(DeclarativeAttributeIntercept):
174
+ metadata: MetaData
175
+ registry: RegistryType
176
+
177
+ def __init__(
178
+ cls, classname: Any, bases: Any, dict_: Any, **kw: Any
179
+ ) -> None:
180
+ # use cls.__dict__, which can be modified by an
181
+ # __init_subclass__() method (#7900)
182
+ dict_ = cls.__dict__
183
+
184
+ # early-consume registry from the initial declarative base,
185
+ # assign privately to not conflict with subclass attributes named
186
+ # "registry"
187
+ reg = getattr(cls, "_sa_registry", None)
188
+ if reg is None:
189
+ reg = dict_.get("registry", None)
190
+ if not isinstance(reg, registry):
191
+ raise exc.InvalidRequestError(
192
+ "Declarative base class has no 'registry' attribute, "
193
+ "or registry is not a sqlalchemy.orm.registry() object"
194
+ )
195
+ else:
196
+ cls._sa_registry = reg
197
+
198
+ if not cls.__dict__.get("__abstract__", False):
199
+ _as_declarative(reg, cls, dict_)
200
+ type.__init__(cls, classname, bases, dict_)
201
+
202
+
203
+ def synonym_for(
204
+ name: str, map_column: bool = False
205
+ ) -> Callable[[Callable[..., Any]], Synonym[Any]]:
206
+ """Decorator that produces an :func:`_orm.synonym`
207
+ attribute in conjunction with a Python descriptor.
208
+
209
+ The function being decorated is passed to :func:`_orm.synonym` as the
210
+ :paramref:`.orm.synonym.descriptor` parameter::
211
+
212
+ class MyClass(Base):
213
+ __tablename__ = "my_table"
214
+
215
+ id = Column(Integer, primary_key=True)
216
+ _job_status = Column("job_status", String(50))
217
+
218
+ @synonym_for("job_status")
219
+ @property
220
+ def job_status(self):
221
+ return "Status: %s" % self._job_status
222
+
223
+ The :ref:`hybrid properties <mapper_hybrids>` feature of SQLAlchemy
224
+ is typically preferred instead of synonyms, which is a more legacy
225
+ feature.
226
+
227
+ .. seealso::
228
+
229
+ :ref:`synonyms` - Overview of synonyms
230
+
231
+ :func:`_orm.synonym` - the mapper-level function
232
+
233
+ :ref:`mapper_hybrids` - The Hybrid Attribute extension provides an
234
+ updated approach to augmenting attribute behavior more flexibly than
235
+ can be achieved with synonyms.
236
+
237
+ """
238
+
239
+ def decorate(fn: Callable[..., Any]) -> Synonym[Any]:
240
+ return _orm_synonym(name, map_column=map_column, descriptor=fn)
241
+
242
+ return decorate
243
+
244
+
245
+ class _declared_attr_common:
246
+ def __init__(
247
+ self,
248
+ fn: Callable[..., Any],
249
+ cascading: bool = False,
250
+ quiet: bool = False,
251
+ ):
252
+ # support
253
+ # @declared_attr
254
+ # @classmethod
255
+ # def foo(cls) -> Mapped[thing]:
256
+ # ...
257
+ # which seems to help typing tools interpret the fn as a classmethod
258
+ # for situations where needed
259
+ if isinstance(fn, classmethod):
260
+ fn = fn.__func__
261
+
262
+ self.fget = fn
263
+ self._cascading = cascading
264
+ self._quiet = quiet
265
+ self.__doc__ = fn.__doc__
266
+
267
+ def _collect_return_annotation(self) -> Optional[Type[Any]]:
268
+ return util.get_annotations(self.fget).get("return")
269
+
270
+ def __get__(self, instance: Optional[object], owner: Any) -> Any:
271
+ # the declared_attr needs to make use of a cache that exists
272
+ # for the span of the declarative scan_attributes() phase.
273
+ # to achieve this we look at the class manager that's configured.
274
+
275
+ # note this method should not be called outside of the declarative
276
+ # setup phase
277
+
278
+ cls = owner
279
+ manager = attributes.opt_manager_of_class(cls)
280
+ if manager is None:
281
+ if not re.match(r"^__.+__$", self.fget.__name__):
282
+ # if there is no manager at all, then this class hasn't been
283
+ # run through declarative or mapper() at all, emit a warning.
284
+ util.warn(
285
+ "Unmanaged access of declarative attribute %s from "
286
+ "non-mapped class %s" % (self.fget.__name__, cls.__name__)
287
+ )
288
+ return self.fget(cls)
289
+ elif manager.is_mapped:
290
+ # the class is mapped, which means we're outside of the declarative
291
+ # scan setup, just run the function.
292
+ return self.fget(cls)
293
+
294
+ # here, we are inside of the declarative scan. use the registry
295
+ # that is tracking the values of these attributes.
296
+ declarative_scan = manager.declarative_scan()
297
+
298
+ # assert that we are in fact in the declarative scan
299
+ assert declarative_scan is not None
300
+
301
+ reg = declarative_scan.declared_attr_reg
302
+
303
+ if self in reg:
304
+ return reg[self]
305
+ else:
306
+ reg[self] = obj = self.fget(cls)
307
+ return obj
308
+
309
+
310
+ class _declared_directive(_declared_attr_common, Generic[_T]):
311
+ # see mapping_api.rst for docstring
312
+
313
+ if typing.TYPE_CHECKING:
314
+
315
+ def __init__(
316
+ self,
317
+ fn: Callable[..., _T],
318
+ cascading: bool = False,
319
+ ): ...
320
+
321
+ def __get__(self, instance: Optional[object], owner: Any) -> _T: ...
322
+
323
+ def __set__(self, instance: Any, value: Any) -> None: ...
324
+
325
+ def __delete__(self, instance: Any) -> None: ...
326
+
327
+ def __call__(self, fn: Callable[..., _TT]) -> _declared_directive[_TT]:
328
+ # extensive fooling of mypy underway...
329
+ ...
330
+
331
+
332
+ class declared_attr(interfaces._MappedAttribute[_T], _declared_attr_common):
333
+ """Mark a class-level method as representing the definition of
334
+ a mapped property or Declarative directive.
335
+
336
+ :class:`_orm.declared_attr` is typically applied as a decorator to a class
337
+ level method, turning the attribute into a scalar-like property that can be
338
+ invoked from the uninstantiated class. The Declarative mapping process
339
+ looks for these :class:`_orm.declared_attr` callables as it scans classes,
340
+ and assumes any attribute marked with :class:`_orm.declared_attr` will be a
341
+ callable that will produce an object specific to the Declarative mapping or
342
+ table configuration.
343
+
344
+ :class:`_orm.declared_attr` is usually applicable to
345
+ :ref:`mixins <orm_mixins_toplevel>`, to define relationships that are to be
346
+ applied to different implementors of the class. It may also be used to
347
+ define dynamically generated column expressions and other Declarative
348
+ attributes.
349
+
350
+ Example::
351
+
352
+ class ProvidesUserMixin:
353
+ "A mixin that adds a 'user' relationship to classes."
354
+
355
+ user_id: Mapped[int] = mapped_column(ForeignKey("user_table.id"))
356
+
357
+ @declared_attr
358
+ def user(cls) -> Mapped["User"]:
359
+ return relationship("User")
360
+
361
+ When used with Declarative directives such as ``__tablename__``, the
362
+ :meth:`_orm.declared_attr.directive` modifier may be used which indicates
363
+ to :pep:`484` typing tools that the given method is not dealing with
364
+ :class:`_orm.Mapped` attributes::
365
+
366
+ class CreateTableName:
367
+ @declared_attr.directive
368
+ def __tablename__(cls) -> str:
369
+ return cls.__name__.lower()
370
+
371
+ :class:`_orm.declared_attr` can also be applied directly to mapped
372
+ classes, to allow for attributes that dynamically configure themselves
373
+ on subclasses when using mapped inheritance schemes. Below
374
+ illustrates :class:`_orm.declared_attr` to create a dynamic scheme
375
+ for generating the :paramref:`_orm.Mapper.polymorphic_identity` parameter
376
+ for subclasses::
377
+
378
+ class Employee(Base):
379
+ __tablename__ = "employee"
380
+
381
+ id: Mapped[int] = mapped_column(primary_key=True)
382
+ type: Mapped[str] = mapped_column(String(50))
383
+
384
+ @declared_attr.directive
385
+ def __mapper_args__(cls) -> Dict[str, Any]:
386
+ if cls.__name__ == "Employee":
387
+ return {
388
+ "polymorphic_on": cls.type,
389
+ "polymorphic_identity": "Employee",
390
+ }
391
+ else:
392
+ return {"polymorphic_identity": cls.__name__}
393
+
394
+
395
+ class Engineer(Employee):
396
+ pass
397
+
398
+ :class:`_orm.declared_attr` supports decorating functions that are
399
+ explicitly decorated with ``@classmethod``. This is never necessary from a
400
+ runtime perspective, however may be needed in order to support :pep:`484`
401
+ typing tools that don't otherwise recognize the decorated function as
402
+ having class-level behaviors for the ``cls`` parameter::
403
+
404
+ class SomethingMixin:
405
+ x: Mapped[int]
406
+ y: Mapped[int]
407
+
408
+ @declared_attr
409
+ @classmethod
410
+ def x_plus_y(cls) -> Mapped[int]:
411
+ return column_property(cls.x + cls.y)
412
+
413
+ .. versionadded:: 2.0 - :class:`_orm.declared_attr` can accommodate a
414
+ function decorated with ``@classmethod`` to help with :pep:`484`
415
+ integration where needed.
416
+
417
+
418
+ .. seealso::
419
+
420
+ :ref:`orm_mixins_toplevel` - Declarative Mixin documentation with
421
+ background on use patterns for :class:`_orm.declared_attr`.
422
+
423
+ """ # noqa: E501
424
+
425
+ if typing.TYPE_CHECKING:
426
+
427
+ def __init__(
428
+ self,
429
+ fn: _DeclaredAttrDecorated[_T],
430
+ cascading: bool = False,
431
+ ): ...
432
+
433
+ def __set__(self, instance: Any, value: Any) -> None: ...
434
+
435
+ def __delete__(self, instance: Any) -> None: ...
436
+
437
+ # this is the Mapped[] API where at class descriptor get time we want
438
+ # the type checker to see InstrumentedAttribute[_T]. However the
439
+ # callable function prior to mapping in fact calls the given
440
+ # declarative function that does not return InstrumentedAttribute
441
+ @overload
442
+ def __get__(
443
+ self, instance: None, owner: Any
444
+ ) -> InstrumentedAttribute[_T]: ...
445
+
446
+ @overload
447
+ def __get__(self, instance: object, owner: Any) -> _T: ...
448
+
449
+ def __get__(
450
+ self, instance: Optional[object], owner: Any
451
+ ) -> Union[InstrumentedAttribute[_T], _T]: ...
452
+
453
+ @hybridmethod
454
+ def _stateful(cls, **kw: Any) -> _stateful_declared_attr[_T]:
455
+ return _stateful_declared_attr(**kw)
456
+
457
+ @hybridproperty
458
+ def directive(cls) -> _declared_directive[Any]:
459
+ # see mapping_api.rst for docstring
460
+ return _declared_directive # type: ignore
461
+
462
+ @hybridproperty
463
+ def cascading(cls) -> _stateful_declared_attr[_T]:
464
+ # see mapping_api.rst for docstring
465
+ return cls._stateful(cascading=True)
466
+
467
+
468
+ class _stateful_declared_attr(declared_attr[_T]):
469
+ kw: Dict[str, Any]
470
+
471
+ def __init__(self, **kw: Any):
472
+ self.kw = kw
473
+
474
+ @hybridmethod
475
+ def _stateful(self, **kw: Any) -> _stateful_declared_attr[_T]:
476
+ new_kw = self.kw.copy()
477
+ new_kw.update(kw)
478
+ return _stateful_declared_attr(**new_kw)
479
+
480
+ def __call__(self, fn: _DeclaredAttrDecorated[_T]) -> declared_attr[_T]:
481
+ return declared_attr(fn, **self.kw)
482
+
483
+
484
+ def declarative_mixin(cls: Type[_T]) -> Type[_T]:
485
+ """Mark a class as providing the feature of "declarative mixin".
486
+
487
+ E.g.::
488
+
489
+ from sqlalchemy.orm import declared_attr
490
+ from sqlalchemy.orm import declarative_mixin
491
+
492
+
493
+ @declarative_mixin
494
+ class MyMixin:
495
+
496
+ @declared_attr
497
+ def __tablename__(cls):
498
+ return cls.__name__.lower()
499
+
500
+ __table_args__ = {"mysql_engine": "InnoDB"}
501
+ __mapper_args__ = {"always_refresh": True}
502
+
503
+ id = Column(Integer, primary_key=True)
504
+
505
+
506
+ class MyModel(MyMixin, Base):
507
+ name = Column(String(1000))
508
+
509
+ The :func:`_orm.declarative_mixin` decorator currently does not modify
510
+ the given class in any way; it's current purpose is strictly to assist
511
+ the :ref:`Mypy plugin <mypy_toplevel>` in being able to identify
512
+ SQLAlchemy declarative mixin classes when no other context is present.
513
+
514
+ .. versionadded:: 1.4.6
515
+
516
+ .. legacy:: This api is considered legacy and will be deprecated in the next
517
+ SQLAlchemy version.
518
+
519
+ .. seealso::
520
+
521
+ :ref:`orm_mixins_toplevel`
522
+
523
+ :ref:`mypy_declarative_mixins` - in the
524
+ :ref:`Mypy plugin documentation <mypy_toplevel>`
525
+
526
+ """ # noqa: E501
527
+
528
+ return cls
529
+
530
+
531
+ def _setup_declarative_base(cls: Type[Any]) -> None:
532
+ if "metadata" in cls.__dict__:
533
+ metadata = cls.__dict__["metadata"]
534
+ else:
535
+ metadata = None
536
+
537
+ if "type_annotation_map" in cls.__dict__:
538
+ type_annotation_map = cls.__dict__["type_annotation_map"]
539
+ else:
540
+ type_annotation_map = None
541
+
542
+ reg = cls.__dict__.get("registry", None)
543
+ if reg is not None:
544
+ if not isinstance(reg, registry):
545
+ raise exc.InvalidRequestError(
546
+ "Declarative base class has a 'registry' attribute that is "
547
+ "not an instance of sqlalchemy.orm.registry()"
548
+ )
549
+ elif type_annotation_map is not None:
550
+ raise exc.InvalidRequestError(
551
+ "Declarative base class has both a 'registry' attribute and a "
552
+ "type_annotation_map entry. Per-base type_annotation_maps "
553
+ "are not supported. Please apply the type_annotation_map "
554
+ "to this registry directly."
555
+ )
556
+
557
+ else:
558
+ reg = registry(
559
+ metadata=metadata, type_annotation_map=type_annotation_map
560
+ )
561
+ cls.registry = reg
562
+
563
+ cls._sa_registry = reg
564
+
565
+ if "metadata" not in cls.__dict__:
566
+ cls.metadata = cls.registry.metadata
567
+
568
+ if getattr(cls, "__init__", object.__init__) is object.__init__:
569
+ cls.__init__ = cls.registry.constructor
570
+
571
+
572
+ class MappedAsDataclass(metaclass=DCTransformDeclarative):
573
+ """Mixin class to indicate when mapping this class, also convert it to be
574
+ a dataclass.
575
+
576
+ .. seealso::
577
+
578
+ :ref:`orm_declarative_native_dataclasses` - complete background
579
+ on SQLAlchemy native dataclass mapping
580
+
581
+ .. versionadded:: 2.0
582
+
583
+ """
584
+
585
+ def __init_subclass__(
586
+ cls,
587
+ init: Union[_NoArg, bool] = _NoArg.NO_ARG,
588
+ repr: Union[_NoArg, bool] = _NoArg.NO_ARG, # noqa: A002
589
+ eq: Union[_NoArg, bool] = _NoArg.NO_ARG,
590
+ order: Union[_NoArg, bool] = _NoArg.NO_ARG,
591
+ unsafe_hash: Union[_NoArg, bool] = _NoArg.NO_ARG,
592
+ match_args: Union[_NoArg, bool] = _NoArg.NO_ARG,
593
+ kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG,
594
+ dataclass_callable: Union[
595
+ _NoArg, Callable[..., Type[Any]]
596
+ ] = _NoArg.NO_ARG,
597
+ **kw: Any,
598
+ ) -> None:
599
+ apply_dc_transforms: _DataclassArguments = {
600
+ "init": init,
601
+ "repr": repr,
602
+ "eq": eq,
603
+ "order": order,
604
+ "unsafe_hash": unsafe_hash,
605
+ "match_args": match_args,
606
+ "kw_only": kw_only,
607
+ "dataclass_callable": dataclass_callable,
608
+ }
609
+
610
+ current_transforms: _DataclassArguments
611
+
612
+ if hasattr(cls, "_sa_apply_dc_transforms"):
613
+ current = cls._sa_apply_dc_transforms
614
+
615
+ _ClassScanMapperConfig._assert_dc_arguments(current)
616
+
617
+ cls._sa_apply_dc_transforms = current_transforms = { # type: ignore # noqa: E501
618
+ k: current.get(k, _NoArg.NO_ARG) if v is _NoArg.NO_ARG else v
619
+ for k, v in apply_dc_transforms.items()
620
+ }
621
+ else:
622
+ cls._sa_apply_dc_transforms = current_transforms = (
623
+ apply_dc_transforms
624
+ )
625
+
626
+ super().__init_subclass__(**kw)
627
+
628
+ if not _is_mapped_class(cls):
629
+ new_anno = (
630
+ _ClassScanMapperConfig._update_annotations_for_non_mapped_class
631
+ )(cls)
632
+ _ClassScanMapperConfig._apply_dataclasses_to_any_class(
633
+ current_transforms, cls, new_anno
634
+ )
635
+
636
+
637
+ class DeclarativeBase(
638
+ # Inspectable is used only by the mypy plugin
639
+ inspection.Inspectable[InstanceState[Any]],
640
+ metaclass=DeclarativeAttributeIntercept,
641
+ ):
642
+ """Base class used for declarative class definitions.
643
+
644
+ The :class:`_orm.DeclarativeBase` allows for the creation of new
645
+ declarative bases in such a way that is compatible with type checkers::
646
+
647
+
648
+ from sqlalchemy.orm import DeclarativeBase
649
+
650
+
651
+ class Base(DeclarativeBase):
652
+ pass
653
+
654
+ The above ``Base`` class is now usable as the base for new declarative
655
+ mappings. The superclass makes use of the ``__init_subclass__()``
656
+ method to set up new classes and metaclasses aren't used.
657
+
658
+ When first used, the :class:`_orm.DeclarativeBase` class instantiates a new
659
+ :class:`_orm.registry` to be used with the base, assuming one was not
660
+ provided explicitly. The :class:`_orm.DeclarativeBase` class supports
661
+ class-level attributes which act as parameters for the construction of this
662
+ registry; such as to indicate a specific :class:`_schema.MetaData`
663
+ collection as well as a specific value for
664
+ :paramref:`_orm.registry.type_annotation_map`::
665
+
666
+ from typing_extensions import Annotated
667
+
668
+ from sqlalchemy import BigInteger
669
+ from sqlalchemy import MetaData
670
+ from sqlalchemy import String
671
+ from sqlalchemy.orm import DeclarativeBase
672
+
673
+ bigint = Annotated[int, "bigint"]
674
+ my_metadata = MetaData()
675
+
676
+
677
+ class Base(DeclarativeBase):
678
+ metadata = my_metadata
679
+ type_annotation_map = {
680
+ str: String().with_variant(String(255), "mysql", "mariadb"),
681
+ bigint: BigInteger(),
682
+ }
683
+
684
+ Class-level attributes which may be specified include:
685
+
686
+ :param metadata: optional :class:`_schema.MetaData` collection.
687
+ If a :class:`_orm.registry` is constructed automatically, this
688
+ :class:`_schema.MetaData` collection will be used to construct it.
689
+ Otherwise, the local :class:`_schema.MetaData` collection will supersede
690
+ that used by an existing :class:`_orm.registry` passed using the
691
+ :paramref:`_orm.DeclarativeBase.registry` parameter.
692
+ :param type_annotation_map: optional type annotation map that will be
693
+ passed to the :class:`_orm.registry` as
694
+ :paramref:`_orm.registry.type_annotation_map`.
695
+ :param registry: supply a pre-existing :class:`_orm.registry` directly.
696
+
697
+ .. versionadded:: 2.0 Added :class:`.DeclarativeBase`, so that declarative
698
+ base classes may be constructed in such a way that is also recognized
699
+ by :pep:`484` type checkers. As a result, :class:`.DeclarativeBase`
700
+ and other subclassing-oriented APIs should be seen as
701
+ superseding previous "class returned by a function" APIs, namely
702
+ :func:`_orm.declarative_base` and :meth:`_orm.registry.generate_base`,
703
+ where the base class returned cannot be recognized by type checkers
704
+ without using plugins.
705
+
706
+ **__init__ behavior**
707
+
708
+ In a plain Python class, the base-most ``__init__()`` method in the class
709
+ hierarchy is ``object.__init__()``, which accepts no arguments. However,
710
+ when the :class:`_orm.DeclarativeBase` subclass is first declared, the
711
+ class is given an ``__init__()`` method that links to the
712
+ :paramref:`_orm.registry.constructor` constructor function, if no
713
+ ``__init__()`` method is already present; this is the usual declarative
714
+ constructor that will assign keyword arguments as attributes on the
715
+ instance, assuming those attributes are established at the class level
716
+ (i.e. are mapped, or are linked to a descriptor). This constructor is
717
+ **never accessed by a mapped class without being called explicitly via
718
+ super()**, as mapped classes are themselves given an ``__init__()`` method
719
+ directly which calls :paramref:`_orm.registry.constructor`, so in the
720
+ default case works independently of what the base-most ``__init__()``
721
+ method does.
722
+
723
+ .. versionchanged:: 2.0.1 :class:`_orm.DeclarativeBase` has a default
724
+ constructor that links to :paramref:`_orm.registry.constructor` by
725
+ default, so that calls to ``super().__init__()`` can access this
726
+ constructor. Previously, due to an implementation mistake, this default
727
+ constructor was missing, and calling ``super().__init__()`` would invoke
728
+ ``object.__init__()``.
729
+
730
+ The :class:`_orm.DeclarativeBase` subclass may also declare an explicit
731
+ ``__init__()`` method which will replace the use of the
732
+ :paramref:`_orm.registry.constructor` function at this level::
733
+
734
+ class Base(DeclarativeBase):
735
+ def __init__(self, id=None):
736
+ self.id = id
737
+
738
+ Mapped classes still will not invoke this constructor implicitly; it
739
+ remains only accessible by calling ``super().__init__()``::
740
+
741
+ class MyClass(Base):
742
+ def __init__(self, id=None, name=None):
743
+ self.name = name
744
+ super().__init__(id=id)
745
+
746
+ Note that this is a different behavior from what functions like the legacy
747
+ :func:`_orm.declarative_base` would do; the base created by those functions
748
+ would always install :paramref:`_orm.registry.constructor` for
749
+ ``__init__()``.
750
+
751
+
752
+ """
753
+
754
+ if typing.TYPE_CHECKING:
755
+
756
+ def _sa_inspect_type(self) -> Mapper[Self]: ...
757
+
758
+ def _sa_inspect_instance(self) -> InstanceState[Self]: ...
759
+
760
+ _sa_registry: ClassVar[_RegistryType]
761
+
762
+ registry: ClassVar[_RegistryType]
763
+ """Refers to the :class:`_orm.registry` in use where new
764
+ :class:`_orm.Mapper` objects will be associated."""
765
+
766
+ metadata: ClassVar[MetaData]
767
+ """Refers to the :class:`_schema.MetaData` collection that will be used
768
+ for new :class:`_schema.Table` objects.
769
+
770
+ .. seealso::
771
+
772
+ :ref:`orm_declarative_metadata`
773
+
774
+ """
775
+
776
+ __name__: ClassVar[str]
777
+
778
+ # this ideally should be Mapper[Self], but mypy as of 1.4.1 does not
779
+ # like it, and breaks the declared_attr_one test. Pyright/pylance is
780
+ # ok with it.
781
+ __mapper__: ClassVar[Mapper[Any]]
782
+ """The :class:`_orm.Mapper` object to which a particular class is
783
+ mapped.
784
+
785
+ May also be acquired using :func:`_sa.inspect`, e.g.
786
+ ``inspect(klass)``.
787
+
788
+ """
789
+
790
+ __table__: ClassVar[FromClause]
791
+ """The :class:`_sql.FromClause` to which a particular subclass is
792
+ mapped.
793
+
794
+ This is usually an instance of :class:`_schema.Table` but may also
795
+ refer to other kinds of :class:`_sql.FromClause` such as
796
+ :class:`_sql.Subquery`, depending on how the class is mapped.
797
+
798
+ .. seealso::
799
+
800
+ :ref:`orm_declarative_metadata`
801
+
802
+ """
803
+
804
+ # pyright/pylance do not consider a classmethod a ClassVar so use Any
805
+ # https://github.com/microsoft/pylance-release/issues/3484
806
+ __tablename__: Any
807
+ """String name to assign to the generated
808
+ :class:`_schema.Table` object, if not specified directly via
809
+ :attr:`_orm.DeclarativeBase.__table__`.
810
+
811
+ .. seealso::
812
+
813
+ :ref:`orm_declarative_table`
814
+
815
+ """
816
+
817
+ __mapper_args__: Any
818
+ """Dictionary of arguments which will be passed to the
819
+ :class:`_orm.Mapper` constructor.
820
+
821
+ .. seealso::
822
+
823
+ :ref:`orm_declarative_mapper_options`
824
+
825
+ """
826
+
827
+ __table_args__: Any
828
+ """A dictionary or tuple of arguments that will be passed to the
829
+ :class:`_schema.Table` constructor. See
830
+ :ref:`orm_declarative_table_configuration`
831
+ for background on the specific structure of this collection.
832
+
833
+ .. seealso::
834
+
835
+ :ref:`orm_declarative_table_configuration`
836
+
837
+ """
838
+
839
+ def __init__(self, **kw: Any): ...
840
+
841
+ def __init_subclass__(cls, **kw: Any) -> None:
842
+ if DeclarativeBase in cls.__bases__:
843
+ _check_not_declarative(cls, DeclarativeBase)
844
+ _setup_declarative_base(cls)
845
+ else:
846
+ _as_declarative(cls._sa_registry, cls, cls.__dict__)
847
+ super().__init_subclass__(**kw)
848
+
849
+
850
+ def _check_not_declarative(cls: Type[Any], base: Type[Any]) -> None:
851
+ cls_dict = cls.__dict__
852
+ if (
853
+ "__table__" in cls_dict
854
+ and not (
855
+ callable(cls_dict["__table__"])
856
+ or hasattr(cls_dict["__table__"], "__get__")
857
+ )
858
+ ) or isinstance(cls_dict.get("__tablename__", None), str):
859
+ raise exc.InvalidRequestError(
860
+ f"Cannot use {base.__name__!r} directly as a declarative base "
861
+ "class. Create a Base by creating a subclass of it."
862
+ )
863
+
864
+
865
+ class DeclarativeBaseNoMeta(
866
+ # Inspectable is used only by the mypy plugin
867
+ inspection.Inspectable[InstanceState[Any]]
868
+ ):
869
+ """Same as :class:`_orm.DeclarativeBase`, but does not use a metaclass
870
+ to intercept new attributes.
871
+
872
+ The :class:`_orm.DeclarativeBaseNoMeta` base may be used when use of
873
+ custom metaclasses is desirable.
874
+
875
+ .. versionadded:: 2.0
876
+
877
+
878
+ """
879
+
880
+ _sa_registry: ClassVar[_RegistryType]
881
+
882
+ registry: ClassVar[_RegistryType]
883
+ """Refers to the :class:`_orm.registry` in use where new
884
+ :class:`_orm.Mapper` objects will be associated."""
885
+
886
+ metadata: ClassVar[MetaData]
887
+ """Refers to the :class:`_schema.MetaData` collection that will be used
888
+ for new :class:`_schema.Table` objects.
889
+
890
+ .. seealso::
891
+
892
+ :ref:`orm_declarative_metadata`
893
+
894
+ """
895
+
896
+ # this ideally should be Mapper[Self], but mypy as of 1.4.1 does not
897
+ # like it, and breaks the declared_attr_one test. Pyright/pylance is
898
+ # ok with it.
899
+ __mapper__: ClassVar[Mapper[Any]]
900
+ """The :class:`_orm.Mapper` object to which a particular class is
901
+ mapped.
902
+
903
+ May also be acquired using :func:`_sa.inspect`, e.g.
904
+ ``inspect(klass)``.
905
+
906
+ """
907
+
908
+ __table__: Optional[FromClause]
909
+ """The :class:`_sql.FromClause` to which a particular subclass is
910
+ mapped.
911
+
912
+ This is usually an instance of :class:`_schema.Table` but may also
913
+ refer to other kinds of :class:`_sql.FromClause` such as
914
+ :class:`_sql.Subquery`, depending on how the class is mapped.
915
+
916
+ .. seealso::
917
+
918
+ :ref:`orm_declarative_metadata`
919
+
920
+ """
921
+
922
+ if typing.TYPE_CHECKING:
923
+
924
+ def _sa_inspect_type(self) -> Mapper[Self]: ...
925
+
926
+ def _sa_inspect_instance(self) -> InstanceState[Self]: ...
927
+
928
+ __tablename__: Any
929
+ """String name to assign to the generated
930
+ :class:`_schema.Table` object, if not specified directly via
931
+ :attr:`_orm.DeclarativeBase.__table__`.
932
+
933
+ .. seealso::
934
+
935
+ :ref:`orm_declarative_table`
936
+
937
+ """
938
+
939
+ __mapper_args__: Any
940
+ """Dictionary of arguments which will be passed to the
941
+ :class:`_orm.Mapper` constructor.
942
+
943
+ .. seealso::
944
+
945
+ :ref:`orm_declarative_mapper_options`
946
+
947
+ """
948
+
949
+ __table_args__: Any
950
+ """A dictionary or tuple of arguments that will be passed to the
951
+ :class:`_schema.Table` constructor. See
952
+ :ref:`orm_declarative_table_configuration`
953
+ for background on the specific structure of this collection.
954
+
955
+ .. seealso::
956
+
957
+ :ref:`orm_declarative_table_configuration`
958
+
959
+ """
960
+
961
+ def __init__(self, **kw: Any): ...
962
+
963
+ def __init_subclass__(cls, **kw: Any) -> None:
964
+ if DeclarativeBaseNoMeta in cls.__bases__:
965
+ _check_not_declarative(cls, DeclarativeBaseNoMeta)
966
+ _setup_declarative_base(cls)
967
+ else:
968
+ _as_declarative(cls._sa_registry, cls, cls.__dict__)
969
+ super().__init_subclass__(**kw)
970
+
971
+
972
+ def add_mapped_attribute(
973
+ target: Type[_O], key: str, attr: MapperProperty[Any]
974
+ ) -> None:
975
+ """Add a new mapped attribute to an ORM mapped class.
976
+
977
+ E.g.::
978
+
979
+ add_mapped_attribute(User, "addresses", relationship(Address))
980
+
981
+ This may be used for ORM mappings that aren't using a declarative
982
+ metaclass that intercepts attribute set operations.
983
+
984
+ .. versionadded:: 2.0
985
+
986
+
987
+ """
988
+ _add_attribute(target, key, attr)
989
+
990
+
991
+ def declarative_base(
992
+ *,
993
+ metadata: Optional[MetaData] = None,
994
+ mapper: Optional[Callable[..., Mapper[Any]]] = None,
995
+ cls: Type[Any] = object,
996
+ name: str = "Base",
997
+ class_registry: Optional[clsregistry._ClsRegistryType] = None,
998
+ type_annotation_map: Optional[_TypeAnnotationMapType] = None,
999
+ constructor: Callable[..., None] = _declarative_constructor,
1000
+ metaclass: Type[Any] = DeclarativeMeta,
1001
+ ) -> Any:
1002
+ r"""Construct a base class for declarative class definitions.
1003
+
1004
+ The new base class will be given a metaclass that produces
1005
+ appropriate :class:`~sqlalchemy.schema.Table` objects and makes
1006
+ the appropriate :class:`_orm.Mapper` calls based on the
1007
+ information provided declaratively in the class and any subclasses
1008
+ of the class.
1009
+
1010
+ .. versionchanged:: 2.0 Note that the :func:`_orm.declarative_base`
1011
+ function is superseded by the new :class:`_orm.DeclarativeBase` class,
1012
+ which generates a new "base" class using subclassing, rather than
1013
+ return value of a function. This allows an approach that is compatible
1014
+ with :pep:`484` typing tools.
1015
+
1016
+ The :func:`_orm.declarative_base` function is a shorthand version
1017
+ of using the :meth:`_orm.registry.generate_base`
1018
+ method. That is, the following::
1019
+
1020
+ from sqlalchemy.orm import declarative_base
1021
+
1022
+ Base = declarative_base()
1023
+
1024
+ Is equivalent to::
1025
+
1026
+ from sqlalchemy.orm import registry
1027
+
1028
+ mapper_registry = registry()
1029
+ Base = mapper_registry.generate_base()
1030
+
1031
+ See the docstring for :class:`_orm.registry`
1032
+ and :meth:`_orm.registry.generate_base`
1033
+ for more details.
1034
+
1035
+ .. versionchanged:: 1.4 The :func:`_orm.declarative_base`
1036
+ function is now a specialization of the more generic
1037
+ :class:`_orm.registry` class. The function also moves to the
1038
+ ``sqlalchemy.orm`` package from the ``declarative.ext`` package.
1039
+
1040
+
1041
+ :param metadata:
1042
+ An optional :class:`~sqlalchemy.schema.MetaData` instance. All
1043
+ :class:`~sqlalchemy.schema.Table` objects implicitly declared by
1044
+ subclasses of the base will share this MetaData. A MetaData instance
1045
+ will be created if none is provided. The
1046
+ :class:`~sqlalchemy.schema.MetaData` instance will be available via the
1047
+ ``metadata`` attribute of the generated declarative base class.
1048
+
1049
+ :param mapper:
1050
+ An optional callable, defaults to :class:`_orm.Mapper`. Will
1051
+ be used to map subclasses to their Tables.
1052
+
1053
+ :param cls:
1054
+ Defaults to :class:`object`. A type to use as the base for the generated
1055
+ declarative base class. May be a class or tuple of classes.
1056
+
1057
+ :param name:
1058
+ Defaults to ``Base``. The display name for the generated
1059
+ class. Customizing this is not required, but can improve clarity in
1060
+ tracebacks and debugging.
1061
+
1062
+ :param constructor:
1063
+ Specify the implementation for the ``__init__`` function on a mapped
1064
+ class that has no ``__init__`` of its own. Defaults to an
1065
+ implementation that assigns \**kwargs for declared
1066
+ fields and relationships to an instance. If ``None`` is supplied,
1067
+ no __init__ will be provided and construction will fall back to
1068
+ cls.__init__ by way of the normal Python semantics.
1069
+
1070
+ :param class_registry: optional dictionary that will serve as the
1071
+ registry of class names-> mapped classes when string names
1072
+ are used to identify classes inside of :func:`_orm.relationship`
1073
+ and others. Allows two or more declarative base classes
1074
+ to share the same registry of class names for simplified
1075
+ inter-base relationships.
1076
+
1077
+ :param type_annotation_map: optional dictionary of Python types to
1078
+ SQLAlchemy :class:`_types.TypeEngine` classes or instances. This
1079
+ is used exclusively by the :class:`_orm.MappedColumn` construct
1080
+ to produce column types based on annotations within the
1081
+ :class:`_orm.Mapped` type.
1082
+
1083
+
1084
+ .. versionadded:: 2.0
1085
+
1086
+ .. seealso::
1087
+
1088
+ :ref:`orm_declarative_mapped_column_type_map`
1089
+
1090
+ :param metaclass:
1091
+ Defaults to :class:`.DeclarativeMeta`. A metaclass or __metaclass__
1092
+ compatible callable to use as the meta type of the generated
1093
+ declarative base class.
1094
+
1095
+ .. seealso::
1096
+
1097
+ :class:`_orm.registry`
1098
+
1099
+ """
1100
+
1101
+ return registry(
1102
+ metadata=metadata,
1103
+ class_registry=class_registry,
1104
+ constructor=constructor,
1105
+ type_annotation_map=type_annotation_map,
1106
+ ).generate_base(
1107
+ mapper=mapper,
1108
+ cls=cls,
1109
+ name=name,
1110
+ metaclass=metaclass,
1111
+ )
1112
+
1113
+
1114
+ class registry:
1115
+ """Generalized registry for mapping classes.
1116
+
1117
+ The :class:`_orm.registry` serves as the basis for maintaining a collection
1118
+ of mappings, and provides configurational hooks used to map classes.
1119
+
1120
+ The three general kinds of mappings supported are Declarative Base,
1121
+ Declarative Decorator, and Imperative Mapping. All of these mapping
1122
+ styles may be used interchangeably:
1123
+
1124
+ * :meth:`_orm.registry.generate_base` returns a new declarative base
1125
+ class, and is the underlying implementation of the
1126
+ :func:`_orm.declarative_base` function.
1127
+
1128
+ * :meth:`_orm.registry.mapped` provides a class decorator that will
1129
+ apply declarative mapping to a class without the use of a declarative
1130
+ base class.
1131
+
1132
+ * :meth:`_orm.registry.map_imperatively` will produce a
1133
+ :class:`_orm.Mapper` for a class without scanning the class for
1134
+ declarative class attributes. This method suits the use case historically
1135
+ provided by the ``sqlalchemy.orm.mapper()`` classical mapping function,
1136
+ which is removed as of SQLAlchemy 2.0.
1137
+
1138
+ .. versionadded:: 1.4
1139
+
1140
+ .. seealso::
1141
+
1142
+ :ref:`orm_mapping_classes_toplevel` - overview of class mapping
1143
+ styles.
1144
+
1145
+ """
1146
+
1147
+ _class_registry: clsregistry._ClsRegistryType
1148
+ _managers: weakref.WeakKeyDictionary[ClassManager[Any], Literal[True]]
1149
+ _non_primary_mappers: weakref.WeakKeyDictionary[Mapper[Any], Literal[True]]
1150
+ metadata: MetaData
1151
+ constructor: CallableReference[Callable[..., None]]
1152
+ type_annotation_map: _MutableTypeAnnotationMapType
1153
+ _dependents: Set[_RegistryType]
1154
+ _dependencies: Set[_RegistryType]
1155
+ _new_mappers: bool
1156
+
1157
+ def __init__(
1158
+ self,
1159
+ *,
1160
+ metadata: Optional[MetaData] = None,
1161
+ class_registry: Optional[clsregistry._ClsRegistryType] = None,
1162
+ type_annotation_map: Optional[_TypeAnnotationMapType] = None,
1163
+ constructor: Callable[..., None] = _declarative_constructor,
1164
+ ):
1165
+ r"""Construct a new :class:`_orm.registry`
1166
+
1167
+ :param metadata:
1168
+ An optional :class:`_schema.MetaData` instance. All
1169
+ :class:`_schema.Table` objects generated using declarative
1170
+ table mapping will make use of this :class:`_schema.MetaData`
1171
+ collection. If this argument is left at its default of ``None``,
1172
+ a blank :class:`_schema.MetaData` collection is created.
1173
+
1174
+ :param constructor:
1175
+ Specify the implementation for the ``__init__`` function on a mapped
1176
+ class that has no ``__init__`` of its own. Defaults to an
1177
+ implementation that assigns \**kwargs for declared
1178
+ fields and relationships to an instance. If ``None`` is supplied,
1179
+ no __init__ will be provided and construction will fall back to
1180
+ cls.__init__ by way of the normal Python semantics.
1181
+
1182
+ :param class_registry: optional dictionary that will serve as the
1183
+ registry of class names-> mapped classes when string names
1184
+ are used to identify classes inside of :func:`_orm.relationship`
1185
+ and others. Allows two or more declarative base classes
1186
+ to share the same registry of class names for simplified
1187
+ inter-base relationships.
1188
+
1189
+ :param type_annotation_map: optional dictionary of Python types to
1190
+ SQLAlchemy :class:`_types.TypeEngine` classes or instances.
1191
+ The provided dict will update the default type mapping. This
1192
+ is used exclusively by the :class:`_orm.MappedColumn` construct
1193
+ to produce column types based on annotations within the
1194
+ :class:`_orm.Mapped` type.
1195
+
1196
+ .. versionadded:: 2.0
1197
+
1198
+ .. seealso::
1199
+
1200
+ :ref:`orm_declarative_mapped_column_type_map`
1201
+
1202
+
1203
+ """
1204
+ lcl_metadata = metadata or MetaData()
1205
+
1206
+ if class_registry is None:
1207
+ class_registry = weakref.WeakValueDictionary()
1208
+
1209
+ self._class_registry = class_registry
1210
+ self._managers = weakref.WeakKeyDictionary()
1211
+ self._non_primary_mappers = weakref.WeakKeyDictionary()
1212
+ self.metadata = lcl_metadata
1213
+ self.constructor = constructor
1214
+ self.type_annotation_map = {}
1215
+ if type_annotation_map is not None:
1216
+ self.update_type_annotation_map(type_annotation_map)
1217
+ self._dependents = set()
1218
+ self._dependencies = set()
1219
+
1220
+ self._new_mappers = False
1221
+
1222
+ with mapperlib._CONFIGURE_MUTEX:
1223
+ mapperlib._mapper_registries[self] = True
1224
+
1225
+ def update_type_annotation_map(
1226
+ self,
1227
+ type_annotation_map: _TypeAnnotationMapType,
1228
+ ) -> None:
1229
+ """update the :paramref:`_orm.registry.type_annotation_map` with new
1230
+ values."""
1231
+
1232
+ self.type_annotation_map.update(
1233
+ {
1234
+ de_optionalize_union_types(typ): sqltype
1235
+ for typ, sqltype in type_annotation_map.items()
1236
+ }
1237
+ )
1238
+
1239
+ def _resolve_type(
1240
+ self, python_type: _MatchedOnType, _do_fallbacks: bool = False
1241
+ ) -> Optional[sqltypes.TypeEngine[Any]]:
1242
+ python_type_type: Type[Any]
1243
+ search: Iterable[Tuple[_MatchedOnType, Type[Any]]]
1244
+
1245
+ if is_generic(python_type):
1246
+ if is_literal(python_type):
1247
+ python_type_type = python_type # type: ignore[assignment]
1248
+
1249
+ search = (
1250
+ (python_type, python_type_type),
1251
+ *((lt, python_type_type) for lt in LITERAL_TYPES),
1252
+ )
1253
+ else:
1254
+ python_type_type = python_type.__origin__
1255
+ search = ((python_type, python_type_type),)
1256
+ elif isinstance(python_type, type):
1257
+ python_type_type = python_type
1258
+ search = ((pt, pt) for pt in python_type_type.__mro__)
1259
+ else:
1260
+ python_type_type = python_type # type: ignore[assignment]
1261
+ search = ((python_type, python_type_type),)
1262
+
1263
+ for pt, flattened in search:
1264
+ # we search through full __mro__ for types. however...
1265
+ sql_type = self.type_annotation_map.get(pt)
1266
+ if sql_type is None:
1267
+ sql_type = sqltypes._type_map_get(pt) # type: ignore # noqa: E501
1268
+
1269
+ if sql_type is not None:
1270
+ sql_type_inst = sqltypes.to_instance(sql_type)
1271
+
1272
+ # ... this additional step will reject most
1273
+ # type -> supertype matches, such as if we had
1274
+ # a MyInt(int) subclass. note also we pass NewType()
1275
+ # here directly; these always have to be in the
1276
+ # type_annotation_map to be useful
1277
+ resolved_sql_type = sql_type_inst._resolve_for_python_type(
1278
+ python_type_type,
1279
+ pt,
1280
+ flattened,
1281
+ )
1282
+ if resolved_sql_type is not None:
1283
+ return resolved_sql_type
1284
+
1285
+ # 2.0 fallbacks
1286
+ if _do_fallbacks:
1287
+ python_type_to_check: Any = None
1288
+ kind = None
1289
+ if is_pep695(python_type):
1290
+ # NOTE: assume there aren't type alias types of new types.
1291
+ python_type_to_check = python_type
1292
+ while is_pep695(python_type_to_check) and not is_pep593(
1293
+ python_type_to_check
1294
+ ):
1295
+ python_type_to_check = python_type_to_check.__value__
1296
+ python_type_to_check = de_optionalize_union_types(
1297
+ python_type_to_check
1298
+ )
1299
+ kind = "pep-695 type"
1300
+ if is_newtype(python_type):
1301
+ python_type_to_check = flatten_newtype(python_type)
1302
+ kind = "NewType"
1303
+
1304
+ if python_type_to_check is not None:
1305
+ res_after_fallback = self._resolve_type(
1306
+ python_type_to_check, False
1307
+ )
1308
+ if res_after_fallback is not None:
1309
+ assert kind is not None
1310
+ if kind == "pep-695 type":
1311
+ warn_deprecated(
1312
+ f"Matching to {kind} '{python_type}' in "
1313
+ "a recursive "
1314
+ "fashion without the recursed type being present "
1315
+ "in the type_annotation_map is deprecated; add "
1316
+ "this type or its recursed value to "
1317
+ "the type_annotation_map to allow it to match "
1318
+ "explicitly.",
1319
+ "2.0",
1320
+ )
1321
+ else:
1322
+ warn_deprecated(
1323
+ f"Matching the provided {kind} '{python_type}' on "
1324
+ "its resolved value without matching it in the "
1325
+ "type_annotation_map is deprecated; add this "
1326
+ "type to "
1327
+ "the type_annotation_map to allow it to match "
1328
+ "explicitly.",
1329
+ "2.0",
1330
+ )
1331
+ return res_after_fallback
1332
+
1333
+ return None
1334
+
1335
+ @property
1336
+ def mappers(self) -> FrozenSet[Mapper[Any]]:
1337
+ """read only collection of all :class:`_orm.Mapper` objects."""
1338
+
1339
+ return frozenset(manager.mapper for manager in self._managers).union(
1340
+ self._non_primary_mappers
1341
+ )
1342
+
1343
+ def _set_depends_on(self, registry: RegistryType) -> None:
1344
+ if registry is self:
1345
+ return
1346
+ registry._dependents.add(self)
1347
+ self._dependencies.add(registry)
1348
+
1349
+ def _flag_new_mapper(self, mapper: Mapper[Any]) -> None:
1350
+ mapper._ready_for_configure = True
1351
+ if self._new_mappers:
1352
+ return
1353
+
1354
+ for reg in self._recurse_with_dependents({self}):
1355
+ reg._new_mappers = True
1356
+
1357
+ @classmethod
1358
+ def _recurse_with_dependents(
1359
+ cls, registries: Set[RegistryType]
1360
+ ) -> Iterator[RegistryType]:
1361
+ todo = registries
1362
+ done = set()
1363
+ while todo:
1364
+ reg = todo.pop()
1365
+ done.add(reg)
1366
+
1367
+ # if yielding would remove dependents, make sure we have
1368
+ # them before
1369
+ todo.update(reg._dependents.difference(done))
1370
+ yield reg
1371
+
1372
+ # if yielding would add dependents, make sure we have them
1373
+ # after
1374
+ todo.update(reg._dependents.difference(done))
1375
+
1376
+ @classmethod
1377
+ def _recurse_with_dependencies(
1378
+ cls, registries: Set[RegistryType]
1379
+ ) -> Iterator[RegistryType]:
1380
+ todo = registries
1381
+ done = set()
1382
+ while todo:
1383
+ reg = todo.pop()
1384
+ done.add(reg)
1385
+
1386
+ # if yielding would remove dependencies, make sure we have
1387
+ # them before
1388
+ todo.update(reg._dependencies.difference(done))
1389
+
1390
+ yield reg
1391
+
1392
+ # if yielding would remove dependencies, make sure we have
1393
+ # them before
1394
+ todo.update(reg._dependencies.difference(done))
1395
+
1396
+ def _mappers_to_configure(self) -> Iterator[Mapper[Any]]:
1397
+ return itertools.chain(
1398
+ (
1399
+ manager.mapper
1400
+ for manager in list(self._managers)
1401
+ if manager.is_mapped
1402
+ and not manager.mapper.configured
1403
+ and manager.mapper._ready_for_configure
1404
+ ),
1405
+ (
1406
+ npm
1407
+ for npm in list(self._non_primary_mappers)
1408
+ if not npm.configured and npm._ready_for_configure
1409
+ ),
1410
+ )
1411
+
1412
+ def _add_non_primary_mapper(self, np_mapper: Mapper[Any]) -> None:
1413
+ self._non_primary_mappers[np_mapper] = True
1414
+
1415
+ def _dispose_cls(self, cls: Type[_O]) -> None:
1416
+ clsregistry.remove_class(cls.__name__, cls, self._class_registry)
1417
+
1418
+ def _add_manager(self, manager: ClassManager[Any]) -> None:
1419
+ self._managers[manager] = True
1420
+ if manager.is_mapped:
1421
+ raise exc.ArgumentError(
1422
+ "Class '%s' already has a primary mapper defined. "
1423
+ % manager.class_
1424
+ )
1425
+ assert manager.registry is None
1426
+ manager.registry = self
1427
+
1428
+ def configure(self, cascade: bool = False) -> None:
1429
+ """Configure all as-yet unconfigured mappers in this
1430
+ :class:`_orm.registry`.
1431
+
1432
+ The configure step is used to reconcile and initialize the
1433
+ :func:`_orm.relationship` linkages between mapped classes, as well as
1434
+ to invoke configuration events such as the
1435
+ :meth:`_orm.MapperEvents.before_configured` and
1436
+ :meth:`_orm.MapperEvents.after_configured`, which may be used by ORM
1437
+ extensions or user-defined extension hooks.
1438
+
1439
+ If one or more mappers in this registry contain
1440
+ :func:`_orm.relationship` constructs that refer to mapped classes in
1441
+ other registries, this registry is said to be *dependent* on those
1442
+ registries. In order to configure those dependent registries
1443
+ automatically, the :paramref:`_orm.registry.configure.cascade` flag
1444
+ should be set to ``True``. Otherwise, if they are not configured, an
1445
+ exception will be raised. The rationale behind this behavior is to
1446
+ allow an application to programmatically invoke configuration of
1447
+ registries while controlling whether or not the process implicitly
1448
+ reaches other registries.
1449
+
1450
+ As an alternative to invoking :meth:`_orm.registry.configure`, the ORM
1451
+ function :func:`_orm.configure_mappers` function may be used to ensure
1452
+ configuration is complete for all :class:`_orm.registry` objects in
1453
+ memory. This is generally simpler to use and also predates the usage of
1454
+ :class:`_orm.registry` objects overall. However, this function will
1455
+ impact all mappings throughout the running Python process and may be
1456
+ more memory/time consuming for an application that has many registries
1457
+ in use for different purposes that may not be needed immediately.
1458
+
1459
+ .. seealso::
1460
+
1461
+ :func:`_orm.configure_mappers`
1462
+
1463
+
1464
+ .. versionadded:: 1.4.0b2
1465
+
1466
+ """
1467
+ mapperlib._configure_registries({self}, cascade=cascade)
1468
+
1469
+ def dispose(self, cascade: bool = False) -> None:
1470
+ """Dispose of all mappers in this :class:`_orm.registry`.
1471
+
1472
+ After invocation, all the classes that were mapped within this registry
1473
+ will no longer have class instrumentation associated with them. This
1474
+ method is the per-:class:`_orm.registry` analogue to the
1475
+ application-wide :func:`_orm.clear_mappers` function.
1476
+
1477
+ If this registry contains mappers that are dependencies of other
1478
+ registries, typically via :func:`_orm.relationship` links, then those
1479
+ registries must be disposed as well. When such registries exist in
1480
+ relation to this one, their :meth:`_orm.registry.dispose` method will
1481
+ also be called, if the :paramref:`_orm.registry.dispose.cascade` flag
1482
+ is set to ``True``; otherwise, an error is raised if those registries
1483
+ were not already disposed.
1484
+
1485
+ .. versionadded:: 1.4.0b2
1486
+
1487
+ .. seealso::
1488
+
1489
+ :func:`_orm.clear_mappers`
1490
+
1491
+ """
1492
+
1493
+ mapperlib._dispose_registries({self}, cascade=cascade)
1494
+
1495
+ def _dispose_manager_and_mapper(self, manager: ClassManager[Any]) -> None:
1496
+ if "mapper" in manager.__dict__:
1497
+ mapper = manager.mapper
1498
+
1499
+ mapper._set_dispose_flags()
1500
+
1501
+ class_ = manager.class_
1502
+ self._dispose_cls(class_)
1503
+ instrumentation._instrumentation_factory.unregister(class_)
1504
+
1505
+ def generate_base(
1506
+ self,
1507
+ mapper: Optional[Callable[..., Mapper[Any]]] = None,
1508
+ cls: Type[Any] = object,
1509
+ name: str = "Base",
1510
+ metaclass: Type[Any] = DeclarativeMeta,
1511
+ ) -> Any:
1512
+ """Generate a declarative base class.
1513
+
1514
+ Classes that inherit from the returned class object will be
1515
+ automatically mapped using declarative mapping.
1516
+
1517
+ E.g.::
1518
+
1519
+ from sqlalchemy.orm import registry
1520
+
1521
+ mapper_registry = registry()
1522
+
1523
+ Base = mapper_registry.generate_base()
1524
+
1525
+
1526
+ class MyClass(Base):
1527
+ __tablename__ = "my_table"
1528
+ id = Column(Integer, primary_key=True)
1529
+
1530
+ The above dynamically generated class is equivalent to the
1531
+ non-dynamic example below::
1532
+
1533
+ from sqlalchemy.orm import registry
1534
+ from sqlalchemy.orm.decl_api import DeclarativeMeta
1535
+
1536
+ mapper_registry = registry()
1537
+
1538
+
1539
+ class Base(metaclass=DeclarativeMeta):
1540
+ __abstract__ = True
1541
+ registry = mapper_registry
1542
+ metadata = mapper_registry.metadata
1543
+
1544
+ __init__ = mapper_registry.constructor
1545
+
1546
+ .. versionchanged:: 2.0 Note that the
1547
+ :meth:`_orm.registry.generate_base` method is superseded by the new
1548
+ :class:`_orm.DeclarativeBase` class, which generates a new "base"
1549
+ class using subclassing, rather than return value of a function.
1550
+ This allows an approach that is compatible with :pep:`484` typing
1551
+ tools.
1552
+
1553
+ The :meth:`_orm.registry.generate_base` method provides the
1554
+ implementation for the :func:`_orm.declarative_base` function, which
1555
+ creates the :class:`_orm.registry` and base class all at once.
1556
+
1557
+ See the section :ref:`orm_declarative_mapping` for background and
1558
+ examples.
1559
+
1560
+ :param mapper:
1561
+ An optional callable, defaults to :class:`_orm.Mapper`.
1562
+ This function is used to generate new :class:`_orm.Mapper` objects.
1563
+
1564
+ :param cls:
1565
+ Defaults to :class:`object`. A type to use as the base for the
1566
+ generated declarative base class. May be a class or tuple of classes.
1567
+
1568
+ :param name:
1569
+ Defaults to ``Base``. The display name for the generated
1570
+ class. Customizing this is not required, but can improve clarity in
1571
+ tracebacks and debugging.
1572
+
1573
+ :param metaclass:
1574
+ Defaults to :class:`.DeclarativeMeta`. A metaclass or __metaclass__
1575
+ compatible callable to use as the meta type of the generated
1576
+ declarative base class.
1577
+
1578
+ .. seealso::
1579
+
1580
+ :ref:`orm_declarative_mapping`
1581
+
1582
+ :func:`_orm.declarative_base`
1583
+
1584
+ """
1585
+ metadata = self.metadata
1586
+
1587
+ bases = not isinstance(cls, tuple) and (cls,) or cls
1588
+
1589
+ class_dict: Dict[str, Any] = dict(registry=self, metadata=metadata)
1590
+ if isinstance(cls, type):
1591
+ class_dict["__doc__"] = cls.__doc__
1592
+
1593
+ if self.constructor is not None:
1594
+ class_dict["__init__"] = self.constructor
1595
+
1596
+ class_dict["__abstract__"] = True
1597
+ if mapper:
1598
+ class_dict["__mapper_cls__"] = mapper
1599
+
1600
+ if hasattr(cls, "__class_getitem__"):
1601
+
1602
+ def __class_getitem__(cls: Type[_T], key: Any) -> Type[_T]:
1603
+ # allow generic classes in py3.9+
1604
+ return cls
1605
+
1606
+ class_dict["__class_getitem__"] = __class_getitem__
1607
+
1608
+ return metaclass(name, bases, class_dict)
1609
+
1610
+ @compat_typing.dataclass_transform(
1611
+ field_specifiers=(
1612
+ MappedColumn,
1613
+ RelationshipProperty,
1614
+ Composite,
1615
+ Synonym,
1616
+ mapped_column,
1617
+ relationship,
1618
+ composite,
1619
+ synonym,
1620
+ deferred,
1621
+ ),
1622
+ )
1623
+ @overload
1624
+ def mapped_as_dataclass(self, __cls: Type[_O]) -> Type[_O]: ...
1625
+
1626
+ @overload
1627
+ def mapped_as_dataclass(
1628
+ self,
1629
+ __cls: Literal[None] = ...,
1630
+ *,
1631
+ init: Union[_NoArg, bool] = ...,
1632
+ repr: Union[_NoArg, bool] = ..., # noqa: A002
1633
+ eq: Union[_NoArg, bool] = ...,
1634
+ order: Union[_NoArg, bool] = ...,
1635
+ unsafe_hash: Union[_NoArg, bool] = ...,
1636
+ match_args: Union[_NoArg, bool] = ...,
1637
+ kw_only: Union[_NoArg, bool] = ...,
1638
+ dataclass_callable: Union[_NoArg, Callable[..., Type[Any]]] = ...,
1639
+ ) -> Callable[[Type[_O]], Type[_O]]: ...
1640
+
1641
+ def mapped_as_dataclass(
1642
+ self,
1643
+ __cls: Optional[Type[_O]] = None,
1644
+ *,
1645
+ init: Union[_NoArg, bool] = _NoArg.NO_ARG,
1646
+ repr: Union[_NoArg, bool] = _NoArg.NO_ARG, # noqa: A002
1647
+ eq: Union[_NoArg, bool] = _NoArg.NO_ARG,
1648
+ order: Union[_NoArg, bool] = _NoArg.NO_ARG,
1649
+ unsafe_hash: Union[_NoArg, bool] = _NoArg.NO_ARG,
1650
+ match_args: Union[_NoArg, bool] = _NoArg.NO_ARG,
1651
+ kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG,
1652
+ dataclass_callable: Union[
1653
+ _NoArg, Callable[..., Type[Any]]
1654
+ ] = _NoArg.NO_ARG,
1655
+ ) -> Union[Type[_O], Callable[[Type[_O]], Type[_O]]]:
1656
+ """Class decorator that will apply the Declarative mapping process
1657
+ to a given class, and additionally convert the class to be a
1658
+ Python dataclass.
1659
+
1660
+ .. seealso::
1661
+
1662
+ :ref:`orm_declarative_native_dataclasses` - complete background
1663
+ on SQLAlchemy native dataclass mapping
1664
+
1665
+ :func:`_orm.mapped_as_dataclass` - functional version that may
1666
+ provide better compatibility with mypy
1667
+
1668
+ .. versionadded:: 2.0
1669
+
1670
+
1671
+ """
1672
+
1673
+ def decorate(cls: Type[_O]) -> Type[_O]:
1674
+ setattr(
1675
+ cls,
1676
+ "_sa_apply_dc_transforms",
1677
+ {
1678
+ "init": init,
1679
+ "repr": repr,
1680
+ "eq": eq,
1681
+ "order": order,
1682
+ "unsafe_hash": unsafe_hash,
1683
+ "match_args": match_args,
1684
+ "kw_only": kw_only,
1685
+ "dataclass_callable": dataclass_callable,
1686
+ },
1687
+ )
1688
+ _as_declarative(self, cls, cls.__dict__)
1689
+ return cls
1690
+
1691
+ if __cls:
1692
+ return decorate(__cls)
1693
+ else:
1694
+ return decorate
1695
+
1696
+ def mapped(self, cls: Type[_O]) -> Type[_O]:
1697
+ """Class decorator that will apply the Declarative mapping process
1698
+ to a given class.
1699
+
1700
+ E.g.::
1701
+
1702
+ from sqlalchemy.orm import registry
1703
+
1704
+ mapper_registry = registry()
1705
+
1706
+
1707
+ @mapper_registry.mapped
1708
+ class Foo:
1709
+ __tablename__ = "some_table"
1710
+
1711
+ id = Column(Integer, primary_key=True)
1712
+ name = Column(String)
1713
+
1714
+ See the section :ref:`orm_declarative_mapping` for complete
1715
+ details and examples.
1716
+
1717
+ :param cls: class to be mapped.
1718
+
1719
+ :return: the class that was passed.
1720
+
1721
+ .. seealso::
1722
+
1723
+ :ref:`orm_declarative_mapping`
1724
+
1725
+ :meth:`_orm.registry.generate_base` - generates a base class
1726
+ that will apply Declarative mapping to subclasses automatically
1727
+ using a Python metaclass.
1728
+
1729
+ .. seealso::
1730
+
1731
+ :meth:`_orm.registry.mapped_as_dataclass`
1732
+
1733
+ """
1734
+ _as_declarative(self, cls, cls.__dict__)
1735
+ return cls
1736
+
1737
+ def as_declarative_base(self, **kw: Any) -> Callable[[Type[_T]], Type[_T]]:
1738
+ """
1739
+ Class decorator which will invoke
1740
+ :meth:`_orm.registry.generate_base`
1741
+ for a given base class.
1742
+
1743
+ E.g.::
1744
+
1745
+ from sqlalchemy.orm import registry
1746
+
1747
+ mapper_registry = registry()
1748
+
1749
+
1750
+ @mapper_registry.as_declarative_base()
1751
+ class Base:
1752
+ @declared_attr
1753
+ def __tablename__(cls):
1754
+ return cls.__name__.lower()
1755
+
1756
+ id = Column(Integer, primary_key=True)
1757
+
1758
+
1759
+ class MyMappedClass(Base): ...
1760
+
1761
+ All keyword arguments passed to
1762
+ :meth:`_orm.registry.as_declarative_base` are passed
1763
+ along to :meth:`_orm.registry.generate_base`.
1764
+
1765
+ """
1766
+
1767
+ def decorate(cls: Type[_T]) -> Type[_T]:
1768
+ kw["cls"] = cls
1769
+ kw["name"] = cls.__name__
1770
+ return self.generate_base(**kw) # type: ignore
1771
+
1772
+ return decorate
1773
+
1774
+ def map_declaratively(self, cls: Type[_O]) -> Mapper[_O]:
1775
+ """Map a class declaratively.
1776
+
1777
+ In this form of mapping, the class is scanned for mapping information,
1778
+ including for columns to be associated with a table, and/or an
1779
+ actual table object.
1780
+
1781
+ Returns the :class:`_orm.Mapper` object.
1782
+
1783
+ E.g.::
1784
+
1785
+ from sqlalchemy.orm import registry
1786
+
1787
+ mapper_registry = registry()
1788
+
1789
+
1790
+ class Foo:
1791
+ __tablename__ = "some_table"
1792
+
1793
+ id = Column(Integer, primary_key=True)
1794
+ name = Column(String)
1795
+
1796
+
1797
+ mapper = mapper_registry.map_declaratively(Foo)
1798
+
1799
+ This function is more conveniently invoked indirectly via either the
1800
+ :meth:`_orm.registry.mapped` class decorator or by subclassing a
1801
+ declarative metaclass generated from
1802
+ :meth:`_orm.registry.generate_base`.
1803
+
1804
+ See the section :ref:`orm_declarative_mapping` for complete
1805
+ details and examples.
1806
+
1807
+ :param cls: class to be mapped.
1808
+
1809
+ :return: a :class:`_orm.Mapper` object.
1810
+
1811
+ .. seealso::
1812
+
1813
+ :ref:`orm_declarative_mapping`
1814
+
1815
+ :meth:`_orm.registry.mapped` - more common decorator interface
1816
+ to this function.
1817
+
1818
+ :meth:`_orm.registry.map_imperatively`
1819
+
1820
+ """
1821
+ _as_declarative(self, cls, cls.__dict__)
1822
+ return cls.__mapper__ # type: ignore
1823
+
1824
+ def map_imperatively(
1825
+ self,
1826
+ class_: Type[_O],
1827
+ local_table: Optional[FromClause] = None,
1828
+ **kw: Any,
1829
+ ) -> Mapper[_O]:
1830
+ r"""Map a class imperatively.
1831
+
1832
+ In this form of mapping, the class is not scanned for any mapping
1833
+ information. Instead, all mapping constructs are passed as
1834
+ arguments.
1835
+
1836
+ This method is intended to be fully equivalent to the now-removed
1837
+ SQLAlchemy ``mapper()`` function, except that it's in terms of
1838
+ a particular registry.
1839
+
1840
+ E.g.::
1841
+
1842
+ from sqlalchemy.orm import registry
1843
+
1844
+ mapper_registry = registry()
1845
+
1846
+ my_table = Table(
1847
+ "my_table",
1848
+ mapper_registry.metadata,
1849
+ Column("id", Integer, primary_key=True),
1850
+ )
1851
+
1852
+
1853
+ class MyClass:
1854
+ pass
1855
+
1856
+
1857
+ mapper_registry.map_imperatively(MyClass, my_table)
1858
+
1859
+ See the section :ref:`orm_imperative_mapping` for complete background
1860
+ and usage examples.
1861
+
1862
+ :param class\_: The class to be mapped. Corresponds to the
1863
+ :paramref:`_orm.Mapper.class_` parameter.
1864
+
1865
+ :param local_table: the :class:`_schema.Table` or other
1866
+ :class:`_sql.FromClause` object that is the subject of the mapping.
1867
+ Corresponds to the
1868
+ :paramref:`_orm.Mapper.local_table` parameter.
1869
+
1870
+ :param \**kw: all other keyword arguments are passed to the
1871
+ :class:`_orm.Mapper` constructor directly.
1872
+
1873
+ .. seealso::
1874
+
1875
+ :ref:`orm_imperative_mapping`
1876
+
1877
+ :ref:`orm_declarative_mapping`
1878
+
1879
+ """
1880
+ return _mapper(self, class_, local_table, kw)
1881
+
1882
+
1883
+ RegistryType = registry
1884
+
1885
+ if not TYPE_CHECKING:
1886
+ # allow for runtime type resolution of ``ClassVar[_RegistryType]``
1887
+ _RegistryType = registry # noqa
1888
+
1889
+
1890
+ def as_declarative(**kw: Any) -> Callable[[Type[_T]], Type[_T]]:
1891
+ """
1892
+ Class decorator which will adapt a given class into a
1893
+ :func:`_orm.declarative_base`.
1894
+
1895
+ This function makes use of the :meth:`_orm.registry.as_declarative_base`
1896
+ method, by first creating a :class:`_orm.registry` automatically
1897
+ and then invoking the decorator.
1898
+
1899
+ E.g.::
1900
+
1901
+ from sqlalchemy.orm import as_declarative
1902
+
1903
+
1904
+ @as_declarative()
1905
+ class Base:
1906
+ @declared_attr
1907
+ def __tablename__(cls):
1908
+ return cls.__name__.lower()
1909
+
1910
+ id = Column(Integer, primary_key=True)
1911
+
1912
+
1913
+ class MyMappedClass(Base): ...
1914
+
1915
+ .. seealso::
1916
+
1917
+ :meth:`_orm.registry.as_declarative_base`
1918
+
1919
+ """
1920
+ metadata, class_registry = (
1921
+ kw.pop("metadata", None),
1922
+ kw.pop("class_registry", None),
1923
+ )
1924
+
1925
+ return registry(
1926
+ metadata=metadata, class_registry=class_registry
1927
+ ).as_declarative_base(**kw)
1928
+
1929
+
1930
+ @compat_typing.dataclass_transform(
1931
+ field_specifiers=(
1932
+ MappedColumn,
1933
+ RelationshipProperty,
1934
+ Composite,
1935
+ Synonym,
1936
+ mapped_column,
1937
+ relationship,
1938
+ composite,
1939
+ synonym,
1940
+ deferred,
1941
+ ),
1942
+ )
1943
+ def mapped_as_dataclass(
1944
+ registry: RegistryType,
1945
+ *,
1946
+ init: Union[_NoArg, bool] = _NoArg.NO_ARG,
1947
+ repr: Union[_NoArg, bool] = _NoArg.NO_ARG, # noqa: A002
1948
+ eq: Union[_NoArg, bool] = _NoArg.NO_ARG,
1949
+ order: Union[_NoArg, bool] = _NoArg.NO_ARG,
1950
+ unsafe_hash: Union[_NoArg, bool] = _NoArg.NO_ARG,
1951
+ match_args: Union[_NoArg, bool] = _NoArg.NO_ARG,
1952
+ kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG,
1953
+ dataclass_callable: Union[
1954
+ _NoArg, Callable[..., Type[Any]]
1955
+ ] = _NoArg.NO_ARG,
1956
+ ) -> Callable[[Type[_O]], Type[_O]]:
1957
+ """Standalone function form of :meth:`_orm.registry.mapped_as_dataclass`
1958
+ which may have better compatibility with mypy.
1959
+
1960
+ The :class:`_orm.registry` is passed as the first argument to the
1961
+ decorator.
1962
+
1963
+ e.g.::
1964
+
1965
+ from sqlalchemy.orm import Mapped
1966
+ from sqlalchemy.orm import mapped_as_dataclass
1967
+ from sqlalchemy.orm import mapped_column
1968
+ from sqlalchemy.orm import registry
1969
+
1970
+ some_registry = registry()
1971
+
1972
+
1973
+ @mapped_as_dataclass(some_registry)
1974
+ class Relationships:
1975
+ __tablename__ = "relationships"
1976
+
1977
+ entity_id1: Mapped[int] = mapped_column(primary_key=True)
1978
+ entity_id2: Mapped[int] = mapped_column(primary_key=True)
1979
+ level: Mapped[int] = mapped_column(Integer)
1980
+
1981
+ .. versionadded:: 2.0.44
1982
+
1983
+ """
1984
+ return registry.mapped_as_dataclass(
1985
+ init=init,
1986
+ repr=repr,
1987
+ eq=eq,
1988
+ order=order,
1989
+ unsafe_hash=unsafe_hash,
1990
+ match_args=match_args,
1991
+ kw_only=kw_only,
1992
+ dataclass_callable=dataclass_callable,
1993
+ )
1994
+
1995
+
1996
+ @inspection._inspects(
1997
+ DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept
1998
+ )
1999
+ def _inspect_decl_meta(cls: Type[Any]) -> Optional[Mapper[Any]]:
2000
+ mp: Optional[Mapper[Any]] = _inspect_mapped_class(cls)
2001
+ if mp is None:
2002
+ if _DeferredMapperConfig.has_cls(cls):
2003
+ _DeferredMapperConfig.raise_unmapped_for_cls(cls)
2004
+ return mp