decl_api.py 66 KB

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