Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/decl_api.py: 53%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

472 statements  

1# orm/decl_api.py 

2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: https://www.opensource.org/licenses/mit-license.php 

7 

8"""Public API functions and helpers for declarative.""" 

9 

10from __future__ import annotations 

11 

12import itertools 

13import re 

14import typing 

15from typing import Any 

16from typing import Callable 

17from typing import ClassVar 

18from typing import Dict 

19from typing import FrozenSet 

20from typing import Generic 

21from typing import Iterable 

22from typing import Iterator 

23from typing import Mapping 

24from typing import Optional 

25from typing import overload 

26from typing import Set 

27from typing import Tuple 

28from typing import Type 

29from typing import TYPE_CHECKING 

30from typing import TypeVar 

31from typing import Union 

32import weakref 

33 

34from . import attributes 

35from . import clsregistry 

36from . import instrumentation 

37from . import interfaces 

38from . import mapperlib 

39from ._orm_constructors import composite 

40from ._orm_constructors import deferred 

41from ._orm_constructors import mapped_column 

42from ._orm_constructors import relationship 

43from ._orm_constructors import synonym 

44from .attributes import InstrumentedAttribute 

45from .base import _inspect_mapped_class 

46from .base import _is_mapped_class 

47from .base import Mapped 

48from .base import ORMDescriptor 

49from .decl_base import _add_attribute 

50from .decl_base import _as_declarative 

51from .decl_base import _ClassScanMapperConfig 

52from .decl_base import _declarative_constructor 

53from .decl_base import _DeferredMapperConfig 

54from .decl_base import _del_attribute 

55from .decl_base import _mapper 

56from .descriptor_props import Composite 

57from .descriptor_props import Synonym 

58from .descriptor_props import Synonym as _orm_synonym 

59from .mapper import Mapper 

60from .properties import MappedColumn 

61from .relationships import RelationshipProperty 

62from .state import InstanceState 

63from .. import exc 

64from .. import inspection 

65from .. import util 

66from ..sql import sqltypes 

67from ..sql.base import _NoArg 

68from ..sql.elements import SQLCoreOperations 

69from ..sql.schema import MetaData 

70from ..sql.selectable import FromClause 

71from ..util import hybridmethod 

72from ..util import hybridproperty 

73from ..util import typing as compat_typing 

74from ..util import warn_deprecated 

75from ..util.typing import CallableReference 

76from ..util.typing import de_optionalize_union_types 

77from ..util.typing import flatten_newtype 

78from ..util.typing import is_generic 

79from ..util.typing import is_literal 

80from ..util.typing import is_newtype 

81from ..util.typing import is_pep593 

82from ..util.typing import is_pep695 

83from ..util.typing import Literal 

84from ..util.typing import LITERAL_TYPES 

85from ..util.typing import Self 

86 

87if TYPE_CHECKING: 

88 from ._typing import _O 

89 from ._typing import _RegistryType 

90 from .decl_base import _DataclassArguments 

91 from .instrumentation import ClassManager 

92 from .interfaces import MapperProperty 

93 from .state import InstanceState # noqa 

94 from ..sql._typing import _TypeEngineArgument 

95 from ..sql.type_api import _MatchedOnType 

96 

97_T = TypeVar("_T", bound=Any) 

98_T_co = TypeVar("_T_co", bound=Any, covariant=True) 

99 

100_TT = TypeVar("_TT", bound=Any) 

101 

102# it's not clear how to have Annotated, Union objects etc. as keys here 

103# from a typing perspective so just leave it open ended for now 

104_TypeAnnotationMapType = Mapping[Any, "_TypeEngineArgument[Any]"] 

105_MutableTypeAnnotationMapType = Dict[Any, "_TypeEngineArgument[Any]"] 

106 

107_DeclaredAttrDecorated = Callable[ 

108 ..., Union[Mapped[_T_co], ORMDescriptor[_T_co], SQLCoreOperations[_T_co]] 

109] 

110 

111 

112def has_inherited_table(cls: Type[_O]) -> bool: 

113 """Given a class, return True if any of the classes it inherits from has a 

114 mapped table, otherwise return False. 

115 

116 This is used in declarative mixins to build attributes that behave 

117 differently for the base class vs. a subclass in an inheritance 

118 hierarchy. 

119 

120 .. seealso:: 

121 

122 :ref:`decl_mixin_inheritance` 

123 

124 """ 

125 for class_ in cls.__mro__[1:]: 

126 if getattr(class_, "__table__", None) is not None: 

127 return True 

128 return False 

129 

130 

131class _DynamicAttributesType(type): 

132 def __setattr__(cls, key: str, value: Any) -> None: 

133 if "__mapper__" in cls.__dict__: 

134 _add_attribute(cls, key, value) 

135 else: 

136 type.__setattr__(cls, key, value) 

137 

138 def __delattr__(cls, key: str) -> None: 

139 if "__mapper__" in cls.__dict__: 

140 _del_attribute(cls, key) 

141 else: 

142 type.__delattr__(cls, key) 

143 

144 

145class DeclarativeAttributeIntercept( 

146 _DynamicAttributesType, 

147 # Inspectable is used only by the mypy plugin 

148 inspection.Inspectable[Mapper[Any]], 

149): 

150 """Metaclass that may be used in conjunction with the 

151 :class:`_orm.DeclarativeBase` class to support addition of class 

152 attributes dynamically. 

153 

154 """ 

155 

156 

157@compat_typing.dataclass_transform( 

158 field_specifiers=( 

159 MappedColumn, 

160 RelationshipProperty, 

161 Composite, 

162 Synonym, 

163 mapped_column, 

164 relationship, 

165 composite, 

166 synonym, 

167 deferred, 

168 ), 

169) 

170class DCTransformDeclarative(DeclarativeAttributeIntercept): 

171 """metaclass that includes @dataclass_transforms""" 

172 

173 

174class DeclarativeMeta(DeclarativeAttributeIntercept): 

175 metadata: MetaData 

176 registry: RegistryType 

177 

178 def __init__( 

179 cls, classname: Any, bases: Any, dict_: Any, **kw: Any 

180 ) -> None: 

181 # use cls.__dict__, which can be modified by an 

182 # __init_subclass__() method (#7900) 

183 dict_ = cls.__dict__ 

184 

185 # early-consume registry from the initial declarative base, 

186 # assign privately to not conflict with subclass attributes named 

187 # "registry" 

188 reg = getattr(cls, "_sa_registry", None) 

189 if reg is None: 

190 reg = dict_.get("registry", None) 

191 if not isinstance(reg, registry): 

192 raise exc.InvalidRequestError( 

193 "Declarative base class has no 'registry' attribute, " 

194 "or registry is not a sqlalchemy.orm.registry() object" 

195 ) 

196 else: 

197 cls._sa_registry = reg 

198 

199 if not cls.__dict__.get("__abstract__", False): 

200 _as_declarative(reg, cls, dict_) 

201 type.__init__(cls, classname, bases, dict_) 

202 

203 

204def synonym_for( 

205 name: str, map_column: bool = False 

206) -> Callable[[Callable[..., Any]], Synonym[Any]]: 

207 """Decorator that produces an :func:`_orm.synonym` 

208 attribute in conjunction with a Python descriptor. 

209 

210 The function being decorated is passed to :func:`_orm.synonym` as the 

211 :paramref:`.orm.synonym.descriptor` parameter:: 

212 

213 class MyClass(Base): 

214 __tablename__ = "my_table" 

215 

216 id = Column(Integer, primary_key=True) 

217 _job_status = Column("job_status", String(50)) 

218 

219 @synonym_for("job_status") 

220 @property 

221 def job_status(self): 

222 return "Status: %s" % self._job_status 

223 

224 The :ref:`hybrid properties <mapper_hybrids>` feature of SQLAlchemy 

225 is typically preferred instead of synonyms, which is a more legacy 

226 feature. 

227 

228 .. seealso:: 

229 

230 :ref:`synonyms` - Overview of synonyms 

231 

232 :func:`_orm.synonym` - the mapper-level function 

233 

234 :ref:`mapper_hybrids` - The Hybrid Attribute extension provides an 

235 updated approach to augmenting attribute behavior more flexibly than 

236 can be achieved with synonyms. 

237 

238 """ 

239 

240 def decorate(fn: Callable[..., Any]) -> Synonym[Any]: 

241 return _orm_synonym(name, map_column=map_column, descriptor=fn) 

242 

243 return decorate 

244 

245 

246class _declared_attr_common: 

247 def __init__( 

248 self, 

249 fn: Callable[..., Any], 

250 cascading: bool = False, 

251 quiet: bool = False, 

252 ): 

253 # support 

254 # @declared_attr 

255 # @classmethod 

256 # def foo(cls) -> Mapped[thing]: 

257 # ... 

258 # which seems to help typing tools interpret the fn as a classmethod 

259 # for situations where needed 

260 if isinstance(fn, classmethod): 

261 fn = fn.__func__ 

262 

263 self.fget = fn 

264 self._cascading = cascading 

265 self._quiet = quiet 

266 self.__doc__ = fn.__doc__ 

267 

268 def _collect_return_annotation(self) -> Optional[Type[Any]]: 

269 return util.get_annotations(self.fget).get("return") 

270 

