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