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

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

437 statements  

1# orm/decl_api.py 

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

3# <see AUTHORS file> 

4# 

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

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

7 

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

9 

10from __future__ import annotations 

11 

12import itertools 

13import re 

14import typing 

15from typing import Any 

16from typing import Callable 

17from typing import cast 

18from typing import ClassVar 

19from typing import Dict 

20from typing import FrozenSet 

21from typing import Generic 

22from typing import Iterable 

23from typing import Iterator 

24from typing import Mapping 

25from typing import Optional 

26from typing import overload 

27from typing import Set 

28from typing import Tuple 

29from typing import Type 

30from typing import TYPE_CHECKING 

31from typing import TypeVar 

32from typing import Union 

33import weakref 

34 

35from . import attributes 

36from . import clsregistry 

37from . import instrumentation 

38from . import interfaces 

39from . import mapperlib 

40from ._orm_constructors import composite 

41from ._orm_constructors import deferred 

42from ._orm_constructors import mapped_column 

43from ._orm_constructors import relationship 

44from ._orm_constructors import synonym 

45from .attributes import InstrumentedAttribute 

46from .base import _inspect_mapped_class 

47from .base import _is_mapped_class 

48from .base import Mapped 

49from .base import ORMDescriptor 

50from .decl_base import _add_attribute 

51from .decl_base import _as_declarative 

52from .decl_base import _ClassScanMapperConfig 

53from .decl_base import _declarative_constructor 

54from .decl_base import _DeferredMapperConfig 

55from .decl_base import _del_attribute 

56from .decl_base import _mapper 

57from .descriptor_props import Composite 

58from .descriptor_props import Synonym 

59from .descriptor_props import Synonym as _orm_synonym 

60from .mapper import Mapper 

61from .properties import MappedColumn 

62from .relationships import RelationshipProperty 

63from .state import InstanceState 

64from .. import exc 

65from .. import inspection 

66from .. import util 

67from ..sql import sqltypes 

68from ..sql.base import _NoArg 

69from ..sql.elements import SQLCoreOperations 

70from ..sql.schema import MetaData 

71from ..sql.selectable import FromClause 

72from ..util import hybridmethod 

73from ..util import hybridproperty 

74from ..util import typing as compat_typing 

75from ..util.typing import CallableReference 

76from ..util.typing import flatten_newtype 

77from ..util.typing import is_generic 

78from ..util.typing import is_literal 

79from ..util.typing import is_newtype 

80from ..util.typing import is_pep695 

81from ..util.typing import Literal 

82from ..util.typing import Self 

83 

84if TYPE_CHECKING: 

85 from ._typing import _O 

86 from ._typing import _RegistryType 

87 from .decl_base import _DataclassArguments 

88 from .instrumentation import ClassManager 

89 from .interfaces import MapperProperty 

90 from .state import InstanceState # noqa 

91 from ..sql._typing import _TypeEngineArgument 

92 from ..sql.type_api import _MatchedOnType 

93 

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

95 

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

97 

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

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

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

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

102 

103_DeclaredAttrDecorated = Callable[ 

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

105] 

106 

107 

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

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

110 mapped table, otherwise return False. 

111 

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

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

114 hierarchy. 

115 

116 .. seealso:: 

117 

118 :ref:`decl_mixin_inheritance` 

119 

120 """ 

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

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

123 return True 

124 return False 

125 

126 

127class _DynamicAttributesType(type): 

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

129 if "__mapper__" in cls.__dict__: 

130 _add_attribute(cls, key, value) 

131 else: 

132 type.__setattr__(cls, key, value) 

133 

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

135 if "__mapper__" in cls.__dict__: 

136 _del_attribute(cls, key) 

137 else: 

138 type.__delattr__(cls, key) 

139 

140 

141class DeclarativeAttributeIntercept( 

142 _DynamicAttributesType, 

143 # Inspectable is used only by the mypy plugin 

144 inspection.Inspectable[Mapper[Any]], 

145): 

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

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

148 attributes dynamically. 

149 

150 """ 

151 

152 

153@compat_typing.dataclass_transform( 

154 field_specifiers=( 

155 MappedColumn, 

156 RelationshipProperty, 

157 Composite, 

158 Synonym, 

159 mapped_column, 

160 relationship, 

161 composite, 

162 synonym, 

163 deferred, 

164 ), 

165) 

166class DCTransformDeclarative(DeclarativeAttributeIntercept): 

167 """metaclass that includes @dataclass_transforms""" 

168 

169 

170class DeclarativeMeta(DeclarativeAttributeIntercept): 

171 metadata: MetaData 

172 registry: RegistryType 

173 

174 def __init__( 

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

176 ) -> None: 

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

178 # __init_subclass__() method (#7900) 

179 dict_ = cls.__dict__ 

180 

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

182 # assign privately to not conflict with subclass attributes named 

183 # "registry" 

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

185 if reg is None: 

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

187 if not isinstance(reg, registry): 

188 raise exc.InvalidRequestError( 

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

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

191 ) 

192 else: 

193 cls._sa_registry = reg 

194 

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

196 _as_declarative(reg, cls, dict_) 

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

198 

199 