271 def __get__(self, instance: Optional[object], owner: Any) -> Any: 

272 # the declared_attr needs to make use of a cache that exists 

273 # for the span of the declarative scan_attributes() phase. 

274 # to achieve this we look at the class manager that's configured. 

275 

276 # note this method should not be called outside of the declarative 

277 # setup phase 

278 

279 cls = owner 

280 manager = attributes.opt_manager_of_class(cls) 

281 if manager is None: 

282 if not re.match(r"^__.+__$", self.fget.__name__): 

283 # if there is no manager at all, then this class hasn't been 

284 # run through declarative or mapper() at all, emit a warning. 

285 util.warn( 

286 "Unmanaged access of declarative attribute %s from " 

287 "non-mapped class %s" % (self.fget.__name__, cls.__name__) 

288 ) 

289 return self.fget(cls) 

290 elif manager.is_mapped: 

291 # the class is mapped, which means we're outside of the declarative 

292 # scan setup, just run the function. 

293 return self.fget(cls) 

294 

295 # here, we are inside of the declarative scan. use the registry 

296 # that is tracking the values of these attributes. 

297 declarative_scan = manager.declarative_scan() 

298 

299 # assert that we are in fact in the declarative scan 

300 assert declarative_scan is not None 

301 

302 reg = declarative_scan.declared_attr_reg 

303 

304 if self in reg: 

305 return reg[self] 

306 else: 

307 reg[self] = obj = self.fget(cls) 

308 return obj 

309 

310 

311class _declared_directive(_declared_attr_common, Generic[_T]): 

312 # see mapping_api.rst for docstring 

313 

314 if typing.TYPE_CHECKING: 

315 

316 def __init__( 

317 self, 

318 fn: Callable[..., _T], 

319 cascading: bool = False, 

320 ): ... 

321 

322 def __get__(self, instance: Optional[object], owner: Any) -> _T: ... 

323 

324 def __set__(self, instance: Any, value: Any) -> None: ... 

325 

326 def __delete__(self, instance: Any) -> None: ... 

327 

328 def __call__(self, fn: Callable[..., _TT]) -> _declared_directive[_TT]: 

329 # extensive fooling of mypy underway... 

330 ... 

331 

332 

333class declared_attr(interfaces._MappedAttribute[_T_co], _declared_attr_common): 

334 """Mark a class-level method as representing the definition of 

335 a mapped property or Declarative directive. 

336 

337 :class:`_orm.declared_attr` is typically applied as a decorator to a class 

338 level method, turning the attribute into a scalar-like property that can be 

339 invoked from the uninstantiated class. The Declarative mapping process 

340 looks for these :class:`_orm.declared_attr` callables as it scans classes, 

341 and assumes any attribute marked with :class:`_orm.declared_attr` will be a 

342 callable that will produce an object specific to the Declarative mapping or 

343 table configuration. 

344 

345 :class:`_orm.declared_attr` is usually applicable to 

346 :ref:`mixins <orm_mixins_toplevel>`, to define relationships that are to be 

347 applied to different implementors of the class. It may also be used to 

348 define dynamically generated column expressions and other Declarative 

349 attributes. 

350 

351 Example:: 

352 

353 class ProvidesUserMixin: 

354 "A mixin that adds a 'user' relationship to classes." 

355 

356 user_id: Mapped[int] = mapped_column(ForeignKey("user_table.id")) 

357 

358 @declared_attr 

359 def user(cls) -> Mapped["User"]: 

360 return relationship("User") 

361 

362 When used with Declarative directives such as ``__tablename__``, the 

363 :meth:`_orm.declared_attr.directive` modifier may be used which indicates 

364 to :pep:`484` typing tools that the given method is not dealing with 

365 :class:`_orm.Mapped` attributes:: 

366 

367 class CreateTableName: 

368 @declared_attr.directive 

369 def __tablename__(cls) -> str: 

370 return cls.__name__.lower() 

371 

372 :class:`_orm.declared_attr` can also be applied directly to mapped 

373 classes, to allow for attributes that dynamically configure themselves 

374 on subclasses when using mapped inheritance schemes. Below 

375 illustrates :class:`_orm.declared_attr` to create a dynamic scheme 

376 for generating the :paramref:`_orm.Mapper.polymorphic_identity` parameter 

377 for subclasses:: 

378 

379 class Employee(Base): 

380 __tablename__ = "employee" 

381 

382 id: Mapped[int] = mapped_column(primary_key=True) 

383 type: Mapped[str] = mapped_column(String(50)) 

384 

385 @declared_attr.directive 

386 def __mapper_args__(cls) -> Dict[str, Any]: 

387 if cls.__name__ == "Employee": 

388 return { 

389 "polymorphic_on": cls.type, 

390 "polymorphic_identity": "Employee", 

391 } 

392 else: 

393 return {"polymorphic_identity": cls.__name__} 

394 

395 

396 class Engineer(Employee): 

397 pass 

398 

399 :class:`_orm.declared_attr` supports decorating functions that are 

400 explicitly decorated with ``@classmethod``. This is never necessary from a 

401 runtime perspective, however may be needed in order to support :pep:`484` 

402 typing tools that don't otherwise recognize the decorated function as 

403 having class-level behaviors for the ``cls`` parameter:: 

404 

405 class SomethingMixin: 

406 x: Mapped[int] 

407 y: Mapped[int] 

408 

409 @declared_attr 

410 @classmethod 

411 def x_plus_y(cls) -> Mapped[int]: 

412 return column_property(cls.x + cls.y) 

413 

414 .. versionadded:: 2.0 - :class:`_orm.declared_attr` can accommodate a 

415 function decorated with ``@classmethod`` to help with :pep:`484` 

416 integration where needed. 

417 

418 

419 .. seealso:: 

420 

421 :ref:`orm_mixins_toplevel` - Declarative Mixin documentation with 

422 background on use patterns for :class:`_orm.declared_attr`. 

423 

424 """ # noqa: E501 

425 

426 if typing.TYPE_CHECKING: 

427 

428 def __init__( 

429 self, 

430 fn: _DeclaredAttrDecorated[_T_co], 

431 cascading: bool = False, 

432 ): ... 

433 

434 def __set__(self, instance: Any, value: Any) -> None: ... 

435 

436 def __delete__(self, instance: Any) -> None: ... 

437 

438 # this is the Mapped[] API where at class descriptor get time we want 

439 # the type checker to see InstrumentedAttribute[_T]. However the 

440 # callable function prior to mapping in fact calls the given 

441 # declarative function that does not return InstrumentedAttribute 

442 @overload 

443 def __get__( 

444 self, instance: None, owner: Any 

445 ) -> InstrumentedAttribute[_T_co]: ... 

446 

447 @overload 

448 def __get__(self, instance: object, owner: Any) -> _T_co: ... 

449 

450 def __get__( 

451 self, instance: Optional[object], owner: Any 

452 ) -> Union[InstrumentedAttribute[_T_co], _T_co]: ... 

453 

454 @hybridmethod 

455 def _stateful(cls, **kw: Any) -> _stateful_declared_attr[_T_co]: 

456 return _stateful_declared_attr(**kw) 

457 

458 @hybridproperty 

459 def directive(cls) -> _declared_directive[Any]: 

460 # see mapping_api.rst for docstring 

461 return _declared_directive # type: ignore 

462 

463 @hybridproperty 

464 def cascading(cls) -> _stateful_declared_attr[_T_co]: 

465 # see mapping_api.rst for docstring 

466 return cls._stateful(cascading=True) 

467 

468 

469class _stateful_declared_attr(declared_attr[_T_co]): 

470 kw: Dict[str, Any] 

471 

472 def __init__(self, **kw: Any): 

473 self.kw = kw 

474 

475 @hybridmethod 

476 def _stateful(self, **kw: Any) -> _stateful_declared_attr[_T_co]: 

477 new_kw = self.kw.copy() 

478 new_kw.update(kw) 

479 return _stateful_declared_attr(**new_kw) 

480 

481 def __call__( 

482 self, fn: _DeclaredAttrDecorated[_T_co] 

483 ) -> declared_attr[_T_co]: 

484 return declared_attr(fn, **self.kw) 

485 

486 

487def declarative_mixin(cls: Type[_T]) -> Type[_T]: 

488 """Mark a class as providing the feature of "declarative mixin". 

489 

490 E.g.:: 

491 

492 from sqlalchemy.orm import declared_attr 

493 from sqlalchemy.orm import declarative_mixin 

494 

495 

496 @declarative_mixin 

497 class MyMixin: 

498 

499 @declared_attr 

500 def __tablename__(cls): 

501 return cls.__name__.lower() 

502 

503 __table_args__ = {"mysql_engine": "InnoDB"} 

504 __mapper_args__ = {"always_refresh": True} 

505 

506 id = Column(Integer, primary_key=True) 

507 

508 

509 class MyModel(MyMixin, Base): 

510 name = Column(String(1000)) 

511 

512 The :func:`_orm.declarative_mixin` decorator currently does not modify 

513 the given class in any way; it's current purpose is strictly to assist 

514 the :ref:`Mypy plugin <mypy_toplevel>` in being able to identify 

515 SQLAlchemy declarative mixin classes when no other context is present. 

516 

517 .. versionadded:: 1.4.6 

518 

519 .. legacy:: This api is considered legacy and will be deprecated in the next 

520 SQLAlchemy version. 

521 

522 .. seealso:: 

523 

524 :ref:`orm_mixins_toplevel` 

525 

526 :ref:`mypy_declarative_mixins` - in the 

527 :ref:`Mypy plugin documentation <mypy_toplevel>` 

528 

529 """ # noqa: E501 

