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

471 statements  

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 

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 

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

100 

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

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

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

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

105 

106_DeclaredAttrDecorated = Callable[ 

107 ..., Union[Mapped[_T], ORMDescriptor[_T], SQLCoreOperations[_T]] 

108] 

109 

110 

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

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

113 mapped table, otherwise return False. 

114 

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

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

117 hierarchy. 

118 

119 .. seealso:: 

120 

121 :ref:`decl_mixin_inheritance` 

122 

123 """ 

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

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

126 return True 

127 return False 

128 

129 

130class _DynamicAttributesType(type): 

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

132 if "__mapper__" in cls.__dict__: 

133 _add_attribute(cls, key, value) 

134 else: 

135 type.__setattr__(cls, key, value) 

136 

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

138 if "__mapper__" in cls.__dict__: 

139 _del_attribute(cls, key) 

140 else: 

141 type.__delattr__(cls, key) 

142 

143 

144class DeclarativeAttributeIntercept( 

145 _DynamicAttributesType, 

146 # Inspectable is used only by the mypy plugin 

147 inspection.Inspectable[Mapper[Any]], 

148): 

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

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

151 attributes dynamically. 

152 

153 """ 

154 

155 

156@compat_typing.dataclass_transform( 

157 field_specifiers=( 

158 MappedColumn, 

159 RelationshipProperty, 

160 Composite, 

161 Synonym, 

162 mapped_column, 

163 relationship, 

164 composite, 

165 synonym, 

166 deferred, 

167 ), 

168) 

169class DCTransformDeclarative(DeclarativeAttributeIntercept): 

170 """metaclass that includes @dataclass_transforms""" 

171 

172 

173class DeclarativeMeta(DeclarativeAttributeIntercept): 

174 metadata: MetaData 

175 registry: RegistryType 

176 

177 def __init__( 

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

179 ) -> None: 

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

181 # __init_subclass__() method (#7900) 

182 dict_ = cls.__dict__ 

183 

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

185 # assign privately to not conflict with subclass attributes named 

186 # "registry" 

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

188 if reg is None: 

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

190 if not isinstance(reg, registry): 

191 raise exc.InvalidRequestError( 

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

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

194 ) 

195 else: 

196 cls._sa_registry = reg 

197 

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

199 _as_declarative(reg, cls, dict_) 

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

201 

202 

