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

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

529 statements  

1# orm/decl_api.py 

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

3# <see AUTHORS file> 

4# 

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

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

7 

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

9 

10from __future__ import annotations 

11 

12import re 

13import typing 

14from typing import Any 

15from typing import Callable 

16from typing import cast 

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 Literal 

24from typing import Mapping 

25from typing import Optional 

26from typing import overload 

27from typing import Protocol 

28from typing import Set 

29from typing import Tuple 

30from typing import Type 

31from typing import TYPE_CHECKING 

32from typing import TypeVar 

33from typing import Union 

34import weakref 

35 

36from . import attributes 

37from . import clsregistry 

38from . import instrumentation 

39from . import interfaces 

40from . import mapperlib 

41from ._orm_constructors import composite 

42from ._orm_constructors import deferred 

43from ._orm_constructors import mapped_column 

44from ._orm_constructors import relationship 

45from ._orm_constructors import synonym 

46from ._orm_constructors import unmapped_column 

47from .attributes import InstrumentedAttribute 

48from .base import _inspect_mapped_class 

49from .base import _is_mapped_class 

50from .base import Mapped 

51from .base import ORMDescriptor 

52from .decl_base import _add_attribute 

53from .decl_base import _declarative_constructor 

54from .decl_base import _DeclarativeMapperConfig 

55from .decl_base import _DeclMappedClassProtocol 

56from .decl_base import _DeferredDeclarativeConfig 

57from .decl_base import _del_attribute 

58from .decl_base import _get_immediate_cls_attr 

59from .decl_base import _ORMClassConfigurator 

60from .decl_base import MappedClassProtocol 

61from .descriptor_props import Composite 

62from .descriptor_props import Synonym 

63from .descriptor_props import Synonym as _orm_synonym 

64from .mapper import Mapper 

65from .properties import MappedColumn 

66from .relationships import RelationshipProperty 

67from .state import InstanceState 

68from .. import event 

69from .. import exc 

70from .. import inspection 

71from .. import util 

72from ..event import dispatcher 

73from ..event import EventTarget 

74from ..sql import sqltypes 

75from ..sql._annotated_cols import _TC 

76from ..sql.base import _NoArg 

77from ..sql.elements import SQLCoreOperations 

78from ..sql.schema import MetaData 

79from ..sql.selectable import FromClause 

80from ..util import hybridmethod 

81from ..util import hybridproperty 

82from ..util import typing as compat_typing 

83from ..util import TypingOnly 

84from ..util.typing import CallableReference 

85from ..util.typing import de_optionalize_union_types 

86from ..util.typing import GenericProtocol 

87from ..util.typing import is_generic 

88from ..util.typing import is_literal 

89from ..util.typing import LITERAL_TYPES 

90from ..util.typing import Self 

91from ..util.typing import TypeAliasType 

92 

93if TYPE_CHECKING: 

94 from ._typing import _O 

95 from ._typing import _RegistryType 

96 from .instrumentation import ClassManager 

97 from .interfaces import _DataclassArguments 

98 from .interfaces import MapperProperty 

99 from .state import InstanceState # noqa 

100 from ..sql._typing import _TypeEngineArgument 

101 from ..util.typing import _MatchedOnType 

102 

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

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

105 

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

107 

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

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

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

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

112 

113_DeclaredAttrDecorated = Callable[ 

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

115] 

116 

117 

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

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

120 mapped table, otherwise return False. 

121 

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

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

124 hierarchy. 

125 

126 .. seealso:: 

127 

128 :ref:`decl_mixin_inheritance` 

129 

130 """ 

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

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

133 return True 

134 return False 

135 

136 

137class _DynamicAttributesType(type): 

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

139 if "__mapper__" in cls.__dict__: 

140 _add_attribute(cls, key, value) 

141 else: 

142 type.__setattr__(cls, key, value) 

143 

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

145 if "__mapper__" in cls.__dict__: 

146 _del_attribute(cls, key) 

147 else: 

148 type.__delattr__(cls, key) 

149 

150 

151class DeclarativeAttributeIntercept( 

152 _DynamicAttributesType, 

153 # Inspectable is used only by the mypy plugin 

154 inspection.Inspectable[Mapper[Any]], 

155): 

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

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

158 attributes dynamically. 

159 

160 """ 

161 

162 

163@compat_typing.dataclass_transform( 

164 field_specifiers=( 

165 MappedColumn, 

166 RelationshipProperty, 

167 Composite, 

168 Synonym, 

169 mapped_column, 

170 unmapped_column, 

171 relationship, 

172 composite, 

173 synonym, 

174 deferred, 

175 ), 

176) 

177class DCTransformDeclarative(DeclarativeAttributeIntercept): 

178 """metaclass that includes @dataclass_transforms""" 

179 

180 

181class DeclarativeMeta(DeclarativeAttributeIntercept): 

182 metadata: MetaData 

183 registry: RegistryType 

184 

185 def __init__( 

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

187 ) -> None: 

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

189 # __init_subclass__() method (#7900) 

190 dict_ = cls.__dict__ 

191 

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

193 # assign privately to not conflict with subclass attributes named 

194 # "registry" 

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

196 if reg is None: 

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

198 if not isinstance(reg, registry): 

199 raise exc.InvalidRequestError( 

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

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

202 ) 

203 else: 

204 cls._sa_registry = reg 

205 

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

207 _ORMClassConfigurator._as_declarative(reg, cls, dict_) 

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

209 

210 