530 

531 return cls 

532 

533 

534def _setup_declarative_base(cls: Type[Any]) -> None: 

535 if "metadata" in cls.__dict__: 

536 metadata = cls.__dict__["metadata"] 

537 else: 

538 metadata = None 

539 

540 if "type_annotation_map" in cls.__dict__: 

541 type_annotation_map = cls.__dict__["type_annotation_map"] 

542 else: 

543 type_annotation_map = None 

544 

545 reg = cls.__dict__.get("registry", None) 

546 if reg is not None: 

547 if not isinstance(reg, registry): 

548 raise exc.InvalidRequestError( 

549 "Declarative base class has a 'registry' attribute that is " 

550 "not an instance of sqlalchemy.orm.registry()" 

551 ) 

552 elif type_annotation_map is not None: 

553 raise exc.InvalidRequestError( 

554 "Declarative base class has both a 'registry' attribute and a " 

555 "type_annotation_map entry. Per-base type_annotation_maps " 

556 "are not supported. Please apply the type_annotation_map " 

557 "to this registry directly." 

558 ) 

559 

560 else: 

561 reg = registry( 

562 metadata=metadata, type_annotation_map=type_annotation_map 

563 ) 

564 cls.registry = reg 

565 

566 cls._sa_registry = reg 

567 

568 if "metadata" not in cls.__dict__: 

569 cls.metadata = cls.registry.metadata 

570 

571 if getattr(cls, "__init__", object.__init__) is object.__init__: 

572 cls.__init__ = cls.registry.constructor 

573 

574 

575class MappedAsDataclass(metaclass=DCTransformDeclarative): 

576 """Mixin class to indicate when mapping this class, also convert it to be 

577 a dataclass. 

578 

579 .. seealso:: 

580 

581 :ref:`orm_declarative_native_dataclasses` - complete background 

582 on SQLAlchemy native dataclass mapping 

583 

584 .. versionadded:: 2.0 

585 

586 """ 

587 

588 def __init_subclass__( 

589 cls, 

590 init: Union[_NoArg, bool] = _NoArg.NO_ARG, 

591 repr: Union[_NoArg, bool] = _NoArg.NO_ARG, # noqa: A002 

592 eq: Union[_NoArg, bool] = _NoArg.NO_ARG, 

593 order: Union[_NoArg, bool] = _NoArg.NO_ARG, 

594 unsafe_hash: Union[_NoArg, bool] = _NoArg.NO_ARG, 

595 match_args: Union[_NoArg, bool] = _NoArg.NO_ARG, 

596 kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG, 

597 dataclass_callable: Union[ 

598 _NoArg, Callable[..., Type[Any]] 

599 ] = _NoArg.NO_ARG, 

600 **kw: Any, 

601 ) -> None: 

602 apply_dc_transforms: _DataclassArguments = { 

603 "init": init, 

604 "repr": repr, 

605 "eq": eq, 

606 "order": order, 

607 "unsafe_hash": unsafe_hash, 

608 "match_args": match_args, 

609 "kw_only": kw_only, 

610 "dataclass_callable": dataclass_callable, 

611 } 

612 

613 current_transforms: _DataclassArguments 

614 

615 if hasattr(cls, "_sa_apply_dc_transforms"): 

616 current = cls._sa_apply_dc_transforms 

617 

618 _ClassScanMapperConfig._assert_dc_arguments(current) 

619 

620 cls._sa_apply_dc_transforms = current_transforms = { # type: ignore # noqa: E501 

621 k: current.get(k, _NoArg.NO_ARG) if v is _NoArg.NO_ARG else v 

622 for k, v in apply_dc_transforms.items() 

623 } 

624 else: 

625 cls._sa_apply_dc_transforms = current_transforms = ( 

626 apply_dc_transforms 

627 ) 

628 

629 super().__init_subclass__(**kw) 

630 

631 if not _is_mapped_class(cls): 

632 new_anno = ( 

633 _ClassScanMapperConfig._update_annotations_for_non_mapped_class 

634 )(cls) 

635 _ClassScanMapperConfig._apply_dataclasses_to_any_class( 

636 current_transforms, cls, new_anno 

637 ) 

638 

639 

640class DeclarativeBase( 

641 # Inspectable is used only by the mypy plugin 

642 inspection.Inspectable[InstanceState[Any]], 

643 metaclass=DeclarativeAttributeIntercept, 

644): 

645 """Base class used for declarative class definitions. 

646 

647 The :class:`_orm.DeclarativeBase` allows for the creation of new 

648 declarative bases in such a way that is compatible with type checkers:: 

649 

650 

651 from sqlalchemy.orm import DeclarativeBase 

652 

653 

654 class Base(DeclarativeBase): 

655 pass 

656 

657 The above ``Base`` class is now usable as the base for new declarative 

658 mappings. The superclass makes use of the ``__init_subclass__()`` 

659 method to set up new classes and metaclasses aren't used. 

660 

661 When first used, the :class:`_orm.DeclarativeBase` class instantiates a new 

662 :class:`_orm.registry` to be used with the base, assuming one was not 

663 provided explicitly. The :class:`_orm.DeclarativeBase` class supports 

664 class-level attributes which act as parameters for the construction of this 

665 registry; such as to indicate a specific :class:`_schema.MetaData` 

666 collection as well as a specific value for 

667 :paramref:`_orm.registry.type_annotation_map`:: 

668 

669 from typing_extensions import Annotated 

670 

671 from sqlalchemy import BigInteger 

672 from sqlalchemy import MetaData 

673 from sqlalchemy import String 

674 from sqlalchemy.orm import DeclarativeBase 

675 

676 bigint = Annotated[int, "bigint"] 

677 my_metadata = MetaData() 

678 

679 

680 class Base(DeclarativeBase): 

681 metadata = my_metadata 

682 type_annotation_map = { 

683 str: String().with_variant(String(255), "mysql", "mariadb"), 

684 bigint: BigInteger(), 

685 } 

686 

687 Class-level attributes which may be specified include: 

688 

689 :param metadata: optional :class:`_schema.MetaData` collection. 

690 If a :class:`_orm.registry` is constructed automatically, this 

691 :class:`_schema.MetaData` collection will be used to construct it. 

692 Otherwise, the local :class:`_schema.MetaData` collection will supersede 

693 that used by an existing :class:`_orm.registry` passed using the 

694 :paramref:`_orm.DeclarativeBase.registry` parameter. 

695 :param type_annotation_map: optional type annotation map that will be 

696 passed to the :class:`_orm.registry` as 

697 :paramref:`_orm.registry.type_annotation_map`. 

698 :param registry: supply a pre-existing :class:`_orm.registry` directly. 

699 

700 .. versionadded:: 2.0 Added :class:`.DeclarativeBase`, so that declarative 

701 base classes may be constructed in such a way that is also recognized 

702 by :pep:`484` type checkers. As a result, :class:`.DeclarativeBase` 

703 and other subclassing-oriented APIs should be seen as 

704 superseding previous "class returned by a function" APIs, namely 

705 :func:`_orm.declarative_base` and :meth:`_orm.registry.generate_base`, 

706 where the base class returned cannot be recognized by type checkers 

707 without using plugins. 

708 

709 **__init__ behavior** 

710 

711 In a plain Python class, the base-most ``__init__()`` method in the class 

712 hierarchy is ``object.__init__()``, which accepts no arguments. However, 

713 when the :class:`_orm.DeclarativeBase` subclass is first declared, the 

714 class is given an ``__init__()`` method that links to the 

715 :paramref:`_orm.registry.constructor` constructor function, if no 

716 ``__init__()`` method is already present; this is the usual declarative 

717 constructor that will assign keyword arguments as attributes on the 

718 instance, assuming those attributes are established at the class level 

719 (i.e. are mapped, or are linked to a descriptor). This constructor is 

720 **never accessed by a mapped class without being called explicitly via 

721 super()**, as mapped classes are themselves given an ``__init__()`` method 

722 directly which calls :paramref:`_orm.registry.constructor`, so in the 

723 default case works independently of what the base-most ``__init__()`` 

724 method does. 

725 

726 .. versionchanged:: 2.0.1 :class:`_orm.DeclarativeBase` has a default 

727 constructor that links to :paramref:`_orm.registry.constructor` by 

728 default, so that calls to ``super().__init__()`` can access this 

729 constructor. Previously, due to an implementation mistake, this default 

730 constructor was missing, and calling ``super().__init__()`` would invoke 

731 ``object.__init__()``. 

732 

733 The :class:`_orm.DeclarativeBase` subclass may also declare an explicit 

734 ``__init__()`` method which will replace the use of the 

735 :paramref:`_orm.registry.constructor` function at this level:: 

736 

737 class Base(DeclarativeBase): 

738 def __init__(self, id=None): 

739 self.id = id 

740 

741 Mapped classes still will not invoke this constructor implicitly; it 

742 remains only accessible by calling ``super().__init__()``:: 

743 

744 class MyClass(Base): 

745 def __init__(self, id=None, name=None): 

746 self.name = name 

747 super().__init__(id=id) 

748 

749 Note that this is a different behavior from what functions like the legacy 

750 :func:`_orm.declarative_base` would do; the base created by those functions 

751 would always install :paramref:`_orm.registry.constructor` for 

752 ``__init__()``. 

753 

754 

755 """ 

