decl_api.py 64 KB

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