203def synonym_for( 

204 name: str, map_column: bool = False 

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

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

207 attribute in conjunction with a Python descriptor. 

208 

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

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

211 

212 class MyClass(Base): 

213 __tablename__ = "my_table" 

214 

215 id = Column(Integer, primary_key=True) 

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

217 

218 @synonym_for("job_status") 

219 @property 

220 def job_status(self): 

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

222 

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

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

225 feature. 

226 

227 .. seealso:: 

228 

229 :ref:`synonyms` - Overview of synonyms 

230 

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

232 

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

234 updated approach to augmenting attribute behavior more flexibly than 

235 can be achieved with synonyms. 

236 

237 """ 

238 

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

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

241 

242 return decorate 

243 

244 

245class _declared_attr_common: 

246 def __init__( 

247 self, 

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

249 cascading: bool = False, 

250 quiet: bool = False, 

251 ): 

252 # suppport 

253 # @declared_attr 

254 # @classmethod 

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

256 # ... 

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

258 # for situations where needed 

259 if isinstance(fn, classmethod): 

260 fn = fn.__func__ 

261 

262 self.fget = fn 

263 self._cascading = cascading 

264 self._quiet = quiet 

265 self.__doc__ = fn.__doc__ 

266 

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

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

269 

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

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

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

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

274 

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

276 # setup phase 

277 

278 cls = owner 

279 manager = attributes.opt_manager_of_class(cls) 

280 if manager is None: 

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

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

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

284 util.warn( 

285 "Unmanaged access of declarative attribute %s from " 

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

287 ) 

288 return self.fget(cls) 

289 elif manager.is_mapped: 

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

291 # scan setup, just run the function. 

292 return self.fget(cls) 

293 

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

295 # that is tracking the values of these attributes. 

296 declarative_scan = manager.declarative_scan() 

297 

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

299 assert declarative_scan is not None 

300 

301 reg = declarative_scan.declared_attr_reg 

302 

303 if self in reg: 

304 return reg[self] 

305 else: 

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

307 return obj 

308 

309 

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

311 # see mapping_api.rst for docstring 

312 

313 if typing.TYPE_CHECKING: 

314 

315 def __init__( 

316 self, 

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

318 cascading: bool = False, 

319 ): ... 

320 

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

322 

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

324 

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

326 

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

328 # extensive fooling of mypy underway... 

329 ... 

330 

331 

332class declared_attr(interfaces._MappedAttribute[_T], _declared_attr_common): 

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

334 a mapped property or Declarative directive. 

335 

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

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

338 invoked from the uninstantiated class. The Declarative mapping process 

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

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

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

342 table configuration. 

343 

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

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

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

347 define dynamically generated column expressions and other Declarative 

348 attributes. 

349 

350 Example:: 

351 

352 class ProvidesUserMixin: 

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

354 

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

356 

357 @declared_attr 

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

359 return relationship("User") 

360 

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

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

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

364 :class:`_orm.Mapped` attributes:: 

365 

366 class CreateTableName: 

367 @declared_attr.directive 

368 def __tablename__(cls) -> str: 

369 return cls.__name__.lower() 

370 

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

372 classes, to allow for attributes that dynamically configure themselves 

373 on subclasses when using mapped inheritance schemes. Below 

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

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

376 for subclasses:: 

377 

378 class Employee(Base): 

379 __tablename__ = "employee" 

380 

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

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

383 

384 @declared_attr.directive 

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

386 if cls.__name__ == "Employee": 

387 return { 

388 "polymorphic_on": cls.type, 

389 "polymorphic_identity": "Employee", 

390 } 

391 else: 

392 return {"polymorphic_identity": cls.__name__} 

393 

394 

395 class Engineer(Employee): 

396 pass 

397 

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

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

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

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

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

403 

404 class SomethingMixin: 

405 x: Mapped[int] 

406 y: Mapped[int] 

407 

408 @declared_attr 

409 @classmethod 

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

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

412 

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

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

415 integration where needed. 

416 

417 

418 .. seealso:: 

419 

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

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

422 

423 """ # noqa: E501 

424 

425 if typing.TYPE_CHECKING: 

426 

427 def __init__( 

428 self, 

429 fn: _DeclaredAttrDecorated[_T], 

430 cascading: bool = False, 

431 ): ... 

432 

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

434 

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

436 

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

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

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

440 # declarative function that does not return InstrumentedAttribute 

441 @overload 

442 def __get__( 

443 self, instance: None, owner: Any 

444 ) -> InstrumentedAttribute[_T]: ... 

445 

446 @overload 

447 def __get__(self, instance: object, owner: Any) -> _T: ... 

448 

449 def __get__( 

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

451 ) -> Union[InstrumentedAttribute[_T], _T]: ... 

452 

453 @hybridmethod 

454 def _stateful(cls, **kw: Any) -> _stateful_declared_attr[_T]: 

455 return _stateful_declared_attr(**kw) 

456 

457 @hybridproperty 

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

459 # see mapping_api.rst for docstring 

460 return _declared_directive # type: ignore 

461 

462 @hybridproperty 

463 def cascading(cls) -> _stateful_declared_attr[_T]: 

464 # see mapping_api.rst for docstring 

465 return cls._stateful(cascading=True) 

466 

467 

468class _stateful_declared_attr(declared_attr[_T]): 

469 kw: Dict[str, Any] 

470 

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

472 self.kw = kw 

473 

474 @hybridmethod 

475 def _stateful(self, **kw: Any) -> _stateful_declared_attr[_T]: 

476 new_kw = self.kw.copy() 

477 new_kw.update(kw) 

478 return _stateful_declared_attr(**new_kw) 

479 

480 def __call__(self, fn: _DeclaredAttrDecorated[_T]) -> declared_attr[_T]: 

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

482 

483 

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

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

486 

487 E.g.:: 

488 

489 from sqlalchemy.orm import declared_attr 

490 from sqlalchemy.orm import declarative_mixin 

491 

492 

493 @declarative_mixin 

494 class MyMixin: 

495 

496 @declared_attr 

497 def __tablename__(cls): 

498 return cls.__name__.lower() 

499 

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

501 __mapper_args__ = {"always_refresh": True} 

502 

503 id = Column(Integer, primary_key=True) 

504 

505 

506 class MyModel(MyMixin, Base): 

507 name = Column(String(1000)) 

508 

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

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

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

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

513 

514 .. versionadded:: 1.4.6 

515 

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

517 SQLAlchemy version. 

518 

519 .. seealso:: 

520 

521 :ref:`orm_mixins_toplevel` 

522 

523 :ref:`mypy_declarative_mixins` - in the 

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

525 

526 """ # noqa: E501 

527 

528 return cls 

529 

530 

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

532 if "metadata" in cls.__dict__: 

533 metadata = cls.__dict__["metadata"] 

534 else: 

535 metadata = None 

536 

537 if "type_annotation_map" in cls.__dict__: 

538 type_annotation_map = cls.__dict__["type_annotation_map"] 

539 else: 

540 type_annotation_map = None 

541 

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

543 if reg is not None: 

544 if not isinstance(reg, registry): 

545 raise exc.InvalidRequestError( 

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

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

548 ) 

549 elif type_annotation_map is not None: 

550 raise exc.InvalidRequestError( 

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

552 "type_annotation_map entry. Per-base type_annotation_maps " 

553 "are not supported. Please apply the type_annotation_map " 

554 "to this registry directly." 

555 ) 

556 

557 else: 

558 reg = registry( 

559 metadata=metadata, type_annotation_map=type_annotation_map 

560 ) 

561 cls.registry = reg 

562 

563 cls._sa_registry = reg 

564 

565 if "metadata" not in cls.__dict__: 

566 cls.metadata = cls.registry.metadata 

567 

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

569 cls.__init__ = cls.registry.constructor 

570 

571 

572class MappedAsDataclass(metaclass=DCTransformDeclarative): 

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

574 a dataclass. 

575 

576 .. seealso:: 

577 

578 :ref:`orm_declarative_native_dataclasses` - complete background 

579 on SQLAlchemy native dataclass mapping 

580 

581 .. versionadded:: 2.0 

582 

583 """ 

584 

585 def __init_subclass__( 

586 cls, 

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

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

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

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

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

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

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

594 dataclass_callable: Union[ 

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

596 ] = _NoArg.NO_ARG, 

597 **kw: Any, 

598 ) -> None: 

599 apply_dc_transforms: _DataclassArguments = { 

600 "init": init, 

601 "repr": repr, 

602 "eq": eq, 

603 "order": order, 

604 "unsafe_hash": unsafe_hash, 

605 "match_args": match_args, 

606 "kw_only": kw_only, 

607 "dataclass_callable": dataclass_callable, 

608 } 

609 

610 current_transforms: _DataclassArguments 

611 

612 if hasattr(cls, "_sa_apply_dc_transforms"): 

613 current = cls._sa_apply_dc_transforms 

614 

615 _ClassScanMapperConfig._assert_dc_arguments(current) 

616 

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

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

619 for k, v in apply_dc_transforms.items() 

620 } 