756 

757 if typing.TYPE_CHECKING: 

758 

759 def _sa_inspect_type(self) -> Mapper[Self]: ... 

760 

761 def _sa_inspect_instance(self) -> InstanceState[Self]: ... 

762 

763 _sa_registry: ClassVar[_RegistryType] 

764 

765 registry: ClassVar[_RegistryType] 

766 """Refers to the :class:`_orm.registry` in use where new 

767 :class:`_orm.Mapper` objects will be associated.""" 

768 

769 metadata: ClassVar[MetaData] 

770 """Refers to the :class:`_schema.MetaData` collection that will be used 

771 for new :class:`_schema.Table` objects. 

772 

773 .. seealso:: 

774 

775 :ref:`orm_declarative_metadata` 

776 

777 """ 

778 

779 __name__: ClassVar[str] 

780 

781 # this ideally should be Mapper[Self], but mypy as of 1.4.1 does not 

782 # like it, and breaks the declared_attr_one test. Pyright/pylance is 

783 # ok with it. 

784 __mapper__: ClassVar[Mapper[Any]] 

785 """The :class:`_orm.Mapper` object to which a particular class is 

786 mapped. 

787 

788 May also be acquired using :func:`_sa.inspect`, e.g. 

789 ``inspect(klass)``. 

790 

791 """ 

792 

793 __table__: ClassVar[FromClause] 

794 """The :class:`_sql.FromClause` to which a particular subclass is 

795 mapped. 

796 

797 This is usually an instance of :class:`_schema.Table` but may also 

798 refer to other kinds of :class:`_sql.FromClause` such as 

799 :class:`_sql.Subquery`, depending on how the class is mapped. 

800 

801 .. seealso:: 

802 

803 :ref:`orm_declarative_metadata` 

804 

805 """ 

806 

807 # pyright/pylance do not consider a classmethod a ClassVar so use Any 

808 # https://github.com/microsoft/pylance-release/issues/3484 

809 __tablename__: Any 

810 """String name to assign to the generated 

811 :class:`_schema.Table` object, if not specified directly via 

812 :attr:`_orm.DeclarativeBase.__table__`. 

813 

814 .. seealso:: 

815 

816 :ref:`orm_declarative_table` 

817 

818 """ 

819 

820 __mapper_args__: Any 

821 """Dictionary of arguments which will be passed to the 

822 :class:`_orm.Mapper` constructor. 

823 

824 .. seealso:: 

825 

826 :ref:`orm_declarative_mapper_options` 

827 

828 """ 

829 

830 __table_args__: Any 

831 """A dictionary or tuple of arguments that will be passed to the 

832 :class:`_schema.Table` constructor. See 

833 :ref:`orm_declarative_table_configuration` 

834 for background on the specific structure of this collection. 

835 

836 .. seealso:: 

837 

838 :ref:`orm_declarative_table_configuration` 

839 

840 """ 

841 

842 def __init__(self, **kw: Any): ... 

843 

844 def __init_subclass__(cls, **kw: Any) -> None: 

845 if DeclarativeBase in cls.__bases__: 

846 _check_not_declarative(cls, DeclarativeBase) 

847 _setup_declarative_base(cls) 

848 else: 

849 _as_declarative(cls._sa_registry, cls, cls.__dict__) 

850 super().__init_subclass__(**kw) 

851 

852 

853def _check_not_declarative(cls: Type[Any], base: Type[Any]) -> None: 

854 cls_dict = cls.__dict__ 

855 if ( 

856 "__table__" in cls_dict 

857 and not ( 

858 callable(cls_dict["__table__"]) 

859 or hasattr(cls_dict["__table__"], "__get__") 

860 ) 

861 ) or isinstance(cls_dict.get("__tablename__", None), str): 

862 raise exc.InvalidRequestError( 

863 f"Cannot use {base.__name__!r} directly as a declarative base " 

864 "class. Create a Base by creating a subclass of it." 

865 ) 

866 

867 

868class DeclarativeBaseNoMeta( 

869 # Inspectable is used only by the mypy plugin 

870 inspection.Inspectable[InstanceState[Any]] 

871): 

872 """Same as :class:`_orm.DeclarativeBase`, but does not use a metaclass 

873 to intercept new attributes. 

874 

875 The :class:`_orm.DeclarativeBaseNoMeta` base may be used when use of 

876 custom metaclasses is desirable. 

877 

878 .. versionadded:: 2.0 

879 

880 

881 """ 

882 

883 _sa_registry: ClassVar[_RegistryType] 

884 

885 registry: ClassVar[_RegistryType] 

886 """Refers to the :class:`_orm.registry` in use where new 

887 :class:`_orm.Mapper` objects will be associated.""" 

888 

889 metadata: ClassVar[MetaData] 

890 """Refers to the :class:`_schema.MetaData` collection that will be used 

891 for new :class:`_schema.Table` objects. 

892 

893 .. seealso:: 

894 

895 :ref:`orm_declarative_metadata` 

896 

897 """ 

898 

899 # this ideally should be Mapper[Self], but mypy as of 1.4.1 does not 

900 # like it, and breaks the declared_attr_one test. Pyright/pylance is 

901 # ok with it. 

902 __mapper__: ClassVar[Mapper[Any]] 

903 """The :class:`_orm.Mapper` object to which a particular class is 

904 mapped. 

905 

906 May also be acquired using :func:`_sa.inspect`, e.g. 

907 ``inspect(klass)``. 

908 

909 """ 

910 

911 __table__: Optional[FromClause] 

912 """The :class:`_sql.FromClause` to which a particular subclass is 

913 mapped. 

914 

915 This is usually an instance of :class:`_schema.Table` but may also 

916 refer to other kinds of :class:`_sql.FromClause` such as 

917 :class:`_sql.Subquery`, depending on how the class is mapped. 

918 

919 .. seealso:: 

920 

921 :ref:`orm_declarative_metadata` 

922 

923 """ 

924 

925 if typing.TYPE_CHECKING: 

926 

927 def _sa_inspect_type(self) -> Mapper[Self]: ... 

928 

929 def _sa_inspect_instance(self) -> InstanceState[Self]: ... 

930 

931 __tablename__: Any 

932 """String name to assign to the generated 

933 :class:`_schema.Table` object, if not specified directly via 

934 :attr:`_orm.DeclarativeBase.__table__`. 

935 

936 .. seealso:: 

937 

938 :ref:`orm_declarative_table` 

939 

940 """ 

941 

942 __mapper_args__: Any 

943 """Dictionary of arguments which will be passed to the 

944 :class:`_orm.Mapper` constructor. 

945 

946 .. seealso:: 

947 

948 :ref:`orm_declarative_mapper_options` 

949 

950 """ 

951 

952 __table_args__: Any 

953 """A dictionary or tuple of arguments that will be passed to the 

954 :class:`_schema.Table` constructor. See 

955 :ref:`orm_declarative_table_configuration` 

956 for background on the specific structure of this collection. 

957 

958 .. seealso:: 

959 

960 :ref:`orm_declarative_table_configuration` 

961 

962 """ 

963 

964 def __init__(self, **kw: Any): ... 

965 

966 def __init_subclass__(cls, **kw: Any) -> None: 

967 if DeclarativeBaseNoMeta in cls.__bases__: 

968 _check_not_declarative(cls, DeclarativeBaseNoMeta) 

969 _setup_declarative_base(cls) 

970 else: 

971 _as_declarative(cls._sa_registry, cls, cls.__dict__) 

972 super().__init_subclass__(**kw) 

973 

974 

975def add_mapped_attribute( 

976 target: Type[_O], key: str, attr: MapperProperty[Any] 

977) -> None: 

978 """Add a new mapped attribute to an ORM mapped class. 

979 

980 E.g.:: 

981 

982 add_mapped_attribute(User, "addresses", relationship(Address)) 

983 

984 This may be used for ORM mappings that aren't using a declarative 

985 metaclass that intercepts attribute set operations. 

986 

987 .. versionadded:: 2.0 

988 

989 

990 """ 

991 _add_attribute(target, key, attr) 

992 

993 

994def declarative_base( 

995 *, 

996 metadata: Optional[MetaData] = None, 

997 mapper: Optional[Callable[..., Mapper[Any]]] = None, 

998 cls: Type[Any] = object, 

999 name: str = "Base", 

1000 class_registry: Optional[clsregistry._ClsRegistryType] = None, 

1001 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

1002 constructor: Callable[..., None] = _declarative_constructor, 

1003 metaclass: Type[Any] = DeclarativeMeta, 

1004) -> Any: 