211def synonym_for( 

212 name: str, map_column: bool = False 

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

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

215 attribute in conjunction with a Python descriptor. 

216 

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

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

219 

220 class MyClass(Base): 

221 __tablename__ = "my_table" 

222 

223 id = Column(Integer, primary_key=True) 

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

225 

226 @synonym_for("job_status") 

227 @property 

228 def job_status(self): 

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

230 

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

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

233 feature. 

234 

235 .. seealso:: 

236 

237 :ref:`synonyms` - Overview of synonyms 

238 

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

240 

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

242 updated approach to augmenting attribute behavior more flexibly than 

243 can be achieved with synonyms. 

244 

245 """ 

246 

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

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

249 

250 return decorate 

251 

252 

253class _declared_attr_common: 

254 def __init__( 

255 self, 

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

257 cascading: bool = False, 

258 quiet: bool = False, 

259 ): 

260 # support 

261 # @declared_attr 

262 # @classmethod 

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

264 # ... 

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

266 # for situations where needed 

267 if isinstance(fn, classmethod): 

268 fn = fn.__func__ 

269 

270 self.fget = fn 

271 self._cascading = cascading 

272 self._quiet = quiet 

273 self.__doc__ = fn.__doc__ 

274 

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

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

277 

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

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

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

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

282 

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

284 # setup phase 

285 

286 cls = owner 

287 manager = attributes.opt_manager_of_class(cls) 

288 if manager is None: 

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

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

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

292 util.warn( 

293 "Unmanaged access of declarative attribute %s from " 

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

295 ) 

296 return self.fget(cls) 

297 elif manager.is_mapped: 

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

299 # scan setup, just run the function. 

300 return self.fget(cls) 

301 

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

303 # that is tracking the values of these attributes. 

304 declarative_scan = manager.declarative_scan() 

305 

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

307 assert declarative_scan is not None 

308 

309 reg = declarative_scan.declared_attr_reg 

310 

311 if self in reg: 

312 return reg[self] 

313 else: 

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

315 return obj 

316 

317 

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

319 # see mapping_api.rst for docstring 

320 

321 if typing.TYPE_CHECKING: 

322 

323 def __init__( 

324 self, 

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

326 cascading: bool = False, 

327 ): ... 

328 

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

330 

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

332 

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

334 

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

336 # extensive fooling of mypy underway... 

337 ... 

338 

339 

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

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

342 a mapped property or Declarative directive. 

343 

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

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

346 invoked from the uninstantiated class. The Declarative mapping process 

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

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

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

350 table configuration. 

351 

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

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

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

355 define dynamically generated column expressions and other Declarative 

356 attributes. 

357 

358 Example:: 

359 

360 class ProvidesUserMixin: 

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

362 

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

364 

365 @declared_attr 

366 @classmethod 

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

368 return relationship("User") 

369 

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

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

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

373 :class:`_orm.Mapped` attributes:: 

374 

375 class CreateTableName: 

376 @declared_attr.directive 

377 @classmethod 

378 def __tablename__(cls) -> str: 

379 return cls.__name__.lower() 

380 

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

382 classes, to allow for attributes that dynamically configure themselves 

383 on subclasses when using mapped inheritance schemes. Below 

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

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

386 for subclasses:: 

387 

388 class Employee(Base): 

389 __tablename__ = "employee" 

390 

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

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

393 

394 @declared_attr.directive 

395 @classmethod 

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

397 if cls.__name__ == "Employee": 

398 return { 

399 "polymorphic_on": cls.type, 

400 "polymorphic_identity": "Employee", 

401 } 

402 else: 

403 return {"polymorphic_identity": cls.__name__} 

404 

405 

406 class Engineer(Employee): 

407 pass 

408 

409 :class:`_orm.declared_attr` can also be applied to non-directive 

410 attributes such as :func:`_orm.column_property`:: 

411 

412 class SomethingMixin: 

413 x: Mapped[int] 

414 y: Mapped[int] 

415 

416 @declared_attr 

417 @classmethod 

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

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

420 

421 .. tip:: 

422 

423 The examples above also apply the ``@classmethod`` decorator. This is 

424 not required at runtime, however :pep:`484` typing tools have no way to 

425 recognize ``def foo(cls)`` as a classmethod unless ``@classmethod`` is 

426 present. Adding ``@classmethod`` allows typing tools to correctly 

427 infer the ``cls`` parameter as the class, which is important when 

428 accessing mapped attributes such as ``cls.ph1`` inside the body of 

429 the method. :class:`_orm.declared_attr` supports both 

430 ``@declared_attr`` and ``@declared_attr.directive`` being combined 

431 with ``@classmethod``. 

432 

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

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

435 integration where needed. 

436 

437 

438 .. seealso:: 

439 

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

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

442 

443 """ # noqa: E501 

444 

445 if typing.TYPE_CHECKING: 

446 

447 def __init__( 

448 self, 

449 fn: _DeclaredAttrDecorated[_T_co], 

450 cascading: bool = False, 

451 ): ... 

452 

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

454 

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

456 

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

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

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

460 # declarative function that does not return InstrumentedAttribute 

461 @overload 

462 def __get__( 

463 self, instance: None, owner: Any 

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

465 

466 @overload 

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

468 

469 def __get__( 

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

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

472 

473 @hybridmethod 

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

475 return _stateful_declared_attr(**kw) 

476 

477 @hybridproperty 

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

479 # see mapping_api.rst for docstring 

480 return _declared_directive # type: ignore[return-value] 

481 

482 @hybridproperty 

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

484 # see mapping_api.rst for docstring 

485 return cls._stateful(cascading=True) 

486 

487 

488class _stateful_declared_attr(declared_attr[_T_co]): 

489 kw: Dict[str, Any] 

490 

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

492 self.kw = kw 

493 

494 @hybridmethod 

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

496 new_kw = self.kw.copy() 

497 new_kw.update(kw) 

498 return _stateful_declared_attr(**new_kw) 

499 

500 def __call__( 

501 self, fn: _DeclaredAttrDecorated[_T_co] 

502 ) -> declared_attr[_T_co]: 

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

504 

505 

506@util.deprecated( 

507 "2.1", 

508 "The declarative_mixin decorator was used only by the now removed " 

509 "mypy plugin so it has no longer any use and can be safely removed.", 

510) 

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

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

513 

514 E.g.:: 

515 

516 from sqlalchemy.orm import declared_attr 

517 from sqlalchemy.orm import declarative_mixin 

518 

519 

520 @declarative_mixin 

521 class MyMixin: 

522 

523 @declared_attr 

524 def __tablename__(cls): 

525 return cls.__name__.lower() 

526 

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

528 __mapper_args__ = {"always_refresh": True} 

529 

530 id = Column(Integer, primary_key=True) 

531 

532 

533 class MyModel(MyMixin, Base): 

534 name = Column(String(1000)) 

535 

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

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

538 the Mypy plugin in being able to identify 

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

540 

541 .. versionadded:: 1.4.6 

542 

543 .. seealso:: 

544 

545 :ref:`orm_mixins_toplevel` 

546 

547 """ # noqa: E501 

548 

549 return cls 

550 

551 

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

553 metadata = getattr(cls, "metadata", None) 

554 type_annotation_map = getattr(cls, "type_annotation_map", None) 

555 reg = getattr(cls, "registry", None) 

556 

557 if reg is not None: 

558 if not isinstance(reg, registry): 

559 raise exc.InvalidRequestError( 

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

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

562 ) 

563 elif type_annotation_map is not None: 

564 raise exc.InvalidRequestError( 

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

566 "type_annotation_map entry. Per-base type_annotation_maps " 

567 "are not supported. Please apply the type_annotation_map " 

568 "to this registry directly." 

569 ) 

570 

571 else: 

572 reg = registry( 

573 metadata=metadata, type_annotation_map=type_annotation_map 

574 ) 

575 cls.registry = reg 

576 

577 cls._sa_registry = reg 

578 

579 if "metadata" not in cls.__dict__: 

580 cls.metadata = cls.registry.metadata 

581 

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

583 cls.__init__ = cls.registry.constructor 

584 

585 

586def _generate_dc_transforms( 

587 cls_: Type[_O], 

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

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

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

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

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

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

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

595 dataclass_callable: Union[ 

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

597 ] = _NoArg.NO_ARG, 

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 if hasattr(cls_, "_sa_apply_dc_transforms"): 

611 current = cls_._sa_apply_dc_transforms # type: ignore[attr-defined] 

612 

613 _DeclarativeMapperConfig._assert_dc_arguments(current) 

614 

615 cls_._sa_apply_dc_transforms = { # type: ignore[attr-defined] # noqa: E501 

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

617 for k, v in apply_dc_transforms.items() 

618 } 

619 else: 

620 setattr(cls_, "_sa_apply_dc_transforms", apply_dc_transforms) 

621 

622 

623class MappedAsDataclass(metaclass=DCTransformDeclarative): 

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

625 a dataclass. 

626 

627 .. seealso:: 

628 

629 :ref:`orm_declarative_native_dataclasses` - complete background 

630 on SQLAlchemy native dataclass mapping with 

631 :class:`_orm.MappedAsDataclass`. 

632 

633 :ref:`orm_declarative_dc_mixins` - examples specific to using 

634 :class:`_orm.MappedAsDataclass` to create mixins 

635 

636 :func:`_orm.mapped_as_dataclass` / :func:`_orm.unmapped_dataclass` - 

637 decorator versions with equivalent functionality 

638 

639 .. versionadded:: 2.0 

640 

641 """ 

642 

643 def __init_subclass__( 

644 cls, 

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

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

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

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

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

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

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

652 dataclass_callable: Union[ 

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

654 ] = _NoArg.NO_ARG, 

655 **kw: Any, 

656 ) -> None: 

657 _generate_dc_transforms( 

658 init=init, 

659 repr=repr, 

660 eq=eq, 

661 order=order, 

662 unsafe_hash=unsafe_hash, 

663 match_args=match_args, 

664 kw_only=kw_only, 

665 dataclass_callable=dataclass_callable, 

666 cls_=cls, 

667 ) 

668 super().__init_subclass__(**kw) 

669 

670 if not _is_mapped_class(cls): 

671 # turn unmapped classes into "good enough" dataclasses to serve 

672 # as a base or a mixin 

673 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

674 

675 

676class _DeclarativeTyping(TypingOnly): 

677 """Common typing annotations shared by the DeclarativeBase and 

678 DeclarativeBaseNoMeta classes. 

679 """ 

680 

681 __slots__ = () 

682 

683 if typing.TYPE_CHECKING: 

684 # protocols for inspection 

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

686 

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

688 

689 # internal stuff 

690 _sa_registry: ClassVar[_RegistryType] 

691 

692 # public interface 

693 registry: ClassVar[_RegistryType] 

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

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

696 

697 metadata: ClassVar[MetaData] 

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

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

700 

701 .. seealso:: 

702 

703 :ref:`orm_declarative_metadata` 

704 

705 """ 

706 

707 __name__: ClassVar[str] 

708 

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

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

711 # ok with it. 

712 __mapper__: ClassVar[Mapper[Any]] 

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

714 mapped. 

715 

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

717 ``inspect(klass)``. 

718 

719 """ 

720 

721 __table__: ClassVar[FromClause] 

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

723 mapped. 

724 

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

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

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

728 

729 .. seealso:: 

730 

731 :ref:`orm_declarative_metadata` 

732 

733 """ 

734 

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

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

737 __tablename__: Any 

738 """String name to assign to the generated 

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

740 :attr:`_orm.DeclarativeBase.__table__`. 

741 

742 .. seealso:: 

743 

744 :ref:`orm_declarative_table` 

745 

746 """ 

747 

748 __mapper_args__: Any 

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

750 :class:`_orm.Mapper` constructor. 

751 

752 .. seealso:: 

753 

754 :ref:`orm_declarative_mapper_options` 

755 

756 """ 

757 

758 __table_args__: Any 

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

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

761 :ref:`orm_declarative_table_configuration` 

762 for background on the specific structure of this collection. 

763 

764 .. seealso:: 

765 

766 :ref:`orm_declarative_table_configuration` 

767 

768 """ 

769 

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

771 

772 

773class MappedClassWithTypedColumnsProtocol(Protocol[_TC]): 

774 """An ORM mapped class that also defines in the ``__typed_cols__`` 

775 attribute its typed columns. 

776 

777 .. versionadded:: 2.1.0b2 

778 """ 

779 

780 __typed_cols__: _TC 

781 """The :class:`_schema.TypedColumns` of this ORM mapped class.""" 

782 

783 __name__: ClassVar[str] 

784 __mapper__: ClassVar[Mapper[Any]] 

785 __table__: ClassVar[FromClause] 

786 

787 

788@overload 

789def as_typed_table( 

790 cls: type[MappedClassWithTypedColumnsProtocol[_TC]], / 

791) -> FromClause[_TC]: ... 

792 

793 

794@overload 

795def as_typed_table( 

796 cls: MappedClassProtocol[Any], typed_columns_cls: type[_TC], / 

797) -> FromClause[_TC]: ... 

798 

799 

800def as_typed_table( 

801 cls: ( 

802 MappedClassProtocol[Any] 

803 | type[MappedClassWithTypedColumnsProtocol[Any]] 

804 ), 

805 typed_columns_cls: Any = None, 

806 /, 

807) -> FromClause[Any]: 

808 """Return a typed :class:`_sql.FromClause` from the give ORM model. 

809 

810 This function is just a typing help, at runtime it just returns the 

811 ``__table__`` attribute of the provided ORM model. 

812 

813 It's usually called providing both the ORM model and the 

814 :class:`_schema.TypedColumns` class. Single argument calls are supported 

815 if the ORM model class provides an annotation pointing to its 

816 :class:`_schema.TypedColumns` in the ``__typed_cols__`` attribute. 

817 

818 

819 Example usage:: 

820 

821 from sqlalchemy import TypedColumns 

822 from sqlalchemy.orm import DeclarativeBase, mapped_column 

823 from sqlalchemy.orm import MappedColumn, as_typed_table 

824 

825 

826 class Base(DeclarativeBase): 

827 pass 

828 

829 

830 class A(Base): 

831 __tablename__ = "a" 

832 

833 id: MappedColumn[int] = mapped_column(primary_key=True) 

834 data: MappedColumn[str] 

835 

836 

837 class a_cols(A, TypedColumns): 

838 pass 

839 

840 

841 # table_a is annotated as FromClause[a_cols] 

842 table_a = as_typed_table(A, a_cols) 

843 

844 

845 class B(Base): 

846 __tablename__ = "b" 

847 __typed_cols__: "b_cols" 

848 

849 a: Mapped[int] = mapped_column(primary_key=True) 

850 b: Mapped[str] 

851 

852 

853 class b_cols(B, TypedColumns): 

854 pass 

855 

856 

857 # table_b is a FromClause[b_cols], can call with just B since it 

858 # provides the __typed_cols__ annotation 

859 table_b = as_typed_table(B) 

860 

861 For proper typing integration :class:`_orm.MappedColumn` should be used 

862 to annotate the single columns, since it's a more specific annotation than 

863 the usual :class:`_orm.Mapped` used for ORM attributes. 

864 

865 .. versionadded:: 2.1.0b2 

866 """ 

867 return cls.__table__ 

868 

869 

870class DeclarativeBase( 

871 # Inspectable is used only by the mypy plugin 

872 inspection.Inspectable[InstanceState[Any]], 

873 _DeclarativeTyping, 

874 metaclass=DeclarativeAttributeIntercept, 

875): 

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

877 

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

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

880 

881 

882 from sqlalchemy.orm import DeclarativeBase 

883 

884 

885 class Base(DeclarativeBase): 

886 pass 

887 

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

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

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

891 

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

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

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

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

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

897 collection as well as a specific value for 

898 :paramref:`_orm.registry.type_annotation_map`:: 

899 

900 from typing import Annotated 

901 

902 from sqlalchemy import BigInteger 

903 from sqlalchemy import MetaData 

904 from sqlalchemy import String 

905 from sqlalchemy.orm import DeclarativeBase 

906 

907 bigint = Annotated[int, "bigint"] 

908 my_metadata = MetaData() 

909 

910 

911 class Base(DeclarativeBase): 

912 metadata = my_metadata 

913 type_annotation_map = { 

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

915 bigint: BigInteger(), 

916 } 

917 

918 Class-level attributes which may be specified include: 

919 

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

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

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

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

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

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

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

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

928 :paramref:`_orm.registry.type_annotation_map`. 

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

930 

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

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

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

934 and other subclassing-oriented APIs should be seen as 

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

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

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

938 without using plugins. 

939 

940 **__init__ behavior** 

941 

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

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

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

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

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

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

948 constructor that will assign keyword arguments as attributes on the 

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

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

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

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

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

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

955 method does. 

956 

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

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

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

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

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

962 ``object.__init__()``. 

963 

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

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

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

967 

968 class Base(DeclarativeBase): 

969 def __init__(self, id=None): 

970 self.id = id 

971 

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

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

974 

975 class MyClass(Base): 

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

977 self.name = name 

978 super().__init__(id=id) 

979 

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

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

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

983 ``__init__()``. 

984 

985 

986 """ 

987 

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

989 if DeclarativeBase in cls.__bases__: 

990 _check_not_declarative(cls, DeclarativeBase) 

991 _setup_declarative_base(cls) 

992 else: 

993 _ORMClassConfigurator._as_declarative( 

994 cls._sa_registry, cls, cls.__dict__ 

995 ) 

996 super().__init_subclass__(**kw) 

997 

998 

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

1000 cls_dict = cls.__dict__ 

1001 if ( 

1002 "__table__" in cls_dict 

1003 and not ( 

1004 callable(cls_dict["__table__"]) 

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

1006 ) 

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

1008 raise exc.InvalidRequestError( 

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

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

1011 ) 

1012 

1013 

1014class DeclarativeBaseNoMeta( 

1015 # Inspectable is used only by the mypy plugin 

1016 inspection.Inspectable[InstanceState[Any]], 

1017 _DeclarativeTyping, 

1018): 

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

1020 to intercept new attributes. 

1021 

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

1023 custom metaclasses is desirable. 

1024 

1025 .. versionadded:: 2.0 

1026 

1027 

1028 """ 

1029 

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

1031 if DeclarativeBaseNoMeta in cls.__bases__: 

1032 _check_not_declarative(cls, DeclarativeBaseNoMeta) 

1033 _setup_declarative_base(cls) 

1034 else: 

1035 _ORMClassConfigurator._as_declarative( 

1036 cls._sa_registry, cls, cls.__dict__ 

1037 ) 

1038 super().__init_subclass__(**kw) 

1039 

1040 

1041def add_mapped_attribute( 

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

1043) -> None: 

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

1045 

1046 E.g.:: 

1047 

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

1049 

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

1051 metaclass that intercepts attribute set operations. 

1052 

1053 .. versionadded:: 2.0 

1054 

1055 

1056 """ 

1057 _add_attribute(target, key, attr) 

1058 

1059 

1060def declarative_base( 

1061 *, 

1062 metadata: Optional[MetaData] = None, 

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

1064 cls: Type[Any] = object, 

1065 name: str = "Base", 

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

1067 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1069 metaclass: Type[Any] = DeclarativeMeta, 

1070) -> Any: 

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

1072 

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

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

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

1076 information provided declaratively in the class and any subclasses 

1077 of the class. 

1078 

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

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

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

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

1083 with :pep:`484` typing tools. 

1084 

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

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

1087 method. That is, the following:: 

1088 

1089 from sqlalchemy.orm import declarative_base 

1090 

1091 Base = declarative_base() 

1092 

1093 Is equivalent to:: 

1094 

1095 from sqlalchemy.orm import registry 

1096 

1097 mapper_registry = registry() 

1098 Base = mapper_registry.generate_base() 

1099 

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

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

1102 for more details. 

1103 

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

1105 function is now a specialization of the more generic 

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

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

1108 

1109 

1110 :param metadata: 

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

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

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

1114 will be created if none is provided. The 

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

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

1117 

1118 :param mapper: 

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

1120 be used to map subclasses to their Tables. 

1121 

1122 :param cls: 

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

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

1125 

1126 :param name: 

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

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

1129 tracebacks and debugging. 

1130 

1131 :param constructor: 

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

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

1134 implementation that assigns \**kwargs for declared 

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

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

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

1138 

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

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

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

1142 and others. Allows two or more declarative base classes 

1143 to share the same registry of class names for simplified 

1144 inter-base relationships. 

1145 

1146 :param type_annotation_map: optional dictionary of Python types to 

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

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

1149 to produce column types based on annotations within the 

1150 :class:`_orm.Mapped` type. 

1151 

1152 

1153 .. versionadded:: 2.0 

1154 

1155 .. seealso:: 

1156 

1157 :ref:`orm_declarative_mapped_column_type_map` 

1158 

1159 :param metaclass: 

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

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

1162 declarative base class. 

1163 

1164 .. seealso:: 

1165 

1166 :class:`_orm.registry` 

1167 

1168 """ 

1169 

1170 return registry( 

1171 metadata=metadata, 

1172 class_registry=class_registry, 

1173 constructor=constructor, 

1174 type_annotation_map=type_annotation_map, 

1175 ).generate_base( 

1176 mapper=mapper, 

1177 cls=cls, 

1178 name=name, 

1179 metaclass=metaclass, 

1180 ) 

1181 

1182 

1183class registry(EventTarget): 

1184 """Generalized registry for mapping classes. 

1185 

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

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

1188 

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

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

1191 styles may be used interchangeably: 

1192 

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

1194 class, and is the underlying implementation of the 

1195 :func:`_orm.declarative_base` function. 

1196 

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

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

1199 base class. 

1200 

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

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

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

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

1205 which is removed as of SQLAlchemy 2.0. 

1206 

1207 .. versionadded:: 1.4 

1208 

1209 .. seealso:: 

1210 

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

1212 styles. 

1213 

1214 """ 

1215 

1216 _class_registry: clsregistry._ClsRegistryType 

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

1218 metadata: MetaData 

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

1220 type_annotation_map: _MutableTypeAnnotationMapType 

1221 _dependents: Set[_RegistryType] 

1222 _dependencies: Set[_RegistryType] 

1223 _declare_first_classes: weakref.WeakKeyDictionary[ 

1224 _DeclMappedClassProtocol[Any], Literal[True] 

1225 ] 

1226 _declare_last_classes: weakref.WeakKeyDictionary[ 

1227 _DeclMappedClassProtocol[Any], Literal[True] 

1228 ] 

1229 _new_mappers: bool 

1230 dispatch: dispatcher["registry"] 

1231 

1232 def __init__( 

1233 self, 

1234 *, 

1235 metadata: Optional[MetaData] = None, 

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

1237 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1239 ): 

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

1241 

1242 :param metadata: 

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

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

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

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

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

1248 

1249 :param constructor: 

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

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

1252 implementation that assigns \**kwargs for declared 

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

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

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

1256 

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

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

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

1260 and others. Allows two or more declarative base classes 

1261 to share the same registry of class names for simplified 

1262 inter-base relationships. 

1263 

1264 :param type_annotation_map: optional dictionary of Python types to 

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

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

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

1268 to produce column types based on annotations within the 

1269 :class:`_orm.Mapped` type. 

1270 

1271 .. versionadded:: 2.0 

1272 

1273 .. seealso:: 

1274 

1275 :ref:`orm_declarative_mapped_column_type_map` 

1276 

1277 

1278 """ 

1279 lcl_metadata = metadata or MetaData() 

1280 

1281 if class_registry is None: 

1282 class_registry = weakref.WeakValueDictionary() 

1283 

1284 self._class_registry = class_registry 

1285 self._managers = weakref.WeakKeyDictionary() 

1286 self.metadata = lcl_metadata 

1287 self.constructor = constructor 

1288 self.type_annotation_map = {} 

1289 if type_annotation_map is not None: 

1290 self.update_type_annotation_map(type_annotation_map) 

1291 self._dependents = set() 

1292 self._dependencies = set() 

1293 self._declare_first_classes = weakref.WeakKeyDictionary() 

1294 self._declare_last_classes = weakref.WeakKeyDictionary() 

1295 

1296 # these listeners are established first, so that user-defined 

1297 # listeners appended to the same events run after the 

1298 # ``__declare_first__()`` / ``__declare_last__()`` hooks; a listener 

1299 # added with ``insert=True`` will run before them 

1300 event.listen(self, "before_configured", _declare_first_for_registry) 

1301 event.listen(self, "after_configured", _declare_last_for_registry) 

1302 

1303 self._new_mappers = False 

1304 

1305 with mapperlib._CONFIGURE_MUTEX: 

1306 mapperlib._mapper_registries[self] = True 

1307 

1308 def update_type_annotation_map( 

1309 self, 

1310 type_annotation_map: _TypeAnnotationMapType, 

1311 ) -> None: 

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

1313 values.""" 

1314 

1315 self.type_annotation_map.update( 

1316 { 

1317 de_optionalize_union_types(typ): sqltype 

1318 for typ, sqltype in type_annotation_map.items() 

1319 } 

1320 ) 

1321 

1322 def _resolve_type_with_events( 

1323 self, 

1324 cls: Any, 

1325 key: str, 

1326 raw_annotation: _MatchedOnType, 

1327 extracted_type: _MatchedOnType, 

1328 *, 

1329 raw_pep_593_type: Optional[GenericProtocol[Any]] = None, 

1330 pep_593_resolved_argument: Optional[_MatchedOnType] = None, 

1331 raw_pep_695_type: Optional[TypeAliasType] = None, 

1332 pep_695_resolved_value: Optional[_MatchedOnType] = None, 

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

1334 """Resolve type with event support for custom type mapping. 

1335 

1336 This method fires the resolve_type_annotation event first to allow 

1337 custom resolution, then falls back to normal resolution. 

1338 

1339 """ 

1340 

1341 if self.dispatch.resolve_type_annotation: 

1342 type_resolve = TypeResolve( 

1343 self, 

1344 cls, 

1345 key, 

1346 raw_annotation, 

1347 ( 

1348 pep_593_resolved_argument 

1349 if pep_593_resolved_argument is not None 

1350 else ( 

1351 pep_695_resolved_value 

1352 if pep_695_resolved_value is not None 

1353 else extracted_type 

1354 ) 

1355 ), 

1356 raw_pep_593_type, 

1357 pep_593_resolved_argument, 

1358 raw_pep_695_type, 

1359 pep_695_resolved_value, 

1360 ) 

1361 

1362 for fn in self.dispatch.resolve_type_annotation: 

1363 result = fn(type_resolve) 

1364 if result is not None: 

1365 return sqltypes.to_instance(result) # type: ignore[no-any-return] # noqa: E501 

1366 

1367 if raw_pep_695_type is not None: 

1368 sqltype = self._resolve_type(raw_pep_695_type) 

1369 if sqltype is not None: 

1370 return sqltype 

1371 

1372 sqltype = self._resolve_type(extracted_type) 

1373 if sqltype is not None: 

1374 return sqltype 

1375 

1376 if pep_593_resolved_argument is not None: 

1377 sqltype = self._resolve_type(pep_593_resolved_argument) 

1378 

1379 return sqltype 

1380 

1381 def _resolve_type( 

1382 self, python_type: _MatchedOnType 

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

1384 python_type_type: Type[Any] 

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

1386 

1387 if is_generic(python_type): 

1388 if is_literal(python_type): 

1389 python_type_type = python_type # type: ignore[assignment] 

1390 

1391 search = ( 

1392 (python_type, python_type_type), 

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

1394 ) 

1395 else: 

1396 python_type_type = python_type.__origin__ 

1397 search = ((python_type, python_type_type),) 

1398 elif isinstance(python_type, type): 

1399 python_type_type = python_type 

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

1401 else: 

1402 python_type_type = python_type # type: ignore[assignment] 

1403 search = ((python_type, python_type_type),) 

1404 

1405 for pt, flattened in search: 

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

1407 sql_type = self.type_annotation_map.get(pt) 

1408 if sql_type is None: 

1409 sql_type = sqltypes._type_map_get(pt) # type: ignore[arg-type] # noqa: E501 

1410 

1411 if sql_type is not None: 

1412 sql_type_inst = sqltypes.to_instance(sql_type) 

1413 

1414 # ... this additional step will reject most 

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

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

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

1418 # type_annotation_map to be useful 

1419 resolved_sql_type = sql_type_inst._resolve_for_python_type( 

1420 python_type_type, 

1421 pt, 

1422 flattened, 

1423 ) 

1424 if resolved_sql_type is not None: 

1425 return resolved_sql_type 

1426 

1427 return None 

1428 

1429 @property 

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

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

1432 

1433 return frozenset(manager.mapper for manager in self._managers) 

1434 

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

1436 if registry is self: 

1437 return 

1438 registry._dependents.add(self) 

1439 self._dependencies.add(registry) 

1440 

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

1442 mapper._ready_for_configure = True 

1443 if self._new_mappers: 

1444 return 

1445 

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

1447 reg._new_mappers = True 

1448 

1449 @classmethod 

1450 def _recurse_with_dependents( 

1451 cls, registries: Set[RegistryType] 

1452 ) -> Iterator[RegistryType]: 

1453 todo = registries 

1454 done = set() 

1455 while todo: 

1456 reg = todo.pop() 

1457 done.add(reg) 

1458 

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

1460 # them before 

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

1462 yield reg 

1463 

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

1465 # after 

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

1467 

1468 @classmethod 

1469 def _recurse_with_dependencies( 

1470 cls, registries: Set[RegistryType] 

1471 ) -> Iterator[RegistryType]: 

1472 todo = registries 

1473 done = set() 

1474 while todo: 

1475 reg = todo.pop() 

1476 done.add(reg) 

1477 

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

1479 # them before 

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

1481 

1482 yield reg 

1483 

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

1485 # them before 

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

1487 

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

1489 return ( 

1490 manager.mapper 

1491 for manager in list(self._managers) 

1492 if manager.is_mapped 

1493 and not manager.mapper.configured 

1494 and manager.mapper._ready_for_configure 

1495 ) 

1496 

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

1498 clsregistry._remove_class(cls.__name__, cls, self._class_registry) 

1499 

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

1501 self._managers[manager] = True 

1502 

1503 # collect the class if it uses the __declare_first__() / 

1504 # __declare_last__() hooks, so that the registry-level listeners 

1505 # established in __init__() can invoke them. the collection is 

1506 # weak so that the class remains garbage collectable. 

1507 # 

1508 # these are insertion ordered dictionaries rather than sets, as a 

1509 # class is necessarily added after its bases, and the hook of a base 

1510 # class has to run before that of its subclasses; ConcreteBase 

1511 # inherits __declare_first__() to the whole hierarchy, and the first 

1512 # class to run establishes the "type" property that the remaining 

1513 # ones then adapt as a ConcreteInheritedProperty 

1514 cls = manager.class_ 

1515 decl_cls = cast("_DeclMappedClassProtocol[Any]", cls) 

1516 if _get_immediate_cls_attr(cls, "__declare_first__"): 

1517 self._declare_first_classes[decl_cls] = True 

1518 if _get_immediate_cls_attr(cls, "__declare_last__"): 

1519 self._declare_last_classes[decl_cls] = True 

1520 

1521 if manager.is_mapped: 

1522 raise exc.ArgumentError( 

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

1524 % manager.class_ 

1525 ) 

1526 assert manager.registry is None 

1527 manager.registry = self 

1528 

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

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

1531 :class:`_orm.registry`. 

1532 

1533 The configure step is used to reconcile and initialize the 

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

1535 to invoke configuration events such as the 

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

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

1538 extensions or user-defined extension hooks. 

1539 

1540 If one or more mappers in this registry contain 

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

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

1543 registries. In order to configure those dependent registries 

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

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

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

1547 allow an application to programmatically invoke configuration of 

1548 registries while controlling whether or not the process implicitly 

1549 reaches other registries. 

1550 

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

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

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

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

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

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

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

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

1559 

1560 .. seealso:: 

1561 

1562 :func:`_orm.configure_mappers` 

1563 

1564 

1565 .. versionadded:: 1.4.0b2 

1566 

1567 """ 

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

1569 

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

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

1572 

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

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

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

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

1577 

1578 If this registry contains mappers that are dependencies of other 

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

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

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

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

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

1584 were not already disposed. 

1585 

1586 .. versionadded:: 1.4.0b2 

1587 

1588 .. seealso:: 

1589 

1590 :func:`_orm.clear_mappers` 

1591 

1592 """ 

1593 

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

1595 

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

1597 if "mapper" in manager.__dict__: 

1598 mapper = manager.mapper 

1599 

1600 mapper._set_dispose_flags() 

1601 

1602 class_ = manager.class_ 

1603 self._dispose_cls(class_) 

1604 instrumentation._instrumentation_factory.unregister(class_) 

1605 

1606 def generate_base( 

1607 self, 

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

1609 cls: Type[Any] = object, 

1610 name: str = "Base", 

1611 metaclass: Type[Any] = DeclarativeMeta, 

1612 ) -> Any: 

1613 """Generate a declarative base class. 

1614 

1615 Classes that inherit from the returned class object will be 

1616 automatically mapped using declarative mapping. 

1617 

1618 E.g.:: 

1619 

1620 from sqlalchemy.orm import registry 

1621 

1622 mapper_registry = registry() 

1623 

1624 Base = mapper_registry.generate_base() 

1625 

1626 

1627 class MyClass(Base): 

1628 __tablename__ = "my_table" 

1629 id = Column(Integer, primary_key=True) 

1630 

1631 The above dynamically generated class is equivalent to the 

1632 non-dynamic example below:: 

1633 

1634 from sqlalchemy.orm import registry 

1635 from sqlalchemy.orm.decl_api import DeclarativeMeta 

1636 

1637 mapper_registry = registry() 

1638 

1639 

1640 class Base(metaclass=DeclarativeMeta): 

1641 __abstract__ = True 

1642 registry = mapper_registry 

1643 metadata = mapper_registry.metadata 

1644 

1645 __init__ = mapper_registry.constructor 

1646 

1647 .. versionchanged:: 2.0 Note that the 

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

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

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

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

1652 tools. 

1653 

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

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

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

1657 

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

1659 examples. 

1660 

1661 :param mapper: 

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

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

1664 

1665 :param cls: 

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

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

1668 

1669 :param name: 

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

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

1672 tracebacks and debugging. 

1673 

1674 :param metaclass: 

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

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

1677 declarative base class. 

1678 

1679 .. seealso:: 

1680 

1681 :ref:`orm_declarative_mapping` 

1682 

1683 :func:`_orm.declarative_base` 

1684 

1685 """ 

1686 metadata = self.metadata 

1687 

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

1689 

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

1691 if isinstance(cls, type): 

1692 class_dict["__doc__"] = cls.__doc__ 

1693 

1694 if self.constructor is not None: 

1695 class_dict["__init__"] = self.constructor 

1696 

1697 class_dict["__abstract__"] = True 

1698 if mapper: 

1699 class_dict["__mapper_cls__"] = mapper 

1700 

1701 if hasattr(cls, "__class_getitem__"): 

1702 

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

1704 # allow generic classes in py3.9+ 

1705 return cls 

1706 

1707 class_dict["__class_getitem__"] = __class_getitem__ 

1708 

1709 return metaclass(name, bases, class_dict) 

1710 

1711 @compat_typing.dataclass_transform( 

1712 field_specifiers=( 

1713 MappedColumn, 

1714 RelationshipProperty, 

1715 Composite, 

1716 Synonym, 

1717 mapped_column, 

1718 unmapped_column, 

1719 relationship, 

1720 composite, 

1721 synonym, 

1722 deferred, 

1723 ), 

1724 ) 

1725 @overload 

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

1727 

1728 @overload 

1729 def mapped_as_dataclass( 

1730 self, 

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

1732 /, 

1733 *, 

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

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

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

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

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

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

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

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

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

1743 

1744 def mapped_as_dataclass( 

1745 self, 

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

1747 /, 

1748 *, 

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

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

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

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

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

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

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

1756 dataclass_callable: Union[ 

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

1758 ] = _NoArg.NO_ARG, 

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

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

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

1762 Python dataclass. 

1763 

1764 .. seealso:: 

1765 

1766 :ref:`orm_declarative_native_dataclasses` - complete background 

1767 on SQLAlchemy native dataclass mapping 

1768 

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

1770 provide better compatibility with mypy 

1771 

1772 .. versionadded:: 2.0 

1773 

1774 

1775 """ 

1776 

1777 decorate = mapped_as_dataclass( 

1778 self, 

1779 init=init, 

1780 repr=repr, 

1781 eq=eq, 

1782 order=order, 

1783 unsafe_hash=unsafe_hash, 

1784 match_args=match_args, 

1785 kw_only=kw_only, 

1786 dataclass_callable=dataclass_callable, 

1787 ) 

1788 

1789 if __cls: 

1790 return decorate(__cls) 

1791 else: 

1792 return decorate 

1793 

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

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

1796 to a given class. 

1797 

1798 E.g.:: 

1799 

1800 from sqlalchemy.orm import registry 

1801 

1802 mapper_registry = registry() 

1803 

1804 

1805 @mapper_registry.mapped 

1806 class Foo: 

1807 __tablename__ = "some_table" 

1808 

1809 id = Column(Integer, primary_key=True) 

1810 name = Column(String) 

1811 

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

1813 details and examples. 

1814 

1815 :param cls: class to be mapped. 

1816 

1817 :return: the class that was passed. 

1818 

1819 .. seealso:: 

1820 

1821 :ref:`orm_declarative_mapping` 

1822 

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

1824 that will apply Declarative mapping to subclasses automatically 

1825 using a Python metaclass. 

1826 

1827 .. seealso:: 

1828 

1829 :meth:`_orm.registry.mapped_as_dataclass` 

1830 

1831 """ 

1832 _ORMClassConfigurator._as_declarative(self, cls, cls.__dict__) 

1833 return cls 

1834 

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

1836 """ 

1837 Class decorator which will invoke 

1838 :meth:`_orm.registry.generate_base` 

1839 for a given base class. 

1840 

1841 E.g.:: 

1842 

1843 from sqlalchemy.orm import registry 

1844 

1845 mapper_registry = registry() 

1846 

1847 

1848 @mapper_registry.as_declarative_base() 

1849 class Base: 

1850 @declared_attr 

1851 def __tablename__(cls): 

1852 return cls.__name__.lower() 

1853 

1854 id = Column(Integer, primary_key=True) 

1855 

1856 

1857 class MyMappedClass(Base): ... 

1858 

1859 All keyword arguments passed to 

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

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

1862 

1863 """ 

1864 

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

1866 kw["cls"] = cls 

1867 kw["name"] = cls.__name__ 

1868 return self.generate_base(**kw) # type: ignore[no-any-return] 

1869 

1870 return decorate 

1871 

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

1873 """Map a class declaratively. 

1874 

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

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

1877 actual table object. 

1878 

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

1880 

1881 E.g.:: 

1882 

1883 from sqlalchemy.orm import registry 

1884 

1885 mapper_registry = registry() 

1886 

1887 

1888 class Foo: 

1889 __tablename__ = "some_table" 

1890 

1891 id = Column(Integer, primary_key=True) 

1892 name = Column(String) 

1893 

1894 

1895 mapper = mapper_registry.map_declaratively(Foo) 

1896 

1897 This function is more conveniently invoked indirectly via either the 

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

1899 declarative metaclass generated from 

1900 :meth:`_orm.registry.generate_base`. 

1901 

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

1903 details and examples. 

1904 

1905 :param cls: class to be mapped. 

1906 

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

1908 

1909 .. seealso:: 

1910 

1911 :ref:`orm_declarative_mapping` 

1912 

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

1914 to this function. 

1915 

1916 :meth:`_orm.registry.map_imperatively` 

1917 

1918 """ 

1919 _ORMClassConfigurator._as_declarative(self, cls, cls.__dict__) 

1920 return cls.__mapper__ # type: ignore[attr-defined, no-any-return] 

1921 

1922 def map_imperatively( 

1923 self, 

1924 class_: Type[_O], 

1925 local_table: Optional[FromClause] = None, 

1926 **kw: Any, 

1927 ) -> Mapper[_O]: 

1928 r"""Map a class imperatively. 

1929 

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

1931 information. Instead, all mapping constructs are passed as 

1932 arguments. 

1933 

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

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

1936 a particular registry. 

1937 

1938 E.g.:: 

1939 

1940 from sqlalchemy.orm import registry 

1941 

1942 mapper_registry = registry() 

1943 

1944 my_table = Table( 

1945 "my_table", 

1946 mapper_registry.metadata, 

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

1948 ) 

1949 

1950 

1951 class MyClass: 

1952 pass 

1953 

1954 

1955 mapper_registry.map_imperatively(MyClass, my_table) 

1956 

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

1958 and usage examples. 

1959 

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

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

1962 

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

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

1965 Corresponds to the 

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

1967 

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

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

1970 

1971 .. seealso:: 

1972 

1973 :ref:`orm_imperative_mapping` 

1974 

1975 :ref:`orm_declarative_mapping` 

1976 

1977 """ 

1978 return _ORMClassConfigurator._mapper(self, class_, local_table, kw) 

1979 

1980 

1981RegistryType = registry 

1982 

1983if not TYPE_CHECKING: 

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

1985 _RegistryType = registry # noqa 

1986 

1987 

1988def _declare_first_for_registry(registry: registry) -> None: 

1989 """Invoke ``__declare_first__()`` for classes within this registry.""" 

1990 

1991 for cls in list(registry._declare_first_classes): 

1992 cls.__declare_first__() 

1993 

1994 

1995def _declare_last_for_registry(registry: registry) -> None: 

1996 """Invoke ``__declare_last__()`` for classes within this registry.""" 

1997 

1998 for cls in list(registry._declare_last_classes): 

1999 cls.__declare_last__() 

2000 

2001 

2002class TypeResolve: 

2003 """Primary argument to the :meth:`.RegistryEvents.resolve_type_annotation` 

2004 event. 

2005 

2006 This object contains all the information needed to resolve a Python 

2007 type to a SQLAlchemy type. The :attr:`.TypeResolve.resolved_type` is 

2008 typically the main type that's resolved. To resolve an arbitrary 

2009 Python type against the current type map, the :meth:`.TypeResolve.resolve` 

2010 method may be used. 

2011 

2012 .. versionadded:: 2.1 

2013 

2014 """ 

2015 

2016 __slots__ = ( 

2017 "registry", 

2018 "cls", 

2019 "key", 

2020 "raw_type", 

2021 "resolved_type", 

2022 "raw_pep_593_type", 

2023 "raw_pep_695_type", 

2024 "pep_593_resolved_argument", 

2025 "pep_695_resolved_value", 

2026 ) 

2027 

2028 cls: Any 

2029 "The class being processed during declarative mapping" 

2030 

2031 registry: "registry" 

2032 "The :class:`registry` being used" 

2033 

2034 key: str 

2035 "String name of the ORM mapped attribute being processed" 

2036 

2037 raw_type: _MatchedOnType 

2038 """The type annotation object directly from the attribute's annotations. 

2039 

2040 It's recommended to look at :attr:`.TypeResolve.resolved_type` or 

2041 one of :attr:`.TypeResolve.pep_593_resolved_argument` or 

2042 :attr:`.TypeResolve.pep_695_resolved_value` rather than the raw type, as 

2043 the raw type will not be de-optionalized. 

2044 

2045 """ 

2046 

2047 resolved_type: _MatchedOnType 

2048 """The de-optionalized, "resolved" type after accounting for :pep:`695` 

2049 and :pep:`593` indirection: 

2050 

2051 * If the annotation were a plain Python type or simple alias e.g. 

2052 ``Mapped[int]``, the resolved_type will be ``int`` 

2053 * If the annotation refers to a :pep:`695` type that references a 

2054 plain Python type or simple alias, e.g. ``type MyType = int`` 

2055 then ``Mapped[MyType]``, the type will refer to the ``__value__`` 

2056 of the :pep:`695` type, e.g. ``int``, the same as 

2057 :attr:`.TypeResolve.pep_695_resolved_value`. 

2058 * If the annotation refers to a :pep:`593` ``Annotated`` object, or 

2059 a :pep:`695` type alias that in turn refers to a :pep:`593` type, 

2060 then the type will be the inner type inside of the ``Annotated``, 

2061 e.g. ``MyType = Annotated[float, mapped_column(...)]`` with 

2062 ``Mapped[MyType]`` becomes ``float``, the same as 

2063 :attr:`.TypeResolve.pep_593_resolved_argument`. 

2064 

2065 """ 

2066 

2067 raw_pep_593_type: Optional[GenericProtocol[Any]] 

2068 """The de-optionalized :pep:`593` type, if the raw type referred to one. 

2069 

2070 This would refer to an ``Annotated`` object. 

2071 

2072 """ 

2073 

2074 pep_593_resolved_argument: Optional[_MatchedOnType] 

2075 """The type extracted from a :pep:`593` ``Annotated`` construct, if the 

2076 type referred to one. 

2077 

2078 When present, this type would be the same as the 

2079 :attr:`.TypeResolve.resolved_type`. 

2080 

2081 """ 

2082 

2083 raw_pep_695_type: Optional[TypeAliasType] 

2084 "The de-optionalized :pep:`695` type, if the raw type referred to one." 

2085 

2086 pep_695_resolved_value: Optional[_MatchedOnType] 

2087 """The de-optionalized type referenced by the raw :pep:`695` type, if the 

2088 raw type referred to one. 

2089 

2090 When present, and a :pep:`593` type is not present, this type would be the 

2091 same as the :attr:`.TypeResolve.resolved_type`. 

2092 

2093 """ 

2094 

2095 def __init__( 

2096 self, 

2097 registry: RegistryType, 

2098 cls: Any, 

2099 key: str, 

2100 raw_type: _MatchedOnType, 

2101 resolved_type: _MatchedOnType, 

2102 raw_pep_593_type: Optional[GenericProtocol[Any]], 

2103 pep_593_resolved_argument: Optional[_MatchedOnType], 

2104 raw_pep_695_type: Optional[TypeAliasType], 

2105 pep_695_resolved_value: Optional[_MatchedOnType], 

2106 ): 

2107 self.registry = registry 

2108 self.cls = cls 

2109 self.key = key 

2110 self.raw_type = raw_type 

2111 self.resolved_type = resolved_type 

2112 self.raw_pep_593_type = raw_pep_593_type 

2113 self.pep_593_resolved_argument = pep_593_resolved_argument 

2114 self.raw_pep_695_type = raw_pep_695_type 

2115 self.pep_695_resolved_value = pep_695_resolved_value 

2116 

2117 def resolve( 

2118 self, python_type: _MatchedOnType 

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

2120 """Resolve the given python type using the type_annotation_map of 

2121 the :class:`registry`. 

2122 

2123 :param python_type: a Python type (e.g. ``int``, ``str``, etc.) Any 

2124 type object that's present in 

2125 :paramref:`_orm.registry_type_annotation_map` should produce a 

2126 non-``None`` result. 

2127 :return: a SQLAlchemy :class:`.TypeEngine` instance 

2128 (e.g. :class:`.Integer`, 

2129 :class:`.String`, etc.), or ``None`` to indicate no type could be 

2130 matched. 

2131 

2132 """ 

2133 return self.registry._resolve_type(python_type) 

2134 

2135 

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

2137 """ 

2138 Class decorator which will adapt a given class into a 

2139 :func:`_orm.declarative_base`. 

2140 

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

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

2143 and then invoking the decorator. 

2144 

2145 E.g.:: 

2146 

2147 from sqlalchemy.orm import as_declarative 

2148 

2149 

2150 @as_declarative() 

2151 class Base: 

2152 @declared_attr 

2153 def __tablename__(cls): 

2154 return cls.__name__.lower() 

2155 

2156 id = Column(Integer, primary_key=True) 

2157 

2158 

2159 class MyMappedClass(Base): ... 

2160 

2161 .. seealso:: 

2162 

2163 :meth:`_orm.registry.as_declarative_base` 

2164 

2165 """ 

2166 metadata, class_registry = ( 

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

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

2169 ) 

2170 

2171 return registry( 

2172 metadata=metadata, class_registry=class_registry 

2173 ).as_declarative_base(**kw) 

2174 

2175 

2176@compat_typing.dataclass_transform( 

2177 field_specifiers=( 

2178 MappedColumn, 

2179 RelationshipProperty, 

2180 Composite, 

2181 Synonym, 

2182 mapped_column, 

2183 unmapped_column, 

2184 relationship, 

2185 composite, 

2186 synonym, 

2187 deferred, 

2188 ), 

2189) 

2190def mapped_as_dataclass( 

2191 registry: RegistryType, 

2192 /, 

2193 *, 

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

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

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

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

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

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

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

2201 dataclass_callable: Union[ 

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

2203 ] = _NoArg.NO_ARG, 

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

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

2206 which may have better compatibility with mypy. 

2207 

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

2209 decorator. 

2210 

2211 e.g.:: 

2212 

2213 from sqlalchemy.orm import Mapped 

2214 from sqlalchemy.orm import mapped_as_dataclass 

2215 from sqlalchemy.orm import mapped_column 

2216 from sqlalchemy.orm import registry 

2217 

2218 some_registry = registry() 

2219 

2220 

2221 @mapped_as_dataclass(some_registry) 

2222 class Relationships: 

2223 __tablename__ = "relationships" 

2224 

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

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

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

2228 

2229 .. versionadded:: 2.0.44 

2230 

2231 """ 

2232 

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

2234 _generate_dc_transforms( 

2235 init=init, 

2236 repr=repr, 

2237 eq=eq, 

2238 order=order, 

2239 unsafe_hash=unsafe_hash, 

2240 match_args=match_args, 

2241 kw_only=kw_only, 

2242 dataclass_callable=dataclass_callable, 

2243 cls_=cls, 

2244 ) 

2245 _ORMClassConfigurator._as_declarative(registry, cls, cls.__dict__) 

2246 return cls 

2247 

2248 return decorate 

2249 

2250 

2251@inspection._inspects( 

2252 DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept 

2253) 

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

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

2256 if mp is None: 

2257 if _DeferredDeclarativeConfig.has_cls(cls): 

2258 _DeferredDeclarativeConfig.raise_unmapped_for_cls(cls) 

2259 return mp 

2260 

2261 

2262@compat_typing.dataclass_transform( 

2263 field_specifiers=( 

2264 MappedColumn, 

2265 RelationshipProperty, 

2266 Composite, 

2267 Synonym, 

2268 mapped_column, 

2269 unmapped_column, 

2270 relationship, 

2271 composite, 

2272 synonym, 

2273 deferred, 

2274 ), 

2275) 

2276@overload 

2277def unmapped_dataclass(__cls: Type[_O], /) -> Type[_O]: ... 

2278 

2279 

2280@overload 

2281def unmapped_dataclass( 

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

2283 /, 

2284 *, 

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

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

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

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

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

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

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

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

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

2294 

2295 

2296def unmapped_dataclass( 

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

2298 /, 

2299 *, 

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

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

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

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

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

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

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

2307 dataclass_callable: Union[ 

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

2309 ] = _NoArg.NO_ARG, 

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

2311 """Decorator which allows the creation of dataclass-compatible mixins 

2312 within mapped class hierarchies based on the 

2313 :func:`_orm.mapped_as_dataclass` decorator. 

2314 

2315 Parameters are the same as those of :func:`_orm.mapped_as_dataclass`. 

2316 The decorator turns the given class into a SQLAlchemy-compatible dataclass 

2317 in the same way that :func:`_orm.mapped_as_dataclass` does, taking 

2318 into account :func:`_orm.mapped_column` and other attributes for dataclass- 

2319 specific directives, but not actually mapping the class. 

2320 

2321 To create unmapped dataclass mixins when using a class hierarchy defined 

2322 by :class:`.DeclarativeBase` and :class:`.MappedAsDataclass`, the 

2323 :class:`.MappedAsDataclass` class may be subclassed alone for a similar 

2324 effect. 

2325 

2326 .. versionadded:: 2.1 

2327 

2328 .. seealso:: 

2329 

2330 :ref:`orm_declarative_dc_mixins` - background and example use. 

2331 

2332 """ 

2333 

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

2335 _generate_dc_transforms( 

2336 init=init, 

2337 repr=repr, 

2338 eq=eq, 

2339 order=order, 

2340 unsafe_hash=unsafe_hash, 

2341 match_args=match_args, 

2342 kw_only=kw_only, 

2343 dataclass_callable=dataclass_callable, 

2344 cls_=cls, 

2345 ) 

2346 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

2347 return cls 

2348 

2349 if __cls: 

2350 return decorate(__cls) 

2351 else: 

2352 return decorate