621 else: 

622 cls._sa_apply_dc_transforms = current_transforms = ( 

623 apply_dc_transforms 

624 ) 

625 

626 super().__init_subclass__(**kw) 

627 

628 if not _is_mapped_class(cls): 

629 new_anno = ( 

630 _ClassScanMapperConfig._update_annotations_for_non_mapped_class 

631 )(cls) 

632 _ClassScanMapperConfig._apply_dataclasses_to_any_class( 

633 current_transforms, cls, new_anno 

634 ) 

635 

636 

637class DeclarativeBase( 

638 # Inspectable is used only by the mypy plugin 

639 inspection.Inspectable[InstanceState[Any]], 

640 metaclass=DeclarativeAttributeIntercept, 

641): 

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

643 

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

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

646 

647 

648 from sqlalchemy.orm import DeclarativeBase 

649 

650 

651 class Base(DeclarativeBase): 

652 pass 

653 

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

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

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

657 

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

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

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

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

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

663 collection as well as a specific value for 

664 :paramref:`_orm.registry.type_annotation_map`:: 

665 

666 from typing_extensions import Annotated 

667 

668 from sqlalchemy import BigInteger 

669 from sqlalchemy import MetaData 

670 from sqlalchemy import String 

671 from sqlalchemy.orm import DeclarativeBase 

672 

673 bigint = Annotated[int, "bigint"] 

674 my_metadata = MetaData() 

675 

676 

677 class Base(DeclarativeBase): 

678 metadata = my_metadata 

679 type_annotation_map = { 

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

681 bigint: BigInteger(), 

682 } 

683 

684 Class-level attributes which may be specified include: 

685 

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

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

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

689 Otherwise, the local :class:`_schema.MetaData` collection will supercede 

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

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

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

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

694 :paramref:`_orm.registry.type_annotation_map`. 

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

696 

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

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

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

700 and other subclassing-oriented APIs should be seen as 

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

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

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

704 without using plugins. 

705 

706 **__init__ behavior** 

707 

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

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

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

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

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

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

714 constructor that will assign keyword arguments as attributes on the 

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

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

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

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

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

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

721 method does. 

722 

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

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

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

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

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

728 ``object.__init__()``. 

729 

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

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

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

733 

734 class Base(DeclarativeBase): 

735 def __init__(self, id=None): 

736 self.id = id 

737 

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

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

740 

741 class MyClass(Base): 

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

743 self.name = name 

744 super().__init__(id=id) 

745 

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

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

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

749 ``__init__()``. 

750 

751 

752 """ 

753 

754 if typing.TYPE_CHECKING: 

755 

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

757 

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

759 

760 _sa_registry: ClassVar[_RegistryType] 

761 

762 registry: ClassVar[_RegistryType] 

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

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

765 

766 metadata: ClassVar[MetaData] 

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

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

769 

770 .. seealso:: 

771 

772 :ref:`orm_declarative_metadata` 

773 

774 """ 

775 

776 __name__: ClassVar[str] 

777 

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

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

780 # ok with it. 

781 __mapper__: ClassVar[Mapper[Any]] 

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

783 mapped. 

784 

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

786 ``inspect(klass)``. 

787 

788 """ 

789 

790 __table__: ClassVar[FromClause] 

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

792 mapped. 

793 

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

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

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

797 

798 .. seealso:: 

799 

800 :ref:`orm_declarative_metadata` 

801 

802 """ 

803 

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

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

806 __tablename__: Any 

807 """String name to assign to the generated 

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

809 :attr:`_orm.DeclarativeBase.__table__`. 

810 

811 .. seealso:: 

812 

813 :ref:`orm_declarative_table` 

814 

815 """ 

816 

817 __mapper_args__: Any 

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

819 :class:`_orm.Mapper` constructor. 

820 

821 .. seealso:: 

822 

823 :ref:`orm_declarative_mapper_options` 

824 

825 """ 

826 

827 __table_args__: Any 

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

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

830 :ref:`orm_declarative_table_configuration` 

831 for background on the specific structure of this collection. 

832 

833 .. seealso:: 

834 

835 :ref:`orm_declarative_table_configuration` 

836 

837 """ 

838 

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

840 

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

842 if DeclarativeBase in cls.__bases__: 

843 _check_not_declarative(cls, DeclarativeBase) 