1005 r"""Construct a base class for declarative class definitions. 

1006 

1007 The new base class will be given a metaclass that produces 

1008 appropriate :class:`~sqlalchemy.schema.Table` objects and makes 

1009 the appropriate :class:`_orm.Mapper` calls based on the 

1010 information provided declaratively in the class and any subclasses 

1011 of the class. 

1012 

1013 .. versionchanged:: 2.0 Note that the :func:`_orm.declarative_base` 

1014 function is superseded by the new :class:`_orm.DeclarativeBase` class, 

1015 which generates a new "base" class using subclassing, rather than 

1016 return value of a function. This allows an approach that is compatible 

1017 with :pep:`484` typing tools. 

1018 

1019 The :func:`_orm.declarative_base` function is a shorthand version 

1020 of using the :meth:`_orm.registry.generate_base` 

1021 method. That is, the following:: 

1022 

1023 from sqlalchemy.orm import declarative_base 

1024 

1025 Base = declarative_base() 

1026 

1027 Is equivalent to:: 

1028 

1029 from sqlalchemy.orm import registry 

1030 

1031 mapper_registry = registry() 

1032 Base = mapper_registry.generate_base() 

1033 

1034 See the docstring for :class:`_orm.registry` 

1035 and :meth:`_orm.registry.generate_base` 

1036 for more details. 

1037 

1038 .. versionchanged:: 1.4 The :func:`_orm.declarative_base` 

1039 function is now a specialization of the more generic 

1040 :class:`_orm.registry` class. The function also moves to the 

1041 ``sqlalchemy.orm`` package from the ``declarative.ext`` package. 

1042 

1043 

1044 :param metadata: 

1045 An optional :class:`~sqlalchemy.schema.MetaData` instance. All 

1046 :class:`~sqlalchemy.schema.Table` objects implicitly declared by 

1047 subclasses of the base will share this MetaData. A MetaData instance 

1048 will be created if none is provided. The 

1049 :class:`~sqlalchemy.schema.MetaData` instance will be available via the 

1050 ``metadata`` attribute of the generated declarative base class. 

1051 

1052 :param mapper: 

1053 An optional callable, defaults to :class:`_orm.Mapper`. Will 

1054 be used to map subclasses to their Tables. 

1055 

1056 :param cls: 

1057 Defaults to :class:`object`. A type to use as the base for the generated 

1058 declarative base class. May be a class or tuple of classes. 

1059 

1060 :param name: 

1061 Defaults to ``Base``. The display name for the generated 

1062 class. Customizing this is not required, but can improve clarity in 

1063 tracebacks and debugging. 

1064 

1065 :param constructor: 

1066 Specify the implementation for the ``__init__`` function on a mapped 

1067 class that has no ``__init__`` of its own. Defaults to an 

1068 implementation that assigns \**kwargs for declared 

1069 fields and relationships to an instance. If ``None`` is supplied, 

1070 no __init__ will be provided and construction will fall back to 

1071 cls.__init__ by way of the normal Python semantics. 

1072 

1073 :param class_registry: optional dictionary that will serve as the 

1074 registry of class names-> mapped classes when string names 

1075 are used to identify classes inside of :func:`_orm.relationship` 

1076 and others. Allows two or more declarative base classes 

1077 to share the same registry of class names for simplified 

1078 inter-base relationships. 

1079 

1080 :param type_annotation_map: optional dictionary of Python types to 

1081 SQLAlchemy :class:`_types.TypeEngine` classes or instances. This 

1082 is used exclusively by the :class:`_orm.MappedColumn` construct 

1083 to produce column types based on annotations within the 

1084 :class:`_orm.Mapped` type. 

1085 

1086 

1087 .. versionadded:: 2.0 

1088 

1089 .. seealso:: 

1090 

1091 :ref:`orm_declarative_mapped_column_type_map` 

1092 

1093 :param metaclass: 

1094 Defaults to :class:`.DeclarativeMeta`. A metaclass or __metaclass__ 

1095 compatible callable to use as the meta type of the generated 

1096 declarative base class. 

1097 

1098 .. seealso:: 

1099 

1100 :class:`_orm.registry` 

1101 

1102 """ 

1103 

1104 return registry( 

1105 metadata=metadata, 

1106 class_registry=class_registry, 

1107 constructor=constructor, 

1108 type_annotation_map=type_annotation_map, 

1109 ).generate_base( 

1110 mapper=mapper, 

1111 cls=cls, 

1112 name=name, 

1113 metaclass=metaclass, 

1114 ) 

1115 

1116 

1117class registry: 

1118 """Generalized registry for mapping classes. 

1119 

1120 The :class:`_orm.registry` serves as the basis for maintaining a collection 

1121 of mappings, and provides configurational hooks used to map classes. 

1122 

1123 The three general kinds of mappings supported are Declarative Base, 

1124 Declarative Decorator, and Imperative Mapping. All of these mapping 

1125 styles may be used interchangeably: 

1126 

1127 * :meth:`_orm.registry.generate_base` returns a new declarative base 

1128 class, and is the underlying implementation of the 

1129 :func:`_orm.declarative_base` function. 

1130 

1131 * :meth:`_orm.registry.mapped` provides a class decorator that will 

1132 apply declarative mapping to a class without the use of a declarative 

1133 base class. 

1134 

1135 * :meth:`_orm.registry.map_imperatively` will produce a 

1136 :class:`_orm.Mapper` for a class without scanning the class for 

1137 declarative class attributes. This method suits the use case historically 

1138 provided by the ``sqlalchemy.orm.mapper()`` classical mapping function, 

1139 which is removed as of SQLAlchemy 2.0. 

1140 

1141 .. versionadded:: 1.4 

1142 

1143 .. seealso:: 

1144 

1145 :ref:`orm_mapping_classes_toplevel` - overview of class mapping 

1146 styles. 

1147 

1148 """ 

1149 

1150 _class_registry: clsregistry._ClsRegistryType 

1151 _managers: weakref.WeakKeyDictionary[ClassManager[Any], Literal[True]] 

1152 _non_primary_mappers: weakref.WeakKeyDictionary[Mapper[Any], Literal[True]] 

1153 metadata: MetaData 

1154 constructor: CallableReference[Callable[..., None]] 

1155 type_annotation_map: _MutableTypeAnnotationMapType 

1156 _dependents: Set[_RegistryType] 

1157 _dependencies: Set[_RegistryType] 

1158 _new_mappers: bool 

1159 

1160 def __init__( 

1161 self, 

1162 *, 

1163 metadata: Optional[MetaData] = None, 

1164 class_registry: Optional[clsregistry._ClsRegistryType] = None, 

1165 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

1166 constructor: Callable[..., None] = _declarative_constructor, 

1167 ): 

1168 r"""Construct a new :class:`_orm.registry` 

1169 

1170 :param metadata: 

1171 An optional :class:`_schema.MetaData` instance. All 

1172 :class:`_schema.Table` objects generated using declarative 

1173 table mapping will make use of this :class:`_schema.MetaData` 

1174 collection. If this argument is left at its default of ``None``, 

1175 a blank :class:`_schema.MetaData` collection is created. 

1176 

1177 :param constructor: 

1178 Specify the implementation for the ``__init__`` function on a mapped 

1179 class that has no ``__init__`` of its own. Defaults to an 

1180 implementation that assigns \**kwargs for declared 

1181 fields and relationships to an instance. If ``None`` is supplied, 

1182 no __init__ will be provided and construction will fall back to 

1183 cls.__init__ by way of the normal Python semantics. 

1184 

1185 :param class_registry: optional dictionary that will serve as the 

1186 registry of class names-> mapped classes when string names 

1187 are used to identify classes inside of :func:`_orm.relationship` 

1188 and others. Allows two or more declarative base classes 

1189 to share the same registry of class names for simplified 

1190 inter-base relationships. 

1191 

1192 :param type_annotation_map: optional dictionary of Python types to 

1193 SQLAlchemy :class:`_types.TypeEngine` classes or instances. 

1194 The provided dict will update the default type mapping. This 

1195 is used exclusively by the :class:`_orm.MappedColumn` construct 

1196 to produce column types based on annotations within the 

1197 :class:`_orm.Mapped` type. 

1198 

1199 .. versionadded:: 2.0 

1200 

1201 .. seealso:: 

1202 

1203 :ref:`orm_declarative_mapped_column_type_map` 

1204 

1205 

1206 """ 

1207 lcl_metadata = metadata or MetaData() 

1208 

1209 if class_registry is None: 

1210 class_registry = weakref.WeakValueDictionary() 

1211 

1212 self._class_registry = class_registry 

1213 self._managers = weakref.WeakKeyDictionary() 

1214 self._non_primary_mappers = weakref.WeakKeyDictionary() 

1215 self.metadata = lcl_metadata 

1216 self.constructor = constructor 

1217 self.type_annotation_map = {} 

1218 if type_annotation_map is not None: 

1219 self.update_type_annotation_map(type_annotation_map) 

1220 self._dependents = set() 

1221 self._dependencies = set() 

1222 

1223 self._new_mappers = False 

1224 

1225 with mapperlib._CONFIGURE_MUTEX: 

1226 mapperlib._mapper_registries[self] = True 

1227 

1228 def update_type_annotation_map( 

1229 self, 

1230 type_annotation_map: _TypeAnnotationMapType, 

1231 ) -> None: 

1232 """update the :paramref:`_orm.registry.type_annotation_map` with new 

1233 values.""" 

1234 