200def synonym_for( 

201 name: str, map_column: bool = False 

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

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

204 attribute in conjunction with a Python descriptor. 

205 

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

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

208 

209 class MyClass(Base): 

210 __tablename__ = 'my_table' 

211 

212 id = Column(Integer, primary_key=True) 

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

214 

215 @synonym_for("job_status") 

216 @property 

217 def job_status(self): 

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

219 

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

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

222 feature. 

223 

224 .. seealso:: 

225 

226 :ref:`synonyms` - Overview of synonyms 

227 

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

229 

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

231 updated approach to augmenting attribute behavior more flexibly than 

232 can be achieved with synonyms. 

233 

234 """ 

235 

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

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

238 

239 return decorate 

240 

241 

242class _declared_attr_common: 

243 def __init__( 

244 self, 

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

246 cascading: bool = False, 

247 quiet: bool = False, 

248 ): 

249 # suppport 

250 # @declared_attr 

251 # @classmethod 

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

253 # ... 

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

255 # for situations where needed 

256 if isinstance(fn, classmethod): 

257 fn = fn.__func__ 

258 

259 self.fget = fn 

260 self._cascading = cascading 

261 self._quiet = quiet 

262 self.__doc__ = fn.__doc__ 

263 

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

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

266 

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

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

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

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

271 

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

273 # setup phase 

274 

275 cls = owner 

276 manager = attributes.opt_manager_of_class(cls) 

277 if manager is None: 

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

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

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

281 util.warn( 

282 "Unmanaged access of declarative attribute %s from " 

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

284 ) 

285 return self.fget(cls) 

286 elif manager.is_mapped: 

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

288 # scan setup, just run the function. 

289 return self.fget(cls) 

290 

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

292 # that is tracking the values of these attributes. 

293 declarative_scan = manager.declarative_scan() 

294 

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

296 assert declarative_scan is not None 

297 

298 reg = declarative_scan.declared_attr_reg 

299 

300 if self in reg: 

301 return reg[self] 

302 else: 

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

304 return obj 

305 

306 

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

308 # see mapping_api.rst for docstring 

309 

310 if typing.TYPE_CHECKING: 

311 

312 def __init__( 

313 self, 

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

315 cascading: bool = False, 

316 ): ... 

317 

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

319 

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

321 

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

323 

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

325 # extensive fooling of mypy underway... 

326 ... 

327 

328 

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

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

331 a mapped property or Declarative directive. 

332 

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

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

335 invoked from the uninstantiated class. The Declarative mapping process 

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

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

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

339 table configuration. 

340 

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

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

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

344 define dynamically generated column expressions and other Declarative 

345 attributes. 

346 

347 Example:: 

348 

349 class ProvidesUserMixin: 

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

351 

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

353 

354 @declared_attr 

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

356 return relationship("User") 

357 

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

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

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

361 :class:`_orm.Mapped` attributes:: 

362 

363 class CreateTableName: 

364 @declared_attr.directive 

365 def __tablename__(cls) -> str: 

366 return cls.__name__.lower() 

367 

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

369 classes, to allow for attributes that dynamically configure themselves 

370 on subclasses when using mapped inheritance schemes. Below 

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

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

373 for subclasses:: 

374 

375 class Employee(Base): 

376 __tablename__ = 'employee' 

377 

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

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

380 

381 @declared_attr.directive 

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

383 if cls.__name__ == 'Employee': 

384 return { 

385 "polymorphic_on":cls.type, 

386 "polymorphic_identity":"Employee" 

387 } 

388 else: 

389 return {"polymorphic_identity":cls.__name__} 

390 

391 class Engineer(Employee): 

392 pass 

393 

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

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

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

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

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

399 

400 class SomethingMixin: 

401 x: Mapped[int] 

402 y: Mapped[int] 

403 

404 @declared_attr 

405 @classmethod 

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

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

408 

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

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

411 integration where needed. 

412 

413 

414 .. seealso:: 

415 

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

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

418 

419 """ # noqa: E501 

420 

421 if typing.TYPE_CHECKING: 

422 

423 def __init__( 

424 self, 

425 fn: _DeclaredAttrDecorated[_T], 

426 cascading: bool = False, 

427 ): ... 

428 

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

430 

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

432 

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

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

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

436 # declarative function that does not return InstrumentedAttribute 

437 @overload 

438 def __get__( 

439 self, instance: None, owner: Any 

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

441 

442 @overload 

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

444 

445 def __get__( 

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

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

448 

449 @hybridmethod 

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

451 return _stateful_declared_attr(**kw) 

452 

453 @hybridproperty 

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

455 # see mapping_api.rst for docstring 

456 return _declared_directive # type: ignore 

457 

458 @hybridproperty 

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

460 # see mapping_api.rst for docstring 

461 return cls._stateful(cascading=True) 

462 

463 

464class _stateful_declared_attr(declared_attr[_T]): 

465 kw: Dict[str, Any] 

466 

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

468 self.kw = kw 

469 

470 @hybridmethod 

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

472 new_kw = self.kw.copy() 

473 new_kw.update(kw) 

474 return _stateful_declared_attr(**new_kw) 

475 

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

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

478 

479 

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

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

482 

483 E.g.:: 

484 

485 from sqlalchemy.orm import declared_attr 

486 from sqlalchemy.orm import declarative_mixin 

487 

488 @declarative_mixin 

489 class MyMixin: 

490 

491 @declared_attr 

492 def __tablename__(cls): 

493 return cls.__name__.lower() 

494 

495 __table_args__ = {'mysql_engine': 'InnoDB'} 

496 __mapper_args__= {'always_refresh': True} 

497 

498 id = Column(Integer, primary_key=True) 

499 

500 class MyModel(MyMixin, Base): 

501 name = Column(String(1000)) 

502 

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

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

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

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

507 

508 .. versionadded:: 1.4.6 

509 

510 .. seealso:: 

511 

512 :ref:`orm_mixins_toplevel` 

513 

514 :ref:`mypy_declarative_mixins` - in the 

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

516 

517 """ # noqa: E501 

518 

519 return cls 

520 

521 

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

523 if "metadata" in cls.__dict__: 

524 metadata = cls.__dict__["metadata"] 

525 else: 

526 metadata = None 

527 

528 if "type_annotation_map" in cls.__dict__: 

529 type_annotation_map = cls.__dict__["type_annotation_map"] 

530 else: 

531 type_annotation_map = None 

532 

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

534 if reg is not None: 

535 if not isinstance(reg, registry): 

536 raise exc.InvalidRequestError( 

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

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

539 ) 

540 elif type_annotation_map is not None: 

541 raise exc.InvalidRequestError( 

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

543 "type_annotation_map entry. Per-base type_annotation_maps " 

544 "are not supported. Please apply the type_annotation_map " 

545 "to this registry directly." 

546 ) 

547 

548 else: 

549 reg = registry( 

550 metadata=metadata, type_annotation_map=type_annotation_map 

551 ) 

552 cls.registry = reg 

553 

554 cls._sa_registry = reg 

555 

556 if "metadata" not in cls.__dict__: 

557 cls.metadata = cls.registry.metadata 

558 

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

560 cls.__init__ = cls.registry.constructor 

561 

562 

563class MappedAsDataclass(metaclass=DCTransformDeclarative): 

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

565 a dataclass. 

566 

567 .. seealso:: 

568 

569 :ref:`orm_declarative_native_dataclasses` - complete background 

570 on SQLAlchemy native dataclass mapping 

571 

572 .. versionadded:: 2.0 

573 

574 """ 

575 

576 def __init_subclass__( 

577 cls, 

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

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

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

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

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

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

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

585 dataclass_callable: Union[ 

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

587 ] = _NoArg.NO_ARG, 

588 **kw: Any, 

589 ) -> None: 

590 apply_dc_transforms: _DataclassArguments = { 

591 "init": init, 

592 "repr": repr, 

593 "eq": eq, 

594 "order": order, 

595 "unsafe_hash": unsafe_hash, 

596 "match_args": match_args, 

597 "kw_only": kw_only, 

598 "dataclass_callable": dataclass_callable, 

599 } 

600 

601 current_transforms: _DataclassArguments 

602 

603 if hasattr(cls, "_sa_apply_dc_transforms"): 

604 current = cls._sa_apply_dc_transforms 

605 

606 _ClassScanMapperConfig._assert_dc_arguments(current) 

607 

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

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

610 for k, v in apply_dc_transforms.items() 

611 } 

612 else: 

613 cls._sa_apply_dc_transforms = current_transforms = ( 

614 apply_dc_transforms 

615 ) 

616 

617 super().__init_subclass__(**kw) 

618 

619 if not _is_mapped_class(cls): 

620 new_anno = ( 

621 _ClassScanMapperConfig._update_annotations_for_non_mapped_class 

622 )(cls) 

623 _ClassScanMapperConfig._apply_dataclasses_to_any_class( 

624 current_transforms, cls, new_anno 

625 ) 

626 

627 

628class DeclarativeBase( 

629 # Inspectable is used only by the mypy plugin 

630 inspection.Inspectable[InstanceState[Any]], 

631 metaclass=DeclarativeAttributeIntercept, 

632): 

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

634 

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

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

637 

638 

639 from sqlalchemy.orm import DeclarativeBase 

640 

641 class Base(DeclarativeBase): 

642 pass 

643 

644 

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

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

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

648 

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

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

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

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

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

654 collection as well as a specific value for 

655 :paramref:`_orm.registry.type_annotation_map`:: 

656 

657 from typing import Annotated 

658 

659 from sqlalchemy import BigInteger 

660 from sqlalchemy import MetaData 

661 from sqlalchemy import String 

662 from sqlalchemy.orm import DeclarativeBase 

663 

664 bigint = Annotated[int, "bigint"] 

665 my_metadata = MetaData() 

666 

667 class Base(DeclarativeBase): 

668 metadata = my_metadata 

669 type_annotation_map = { 

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

671 bigint: BigInteger() 

672 } 

673 

674 Class-level attributes which may be specified include: 

675 

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

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

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

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

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

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

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

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

684 :paramref:`_orm.registry.type_annotation_map`. 

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

686 

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

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

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

690 and other subclassing-oriented APIs should be seen as 

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

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

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

694 without using plugins. 

695 

696 **__init__ behavior** 

697 

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

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

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

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

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

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

704 constructor that will assign keyword arguments as attributes on the 

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

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

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

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

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

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

711 method does. 

712 

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

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

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

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

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

718 ``object.__init__()``. 

719 

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

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

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

723 

724 class Base(DeclarativeBase): 

725 def __init__(self, id=None): 

726 self.id = id 

727 

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

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

730 

731 class MyClass(Base): 

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

733 self.name = name 

734 super().__init__(id=id) 

735 

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

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

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

739 ``__init__()``. 

740 

741 

742 """ 

743 

744 if typing.TYPE_CHECKING: 

745 

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

747 

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

749 

750 _sa_registry: ClassVar[_RegistryType] 

751 

752 registry: ClassVar[_RegistryType] 

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

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

755 

756 metadata: ClassVar[MetaData] 

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

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

759 

760 .. seealso:: 

761 

762 :ref:`orm_declarative_metadata` 

763 

764 """ 

765 

766 __name__: ClassVar[str] 

767 

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

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

770 # ok with it. 

771 __mapper__: ClassVar[Mapper[Any]] 

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

773 mapped. 

774 

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

776 ``inspect(klass)``. 

777 

778 """ 

779 

780 __table__: ClassVar[FromClause] 

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

782 mapped. 

783 

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

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

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

787 

788 .. seealso:: 

789 

790 :ref:`orm_declarative_metadata` 

791 

792 """ 

793 

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

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

796 __tablename__: Any 

797 """String name to assign to the generated 

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

799 :attr:`_orm.DeclarativeBase.__table__`. 

800 

801 .. seealso:: 

802 

803 :ref:`orm_declarative_table` 

804 

805 """ 

806 

807 __mapper_args__: Any 

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

809 :class:`_orm.Mapper` constructor. 

810 

811 .. seealso:: 

812 

813 :ref:`orm_declarative_mapper_options` 

814 

815 """ 

816 

817 __table_args__: Any 

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

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

820 :ref:`orm_declarative_table_configuration` 

821 for background on the specific structure of this collection. 

822 

823 .. seealso:: 

824 

825 :ref:`orm_declarative_table_configuration` 

826 

827 """ 

828 

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

830 

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

832 if DeclarativeBase in cls.__bases__: 

833 _check_not_declarative(cls, DeclarativeBase) 

834 _setup_declarative_base(cls) 

835 else: 

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

837 super().__init_subclass__(**kw) 

838 

839 

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

841 cls_dict = cls.__dict__ 

842 if ( 

843 "__table__" in cls_dict 

844 and not ( 

845 callable(cls_dict["__table__"]) 

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

847 ) 

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

849 raise exc.InvalidRequestError( 

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

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

852 ) 

853 

854 

855class DeclarativeBaseNoMeta( 

856 # Inspectable is used only by the mypy plugin 

857 inspection.Inspectable[InstanceState[Any]] 

858): 

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

860 to intercept new attributes. 

861 

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

863 custom metaclasses is desirable. 

864 

865 .. versionadded:: 2.0 

866 

867 

868 """ 

869 

870 _sa_registry: ClassVar[_RegistryType] 

871 

872 registry: ClassVar[_RegistryType] 

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

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

875 

876 metadata: ClassVar[MetaData] 

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

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

879 

880 .. seealso:: 

881 

882 :ref:`orm_declarative_metadata` 

883 

884 """ 

885 

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

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

888 # ok with it. 

889 __mapper__: ClassVar[Mapper[Any]] 

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

891 mapped. 

892 

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

894 ``inspect(klass)``. 

895 

896 """ 

897 

898 __table__: Optional[FromClause] 

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

900 mapped. 

901 

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

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

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

905 

906 .. seealso:: 

907 

908 :ref:`orm_declarative_metadata` 

909 

910 """ 

911 

912 if typing.TYPE_CHECKING: 

913 

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

915 

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

917 

918 __tablename__: Any 

919 """String name to assign to the generated 

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

921 :attr:`_orm.DeclarativeBase.__table__`. 

922 

923 .. seealso:: 

924 

925 :ref:`orm_declarative_table` 

926 

927 """ 

928 

929 __mapper_args__: Any 

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

931 :class:`_orm.Mapper` constructor. 

932 

933 .. seealso:: 

934 

935 :ref:`orm_declarative_mapper_options` 

936 

937 """ 

938 

939 __table_args__: Any 

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

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

942 :ref:`orm_declarative_table_configuration` 

943 for background on the specific structure of this collection. 

944 

945 .. seealso:: 

946 

947 :ref:`orm_declarative_table_configuration` 

948 

949 """ 

950 

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

952 

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

954 if DeclarativeBaseNoMeta in cls.__bases__: 

955 _check_not_declarative(cls, DeclarativeBaseNoMeta) 

956 _setup_declarative_base(cls) 

957 else: 

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

959 super().__init_subclass__(**kw) 

960 

961 

962def add_mapped_attribute( 

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

964) -> None: 

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

966 

967 E.g.:: 

968 

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

970 

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

972 metaclass that intercepts attribute set operations. 

973 

974 .. versionadded:: 2.0 

975 

976 

977 """ 

978 _add_attribute(target, key, attr) 

979 

980 

981def declarative_base( 

982 *, 

983 metadata: Optional[MetaData] = None, 

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

985 cls: Type[Any] = object, 

986 name: str = "Base", 

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

988 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

990 metaclass: Type[Any] = DeclarativeMeta, 

991) -> Any: 

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

993 

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

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

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

997 information provided declaratively in the class and any subclasses 

998 of the class. 

999 

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

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

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

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

1004 with :pep:`484` typing tools. 

1005 

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

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

1008 method. That is, the following:: 

1009 

1010 from sqlalchemy.orm import declarative_base 

1011 

1012 Base = declarative_base() 

1013 

1014 Is equivalent to:: 

1015 

1016 from sqlalchemy.orm import registry 

1017 

1018 mapper_registry = registry() 

1019 Base = mapper_registry.generate_base() 

1020 

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

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

1023 for more details. 

1024 

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

1026 function is now a specialization of the more generic 

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

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

1029 

1030 

1031 :param metadata: 

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

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

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

1035 will be created if none is provided. The 

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

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

1038 

1039 :param mapper: 

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

1041 be used to map subclasses to their Tables. 

1042 

1043 :param cls: 

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

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

1046 

1047 :param name: 

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

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

1050 tracebacks and debugging. 

1051 

1052 :param constructor: 

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

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

1055 implementation that assigns \**kwargs for declared 

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

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

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

1059 

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

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

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

1063 and others. Allows two or more declarative base classes 

1064 to share the same registry of class names for simplified 

1065 inter-base relationships. 

1066 

1067 :param type_annotation_map: optional dictionary of Python types to 

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

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

1070 to produce column types based on annotations within the 

1071 :class:`_orm.Mapped` type. 

1072 

1073 

1074 .. versionadded:: 2.0 

1075 

1076 .. seealso:: 

1077 

1078 :ref:`orm_declarative_mapped_column_type_map` 

1079 

1080 :param metaclass: 

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

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

1083 declarative base class. 

1084 

1085 .. seealso:: 

1086 

1087 :class:`_orm.registry` 

1088 

1089 """ 

1090 

1091 return registry( 

1092 metadata=metadata, 

1093 class_registry=class_registry, 

1094 constructor=constructor, 

1095 type_annotation_map=type_annotation_map, 

1096 ).generate_base( 

1097 mapper=mapper, 

1098 cls=cls, 

1099 name=name, 

1100 metaclass=metaclass, 

1101 ) 

1102 

1103 

1104class registry: 

1105 """Generalized registry for mapping classes. 

1106 

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

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

1109 

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

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

1112 styles may be used interchangeably: 

1113 

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

1115 class, and is the underlying implementation of the 

1116 :func:`_orm.declarative_base` function. 

1117 

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

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

1120 base class. 

1121 

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

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

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

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

1126 which is removed as of SQLAlchemy 2.0. 

1127 

1128 .. versionadded:: 1.4 

1129 

1130 .. seealso:: 

1131 

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

1133 styles. 

1134 

1135 """ 

1136 

1137 _class_registry: clsregistry._ClsRegistryType 

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

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

1140 metadata: MetaData 

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

1142 type_annotation_map: _MutableTypeAnnotationMapType 

1143 _dependents: Set[_RegistryType] 

1144 _dependencies: Set[_RegistryType] 

1145 _new_mappers: bool 

1146 

1147 def __init__( 

1148 self, 

1149 *, 

1150 metadata: Optional[MetaData] = None, 

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

1152 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1154 ): 

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

1156 

1157 :param metadata: 

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

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

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

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

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

1163 

1164 :param constructor: 

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

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

1167 implementation that assigns \**kwargs for declared 

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

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

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

1171 

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

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

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

1175 and others. Allows two or more declarative base classes 

1176 to share the same registry of class names for simplified 

1177 inter-base relationships. 

1178 

1179 :param type_annotation_map: optional dictionary of Python types to 

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

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

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

1183 to produce column types based on annotations within the 

1184 :class:`_orm.Mapped` type. 

1185 

1186 .. versionadded:: 2.0 

1187 

1188 .. seealso:: 

1189 

1190 :ref:`orm_declarative_mapped_column_type_map` 

1191 

1192 

1193 """ 

1194 lcl_metadata = metadata or MetaData() 

1195 

1196 if class_registry is None: 

1197 class_registry = weakref.WeakValueDictionary() 

1198 

1199 self._class_registry = class_registry 

1200 self._managers = weakref.WeakKeyDictionary() 

1201 self._non_primary_mappers = weakref.WeakKeyDictionary() 

1202 self.metadata = lcl_metadata 

1203 self.constructor = constructor 

1204 self.type_annotation_map = {} 

1205 if type_annotation_map is not None: 

1206 self.update_type_annotation_map(type_annotation_map) 

1207 self._dependents = set() 

1208 self._dependencies = set() 

1209 

1210 self._new_mappers = False 

1211 

1212 with mapperlib._CONFIGURE_MUTEX: 

1213 mapperlib._mapper_registries[self] = True 

1214 

1215 def update_type_annotation_map( 

1216 self, 

1217 type_annotation_map: _TypeAnnotationMapType, 

1218 ) -> None: 

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

1220 values.""" 

1221 

1222 self.type_annotation_map.update( 

1223 { 

1224 sub_type: sqltype 

1225 for typ, sqltype in type_annotation_map.items() 

1226 for sub_type in compat_typing.expand_unions( 

1227 typ, include_union=True, discard_none=True 

1228 ) 

1229 } 

1230 ) 

1231 

1232 def _resolve_type( 

1233 self, python_type: _MatchedOnType 

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

1235 

1236 python_type_to_check = python_type 

1237 while is_pep695(python_type_to_check): 

1238 python_type_to_check = python_type_to_check.__value__ 

1239 

1240 check_is_pt = python_type is python_type_to_check 

1241 

1242 python_type_type: Type[Any] 

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

1244 

1245 if is_generic(python_type_to_check): 

1246 if is_literal(python_type_to_check): 

1247 python_type_type = cast("Type[Any]", python_type_to_check) 

1248 

1249 search = ( # type: ignore[assignment] 

1250 (python_type, python_type_type), 

1251 (Literal, python_type_type), 

1252 ) 

1253 else: 

1254 python_type_type = python_type_to_check.__origin__ 

1255 search = ((python_type, python_type_type),) 

1256 elif is_newtype(python_type_to_check): 

1257 python_type_type = flatten_newtype(python_type_to_check) 

1258 search = ((python_type, python_type_type),) 

1259 elif isinstance(python_type_to_check, type): 

1260 python_type_type = python_type_to_check 

1261 search = ( 

1262 (pt if check_is_pt else python_type, pt) 

1263 for pt in python_type_type.__mro__ 

1264 ) 

1265 else: 

1266 python_type_type = python_type_to_check # type: ignore[assignment] 

1267 search = ((python_type, python_type_type),) 

1268 

1269 for pt, flattened in search: 

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

1271 sql_type = self.type_annotation_map.get(pt) 

1272 if sql_type is None: 

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

1274 

1275 if sql_type is not None: 

1276 sql_type_inst = sqltypes.to_instance(sql_type) 

1277 

1278 # ... this additional step will reject most 

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

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

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

1282 # type_annotation_map to be useful 

1283 resolved_sql_type = sql_type_inst._resolve_for_python_type( 

1284 python_type_type, 

1285 pt, 

1286 flattened, 

1287 ) 

1288 if resolved_sql_type is not None: 

1289 return resolved_sql_type 

1290 

1291 return None 

1292 

1293 @property 

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

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

1296 

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

1298 self._non_primary_mappers 

1299 ) 

1300 

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

1302 if registry is self: 

1303 return 

1304 registry._dependents.add(self) 

1305 self._dependencies.add(registry) 

1306 

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

1308 mapper._ready_for_configure = True 

1309 if self._new_mappers: 

1310 return 

1311 

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

1313 reg._new_mappers = True 

1314 

1315 @classmethod 

1316 def _recurse_with_dependents( 

1317 cls, registries: Set[RegistryType] 

1318 ) -> Iterator[RegistryType]: 

1319 todo = registries 

1320 done = set() 

1321 while todo: 

1322 reg = todo.pop() 

1323 done.add(reg) 

1324 

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

1326 # them before 

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

1328 yield reg 

1329 

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

1331 # after 

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

1333 

1334 @classmethod 

1335 def _recurse_with_dependencies( 

1336 cls, registries: Set[RegistryType] 

1337 ) -> Iterator[RegistryType]: 

1338 todo = registries 

1339 done = set() 

1340 while todo: 

1341 reg = todo.pop() 

1342 done.add(reg) 

1343 

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

1345 # them before 

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

1347 

1348 yield reg 

1349 

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

1351 # them before 

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

1353 

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

1355 return itertools.chain( 

1356 ( 

1357 manager.mapper 

1358 for manager in list(self._managers) 

1359 if manager.is_mapped 

1360 and not manager.mapper.configured 

1361 and manager.mapper._ready_for_configure 

1362 ), 

1363 ( 

1364 npm 

1365 for npm in list(self._non_primary_mappers) 

1366 if not npm.configured and npm._ready_for_configure 

1367 ), 

1368 ) 

1369 

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

1371 self._non_primary_mappers[np_mapper] = True 

1372 

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

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

1375 

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

1377 self._managers[manager] = True 

1378 if manager.is_mapped: 

1379 raise exc.ArgumentError( 

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

1381 % manager.class_ 

1382 ) 

1383 assert manager.registry is None 

1384 manager.registry = self 

1385 

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

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

1388 :class:`_orm.registry`. 

1389 

1390 The configure step is used to reconcile and initialize the 

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

1392 to invoke configuration events such as the 

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

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

1395 extensions or user-defined extension hooks. 

1396 

1397 If one or more mappers in this registry contain 

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

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

1400 registries. In order to configure those dependent registries 

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

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

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

1404 allow an application to programmatically invoke configuration of 

1405 registries while controlling whether or not the process implicitly 

1406 reaches other registries. 

1407 

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

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

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

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

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

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

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

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

1416 

1417 .. seealso:: 

1418 

1419 :func:`_orm.configure_mappers` 

1420 

1421 

1422 .. versionadded:: 1.4.0b2 

1423 

1424 """ 

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

1426 

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

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

1429 

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

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

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

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

1434 

1435 If this registry contains mappers that are dependencies of other 

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

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

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

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

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

1441 were not already disposed. 

1442 

1443 .. versionadded:: 1.4.0b2 

1444 

1445 .. seealso:: 

1446 

1447 :func:`_orm.clear_mappers` 

1448 

1449 """ 

1450 

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

1452 

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

1454 if "mapper" in manager.__dict__: 

1455 mapper = manager.mapper 

1456 

1457 mapper._set_dispose_flags() 

1458 

1459 class_ = manager.class_ 

1460 self._dispose_cls(class_) 

1461 instrumentation._instrumentation_factory.unregister(class_) 

1462 

1463 def generate_base( 

1464 self, 

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

1466 cls: Type[Any] = object, 

1467 name: str = "Base", 

1468 metaclass: Type[Any] = DeclarativeMeta, 

1469 ) -> Any: 

1470 """Generate a declarative base class. 

1471 

1472 Classes that inherit from the returned class object will be 

1473 automatically mapped using declarative mapping. 

1474 

1475 E.g.:: 

1476 

1477 from sqlalchemy.orm import registry 

1478 

1479 mapper_registry = registry() 

1480 

1481 Base = mapper_registry.generate_base() 

1482 

1483 class MyClass(Base): 

1484 __tablename__ = "my_table" 

1485 id = Column(Integer, primary_key=True) 

1486 

1487 The above dynamically generated class is equivalent to the 

1488 non-dynamic example below:: 

1489 

1490 from sqlalchemy.orm import registry 

1491 from sqlalchemy.orm.decl_api import DeclarativeMeta 

1492 

1493 mapper_registry = registry() 

1494 

1495 class Base(metaclass=DeclarativeMeta): 

1496 __abstract__ = True 

1497 registry = mapper_registry 

1498 metadata = mapper_registry.metadata 

1499 

1500 __init__ = mapper_registry.constructor 

1501 

1502 .. versionchanged:: 2.0 Note that the 

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

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

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

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

1507 tools. 

1508 

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

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

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

1512 

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

1514 examples. 

1515 

1516 :param mapper: 

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

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

1519 

1520 :param cls: 

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

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

1523 

1524 :param name: 

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

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

1527 tracebacks and debugging. 

1528 

1529 :param metaclass: 

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

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

1532 declarative base class. 

1533 

1534 .. seealso:: 

1535 

1536 :ref:`orm_declarative_mapping` 

1537 

1538 :func:`_orm.declarative_base` 

1539 

1540 """ 

1541 metadata = self.metadata 

1542 

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

1544 

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

1546 if isinstance(cls, type): 

1547 class_dict["__doc__"] = cls.__doc__ 

1548 

1549 if self.constructor is not None: 

1550 class_dict["__init__"] = self.constructor 

1551 

1552 class_dict["__abstract__"] = True 

1553 if mapper: 

1554 class_dict["__mapper_cls__"] = mapper 

1555 

1556 if hasattr(cls, "__class_getitem__"): 

1557 

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

1559 # allow generic classes in py3.9+ 

1560 return cls 

1561 

1562 class_dict["__class_getitem__"] = __class_getitem__ 

1563 

1564 return metaclass(name, bases, class_dict) 

1565 

1566 @compat_typing.dataclass_transform( 

1567 field_specifiers=( 

1568 MappedColumn, 

1569 RelationshipProperty, 

1570 Composite, 

1571 Synonym, 

1572 mapped_column, 

1573 relationship, 

1574 composite, 

1575 synonym, 

1576 deferred, 

1577 ), 

1578 ) 

1579 @overload 

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

1581 

1582 @overload 

1583 def mapped_as_dataclass( 

1584 self, 

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

1586 /, 

1587 *, 

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

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

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

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

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

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

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

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

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

1597 

1598 def mapped_as_dataclass( 

1599 self, 

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

1601 /, 

1602 *, 

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

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

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

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

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

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

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

1610 dataclass_callable: Union[ 

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

1612 ] = _NoArg.NO_ARG, 

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

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

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

1616 Python dataclass. 

1617 

1618 .. seealso:: 

1619 

1620 :ref:`orm_declarative_native_dataclasses` - complete background 

1621 on SQLAlchemy native dataclass mapping 

1622 

1623 

1624 .. versionadded:: 2.0 

1625 

1626 

1627 """ 

1628 

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

1630 setattr( 

1631 cls, 

1632 "_sa_apply_dc_transforms", 

1633 { 

1634 "init": init, 

1635 "repr": repr, 

1636 "eq": eq, 

1637 "order": order, 

1638 "unsafe_hash": unsafe_hash, 

1639 "match_args": match_args, 

1640 "kw_only": kw_only, 

1641 "dataclass_callable": dataclass_callable, 

1642 }, 

1643 ) 

1644 _as_declarative(self, cls, cls.__dict__) 

1645 return cls 

1646 

1647 if __cls: 

1648 return decorate(__cls) 

1649 else: 

1650 return decorate 

1651 

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

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

1654 to a given class. 

1655 

1656 E.g.:: 

1657 

1658 from sqlalchemy.orm import registry 

1659 

1660 mapper_registry = registry() 

1661 

1662 @mapper_registry.mapped 

1663 class Foo: 

1664 __tablename__ = 'some_table' 

1665 

1666 id = Column(Integer, primary_key=True) 

1667 name = Column(String) 

1668 

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

1670 details and examples. 

1671 

1672 :param cls: class to be mapped. 

1673 

1674 :return: the class that was passed. 

1675 

1676 .. seealso:: 

1677 

1678 :ref:`orm_declarative_mapping` 

1679 

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

1681 that will apply Declarative mapping to subclasses automatically 

1682 using a Python metaclass. 

1683 

1684 .. seealso:: 

1685 

1686 :meth:`_orm.registry.mapped_as_dataclass` 

1687 

1688 """ 

1689 _as_declarative(self, cls, cls.__dict__) 

1690 return cls 

1691 

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

1693 """ 

1694 Class decorator which will invoke 

1695 :meth:`_orm.registry.generate_base` 

1696 for a given base class. 

1697 

1698 E.g.:: 

1699 

1700 from sqlalchemy.orm import registry 

1701 

1702 mapper_registry = registry() 

1703 

1704 @mapper_registry.as_declarative_base() 

1705 class Base: 

1706 @declared_attr 

1707 def __tablename__(cls): 

1708 return cls.__name__.lower() 

1709 id = Column(Integer, primary_key=True) 

1710 

1711 class MyMappedClass(Base): 

1712 # ... 

1713 

1714 All keyword arguments passed to 

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

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

1717 

1718 """ 

1719 

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

1721 kw["cls"] = cls 

1722 kw["name"] = cls.__name__ 

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

1724 

1725 return decorate 

1726 

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

1728 """Map a class declaratively. 

1729 

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

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

1732 actual table object. 

1733 

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

1735 

1736 E.g.:: 

1737 

1738 from sqlalchemy.orm import registry 

1739 

1740 mapper_registry = registry() 

1741 

1742 class Foo: 

1743 __tablename__ = 'some_table' 

1744 

1745 id = Column(Integer, primary_key=True) 

1746 name = Column(String) 

1747 

1748 mapper = mapper_registry.map_declaratively(Foo) 

1749 

1750 This function is more conveniently invoked indirectly via either the 

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

1752 declarative metaclass generated from 

1753 :meth:`_orm.registry.generate_base`. 

1754 

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

1756 details and examples. 

1757 

1758 :param cls: class to be mapped. 

1759 

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

1761 

1762 .. seealso:: 

1763 

1764 :ref:`orm_declarative_mapping` 

1765 

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

1767 to this function. 

1768 

1769 :meth:`_orm.registry.map_imperatively` 

1770 

1771 """ 

1772 _as_declarative(self, cls, cls.__dict__) 

1773 return cls.__mapper__ # type: ignore 

1774 

1775 def map_imperatively( 

1776 self, 

1777 class_: Type[_O], 

1778 local_table: Optional[FromClause] = None, 

1779 **kw: Any, 

1780 ) -> Mapper[_O]: 

1781 r"""Map a class imperatively. 

1782 

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

1784 information. Instead, all mapping constructs are passed as 

1785 arguments. 

1786 

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

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

1789 a particular registry. 

1790 

1791 E.g.:: 

1792 

1793 from sqlalchemy.orm import registry 

1794 

1795 mapper_registry = registry() 

1796 

1797 my_table = Table( 

1798 "my_table", 

1799 mapper_registry.metadata, 

1800 Column('id', Integer, primary_key=True) 

1801 ) 

1802 

1803 class MyClass: 

1804 pass 

1805 

1806 mapper_registry.map_imperatively(MyClass, my_table) 

1807 

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

1809 and usage examples. 

1810 

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

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

1813 

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

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

1816 Corresponds to the 

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

1818 

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

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

1821 

1822 .. seealso:: 

1823 

1824 :ref:`orm_imperative_mapping` 

1825 

1826 :ref:`orm_declarative_mapping` 

1827 

1828 """ 

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

1830 

1831 

1832RegistryType = registry 

1833 

1834if not TYPE_CHECKING: 

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

1836 _RegistryType = registry # noqa 

1837 

1838 

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

1840 """ 

1841 Class decorator which will adapt a given class into a 

1842 :func:`_orm.declarative_base`. 

1843 

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

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

1846 and then invoking the decorator. 

1847 

1848 E.g.:: 

1849 

1850 from sqlalchemy.orm import as_declarative 

1851 

1852 @as_declarative() 

1853 class Base: 

1854 @declared_attr 

1855 def __tablename__(cls): 

1856 return cls.__name__.lower() 

1857 id = Column(Integer, primary_key=True) 

1858 

1859 class MyMappedClass(Base): 

1860 # ... 

1861 

1862 .. seealso:: 

1863 

1864 :meth:`_orm.registry.as_declarative_base` 

1865 

1866 """ 

1867 metadata, class_registry = ( 

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

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

1870 ) 

1871 

1872 return registry( 

1873 metadata=metadata, class_registry=class_registry 

1874 ).as_declarative_base(**kw) 

1875 

1876 

1877@inspection._inspects( 

1878 DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept 

1879) 

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

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

1882 if mp is None: 

1883 if _DeferredMapperConfig.has_cls(cls): 

1884 _DeferredMapperConfig.raise_unmapped_for_cls(cls) 

1885 return mp