844 _setup_declarative_base(cls) 

845 else: 

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

847 super().__init_subclass__(**kw) 

848 

849 

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

851 cls_dict = cls.__dict__ 

852 if ( 

853 "__table__" in cls_dict 

854 and not ( 

855 callable(cls_dict["__table__"]) 

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

857 ) 

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

859 raise exc.InvalidRequestError( 

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

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

862 ) 

863 

864 

865class DeclarativeBaseNoMeta( 

866 # Inspectable is used only by the mypy plugin 

867 inspection.Inspectable[InstanceState[Any]] 

868): 

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

870 to intercept new attributes. 

871 

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

873 custom metaclasses is desirable. 

874 

875 .. versionadded:: 2.0 

876 

877 

878 """ 

879 

880 _sa_registry: ClassVar[_RegistryType] 

881 

882 registry: ClassVar[_RegistryType] 

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

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

885 

886 metadata: ClassVar[MetaData] 

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

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

889 

890 .. seealso:: 

891 

892 :ref:`orm_declarative_metadata` 

893 

894 """ 

895 

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

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

898 # ok with it. 

899 __mapper__: ClassVar[Mapper[Any]] 

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

901 mapped. 

902 

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

904 ``inspect(klass)``. 

905 

906 """ 

907 

908 __table__: Optional[FromClause] 

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

910 mapped. 

911 

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

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

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

915 

916 .. seealso:: 

917 

918 :ref:`orm_declarative_metadata` 

919 

920 """ 

921 

922 if typing.TYPE_CHECKING: 

923 

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

925 

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

927 

928 __tablename__: Any 

929 """String name to assign to the generated 

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

931 :attr:`_orm.DeclarativeBase.__table__`. 

932 

933 .. seealso:: 

934 

935 :ref:`orm_declarative_table` 

936 

937 """ 

938 

939 __mapper_args__: Any 

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

941 :class:`_orm.Mapper` constructor. 

942 

943 .. seealso:: 

944 

945 :ref:`orm_declarative_mapper_options` 

946 

947 """ 

948 

949 __table_args__: Any 

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

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

952 :ref:`orm_declarative_table_configuration` 

953 for background on the specific structure of this collection. 

954 

955 .. seealso:: 

956 

957 :ref:`orm_declarative_table_configuration` 

958 

959 """ 

960 

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

962 

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

964 if DeclarativeBaseNoMeta in cls.__bases__: 

965 _check_not_declarative(cls, DeclarativeBaseNoMeta) 

966 _setup_declarative_base(cls) 

967 else: 

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

969 super().__init_subclass__(**kw) 

970 

971 

972def add_mapped_attribute( 

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

974) -> None: 

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

976 

977 E.g.:: 

978 

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

980 

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

982 metaclass that intercepts attribute set operations. 

983 

984 .. versionadded:: 2.0 

985 

986 

987 """ 

988 _add_attribute(target, key, attr) 

989 

990 

991def declarative_base( 

992 *, 

993 metadata: Optional[MetaData] = None, 

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

995 cls: Type[Any] = object, 

996 name: str = "Base", 

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

998 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1000 metaclass: Type[Any] = DeclarativeMeta, 

1001) -> Any: 

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

1003 

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

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

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

1007 information provided declaratively in the class and any subclasses 

1008 of the class. 

1009 

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

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

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

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

1014 with :pep:`484` typing tools. 

1015 

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

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

1018 method. That is, the following:: 

1019 

1020 from sqlalchemy.orm import declarative_base 

1021 

1022 Base = declarative_base() 

1023 

1024 Is equivalent to:: 

1025 

1026 from sqlalchemy.orm import registry 

1027 

1028 mapper_registry = registry() 

1029 Base = mapper_registry.generate_base() 

1030 

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

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

1033 for more details. 

1034 

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

1036 function is now a specialization of the more generic 

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

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

1039 

1040 

1041 :param metadata: 

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

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

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

1045 will be created if none is provided. The 

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

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

1048 

1049 :param mapper: 

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

1051 be used to map subclasses to their Tables. 

1052 

1053 :param cls: 

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

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

1056 

1057 :param name: 

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

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

1060 tracebacks and debugging. 

1061 

1062 :param constructor: 

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

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

1065 implementation that assigns \**kwargs for declared 

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

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

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

1069 

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

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

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

1073 and others. Allows two or more declarative base classes 

1074 to share the same registry of class names for simplified 

1075 inter-base relationships. 

1076 

1077 :param type_annotation_map: optional dictionary of Python types to 

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

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

1080 to produce column types based on annotations within the 

1081 :class:`_orm.Mapped` type. 

1082 

1083 

1084 .. versionadded:: 2.0 

1085 

1086 .. seealso:: 

1087 

1088 :ref:`orm_declarative_mapped_column_type_map` 

1089 

1090 :param metaclass: 

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

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

1093 declarative base class. 

1094 

1095 .. seealso:: 

1096 

1097 :class:`_orm.registry` 

1098 

1099 """ 

1100 

1101 return registry( 

1102 metadata=metadata, 

1103 class_registry=class_registry, 

1104 constructor=constructor, 

1105 type_annotation_map=type_annotation_map, 

1106 ).generate_base( 

1107 mapper=mapper, 

1108 cls=cls, 

1109 name=name, 

1110 metaclass=metaclass, 

1111 ) 

1112 

1113 

1114class registry: 

1115 """Generalized registry for mapping classes. 

1116 

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

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

1119 

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

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

1122 styles may be used interchangeably: 

1123 

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

1125 class, and is the underlying implementation of the 

1126 :func:`_orm.declarative_base` function. 

1127 

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

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

1130 base class. 

1131 

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

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

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

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

1136 which is removed as of SQLAlchemy 2.0. 

1137 

1138 .. versionadded:: 1.4 

1139 

1140 .. seealso:: 

1141 

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

1143 styles. 

1144 

1145 """ 

1146 

1147 _class_registry: clsregistry._ClsRegistryType 

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

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

1150 metadata: MetaData 

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

1152 type_annotation_map: _MutableTypeAnnotationMapType 

1153 _dependents: Set[_RegistryType] 

1154 _dependencies: Set[_RegistryType] 

1155 _new_mappers: bool 

1156 

1157 def __init__( 

1158 self, 

1159 *, 

1160 metadata: Optional[MetaData] = None, 

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

1162 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1164 ): 

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

1166 

1167 :param metadata: 

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

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

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

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

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

1173 

1174 :param constructor: 

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

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

1177 implementation that assigns \**kwargs for declared 

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

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

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

1181 

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

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

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

1185 and others. Allows two or more declarative base classes 

1186 to share the same registry of class names for simplified 

1187 inter-base relationships. 

1188 

1189 :param type_annotation_map: optional dictionary of Python types to 

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

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

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

1193 to produce column types based on annotations within the 

1194 :class:`_orm.Mapped` type. 

1195 

1196 .. versionadded:: 2.0 

1197 

1198 .. seealso:: 

1199 

1200 :ref:`orm_declarative_mapped_column_type_map` 

1201 

1202 

1203 """ 

1204 lcl_metadata = metadata or MetaData() 

1205 

1206 if class_registry is None: 

1207 class_registry = weakref.WeakValueDictionary() 

1208 

1209 self._class_registry = class_registry 

1210 self._managers = weakref.WeakKeyDictionary() 

1211 self._non_primary_mappers = weakref.WeakKeyDictionary() 

1212 self.metadata = lcl_metadata 

1213 self.constructor = constructor 

1214 self.type_annotation_map = {} 

1215 if type_annotation_map is not None: 

1216 self.update_type_annotation_map(type_annotation_map) 

1217 self._dependents = set() 

1218 self._dependencies = set() 

1219 

1220 self._new_mappers = False 

1221 

1222 with mapperlib._CONFIGURE_MUTEX: 

1223 mapperlib._mapper_registries[self] = True 

1224 

1225 def update_type_annotation_map( 

1226 self, 

1227 type_annotation_map: _TypeAnnotationMapType, 

1228 ) -> None: 

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

1230 values.""" 

1231 

1232 self.type_annotation_map.update( 

1233 { 

1234 de_optionalize_union_types(typ): sqltype 

1235 for typ, sqltype in type_annotation_map.items() 

1236 } 

1237 ) 

1238 

1239 def _resolve_type( 

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

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

1242 python_type_type: Type[Any] 

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

1244 

1245 if is_generic(python_type): 

1246 if is_literal(python_type): 

1247 python_type_type = python_type # type: ignore[assignment] 

1248 

1249 search = ( 

1250 (python_type, python_type_type), 

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

1252 ) 

1253 else: 

1254 python_type_type = python_type.__origin__ 

1255 search = ((python_type, python_type_type),) 

1256 elif isinstance(python_type, type): 

1257 python_type_type = python_type 

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

1259 else: 

1260 python_type_type = python_type # type: ignore[assignment] 

1261 search = ((python_type, python_type_type),) 

1262 

1263 for pt, flattened in search: 

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

1265 sql_type = self.type_annotation_map.get(pt) 

1266 if sql_type is None: 

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

1268 

1269 if sql_type is not None: 

1270 sql_type_inst = sqltypes.to_instance(sql_type) 

1271 

1272 # ... this additional step will reject most 

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

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

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

1276 # type_annotation_map to be useful 

1277 resolved_sql_type = sql_type_inst._resolve_for_python_type( 

1278 python_type_type, 

1279 pt, 

1280 flattened, 

1281 ) 

1282 if resolved_sql_type is not None: 

1283 return resolved_sql_type 

1284 

1285 # 2.0 fallbacks 

1286 if _do_fallbacks: 

1287 python_type_to_check: Any = None 

1288 kind = None 

1289 if is_pep695(python_type): 

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

1291 python_type_to_check = python_type 

1292 while is_pep695(python_type_to_check) and not is_pep593( 

1293 python_type_to_check 

1294 ): 

1295 python_type_to_check = python_type_to_check.__value__ 

1296 python_type_to_check = de_optionalize_union_types( 

1297 python_type_to_check 

1298 ) 

1299 kind = "pep-695 type" 

1300 if is_newtype(python_type): 

1301 python_type_to_check = flatten_newtype(python_type) 

1302 kind = "NewType" 

1303 

1304 if python_type_to_check is not None: 

1305 res_after_fallback = self._resolve_type( 

1306 python_type_to_check, False 

1307 ) 

1308 if res_after_fallback is not None: 

1309 assert kind is not None 

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

1311 warn_deprecated( 

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

1313 "a recursive " 

1314 "fashion without the recursed type being present " 

1315 "in the type_annotation_map is deprecated; add " 

1316 "this type or its recursed value to " 

1317 "the type_annotation_map to allow it to match " 

1318 "explicitly.", 

1319 "2.0", 

1320 ) 

1321 else: 

1322 warn_deprecated( 

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

1324 "its resolved value without matching it in the " 

1325 "type_annotation_map is deprecated; add this " 

1326 "type to " 

1327 "the type_annotation_map to allow it to match " 

1328 "explicitly.", 

1329 "2.0", 

1330 ) 

1331 return res_after_fallback 

1332 

1333 return None 

1334 

1335 @property 

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

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

1338 

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

1340 self._non_primary_mappers 

1341 ) 

1342 

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

1344 if registry is self: 

1345 return 

1346 registry._dependents.add(self) 

1347 self._dependencies.add(registry) 

1348 

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

1350 mapper._ready_for_configure = True 

1351 if self._new_mappers: 

1352 return 

1353 

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

1355 reg._new_mappers = True 

1356 

1357 @classmethod 

1358 def _recurse_with_dependents( 

1359 cls, registries: Set[RegistryType] 

1360 ) -> Iterator[RegistryType]: 

1361 todo = registries 

1362 done = set() 

1363 while todo: 

1364 reg = todo.pop() 

1365 done.add(reg) 

1366 

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

1368 # them before 

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

1370 yield reg 

1371 

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

1373 # after 

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

1375 

1376 @classmethod 

1377 def _recurse_with_dependencies( 

1378 cls, registries: Set[RegistryType] 

1379 ) -> Iterator[RegistryType]: 

1380 todo = registries 

1381 done = set() 

1382 while todo: 

1383 reg = todo.pop() 

1384 done.add(reg) 

1385 

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

1387 # them before 

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

1389 

1390 yield reg 

1391 

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

1393 # them before 

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

1395 

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

1397 return itertools.chain( 

1398 ( 

1399 manager.mapper 

1400 for manager in list(self._managers) 

1401 if manager.is_mapped 

1402 and not manager.mapper.configured 

1403 and manager.mapper._ready_for_configure 

1404 ), 

1405 ( 

1406 npm 

1407 for npm in list(self._non_primary_mappers) 

1408 if not npm.configured and npm._ready_for_configure 

1409 ), 

1410 ) 

1411 

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

1413 self._non_primary_mappers[np_mapper] = True 

1414 

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

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

1417 

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

1419 self._managers[manager] = True 

1420 if manager.is_mapped: 

1421 raise exc.ArgumentError( 

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

1423 % manager.class_ 

1424 ) 

1425 assert manager.registry is None 

1426 manager.registry = self 

1427 

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

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

1430 :class:`_orm.registry`. 

1431 

1432 The configure step is used to reconcile and initialize the 

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

1434 to invoke configuration events such as the 

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

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

1437 extensions or user-defined extension hooks. 

1438 

1439 If one or more mappers in this registry contain 

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

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

1442 registries. In order to configure those dependent registries 

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

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

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

1446 allow an application to programmatically invoke configuration of 

1447 registries while controlling whether or not the process implicitly 

1448 reaches other registries. 

1449 

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

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

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

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

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

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

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

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

1458 

1459 .. seealso:: 

1460 

1461 :func:`_orm.configure_mappers` 

1462 

1463 

1464 .. versionadded:: 1.4.0b2 

1465 

1466 """ 

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

1468 

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

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

1471 

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

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

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

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

1476 

1477 If this registry contains mappers that are dependencies of other 

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

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

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

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

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

1483 were not already disposed. 

1484 

1485 .. versionadded:: 1.4.0b2 

1486 

1487 .. seealso:: 

1488 

1489 :func:`_orm.clear_mappers` 

1490 

1491 """ 

1492 

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

1494 

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

1496 if "mapper" in manager.__dict__: 

1497 mapper = manager.mapper 

1498 

1499 mapper._set_dispose_flags() 

1500 

1501 class_ = manager.class_ 

1502 self._dispose_cls(class_) 

1503 instrumentation._instrumentation_factory.unregister(class_) 

1504 

1505 def generate_base( 

1506 self, 

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

1508 cls: Type[Any] = object, 

1509 name: str = "Base", 

1510 metaclass: Type[Any] = DeclarativeMeta, 

1511 ) -> Any: 

1512 """Generate a declarative base class. 

1513 

1514 Classes that inherit from the returned class object will be 

1515 automatically mapped using declarative mapping. 

1516 

1517 E.g.:: 

1518 

1519 from sqlalchemy.orm import registry 

1520 

1521 mapper_registry = registry() 

1522 

1523 Base = mapper_registry.generate_base() 

1524 

1525 

1526 class MyClass(Base): 

1527 __tablename__ = "my_table" 

1528 id = Column(Integer, primary_key=True) 

1529 

1530 The above dynamically generated class is equivalent to the 

1531 non-dynamic example below:: 

1532 

1533 from sqlalchemy.orm import registry 

1534 from sqlalchemy.orm.decl_api import DeclarativeMeta 

1535 

1536 mapper_registry = registry() 

1537 

1538 

1539 class Base(metaclass=DeclarativeMeta): 

1540 __abstract__ = True 

1541 registry = mapper_registry 

1542 metadata = mapper_registry.metadata 

1543 

1544 __init__ = mapper_registry.constructor 

1545 

1546 .. versionchanged:: 2.0 Note that the 

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

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

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

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

1551 tools. 

1552 

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

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

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

1556 

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

1558 examples. 

1559 

1560 :param mapper: 

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

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

1563 

1564 :param cls: 

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

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

1567 

1568 :param name: 

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

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

1571 tracebacks and debugging. 

1572 

1573 :param metaclass: 

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

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

1576 declarative base class. 

1577 

1578 .. seealso:: 

1579 

1580 :ref:`orm_declarative_mapping` 

1581 

1582 :func:`_orm.declarative_base` 

1583 

1584 """ 

1585 metadata = self.metadata 

1586 

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

1588 

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

1590 if isinstance(cls, type): 

1591 class_dict["__doc__"] = cls.__doc__ 

1592 

1593 if self.constructor is not None: 

1594 class_dict["__init__"] = self.constructor 

1595 

1596 class_dict["__abstract__"] = True 

1597 if mapper: 

1598 class_dict["__mapper_cls__"] = mapper 

1599 

1600 if hasattr(cls, "__class_getitem__"): 

1601 

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

1603 # allow generic classes in py3.9+ 

1604 return cls 

1605 

1606 class_dict["__class_getitem__"] = __class_getitem__ 

1607 

1608 return metaclass(name, bases, class_dict) 

1609 

1610 @compat_typing.dataclass_transform( 

1611 field_specifiers=( 

1612 MappedColumn, 

1613 RelationshipProperty, 

1614 Composite, 

1615 Synonym, 

1616 mapped_column, 

1617 relationship, 

1618 composite, 

1619 synonym, 

1620 deferred, 

1621 ), 

1622 ) 

1623 @overload 

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

1625 

1626 @overload 

1627 def mapped_as_dataclass( 

1628 self, 

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

1630 *, 

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

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

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

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

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

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

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

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

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

1640 

1641 def mapped_as_dataclass( 

1642 self, 

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

1644 *, 

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

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

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

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

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

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

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

1652 dataclass_callable: Union[ 

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

1654 ] = _NoArg.NO_ARG, 

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

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

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

1658 Python dataclass. 

1659 

1660 .. seealso:: 

1661 

1662 :ref:`orm_declarative_native_dataclasses` - complete background 

1663 on SQLAlchemy native dataclass mapping 

1664 

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

1666 provide better compatibility with mypy 

1667 

1668 .. versionadded:: 2.0 

1669 

1670 

1671 """ 

1672 

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

1674 setattr( 

1675 cls, 

1676 "_sa_apply_dc_transforms", 

1677 { 

1678 "init": init, 

1679 "repr": repr, 

1680 "eq": eq, 

1681 "order": order, 

1682 "unsafe_hash": unsafe_hash, 

1683 "match_args": match_args, 

1684 "kw_only": kw_only, 

1685 "dataclass_callable": dataclass_callable, 

1686 }, 

1687 ) 

1688 _as_declarative(self, cls, cls.__dict__) 

1689 return cls 

1690 

1691 if __cls: 

1692 return decorate(__cls) 

1693 else: 

1694 return decorate 

1695 

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

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

1698 to a given class. 

1699 

1700 E.g.:: 

1701 

1702 from sqlalchemy.orm import registry 

1703 

1704 mapper_registry = registry() 

1705 

1706 

1707 @mapper_registry.mapped 

1708 class Foo: 

1709 __tablename__ = "some_table" 

1710 

1711 id = Column(Integer, primary_key=True) 

1712 name = Column(String) 

1713 

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

1715 details and examples. 

1716 

1717 :param cls: class to be mapped. 

1718 

1719 :return: the class that was passed. 

1720 

1721 .. seealso:: 

1722 

1723 :ref:`orm_declarative_mapping` 

1724 

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

1726 that will apply Declarative mapping to subclasses automatically 

1727 using a Python metaclass. 

1728 

1729 .. seealso:: 

1730 

1731 :meth:`_orm.registry.mapped_as_dataclass` 

1732 

1733 """ 

1734 _as_declarative(self, cls, cls.__dict__) 

1735 return cls 

1736 

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

1738 """ 

1739 Class decorator which will invoke 

1740 :meth:`_orm.registry.generate_base` 

1741 for a given base class. 

1742 

1743 E.g.:: 

1744 

1745 from sqlalchemy.orm import registry 

1746 

1747 mapper_registry = registry() 

1748 

1749 

1750 @mapper_registry.as_declarative_base() 

1751 class Base: 

1752 @declared_attr 

1753 def __tablename__(cls): 

1754 return cls.__name__.lower() 

1755 

1756 id = Column(Integer, primary_key=True) 

1757 

1758 

1759 class MyMappedClass(Base): ... 

1760 

1761 All keyword arguments passed to 

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

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

1764 

1765 """ 

1766 

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

1768 kw["cls"] = cls 

1769 kw["name"] = cls.__name__ 

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

1771 

1772 return decorate 

1773 

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

1775 """Map a class declaratively. 

1776 

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

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

1779 actual table object. 

1780 

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

1782 

1783 E.g.:: 

1784 

1785 from sqlalchemy.orm import registry 

1786 

1787 mapper_registry = registry() 

1788 

1789 

1790 class Foo: 

1791 __tablename__ = "some_table" 

1792 

1793 id = Column(Integer, primary_key=True) 

1794 name = Column(String) 

1795 

1796 

1797 mapper = mapper_registry.map_declaratively(Foo) 

1798 

1799 This function is more conveniently invoked indirectly via either the 

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

1801 declarative metaclass generated from 

1802 :meth:`_orm.registry.generate_base`. 

1803 

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

1805 details and examples. 

1806 

1807 :param cls: class to be mapped. 

1808 

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

1810 

1811 .. seealso:: 

1812 

1813 :ref:`orm_declarative_mapping` 

1814 

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

1816 to this function. 

1817 

1818 :meth:`_orm.registry.map_imperatively` 

1819 

1820 """ 

1821 _as_declarative(self, cls, cls.__dict__) 

1822 return cls.__mapper__ # type: ignore 

1823 

1824 def map_imperatively( 

1825 self, 

1826 class_: Type[_O], 

1827 local_table: Optional[FromClause] = None, 

1828 **kw: Any, 

1829 ) -> Mapper[_O]: 

1830 r"""Map a class imperatively. 

1831 

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

1833 information. Instead, all mapping constructs are passed as 

1834 arguments. 

1835 

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

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

1838 a particular registry. 

1839 

1840 E.g.:: 

1841 

1842 from sqlalchemy.orm import registry 

1843 

1844 mapper_registry = registry() 

1845 

1846 my_table = Table( 

1847 "my_table", 

1848 mapper_registry.metadata, 

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

1850 ) 

1851 

1852 

1853 class MyClass: 

1854 pass 

1855 

1856 

1857 mapper_registry.map_imperatively(MyClass, my_table) 

1858 

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

1860 and usage examples. 

1861 

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

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

1864 

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

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

1867 Corresponds to the 

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

1869 

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

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

1872 

1873 .. seealso:: 

1874 

1875 :ref:`orm_imperative_mapping` 

1876 

1877 :ref:`orm_declarative_mapping` 

1878 

1879 """ 

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

1881 

1882 

1883RegistryType = registry 

1884 

1885if not TYPE_CHECKING: 

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

1887 _RegistryType = registry # noqa 

1888 

1889 

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

1891 """ 

1892 Class decorator which will adapt a given class into a 

1893 :func:`_orm.declarative_base`. 

1894 

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

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

1897 and then invoking the decorator. 

1898 

1899 E.g.:: 

1900 

1901 from sqlalchemy.orm import as_declarative 

1902 

1903 

1904 @as_declarative() 

1905 class Base: 

1906 @declared_attr 

1907 def __tablename__(cls): 

1908 return cls.__name__.lower() 

1909 

1910 id = Column(Integer, primary_key=True) 

1911 

1912 

1913 class MyMappedClass(Base): ... 

1914 

1915 .. seealso:: 

1916 

1917 :meth:`_orm.registry.as_declarative_base` 

1918 

1919 """ 

1920 metadata, class_registry = ( 

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

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

1923 ) 

1924 

1925 return registry( 

1926 metadata=metadata, class_registry=class_registry 

1927 ).as_declarative_base(**kw) 

1928 

1929 

1930@compat_typing.dataclass_transform( 

1931 field_specifiers=( 

1932 MappedColumn, 

1933 RelationshipProperty, 

1934 Composite, 

1935 Synonym, 

1936 mapped_column, 

1937 relationship, 

1938 composite, 

1939 synonym, 

1940 deferred, 

1941 ), 

1942) 

1943def mapped_as_dataclass( 

1944 registry: RegistryType, 

1945 *, 

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

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

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

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

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

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

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

1953 dataclass_callable: Union[ 

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

1955 ] = _NoArg.NO_ARG, 

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

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

1958 which may have better compatibility with mypy. 

1959 

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

1961 decorator. 

1962 

1963 e.g.:: 

1964 

1965 from sqlalchemy.orm import Mapped 

1966 from sqlalchemy.orm import mapped_as_dataclass 

1967 from sqlalchemy.orm import mapped_column 

1968 from sqlalchemy.orm import registry 

1969 

1970 some_registry = registry() 

1971 

1972 

1973 @mapped_as_dataclass(some_registry) 

1974 class Relationships: 

1975 __tablename__ = "relationships" 

1976 

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

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

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

1980 

1981 .. versionadded:: 2.0.44 

1982 

1983 """ 

1984 return registry.mapped_as_dataclass( 

1985 init=init, 

1986 repr=repr, 

1987 eq=eq, 

1988 order=order, 

1989 unsafe_hash=unsafe_hash, 

1990 match_args=match_args, 

1991 kw_only=kw_only, 

1992 dataclass_callable=dataclass_callable, 

1993 ) 

1994 

1995 

1996@inspection._inspects( 

1997 DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept 

1998) 

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

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

2001 if mp is None: 

2002 if _DeferredMapperConfig.has_cls(cls): 

2003 _DeferredMapperConfig.raise_unmapped_for_cls(cls) 

2004 return mp