1235 self.type_annotation_map.update( 

1236 { 

1237 de_optionalize_union_types(typ): sqltype 

1238 for typ, sqltype in type_annotation_map.items() 

1239 } 

1240 ) 

1241 

1242 def _resolve_type( 

1243 self, python_type: _MatchedOnType, _do_fallbacks: bool = False 

1244 ) -> Optional[sqltypes.TypeEngine[Any]]: 

1245 python_type_type: Type[Any] 

1246 search: Iterable[Tuple[_MatchedOnType, Type[Any]]] 

1247 

1248 if is_generic(python_type): 

1249 if is_literal(python_type): 

1250 python_type_type = python_type # type: ignore[assignment] 

1251 

1252 search = ( 

1253 (python_type, python_type_type), 

1254 *((lt, python_type_type) for lt in LITERAL_TYPES), 

1255 ) 

1256 else: 

1257 python_type_type = python_type.__origin__ 

1258 search = ((python_type, python_type_type),) 

1259 elif isinstance(python_type, type): 

1260 python_type_type = python_type 

1261 search = ((pt, pt) for pt in python_type_type.__mro__) 

1262 else: 

1263 python_type_type = python_type # type: ignore[assignment] 

1264 search = ((python_type, python_type_type),) 

1265 

1266 for pt, flattened in search: 

1267 # we search through full __mro__ for types. however... 

1268 sql_type = self.type_annotation_map.get(pt) 

1269 if sql_type is None: 

1270 sql_type = sqltypes._type_map_get(pt) # type: ignore # noqa: E501 

1271 

1272 if sql_type is not None: 

1273 sql_type_inst = sqltypes.to_instance(sql_type) 

1274 

1275 # ... this additional step will reject most 

1276 # type -> supertype matches, such as if we had 

1277 # a MyInt(int) subclass. note also we pass NewType() 

1278 # here directly; these always have to be in the 

1279 # type_annotation_map to be useful 

1280 resolved_sql_type = sql_type_inst._resolve_for_python_type( 

1281 python_type_type, 

1282 pt, 

1283 flattened, 

1284 ) 

1285 if resolved_sql_type is not None: 

1286 return resolved_sql_type 

1287 

1288 # 2.0 fallbacks 

1289 if _do_fallbacks: 

1290 python_type_to_check: Any = None 

1291 kind = None 

1292 if is_pep695(python_type): 

1293 # NOTE: assume there aren't type alias types of new types. 

1294 python_type_to_check = python_type 

1295 while is_pep695(python_type_to_check) and not is_pep593( 

1296 python_type_to_check 

1297 ): 

1298 python_type_to_check = python_type_to_check.__value__ 

1299 python_type_to_check = de_optionalize_union_types( 

1300 python_type_to_check 

1301 ) 

1302 kind = "pep-695 type" 

1303 if is_newtype(python_type): 

1304 python_type_to_check = flatten_newtype(python_type) 

1305 kind = "NewType" 

1306 

1307 if python_type_to_check is not None: 

1308 res_after_fallback = self._resolve_type( 

1309 python_type_to_check, False 

1310 ) 

1311 if res_after_fallback is not None: 

1312 assert kind is not None 

1313 if kind == "pep-695 type": 

1314 warn_deprecated( 

1315 f"Matching to {kind} '{python_type}' in " 

1316 "a recursive " 

1317 "fashion without the recursed type being present " 

1318 "in the type_annotation_map is deprecated; add " 

1319 "this type or its recursed value to " 

1320 "the type_annotation_map to allow it to match " 

1321 "explicitly.", 

1322 "2.0", 

1323 ) 

1324 else: 

1325 warn_deprecated( 

1326 f"Matching the provided {kind} '{python_type}' on " 

1327 "its resolved value without matching it in the " 

1328 "type_annotation_map is deprecated; add this " 

1329 "type to " 

1330 "the type_annotation_map to allow it to match " 

1331 "explicitly.", 

1332 "2.0", 

1333 ) 

1334 return res_after_fallback 

1335 

1336 return None 

1337 

1338 @property 

1339 def mappers(self) -> FrozenSet[Mapper[Any]]: 

1340 """read only collection of all :class:`_orm.Mapper` objects.""" 

1341 

1342 return frozenset(manager.mapper for manager in self._managers).union( 

1343 self._non_primary_mappers 

1344 ) 

1345 

1346 def _set_depends_on(self, registry: RegistryType) -> None: 

1347 if registry is self: 

1348 return 

1349 registry._dependents.add(self) 

1350 self._dependencies.add(registry) 

1351 

1352 def _flag_new_mapper(self, mapper: Mapper[Any]) -> None: 

1353 mapper._ready_for_configure = True 

1354 if self._new_mappers: 

1355 return 

1356 

1357 for reg in self._recurse_with_dependents({self}): 

1358 reg._new_mappers = True 

1359 

1360 @classmethod 

1361 def _recurse_with_dependents( 

1362 cls, registries: Set[RegistryType] 

1363 ) -> Iterator[RegistryType]: 

1364 todo = registries 

1365 done = set() 

1366 while todo: 

1367 reg = todo.pop() 

1368 done.add(reg) 

1369 

1370 # if yielding would remove dependents, make sure we have 

1371 # them before 

1372 todo.update(reg._dependents.difference(done)) 

1373 yield reg 

1374 

1375 # if yielding would add dependents, make sure we have them 

1376 # after 

1377 todo.update(reg._dependents.difference(done)) 

1378 

1379 @classmethod 

1380 def _recurse_with_dependencies( 

1381 cls, registries: Set[RegistryType] 

1382 ) -> Iterator[RegistryType]: 

1383 todo = registries 

1384 done = set() 

1385 while todo: 

1386 reg = todo.pop() 

1387 done.add(reg) 

1388 

1389 # if yielding would remove dependencies, make sure we have 

1390 # them before 

1391 todo.update(reg._dependencies.difference(done)) 

1392 

1393 yield reg 

1394 

1395 # if yielding would remove dependencies, make sure we have 

1396 # them before 

1397 todo.update(reg._dependencies.difference(done)) 

1398 

1399 def _mappers_to_configure(self) -> Iterator[Mapper[Any]]: 

1400 return itertools.chain( 

1401 ( 

1402 manager.mapper 

1403 for manager in list(self._managers) 

1404 if manager.is_mapped 

1405 and not manager.mapper.configured 

1406 and manager.mapper._ready_for_configure 

1407 ), 

1408 ( 

1409 npm 

1410 for npm in list(self._non_primary_mappers) 

1411 if not npm.configured and npm._ready_for_configure 

1412 ), 

1413 ) 

1414 

1415 def _add_non_primary_mapper(self, np_mapper: Mapper[Any]) -> None: 

1416 self._non_primary_mappers[np_mapper] = True 

1417 

1418 def _dispose_cls(self, cls: Type[_O]) -> None: 

1419 clsregistry.remove_class(cls.__name__, cls, self._class_registry) 

1420 

1421 def _add_manager(self, manager: ClassManager[Any]) -> None: 

1422 self._managers[manager] = True 

1423 if manager.is_mapped: 

1424 raise exc.ArgumentError( 

1425 "Class '%s' already has a primary mapper defined. " 

1426 % manager.class_ 

1427 ) 

1428 assert manager.registry is None 

1429 manager.registry = self 

1430 

1431 def configure(self, cascade: bool = False) -> None: 

1432 """Configure all as-yet unconfigured mappers in this 

1433 :class:`_orm.registry`. 

1434 

1435 The configure step is used to reconcile and initialize the 

1436 :func:`_orm.relationship` linkages between mapped classes, as well as 

1437 to invoke configuration events such as the 

1438 :meth:`_orm.MapperEvents.before_configured` and 

1439 :meth:`_orm.MapperEvents.after_configured`, which may be used by ORM 

1440 extensions or user-defined extension hooks. 

1441 

1442 If one or more mappers in this registry contain 

1443 :func:`_orm.relationship` constructs that refer to mapped classes in 

1444 other registries, this registry is said to be *dependent* on those 

1445 registries. In order to configure those dependent registries 

1446 automatically, the :paramref:`_orm.registry.configure.cascade` flag 

1447 should be set to ``True``. Otherwise, if they are not configured, an 

1448 exception will be raised. The rationale behind this behavior is to 

1449 allow an application to programmatically invoke configuration of 

1450 registries while controlling whether or not the process implicitly 

1451 reaches other registries. 

1452 

1453 As an alternative to invoking :meth:`_orm.registry.configure`, the ORM 

1454 function :func:`_orm.configure_mappers` function may be used to ensure 

1455 configuration is complete for all :class:`_orm.registry` objects in 

1456 memory. This is generally simpler to use and also predates the usage of 

1457 :class:`_orm.registry` objects overall. However, this function will 

1458 impact all mappings throughout the running Python process and may be 

1459 more memory/time consuming for an application that has many registries 

1460 in use for different purposes that may not be needed immediately. 

1461 

1462 .. seealso:: 

1463 

1464 :func:`_orm.configure_mappers` 

1465 

1466 

1467 .. versionadded:: 1.4.0b2 

1468 

1469 """ 

1470 mapperlib._configure_registries({self}, cascade=cascade) 

1471 

1472 def dispose(self, cascade: bool = False) -> None: 

1473 """Dispose of all mappers in this :class:`_orm.registry`. 

1474 

1475 After invocation, all the classes that were mapped within this registry 

1476 will no longer have class instrumentation associated with them. This 

1477 method is the per-:class:`_orm.registry` analogue to the 

1478 application-wide :func:`_orm.clear_mappers` function. 

1479 

1480 If this registry contains mappers that are dependencies of other 

1481 registries, typically via :func:`_orm.relationship` links, then those 

1482 registries must be disposed as well. When such registries exist in 

1483 relation to this one, their :meth:`_orm.registry.dispose` method will 

1484 also be called, if the :paramref:`_orm.registry.dispose.cascade` flag 

1485 is set to ``True``; otherwise, an error is raised if those registries 

1486 were not already disposed. 

1487 

1488 .. versionadded:: 1.4.0b2 

1489 

1490 .. seealso:: 

1491 

1492 :func:`_orm.clear_mappers` 

1493 

1494 """ 

1495 

1496 mapperlib._dispose_registries({self}, cascade=cascade) 

1497 

1498 def _dispose_manager_and_mapper(self, manager: ClassManager[Any]) -> None: 

1499 if "mapper" in manager.__dict__: 

1500 mapper = manager.mapper 

1501 

1502 mapper._set_dispose_flags() 

1503 

1504 class_ = manager.class_ 

1505 self._dispose_cls(class_) 

1506 instrumentation._instrumentation_factory.unregister(class_) 

1507 

1508 def generate_base( 

1509 self, 

1510 mapper: Optional[Callable[..., Mapper[Any]]] = None, 

1511 cls: Type[Any] = object, 

1512 name: str = "Base", 

1513 metaclass: Type[Any] = DeclarativeMeta, 

1514 ) -> Any: 

1515 """Generate a declarative base class. 

1516 

1517 Classes that inherit from the returned class object will be 

1518 automatically mapped using declarative mapping. 

1519 

1520 E.g.:: 

1521 

1522 from sqlalchemy.orm import registry 

1523 

1524 mapper_registry = registry() 

1525 

1526 Base = mapper_registry.generate_base() 

1527 

1528 

1529 class MyClass(Base): 

1530 __tablename__ = "my_table" 

1531 id = Column(Integer, primary_key=True) 

1532 

1533 The above dynamically generated class is equivalent to the 

1534 non-dynamic example below:: 

1535 

1536 from sqlalchemy.orm import registry 

1537 from sqlalchemy.orm.decl_api import DeclarativeMeta 

1538 

1539 mapper_registry = registry() 

1540 

1541 

1542 class Base(metaclass=DeclarativeMeta): 

1543 __abstract__ = True 

1544 registry = mapper_registry 

1545 metadata = mapper_registry.metadata 

1546 

1547 __init__ = mapper_registry.constructor 

1548 

1549 .. versionchanged:: 2.0 Note that the 

1550 :meth:`_orm.registry.generate_base` method is superseded by the new 

1551 :class:`_orm.DeclarativeBase` class, which generates a new "base" 

1552 class using subclassing, rather than return value of a function. 

1553 This allows an approach that is compatible with :pep:`484` typing 

1554 tools. 

1555 

1556 The :meth:`_orm.registry.generate_base` method provides the 

1557 implementation for the :func:`_orm.declarative_base` function, which 

1558 creates the :class:`_orm.registry` and base class all at once. 

1559 

1560 See the section :ref:`orm_declarative_mapping` for background and 

1561 examples. 

1562 

1563 :param mapper: 

1564 An optional callable, defaults to :class:`_orm.Mapper`. 

1565 This function is used to generate new :class:`_orm.Mapper` objects. 

1566 

1567 :param cls: 

1568 Defaults to :class:`object`. A type to use as the base for the 

1569 generated declarative base class. May be a class or tuple of classes. 

1570 

1571 :param name: 

1572 Defaults to ``Base``. The display name for the generated 

1573 class. Customizing this is not required, but can improve clarity in 

1574 tracebacks and debugging. 

1575 

1576 :param metaclass: 

1577 Defaults to :class:`.DeclarativeMeta`. A metaclass or __metaclass__ 

1578 compatible callable to use as the meta type of the generated 

1579 declarative base class. 

1580 

1581 .. seealso:: 

1582 

1583 :ref:`orm_declarative_mapping` 

1584 

1585 :func:`_orm.declarative_base` 

1586 

1587 """ 

1588 metadata = self.metadata 

1589 

1590 bases = not isinstance(cls, tuple) and (cls,) or cls 

1591 

1592 class_dict: Dict[str, Any] = dict(registry=self, metadata=metadata) 

1593 if isinstance(cls, type): 

1594 class_dict["__doc__"] = cls.__doc__ 

1595 

1596 if self.constructor is not None: 

1597 class_dict["__init__"] = self.constructor 

1598 

1599 class_dict["__abstract__"] = True 

1600 if mapper: 

1601 class_dict["__mapper_cls__"] = mapper 

1602 

1603 if hasattr(cls, "__class_getitem__"): 

1604 

1605 def __class_getitem__(cls: Type[_T], key: Any) -> Type[_T]: 

1606 # allow generic classes in py3.9+ 

1607 return cls 

1608 

1609 class_dict["__class_getitem__"] = __class_getitem__ 

1610 

1611 return metaclass(name, bases, class_dict) 

1612 

1613 @compat_typing.dataclass_transform( 

1614 field_specifiers=( 

1615 MappedColumn, 

1616 RelationshipProperty, 

1617 Composite, 

1618 Synonym, 

1619 mapped_column, 

1620 relationship, 

1621 composite, 

1622 synonym, 

1623 deferred, 

1624 ), 

1625 ) 

1626 @overload 

1627 def mapped_as_dataclass(self, __cls: Type[_O]) -> Type[_O]: ... 

1628 

1629 @overload 

1630 def mapped_as_dataclass( 

1631 self, 

1632 __cls: Literal[None] = ..., 

1633 *, 

1634 init: Union[_NoArg, bool] = ..., 

1635 repr: Union[_NoArg, bool] = ..., # noqa: A002 

1636 eq: Union[_NoArg, bool] = ..., 

1637 order: Union[_NoArg, bool] = ..., 

1638 unsafe_hash: Union[_NoArg, bool] = ..., 

1639 match_args: Union[_NoArg, bool] = ..., 

1640 kw_only: Union[_NoArg, bool] = ..., 

1641 dataclass_callable: Union[_NoArg, Callable[..., Type[Any]]] = ..., 

1642 ) -> Callable[[Type[_O]], Type[_O]]: ... 

1643 

1644 def mapped_as_dataclass( 

1645 self, 

1646 __cls: Optional[Type[_O]] = None, 

1647 *, 

1648 init: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1649 repr: Union[_NoArg, bool] = _NoArg.NO_ARG, # noqa: A002 

1650 eq: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1651 order: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1652 unsafe_hash: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1653 match_args: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1654 kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1655 dataclass_callable: Union[ 

1656 _NoArg, Callable[..., Type[Any]] 

1657 ] = _NoArg.NO_ARG, 

1658 ) -> Union[Type[_O], Callable[[Type[_O]], Type[_O]]]: 

1659 """Class decorator that will apply the Declarative mapping process 

1660 to a given class, and additionally convert the class to be a 

1661 Python dataclass. 

1662 

1663 .. seealso:: 

1664 

1665 :ref:`orm_declarative_native_dataclasses` - complete background 

1666 on SQLAlchemy native dataclass mapping 

1667 

1668 :func:`_orm.mapped_as_dataclass` - functional version that may 

1669 provide better compatibility with mypy 

1670 

1671 .. versionadded:: 2.0 

1672 

1673 

1674 """ 

1675 

1676 def decorate(cls: Type[_O]) -> Type[_O]: 

1677 setattr( 

1678 cls, 

1679 "_sa_apply_dc_transforms", 

1680 { 

1681 "init": init, 

1682 "repr": repr, 

1683 "eq": eq, 

1684 "order": order, 

1685 "unsafe_hash": unsafe_hash, 

1686 "match_args": match_args, 

1687 "kw_only": kw_only, 

1688 "dataclass_callable": dataclass_callable, 

1689 }, 

1690 ) 

1691 _as_declarative(self, cls, cls.__dict__) 

1692 return cls 

1693 

1694 if __cls: 

1695 return decorate(__cls) 

1696 else: 

1697 return decorate 

1698 

1699 def mapped(self, cls: Type[_O]) -> Type[_O]: 

1700 """Class decorator that will apply the Declarative mapping process 

1701 to a given class. 

1702 

1703 E.g.:: 

1704 

1705 from sqlalchemy.orm import registry 

1706 

1707 mapper_registry = registry() 

1708 

1709 

1710 @mapper_registry.mapped 

1711 class Foo: 

1712 __tablename__ = "some_table" 

1713 

1714 id = Column(Integer, primary_key=True) 

1715 name = Column(String) 

1716 

1717 See the section :ref:`orm_declarative_mapping` for complete 

1718 details and examples. 

1719 

1720 :param cls: class to be mapped. 

1721 

1722 :return: the class that was passed. 

1723 

1724 .. seealso:: 

1725 

1726 :ref:`orm_declarative_mapping` 

1727 

1728 :meth:`_orm.registry.generate_base` - generates a base class 

1729 that will apply Declarative mapping to subclasses automatically 

1730 using a Python metaclass. 

1731 

1732 .. seealso:: 

1733 

1734 :meth:`_orm.registry.mapped_as_dataclass` 

1735 

1736 """ 

1737 _as_declarative(self, cls, cls.__dict__) 

1738 return cls 

1739 

1740 def as_declarative_base(self, **kw: Any) -> Callable[[Type[_T]], Type[_T]]: 

1741 """ 

1742 Class decorator which will invoke 

1743 :meth:`_orm.registry.generate_base` 

1744 for a given base class. 

1745 

1746 E.g.:: 

1747 

1748 from sqlalchemy.orm import registry 

1749 

1750 mapper_registry = registry() 

1751 

1752 

1753 @mapper_registry.as_declarative_base() 

1754 class Base: 

1755 @declared_attr 

1756 def __tablename__(cls): 

1757 return cls.__name__.lower() 

1758 

1759 id = Column(Integer, primary_key=True) 

1760 

1761 

1762 class MyMappedClass(Base): ... 

1763 

1764 All keyword arguments passed to 

1765 :meth:`_orm.registry.as_declarative_base` are passed 

1766 along to :meth:`_orm.registry.generate_base`. 

1767 

1768 """ 

1769 

1770 def decorate(cls: Type[_T]) -> Type[_T]: 

1771 kw["cls"] = cls 

1772 kw["name"] = cls.__name__ 

1773 return self.generate_base(**kw) # type: ignore 

1774 

1775 return decorate 

1776 

1777 def map_declaratively(self, cls: Type[_O]) -> Mapper[_O]: 

1778 """Map a class declaratively. 

1779 

1780 In this form of mapping, the class is scanned for mapping information, 

1781 including for columns to be associated with a table, and/or an 

1782 actual table object. 

1783 

1784 Returns the :class:`_orm.Mapper` object. 

1785 

1786 E.g.:: 

1787 

1788 from sqlalchemy.orm import registry 

1789 

1790 mapper_registry = registry() 

1791 

1792 

1793 class Foo: 

1794 __tablename__ = "some_table" 

1795 

1796 id = Column(Integer, primary_key=True) 

1797 name = Column(String) 

1798 

1799 

1800 mapper = mapper_registry.map_declaratively(Foo) 

1801 

1802 This function is more conveniently invoked indirectly via either the 

1803 :meth:`_orm.registry.mapped` class decorator or by subclassing a 

1804 declarative metaclass generated from 

1805 :meth:`_orm.registry.generate_base`. 

1806 

1807 See the section :ref:`orm_declarative_mapping` for complete 

1808 details and examples. 

1809 

1810 :param cls: class to be mapped. 

1811 

1812 :return: a :class:`_orm.Mapper` object. 

1813 

1814 .. seealso:: 

1815 

1816 :ref:`orm_declarative_mapping` 

1817 

1818 :meth:`_orm.registry.mapped` - more common decorator interface 

1819 to this function. 

1820 

1821 :meth:`_orm.registry.map_imperatively` 

1822 

1823 """ 

1824 _as_declarative(self, cls, cls.__dict__) 

1825 return cls.__mapper__ # type: ignore 

1826 

1827 def map_imperatively( 

1828 self, 

1829 class_: Type[_O], 

1830 local_table: Optional[FromClause] = None, 

1831 **kw: Any, 

1832 ) -> Mapper[_O]: 

1833 r"""Map a class imperatively. 

1834 

1835 In this form of mapping, the class is not scanned for any mapping 

1836 information. Instead, all mapping constructs are passed as 

1837 arguments. 

1838 

1839 This method is intended to be fully equivalent to the now-removed 

1840 SQLAlchemy ``mapper()`` function, except that it's in terms of 

1841 a particular registry. 

1842 

1843 E.g.:: 

1844 

1845 from sqlalchemy.orm import registry 

1846 

1847 mapper_registry = registry() 

1848 

1849 my_table = Table( 

1850 "my_table", 

1851 mapper_registry.metadata, 

1852 Column("id", Integer, primary_key=True), 

1853 ) 

1854 

1855 

1856 class MyClass: 

1857 pass 

1858 

1859 

1860 mapper_registry.map_imperatively(MyClass, my_table) 

1861 

1862 See the section :ref:`orm_imperative_mapping` for complete background 

1863 and usage examples. 

1864 

1865 :param class\_: The class to be mapped. Corresponds to the 

1866 :paramref:`_orm.Mapper.class_` parameter. 

1867 

1868 :param local_table: the :class:`_schema.Table` or other 

1869 :class:`_sql.FromClause` object that is the subject of the mapping. 

1870 Corresponds to the 

1871 :paramref:`_orm.Mapper.local_table` parameter. 

1872 

1873 :param \**kw: all other keyword arguments are passed to the 

1874 :class:`_orm.Mapper` constructor directly. 

1875 

1876 .. seealso:: 

1877 

1878 :ref:`orm_imperative_mapping` 

1879 

1880 :ref:`orm_declarative_mapping` 

1881 

1882 """ 

1883 return _mapper(self, class_, local_table, kw) 

1884 

1885 

1886RegistryType = registry 

1887 

1888if not TYPE_CHECKING: 

1889 # allow for runtime type resolution of ``ClassVar[_RegistryType]`` 

1890 _RegistryType = registry # noqa 

1891 

1892 

1893def as_declarative(**kw: Any) -> Callable[[Type[_T]], Type[_T]]: 

1894 """ 

1895 Class decorator which will adapt a given class into a 

1896 :func:`_orm.declarative_base`. 

1897 

1898 This function makes use of the :meth:`_orm.registry.as_declarative_base` 

1899 method, by first creating a :class:`_orm.registry` automatically 

1900 and then invoking the decorator. 

1901 

1902 E.g.:: 

1903 

1904 from sqlalchemy.orm import as_declarative 

1905 

1906 

1907 @as_declarative() 

1908 class Base: 

1909 @declared_attr 

1910 def __tablename__(cls): 

1911 return cls.__name__.lower() 

1912 

1913 id = Column(Integer, primary_key=True) 

1914 

1915 

1916 class MyMappedClass(Base): ... 

1917 

1918 .. seealso:: 

1919 

1920 :meth:`_orm.registry.as_declarative_base` 

1921 

1922 """ 

1923 metadata, class_registry = ( 

1924 kw.pop("metadata", None), 

1925 kw.pop("class_registry", None), 

1926 ) 

1927 

1928 return registry( 

1929 metadata=metadata, class_registry=class_registry 

1930 ).as_declarative_base(**kw) 

1931 

1932 

1933@compat_typing.dataclass_transform( 

1934 field_specifiers=( 

1935 MappedColumn, 

1936 RelationshipProperty, 

1937 Composite, 

1938 Synonym, 

1939 mapped_column, 

1940 relationship, 

1941 composite, 

1942 synonym, 

1943 deferred, 

1944 ), 

1945) 

1946def mapped_as_dataclass( 

1947 registry: RegistryType, 

1948 *, 

1949 init: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1950 repr: Union[_NoArg, bool] = _NoArg.NO_ARG, # noqa: A002 

1951 eq: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1952 order: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1953 unsafe_hash: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1954 match_args: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1955 kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG, 

1956 dataclass_callable: Union[ 

1957 _NoArg, Callable[..., Type[Any]] 

1958 ] = _NoArg.NO_ARG, 

1959) -> Callable[[Type[_O]], Type[_O]]: 

1960 """Standalone function form of :meth:`_orm.registry.mapped_as_dataclass` 

1961 which may have better compatibility with mypy. 

1962 

1963 The :class:`_orm.registry` is passed as the first argument to the 

1964 decorator. 

1965 

1966 e.g.:: 

1967 

1968 from sqlalchemy.orm import Mapped 

1969 from sqlalchemy.orm import mapped_as_dataclass 

1970 from sqlalchemy.orm import mapped_column 

1971 from sqlalchemy.orm import registry 

1972 

1973 some_registry = registry() 

1974 

1975 

1976 @mapped_as_dataclass(some_registry) 

1977 class Relationships: 

1978 __tablename__ = "relationships" 

1979 

1980 entity_id1: Mapped[int] = mapped_column(primary_key=True) 

1981 entity_id2: Mapped[int] = mapped_column(primary_key=True) 

1982 level: Mapped[int] = mapped_column(Integer) 

1983 

1984 .. versionadded:: 2.0.44 

1985 

1986 """ 

1987 return registry.mapped_as_dataclass( 

1988 init=init, 

1989 repr=repr, 

1990 eq=eq, 

1991 order=order, 

1992 unsafe_hash=unsafe_hash, 

1993 match_args=match_args, 

1994 kw_only=kw_only, 

1995 dataclass_callable=dataclass_callable, 

1996 ) 

1997 

1998 

1999@inspection._inspects( 

2000 DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept 

2001) 

2002def _inspect_decl_meta(cls: Type[Any]) -> Optional[Mapper[Any]]: 

2003 mp: Optional[Mapper[Any]] = _inspect_mapped_class(cls) 

2004 if mp is None: 

2005 if _DeferredMapperConfig.has_cls(cls): 

2006 _DeferredMapperConfig.raise_unmapped_for_cls(cls) 

2007 return mp