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

528 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 .attributes import InstrumentedAttribute 

47from .base import _inspect_mapped_class 

48from .base import _is_mapped_class 

49from .base import Mapped 

50from .base import ORMDescriptor 

51from .decl_base import _add_attribute 

52from .decl_base import _declarative_constructor 

53from .decl_base import _DeclarativeMapperConfig 

54from .decl_base import _DeclMappedClassProtocol 

55from .decl_base import _DeferredDeclarativeConfig 

56from .decl_base import _del_attribute 

57from .decl_base import _get_immediate_cls_attr 

58from .decl_base import _ORMClassConfigurator 

59from .decl_base import MappedClassProtocol 

60from .descriptor_props import Composite 

61from .descriptor_props import Synonym 

62from .descriptor_props import Synonym as _orm_synonym 

63from .mapper import Mapper 

64from .properties import MappedColumn 

65from .relationships import RelationshipProperty 

66from .state import InstanceState 

67from .. import event 

68from .. import exc 

69from .. import inspection 

70from .. import util 

71from ..event import dispatcher 

72from ..event import EventTarget 

73from ..sql import sqltypes 

74from ..sql._annotated_cols import _TC 

75from ..sql.base import _NoArg 

76from ..sql.elements import SQLCoreOperations 

77from ..sql.schema import MetaData 

78from ..sql.selectable import FromClause 

79from ..util import hybridmethod 

80from ..util import hybridproperty 

81from ..util import typing as compat_typing 

82from ..util import TypingOnly 

83from ..util.typing import CallableReference 

84from ..util.typing import de_optionalize_union_types 

85from ..util.typing import GenericProtocol 

86from ..util.typing import is_generic 

87from ..util.typing import is_literal 

88from ..util.typing import LITERAL_TYPES 

89from ..util.typing import Self 

90from ..util.typing import TypeAliasType 

91 

92if TYPE_CHECKING: 

93 from ._typing import _O 

94 from ._typing import _RegistryType 

95 from .instrumentation import ClassManager 

96 from .interfaces import _DataclassArguments 

97 from .interfaces import MapperProperty 

98 from .state import InstanceState # noqa 

99 from ..sql._typing import _TypeEngineArgument 

100 from ..util.typing import _MatchedOnType 

101 

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

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

104 

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

106 

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

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

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

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

111 

112_DeclaredAttrDecorated = Callable[ 

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

114] 

115 

116 

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

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

119 mapped table, otherwise return False. 

120 

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

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

123 hierarchy. 

124 

125 .. seealso:: 

126 

127 :ref:`decl_mixin_inheritance` 

128 

129 """ 

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

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

132 return True 

133 return False 

134 

135 

136class _DynamicAttributesType(type): 

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

138 if "__mapper__" in cls.__dict__: 

139 _add_attribute(cls, key, value) 

140 else: 

141 type.__setattr__(cls, key, value) 

142 

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

144 if "__mapper__" in cls.__dict__: 

145 _del_attribute(cls, key) 

146 else: 

147 type.__delattr__(cls, key) 

148 

149 

150class DeclarativeAttributeIntercept( 

151 _DynamicAttributesType, 

152 # Inspectable is used only by the mypy plugin 

153 inspection.Inspectable[Mapper[Any]], 

154): 

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

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

157 attributes dynamically. 

158 

159 """ 

160 

161 

162@compat_typing.dataclass_transform( 

163 field_specifiers=( 

164 MappedColumn, 

165 RelationshipProperty, 

166 Composite, 

167 Synonym, 

168 mapped_column, 

169 relationship, 

170 composite, 

171 synonym, 

172 deferred, 

173 ), 

174) 

175class DCTransformDeclarative(DeclarativeAttributeIntercept): 

176 """metaclass that includes @dataclass_transforms""" 

177 

178 

179class DeclarativeMeta(DeclarativeAttributeIntercept): 

180 metadata: MetaData 

181 registry: RegistryType 

182 

183 def __init__( 

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

185 ) -> None: 

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

187 # __init_subclass__() method (#7900) 

188 dict_ = cls.__dict__ 

189 

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

191 # assign privately to not conflict with subclass attributes named 

192 # "registry" 

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

194 if reg is None: 

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

196 if not isinstance(reg, registry): 

197 raise exc.InvalidRequestError( 

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

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

200 ) 

201 else: 

202 cls._sa_registry = reg 

203 

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

205 _ORMClassConfigurator._as_declarative(reg, cls, dict_) 

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

207 

208 

209def synonym_for( 

210 name: str, map_column: bool = False 

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

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

213 attribute in conjunction with a Python descriptor. 

214 

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

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

217 

218 class MyClass(Base): 

219 __tablename__ = "my_table" 

220 

221 id = Column(Integer, primary_key=True) 

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

223 

224 @synonym_for("job_status") 

225 @property 

226 def job_status(self): 

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

228 

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

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

231 feature. 

232 

233 .. seealso:: 

234 

235 :ref:`synonyms` - Overview of synonyms 

236 

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

238 

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

240 updated approach to augmenting attribute behavior more flexibly than 

241 can be achieved with synonyms. 

242 

243 """ 

244 

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

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

247 

248 return decorate 

249 

250 

251class _declared_attr_common: 

252 def __init__( 

253 self, 

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

255 cascading: bool = False, 

256 quiet: bool = False, 

257 ): 

258 # support 

259 # @declared_attr 

260 # @classmethod 

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

262 # ... 

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

264 # for situations where needed 

265 if isinstance(fn, classmethod): 

266 fn = fn.__func__ 

267 

268 self.fget = fn 

269 self._cascading = cascading 

270 self._quiet = quiet 

271 self.__doc__ = fn.__doc__ 

272 

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

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

275 

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

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

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

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

280 

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

282 # setup phase 

283 

284 cls = owner 

285 manager = attributes.opt_manager_of_class(cls) 

286 if manager is None: 

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

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

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

290 util.warn( 

291 "Unmanaged access of declarative attribute %s from " 

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

293 ) 

294 return self.fget(cls) 

295 elif manager.is_mapped: 

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

297 # scan setup, just run the function. 

298 return self.fget(cls) 

299 

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

301 # that is tracking the values of these attributes. 

302 declarative_scan = manager.declarative_scan() 

303 

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

305 assert declarative_scan is not None 

306 

307 reg = declarative_scan.declared_attr_reg 

308 

309 if self in reg: 

310 return reg[self] 

311 else: 

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

313 return obj 

314 

315 

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

317 # see mapping_api.rst for docstring 

318 

319 if typing.TYPE_CHECKING: 

320 

321 def __init__( 

322 self, 

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

324 cascading: bool = False, 

325 ): ... 

326 

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

328 

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

330 

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

332 

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

334 # extensive fooling of mypy underway... 

335 ... 

336 

337 

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

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

340 a mapped property or Declarative directive. 

341 

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

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

344 invoked from the uninstantiated class. The Declarative mapping process 

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

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

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

348 table configuration. 

349 

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

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

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

353 define dynamically generated column expressions and other Declarative 

354 attributes. 

355 

356 Example:: 

357 

358 class ProvidesUserMixin: 

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

360 

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

362 

363 @declared_attr 

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

365 return relationship("User") 

366 

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

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

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

370 :class:`_orm.Mapped` attributes:: 

371 

372 class CreateTableName: 

373 @declared_attr.directive 

374 def __tablename__(cls) -> str: 

375 return cls.__name__.lower() 

376 

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

378 classes, to allow for attributes that dynamically configure themselves 

379 on subclasses when using mapped inheritance schemes. Below 

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

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

382 for subclasses:: 

383 

384 class Employee(Base): 

385 __tablename__ = "employee" 

386 

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

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

389 

390 @declared_attr.directive 

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

392 if cls.__name__ == "Employee": 

393 return { 

394 "polymorphic_on": cls.type, 

395 "polymorphic_identity": "Employee", 

396 } 

397 else: 

398 return {"polymorphic_identity": cls.__name__} 

399 

400 

401 class Engineer(Employee): 

402 pass 

403 

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

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

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

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

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

409 

410 class SomethingMixin: 

411 x: Mapped[int] 

412 y: Mapped[int] 

413 

414 @declared_attr 

415 @classmethod 

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

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

418 

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

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

421 integration where needed. 

422 

423 

424 .. seealso:: 

425 

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

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

428 

429 """ # noqa: E501 

430 

431 if typing.TYPE_CHECKING: 

432 

433 def __init__( 

434 self, 

435 fn: _DeclaredAttrDecorated[_T_co], 

436 cascading: bool = False, 

437 ): ... 

438 

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

440 

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

442 

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

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

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

446 # declarative function that does not return InstrumentedAttribute 

447 @overload 

448 def __get__( 

449 self, instance: None, owner: Any 

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

451 

452 @overload 

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

454 

455 def __get__( 

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

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

458 

459 @hybridmethod 

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

461 return _stateful_declared_attr(**kw) 

462 

463 @hybridproperty 

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

465 # see mapping_api.rst for docstring 

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

467 

468 @hybridproperty 

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

470 # see mapping_api.rst for docstring 

471 return cls._stateful(cascading=True) 

472 

473 

474class _stateful_declared_attr(declared_attr[_T_co]): 

475 kw: Dict[str, Any] 

476 

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

478 self.kw = kw 

479 

480 @hybridmethod 

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

482 new_kw = self.kw.copy() 

483 new_kw.update(kw) 

484 return _stateful_declared_attr(**new_kw) 

485 

486 def __call__( 

487 self, fn: _DeclaredAttrDecorated[_T_co] 

488 ) -> declared_attr[_T_co]: 

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

490 

491 

492@util.deprecated( 

493 "2.1", 

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

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

496) 

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

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

499 

500 E.g.:: 

501 

502 from sqlalchemy.orm import declared_attr 

503 from sqlalchemy.orm import declarative_mixin 

504 

505 

506 @declarative_mixin 

507 class MyMixin: 

508 

509 @declared_attr 

510 def __tablename__(cls): 

511 return cls.__name__.lower() 

512 

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

514 __mapper_args__ = {"always_refresh": True} 

515 

516 id = Column(Integer, primary_key=True) 

517 

518 

519 class MyModel(MyMixin, Base): 

520 name = Column(String(1000)) 

521 

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

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

524 the Mypy plugin in being able to identify 

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

526 

527 .. versionadded:: 1.4.6 

528 

529 .. seealso:: 

530 

531 :ref:`orm_mixins_toplevel` 

532 

533 """ # noqa: E501 

534 

535 return cls 

536 

537 

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

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

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

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

542 

543 if reg is not None: 

544 if not isinstance(reg, registry): 

545 raise exc.InvalidRequestError( 

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

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

548 ) 

549 elif type_annotation_map is not None: 

550 raise exc.InvalidRequestError( 

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

552 "type_annotation_map entry. Per-base type_annotation_maps " 

553 "are not supported. Please apply the type_annotation_map " 

554 "to this registry directly." 

555 ) 

556 

557 else: 

558 reg = registry( 

559 metadata=metadata, type_annotation_map=type_annotation_map 

560 ) 

561 cls.registry = reg 

562 

563 cls._sa_registry = reg 

564 

565 if "metadata" not in cls.__dict__: 

566 cls.metadata = cls.registry.metadata 

567 

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

569 cls.__init__ = cls.registry.constructor 

570 

571 

572def _generate_dc_transforms( 

573 cls_: Type[_O], 

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

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

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

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

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

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

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

581 dataclass_callable: Union[ 

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

583 ] = _NoArg.NO_ARG, 

584) -> None: 

585 apply_dc_transforms: _DataclassArguments = { 

586 "init": init, 

587 "repr": repr, 

588 "eq": eq, 

589 "order": order, 

590 "unsafe_hash": unsafe_hash, 

591 "match_args": match_args, 

592 "kw_only": kw_only, 

593 "dataclass_callable": dataclass_callable, 

594 } 

595 

596 if hasattr(cls_, "_sa_apply_dc_transforms"): 

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

598 

599 _DeclarativeMapperConfig._assert_dc_arguments(current) 

600 

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

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

603 for k, v in apply_dc_transforms.items() 

604 } 

605 else: 

606 setattr(cls_, "_sa_apply_dc_transforms", apply_dc_transforms) 

607 

608 

609class MappedAsDataclass(metaclass=DCTransformDeclarative): 

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

611 a dataclass. 

612 

613 .. seealso:: 

614 

615 :ref:`orm_declarative_native_dataclasses` - complete background 

616 on SQLAlchemy native dataclass mapping with 

617 :class:`_orm.MappedAsDataclass`. 

618 

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

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

621 

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

623 decorator versions with equivalent functionality 

624 

625 .. versionadded:: 2.0 

626 

627 """ 

628 

629 def __init_subclass__( 

630 cls, 

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

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

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

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

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

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

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

638 dataclass_callable: Union[ 

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

640 ] = _NoArg.NO_ARG, 

641 **kw: Any, 

642 ) -> None: 

643 _generate_dc_transforms( 

644 init=init, 

645 repr=repr, 

646 eq=eq, 

647 order=order, 

648 unsafe_hash=unsafe_hash, 

649 match_args=match_args, 

650 kw_only=kw_only, 

651 dataclass_callable=dataclass_callable, 

652 cls_=cls, 

653 ) 

654 super().__init_subclass__(**kw) 

655 

656 if not _is_mapped_class(cls): 

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

658 # as a base or a mixin 

659 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

660 

661 

662class _DeclarativeTyping(TypingOnly): 

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

664 DeclarativeBaseNoMeta classes. 

665 """ 

666 

667 __slots__ = () 

668 

669 if typing.TYPE_CHECKING: 

670 # protocols for inspection 

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

672 

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

674 

675 # internal stuff 

676 _sa_registry: ClassVar[_RegistryType] 

677 

678 # public interface 

679 registry: ClassVar[_RegistryType] 

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

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

682 

683 metadata: ClassVar[MetaData] 

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

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

686 

687 .. seealso:: 

688 

689 :ref:`orm_declarative_metadata` 

690 

691 """ 

692 

693 __name__: ClassVar[str] 

694 

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

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

697 # ok with it. 

698 __mapper__: ClassVar[Mapper[Any]] 

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

700 mapped. 

701 

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

703 ``inspect(klass)``. 

704 

705 """ 

706 

707 __table__: ClassVar[FromClause] 

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

709 mapped. 

710 

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

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

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

714 

715 .. seealso:: 

716 

717 :ref:`orm_declarative_metadata` 

718 

719 """ 

720 

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

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

723 __tablename__: Any 

724 """String name to assign to the generated 

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

726 :attr:`_orm.DeclarativeBase.__table__`. 

727 

728 .. seealso:: 

729 

730 :ref:`orm_declarative_table` 

731 

732 """ 

733 

734 __mapper_args__: Any 

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

736 :class:`_orm.Mapper` constructor. 

737 

738 .. seealso:: 

739 

740 :ref:`orm_declarative_mapper_options` 

741 

742 """ 

743 

744 __table_args__: Any 

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

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

747 :ref:`orm_declarative_table_configuration` 

748 for background on the specific structure of this collection. 

749 

750 .. seealso:: 

751 

752 :ref:`orm_declarative_table_configuration` 

753 

754 """ 

755 

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

757 

758 

759class MappedClassWithTypedColumnsProtocol(Protocol[_TC]): 

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

761 attribute its typed columns. 

762 

763 .. versionadded:: 2.1.0b2 

764 """ 

765 

766 __typed_cols__: _TC 

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

768 

769 __name__: ClassVar[str] 

770 __mapper__: ClassVar[Mapper[Any]] 

771 __table__: ClassVar[FromClause] 

772 

773 

774@overload 

775def as_typed_table( 

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

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

778 

779 

780@overload 

781def as_typed_table( 

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

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

784 

785 

786def as_typed_table( 

787 cls: ( 

788 MappedClassProtocol[Any] 

789 | type[MappedClassWithTypedColumnsProtocol[Any]] 

790 ), 

791 typed_columns_cls: Any = None, 

792 /, 

793) -> FromClause[Any]: 

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

795 

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

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

798 

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

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

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

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

803 

804 

805 Example usage:: 

806 

807 from sqlalchemy import TypedColumns 

808 from sqlalchemy.orm import DeclarativeBase, mapped_column 

809 from sqlalchemy.orm import MappedColumn, as_typed_table 

810 

811 

812 class Base(DeclarativeBase): 

813 pass 

814 

815 

816 class A(Base): 

817 __tablename__ = "a" 

818 

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

820 data: MappedColumn[str] 

821 

822 

823 class a_cols(A, TypedColumns): 

824 pass 

825 

826 

827 # table_a is annotated as FromClause[a_cols] 

828 table_a = as_typed_table(A, a_cols) 

829 

830 

831 class B(Base): 

832 __tablename__ = "b" 

833 __typed_cols__: "b_cols" 

834 

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

836 b: Mapped[str] 

837 

838 

839 class b_cols(B, TypedColumns): 

840 pass 

841 

842 

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

844 # provides the __typed_cols__ annotation 

845 table_b = as_typed_table(B) 

846 

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

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

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

850 

851 .. versionadded:: 2.1.0b2 

852 """ 

853 return cls.__table__ 

854 

855 

856class DeclarativeBase( 

857 # Inspectable is used only by the mypy plugin 

858 inspection.Inspectable[InstanceState[Any]], 

859 _DeclarativeTyping, 

860 metaclass=DeclarativeAttributeIntercept, 

861): 

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

863 

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

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

866 

867 

868 from sqlalchemy.orm import DeclarativeBase 

869 

870 

871 class Base(DeclarativeBase): 

872 pass 

873 

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

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

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

877 

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

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

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

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

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

883 collection as well as a specific value for 

884 :paramref:`_orm.registry.type_annotation_map`:: 

885 

886 from typing import Annotated 

887 

888 from sqlalchemy import BigInteger 

889 from sqlalchemy import MetaData 

890 from sqlalchemy import String 

891 from sqlalchemy.orm import DeclarativeBase 

892 

893 bigint = Annotated[int, "bigint"] 

894 my_metadata = MetaData() 

895 

896 

897 class Base(DeclarativeBase): 

898 metadata = my_metadata 

899 type_annotation_map = { 

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

901 bigint: BigInteger(), 

902 } 

903 

904 Class-level attributes which may be specified include: 

905 

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

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

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

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

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

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

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

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

914 :paramref:`_orm.registry.type_annotation_map`. 

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

916 

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

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

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

920 and other subclassing-oriented APIs should be seen as 

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

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

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

924 without using plugins. 

925 

926 **__init__ behavior** 

927 

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

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

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

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

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

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

934 constructor that will assign keyword arguments as attributes on the 

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

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

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

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

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

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

941 method does. 

942 

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

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

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

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

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

948 ``object.__init__()``. 

949 

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

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

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

953 

954 class Base(DeclarativeBase): 

955 def __init__(self, id=None): 

956 self.id = id 

957 

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

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

960 

961 class MyClass(Base): 

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

963 self.name = name 

964 super().__init__(id=id) 

965 

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

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

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

969 ``__init__()``. 

970 

971 

972 """ 

973 

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

975 if DeclarativeBase in cls.__bases__: 

976 _check_not_declarative(cls, DeclarativeBase) 

977 _setup_declarative_base(cls) 

978 else: 

979 _ORMClassConfigurator._as_declarative( 

980 cls._sa_registry, cls, cls.__dict__ 

981 ) 

982 super().__init_subclass__(**kw) 

983 

984 

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

986 cls_dict = cls.__dict__ 

987 if ( 

988 "__table__" in cls_dict 

989 and not ( 

990 callable(cls_dict["__table__"]) 

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

992 ) 

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

994 raise exc.InvalidRequestError( 

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

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

997 ) 

998 

999 

1000class DeclarativeBaseNoMeta( 

1001 # Inspectable is used only by the mypy plugin 

1002 inspection.Inspectable[InstanceState[Any]], 

1003 _DeclarativeTyping, 

1004): 

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

1006 to intercept new attributes. 

1007 

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

1009 custom metaclasses is desirable. 

1010 

1011 .. versionadded:: 2.0 

1012 

1013 

1014 """ 

1015 

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

1017 if DeclarativeBaseNoMeta in cls.__bases__: 

1018 _check_not_declarative(cls, DeclarativeBaseNoMeta) 

1019 _setup_declarative_base(cls) 

1020 else: 

1021 _ORMClassConfigurator._as_declarative( 

1022 cls._sa_registry, cls, cls.__dict__ 

1023 ) 

1024 super().__init_subclass__(**kw) 

1025 

1026 

1027def add_mapped_attribute( 

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

1029) -> None: 

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

1031 

1032 E.g.:: 

1033 

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

1035 

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

1037 metaclass that intercepts attribute set operations. 

1038 

1039 .. versionadded:: 2.0 

1040 

1041 

1042 """ 

1043 _add_attribute(target, key, attr) 

1044 

1045 

1046def declarative_base( 

1047 *, 

1048 metadata: Optional[MetaData] = None, 

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

1050 cls: Type[Any] = object, 

1051 name: str = "Base", 

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

1053 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1055 metaclass: Type[Any] = DeclarativeMeta, 

1056) -> Any: 

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

1058 

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

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

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

1062 information provided declaratively in the class and any subclasses 

1063 of the class. 

1064 

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

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

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

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

1069 with :pep:`484` typing tools. 

1070 

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

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

1073 method. That is, the following:: 

1074 

1075 from sqlalchemy.orm import declarative_base 

1076 

1077 Base = declarative_base() 

1078 

1079 Is equivalent to:: 

1080 

1081 from sqlalchemy.orm import registry 

1082 

1083 mapper_registry = registry() 

1084 Base = mapper_registry.generate_base() 

1085 

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

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

1088 for more details. 

1089 

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

1091 function is now a specialization of the more generic 

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

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

1094 

1095 

1096 :param metadata: 

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

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

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

1100 will be created if none is provided. The 

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

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

1103 

1104 :param mapper: 

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

1106 be used to map subclasses to their Tables. 

1107 

1108 :param cls: 

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

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

1111 

1112 :param name: 

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

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

1115 tracebacks and debugging. 

1116 

1117 :param constructor: 

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

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

1120 implementation that assigns \**kwargs for declared 

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

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

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

1124 

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

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

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

1128 and others. Allows two or more declarative base classes 

1129 to share the same registry of class names for simplified 

1130 inter-base relationships. 

1131 

1132 :param type_annotation_map: optional dictionary of Python types to 

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

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

1135 to produce column types based on annotations within the 

1136 :class:`_orm.Mapped` type. 

1137 

1138 

1139 .. versionadded:: 2.0 

1140 

1141 .. seealso:: 

1142 

1143 :ref:`orm_declarative_mapped_column_type_map` 

1144 

1145 :param metaclass: 

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

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

1148 declarative base class. 

1149 

1150 .. seealso:: 

1151 

1152 :class:`_orm.registry` 

1153 

1154 """ 

1155 

1156 return registry( 

1157 metadata=metadata, 

1158 class_registry=class_registry, 

1159 constructor=constructor, 

1160 type_annotation_map=type_annotation_map, 

1161 ).generate_base( 

1162 mapper=mapper, 

1163 cls=cls, 

1164 name=name, 

1165 metaclass=metaclass, 

1166 ) 

1167 

1168 

1169class registry(EventTarget): 

1170 """Generalized registry for mapping classes. 

1171 

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

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

1174 

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

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

1177 styles may be used interchangeably: 

1178 

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

1180 class, and is the underlying implementation of the 

1181 :func:`_orm.declarative_base` function. 

1182 

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

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

1185 base class. 

1186 

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

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

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

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

1191 which is removed as of SQLAlchemy 2.0. 

1192 

1193 .. versionadded:: 1.4 

1194 

1195 .. seealso:: 

1196 

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

1198 styles. 

1199 

1200 """ 

1201 

1202 _class_registry: clsregistry._ClsRegistryType 

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

1204 metadata: MetaData 

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

1206 type_annotation_map: _MutableTypeAnnotationMapType 

1207 _dependents: Set[_RegistryType] 

1208 _dependencies: Set[_RegistryType] 

1209 _declare_first_classes: weakref.WeakKeyDictionary[ 

1210 _DeclMappedClassProtocol[Any], Literal[True] 

1211 ] 

1212 _declare_last_classes: weakref.WeakKeyDictionary[ 

1213 _DeclMappedClassProtocol[Any], Literal[True] 

1214 ] 

1215 _new_mappers: bool 

1216 dispatch: dispatcher["registry"] 

1217 

1218 def __init__( 

1219 self, 

1220 *, 

1221 metadata: Optional[MetaData] = None, 

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

1223 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1225 ): 

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

1227 

1228 :param metadata: 

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

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

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

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

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

1234 

1235 :param constructor: 

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

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

1238 implementation that assigns \**kwargs for declared 

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

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

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

1242 

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

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

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

1246 and others. Allows two or more declarative base classes 

1247 to share the same registry of class names for simplified 

1248 inter-base relationships. 

1249 

1250 :param type_annotation_map: optional dictionary of Python types to 

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

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

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

1254 to produce column types based on annotations within the 

1255 :class:`_orm.Mapped` type. 

1256 

1257 .. versionadded:: 2.0 

1258 

1259 .. seealso:: 

1260 

1261 :ref:`orm_declarative_mapped_column_type_map` 

1262 

1263 

1264 """ 

1265 lcl_metadata = metadata or MetaData() 

1266 

1267 if class_registry is None: 

1268 class_registry = weakref.WeakValueDictionary() 

1269 

1270 self._class_registry = class_registry 

1271 self._managers = weakref.WeakKeyDictionary() 

1272 self.metadata = lcl_metadata 

1273 self.constructor = constructor 

1274 self.type_annotation_map = {} 

1275 if type_annotation_map is not None: 

1276 self.update_type_annotation_map(type_annotation_map) 

1277 self._dependents = set() 

1278 self._dependencies = set() 

1279 self._declare_first_classes = weakref.WeakKeyDictionary() 

1280 self._declare_last_classes = weakref.WeakKeyDictionary() 

1281 

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

1283 # listeners appended to the same events run after the 

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

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

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

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

1288 

1289 self._new_mappers = False 

1290 

1291 with mapperlib._CONFIGURE_MUTEX: 

1292 mapperlib._mapper_registries[self] = True 

1293 

1294 def update_type_annotation_map( 

1295 self, 

1296 type_annotation_map: _TypeAnnotationMapType, 

1297 ) -> None: 

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

1299 values.""" 

1300 

1301 self.type_annotation_map.update( 

1302 { 

1303 de_optionalize_union_types(typ): sqltype 

1304 for typ, sqltype in type_annotation_map.items() 

1305 } 

1306 ) 

1307 

1308 def _resolve_type_with_events( 

1309 self, 

1310 cls: Any, 

1311 key: str, 

1312 raw_annotation: _MatchedOnType, 

1313 extracted_type: _MatchedOnType, 

1314 *, 

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

1316 pep_593_resolved_argument: Optional[_MatchedOnType] = None, 

1317 raw_pep_695_type: Optional[TypeAliasType] = None, 

1318 pep_695_resolved_value: Optional[_MatchedOnType] = None, 

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

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

1321 

1322 This method fires the resolve_type_annotation event first to allow 

1323 custom resolution, then falls back to normal resolution. 

1324 

1325 """ 

1326 

1327 if self.dispatch.resolve_type_annotation: 

1328 type_resolve = TypeResolve( 

1329 self, 

1330 cls, 

1331 key, 

1332 raw_annotation, 

1333 ( 

1334 pep_593_resolved_argument 

1335 if pep_593_resolved_argument is not None 

1336 else ( 

1337 pep_695_resolved_value 

1338 if pep_695_resolved_value is not None 

1339 else extracted_type 

1340 ) 

1341 ), 

1342 raw_pep_593_type, 

1343 pep_593_resolved_argument, 

1344 raw_pep_695_type, 

1345 pep_695_resolved_value, 

1346 ) 

1347 

1348 for fn in self.dispatch.resolve_type_annotation: 

1349 result = fn(type_resolve) 

1350 if result is not None: 

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

1352 

1353 if raw_pep_695_type is not None: 

1354 sqltype = self._resolve_type(raw_pep_695_type) 

1355 if sqltype is not None: 

1356 return sqltype 

1357 

1358 sqltype = self._resolve_type(extracted_type) 

1359 if sqltype is not None: 

1360 return sqltype 

1361 

1362 if pep_593_resolved_argument is not None: 

1363 sqltype = self._resolve_type(pep_593_resolved_argument) 

1364 

1365 return sqltype 

1366 

1367 def _resolve_type( 

1368 self, python_type: _MatchedOnType 

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

1370 python_type_type: Type[Any] 

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

1372 

1373 if is_generic(python_type): 

1374 if is_literal(python_type): 

1375 python_type_type = python_type # type: ignore[assignment] 

1376 

1377 search = ( 

1378 (python_type, python_type_type), 

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

1380 ) 

1381 else: 

1382 python_type_type = python_type.__origin__ 

1383 search = ((python_type, python_type_type),) 

1384 elif isinstance(python_type, type): 

1385 python_type_type = python_type 

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

1387 else: 

1388 python_type_type = python_type # type: ignore[assignment] 

1389 search = ((python_type, python_type_type),) 

1390 

1391 for pt, flattened in search: 

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

1393 sql_type = self.type_annotation_map.get(pt) 

1394 if sql_type is None: 

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

1396 

1397 if sql_type is not None: 

1398 sql_type_inst = sqltypes.to_instance(sql_type) 

1399 

1400 # ... this additional step will reject most 

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

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

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

1404 # type_annotation_map to be useful 

1405 resolved_sql_type = sql_type_inst._resolve_for_python_type( 

1406 python_type_type, 

1407 pt, 

1408 flattened, 

1409 ) 

1410 if resolved_sql_type is not None: 

1411 return resolved_sql_type 

1412 

1413 return None 

1414 

1415 @property 

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

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

1418 

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

1420 

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

1422 if registry is self: 

1423 return 

1424 registry._dependents.add(self) 

1425 self._dependencies.add(registry) 

1426 

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

1428 mapper._ready_for_configure = True 

1429 if self._new_mappers: 

1430 return 

1431 

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

1433 reg._new_mappers = True 

1434 

1435 @classmethod 

1436 def _recurse_with_dependents( 

1437 cls, registries: Set[RegistryType] 

1438 ) -> Iterator[RegistryType]: 

1439 todo = registries 

1440 done = set() 

1441 while todo: 

1442 reg = todo.pop() 

1443 done.add(reg) 

1444 

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

1446 # them before 

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

1448 yield reg 

1449 

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

1451 # after 

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

1453 

1454 @classmethod 

1455 def _recurse_with_dependencies( 

1456 cls, registries: Set[RegistryType] 

1457 ) -> Iterator[RegistryType]: 

1458 todo = registries 

1459 done = set() 

1460 while todo: 

1461 reg = todo.pop() 

1462 done.add(reg) 

1463 

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

1465 # them before 

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

1467 

1468 yield reg 

1469 

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

1471 # them before 

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

1473 

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

1475 return ( 

1476 manager.mapper 

1477 for manager in list(self._managers) 

1478 if manager.is_mapped 

1479 and not manager.mapper.configured 

1480 and manager.mapper._ready_for_configure 

1481 ) 

1482 

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

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

1485 

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

1487 self._managers[manager] = True 

1488 

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

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

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

1492 # weak so that the class remains garbage collectable. 

1493 # 

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

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

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

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

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

1499 # ones then adapt as a ConcreteInheritedProperty 

1500 cls = manager.class_ 

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

1502 if _get_immediate_cls_attr(cls, "__declare_first__"): 

1503 self._declare_first_classes[decl_cls] = True 

1504 if _get_immediate_cls_attr(cls, "__declare_last__"): 

1505 self._declare_last_classes[decl_cls] = True 

1506 

1507 if manager.is_mapped: 

1508 raise exc.ArgumentError( 

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

1510 % manager.class_ 

1511 ) 

1512 assert manager.registry is None 

1513 manager.registry = self 

1514 

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

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

1517 :class:`_orm.registry`. 

1518 

1519 The configure step is used to reconcile and initialize the 

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

1521 to invoke configuration events such as the 

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

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

1524 extensions or user-defined extension hooks. 

1525 

1526 If one or more mappers in this registry contain 

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

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

1529 registries. In order to configure those dependent registries 

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

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

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

1533 allow an application to programmatically invoke configuration of 

1534 registries while controlling whether or not the process implicitly 

1535 reaches other registries. 

1536 

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

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

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

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

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

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

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

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

1545 

1546 .. seealso:: 

1547 

1548 :func:`_orm.configure_mappers` 

1549 

1550 

1551 .. versionadded:: 1.4.0b2 

1552 

1553 """ 

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

1555 

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

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

1558 

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

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

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

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

1563 

1564 If this registry contains mappers that are dependencies of other 

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

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

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

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

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

1570 were not already disposed. 

1571 

1572 .. versionadded:: 1.4.0b2 

1573 

1574 .. seealso:: 

1575 

1576 :func:`_orm.clear_mappers` 

1577 

1578 """ 

1579 

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

1581 

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

1583 if "mapper" in manager.__dict__: 

1584 mapper = manager.mapper 

1585 

1586 mapper._set_dispose_flags() 

1587 

1588 class_ = manager.class_ 

1589 self._dispose_cls(class_) 

1590 instrumentation._instrumentation_factory.unregister(class_) 

1591 

1592 def generate_base( 

1593 self, 

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

1595 cls: Type[Any] = object, 

1596 name: str = "Base", 

1597 metaclass: Type[Any] = DeclarativeMeta, 

1598 ) -> Any: 

1599 """Generate a declarative base class. 

1600 

1601 Classes that inherit from the returned class object will be 

1602 automatically mapped using declarative mapping. 

1603 

1604 E.g.:: 

1605 

1606 from sqlalchemy.orm import registry 

1607 

1608 mapper_registry = registry() 

1609 

1610 Base = mapper_registry.generate_base() 

1611 

1612 

1613 class MyClass(Base): 

1614 __tablename__ = "my_table" 

1615 id = Column(Integer, primary_key=True) 

1616 

1617 The above dynamically generated class is equivalent to the 

1618 non-dynamic example below:: 

1619 

1620 from sqlalchemy.orm import registry 

1621 from sqlalchemy.orm.decl_api import DeclarativeMeta 

1622 

1623 mapper_registry = registry() 

1624 

1625 

1626 class Base(metaclass=DeclarativeMeta): 

1627 __abstract__ = True 

1628 registry = mapper_registry 

1629 metadata = mapper_registry.metadata 

1630 

1631 __init__ = mapper_registry.constructor 

1632 

1633 .. versionchanged:: 2.0 Note that the 

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

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

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

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

1638 tools. 

1639 

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

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

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

1643 

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

1645 examples. 

1646 

1647 :param mapper: 

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

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

1650 

1651 :param cls: 

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

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

1654 

1655 :param name: 

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

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

1658 tracebacks and debugging. 

1659 

1660 :param metaclass: 

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

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

1663 declarative base class. 

1664 

1665 .. seealso:: 

1666 

1667 :ref:`orm_declarative_mapping` 

1668 

1669 :func:`_orm.declarative_base` 

1670 

1671 """ 

1672 metadata = self.metadata 

1673 

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

1675 

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

1677 if isinstance(cls, type): 

1678 class_dict["__doc__"] = cls.__doc__ 

1679 

1680 if self.constructor is not None: 

1681 class_dict["__init__"] = self.constructor 

1682 

1683 class_dict["__abstract__"] = True 

1684 if mapper: 

1685 class_dict["__mapper_cls__"] = mapper 

1686 

1687 if hasattr(cls, "__class_getitem__"): 

1688 

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

1690 # allow generic classes in py3.9+ 

1691 return cls 

1692 

1693 class_dict["__class_getitem__"] = __class_getitem__ 

1694 

1695 return metaclass(name, bases, class_dict) 

1696 

1697 @compat_typing.dataclass_transform( 

1698 field_specifiers=( 

1699 MappedColumn, 

1700 RelationshipProperty, 

1701 Composite, 

1702 Synonym, 

1703 mapped_column, 

1704 relationship, 

1705 composite, 

1706 synonym, 

1707 deferred, 

1708 ), 

1709 ) 

1710 @overload 

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

1712 

1713 @overload 

1714 def mapped_as_dataclass( 

1715 self, 

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

1717 /, 

1718 *, 

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

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

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

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

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

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

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

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

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

1728 

1729 def mapped_as_dataclass( 

1730 self, 

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

1732 /, 

1733 *, 

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

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

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

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

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

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

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

1741 dataclass_callable: Union[ 

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

1743 ] = _NoArg.NO_ARG, 

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

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

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

1747 Python dataclass. 

1748 

1749 .. seealso:: 

1750 

1751 :ref:`orm_declarative_native_dataclasses` - complete background 

1752 on SQLAlchemy native dataclass mapping 

1753 

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

1755 provide better compatibility with mypy 

1756 

1757 .. versionadded:: 2.0 

1758 

1759 

1760 """ 

1761 

1762 decorate = mapped_as_dataclass( 

1763 self, 

1764 init=init, 

1765 repr=repr, 

1766 eq=eq, 

1767 order=order, 

1768 unsafe_hash=unsafe_hash, 

1769 match_args=match_args, 

1770 kw_only=kw_only, 

1771 dataclass_callable=dataclass_callable, 

1772 ) 

1773 

1774 if __cls: 

1775 return decorate(__cls) 

1776 else: 

1777 return decorate 

1778 

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

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

1781 to a given class. 

1782 

1783 E.g.:: 

1784 

1785 from sqlalchemy.orm import registry 

1786 

1787 mapper_registry = registry() 

1788 

1789 

1790 @mapper_registry.mapped 

1791 class Foo: 

1792 __tablename__ = "some_table" 

1793 

1794 id = Column(Integer, primary_key=True) 

1795 name = Column(String) 

1796 

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

1798 details and examples. 

1799 

1800 :param cls: class to be mapped. 

1801 

1802 :return: the class that was passed. 

1803 

1804 .. seealso:: 

1805 

1806 :ref:`orm_declarative_mapping` 

1807 

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

1809 that will apply Declarative mapping to subclasses automatically 

1810 using a Python metaclass. 

1811 

1812 .. seealso:: 

1813 

1814 :meth:`_orm.registry.mapped_as_dataclass` 

1815 

1816 """ 

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

1818 return cls 

1819 

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

1821 """ 

1822 Class decorator which will invoke 

1823 :meth:`_orm.registry.generate_base` 

1824 for a given base class. 

1825 

1826 E.g.:: 

1827 

1828 from sqlalchemy.orm import registry 

1829 

1830 mapper_registry = registry() 

1831 

1832 

1833 @mapper_registry.as_declarative_base() 

1834 class Base: 

1835 @declared_attr 

1836 def __tablename__(cls): 

1837 return cls.__name__.lower() 

1838 

1839 id = Column(Integer, primary_key=True) 

1840 

1841 

1842 class MyMappedClass(Base): ... 

1843 

1844 All keyword arguments passed to 

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

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

1847 

1848 """ 

1849 

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

1851 kw["cls"] = cls 

1852 kw["name"] = cls.__name__ 

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

1854 

1855 return decorate 

1856 

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

1858 """Map a class declaratively. 

1859 

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

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

1862 actual table object. 

1863 

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

1865 

1866 E.g.:: 

1867 

1868 from sqlalchemy.orm import registry 

1869 

1870 mapper_registry = registry() 

1871 

1872 

1873 class Foo: 

1874 __tablename__ = "some_table" 

1875 

1876 id = Column(Integer, primary_key=True) 

1877 name = Column(String) 

1878 

1879 

1880 mapper = mapper_registry.map_declaratively(Foo) 

1881 

1882 This function is more conveniently invoked indirectly via either the 

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

1884 declarative metaclass generated from 

1885 :meth:`_orm.registry.generate_base`. 

1886 

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

1888 details and examples. 

1889 

1890 :param cls: class to be mapped. 

1891 

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

1893 

1894 .. seealso:: 

1895 

1896 :ref:`orm_declarative_mapping` 

1897 

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

1899 to this function. 

1900 

1901 :meth:`_orm.registry.map_imperatively` 

1902 

1903 """ 

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

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

1906 

1907 def map_imperatively( 

1908 self, 

1909 class_: Type[_O], 

1910 local_table: Optional[FromClause] = None, 

1911 **kw: Any, 

1912 ) -> Mapper[_O]: 

1913 r"""Map a class imperatively. 

1914 

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

1916 information. Instead, all mapping constructs are passed as 

1917 arguments. 

1918 

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

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

1921 a particular registry. 

1922 

1923 E.g.:: 

1924 

1925 from sqlalchemy.orm import registry 

1926 

1927 mapper_registry = registry() 

1928 

1929 my_table = Table( 

1930 "my_table", 

1931 mapper_registry.metadata, 

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

1933 ) 

1934 

1935 

1936 class MyClass: 

1937 pass 

1938 

1939 

1940 mapper_registry.map_imperatively(MyClass, my_table) 

1941 

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

1943 and usage examples. 

1944 

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

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

1947 

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

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

1950 Corresponds to the 

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

1952 

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

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

1955 

1956 .. seealso:: 

1957 

1958 :ref:`orm_imperative_mapping` 

1959 

1960 :ref:`orm_declarative_mapping` 

1961 

1962 """ 

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

1964 

1965 

1966RegistryType = registry 

1967 

1968if not TYPE_CHECKING: 

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

1970 _RegistryType = registry # noqa 

1971 

1972 

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

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

1975 

1976 for cls in list(registry._declare_first_classes): 

1977 cls.__declare_first__() 

1978 

1979 

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

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

1982 

1983 for cls in list(registry._declare_last_classes): 

1984 cls.__declare_last__() 

1985 

1986 

1987class TypeResolve: 

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

1989 event. 

1990 

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

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

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

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

1995 method may be used. 

1996 

1997 .. versionadded:: 2.1 

1998 

1999 """ 

2000 

2001 __slots__ = ( 

2002 "registry", 

2003 "cls", 

2004 "key", 

2005 "raw_type", 

2006 "resolved_type", 

2007 "raw_pep_593_type", 

2008 "raw_pep_695_type", 

2009 "pep_593_resolved_argument", 

2010 "pep_695_resolved_value", 

2011 ) 

2012 

2013 cls: Any 

2014 "The class being processed during declarative mapping" 

2015 

2016 registry: "registry" 

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

2018 

2019 key: str 

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

2021 

2022 raw_type: _MatchedOnType 

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

2024 

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

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

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

2028 the raw type will not be de-optionalized. 

2029 

2030 """ 

2031 

2032 resolved_type: _MatchedOnType 

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

2034 and :pep:`593` indirection: 

2035 

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

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

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

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

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

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

2042 :attr:`.TypeResolve.pep_695_resolved_value`. 

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

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

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

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

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

2048 :attr:`.TypeResolve.pep_593_resolved_argument`. 

2049 

2050 """ 

2051 

2052 raw_pep_593_type: Optional[GenericProtocol[Any]] 

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

2054 

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

2056 

2057 """ 

2058 

2059 pep_593_resolved_argument: Optional[_MatchedOnType] 

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

2061 type referred to one. 

2062 

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

2064 :attr:`.TypeResolve.resolved_type`. 

2065 

2066 """ 

2067 

2068 raw_pep_695_type: Optional[TypeAliasType] 

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

2070 

2071 pep_695_resolved_value: Optional[_MatchedOnType] 

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

2073 raw type referred to one. 

2074 

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

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

2077 

2078 """ 

2079 

2080 def __init__( 

2081 self, 

2082 registry: RegistryType, 

2083 cls: Any, 

2084 key: str, 

2085 raw_type: _MatchedOnType, 

2086 resolved_type: _MatchedOnType, 

2087 raw_pep_593_type: Optional[GenericProtocol[Any]], 

2088 pep_593_resolved_argument: Optional[_MatchedOnType], 

2089 raw_pep_695_type: Optional[TypeAliasType], 

2090 pep_695_resolved_value: Optional[_MatchedOnType], 

2091 ): 

2092 self.registry = registry 

2093 self.cls = cls 

2094 self.key = key 

2095 self.raw_type = raw_type 

2096 self.resolved_type = resolved_type 

2097 self.raw_pep_593_type = raw_pep_593_type 

2098 self.pep_593_resolved_argument = pep_593_resolved_argument 

2099 self.raw_pep_695_type = raw_pep_695_type 

2100 self.pep_695_resolved_value = pep_695_resolved_value 

2101 

2102 def resolve( 

2103 self, python_type: _MatchedOnType 

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

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

2106 the :class:`registry`. 

2107 

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

2109 type object that's present in 

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

2111 non-``None`` result. 

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

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

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

2115 matched. 

2116 

2117 """ 

2118 return self.registry._resolve_type(python_type) 

2119 

2120 

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

2122 """ 

2123 Class decorator which will adapt a given class into a 

2124 :func:`_orm.declarative_base`. 

2125 

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

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

2128 and then invoking the decorator. 

2129 

2130 E.g.:: 

2131 

2132 from sqlalchemy.orm import as_declarative 

2133 

2134 

2135 @as_declarative() 

2136 class Base: 

2137 @declared_attr 

2138 def __tablename__(cls): 

2139 return cls.__name__.lower() 

2140 

2141 id = Column(Integer, primary_key=True) 

2142 

2143 

2144 class MyMappedClass(Base): ... 

2145 

2146 .. seealso:: 

2147 

2148 :meth:`_orm.registry.as_declarative_base` 

2149 

2150 """ 

2151 metadata, class_registry = ( 

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

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

2154 ) 

2155 

2156 return registry( 

2157 metadata=metadata, class_registry=class_registry 

2158 ).as_declarative_base(**kw) 

2159 

2160 

2161@compat_typing.dataclass_transform( 

2162 field_specifiers=( 

2163 MappedColumn, 

2164 RelationshipProperty, 

2165 Composite, 

2166 Synonym, 

2167 mapped_column, 

2168 relationship, 

2169 composite, 

2170 synonym, 

2171 deferred, 

2172 ), 

2173) 

2174def mapped_as_dataclass( 

2175 registry: RegistryType, 

2176 /, 

2177 *, 

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

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

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

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

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

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

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

2185 dataclass_callable: Union[ 

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

2187 ] = _NoArg.NO_ARG, 

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

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

2190 which may have better compatibility with mypy. 

2191 

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

2193 decorator. 

2194 

2195 e.g.:: 

2196 

2197 from sqlalchemy.orm import Mapped 

2198 from sqlalchemy.orm import mapped_as_dataclass 

2199 from sqlalchemy.orm import mapped_column 

2200 from sqlalchemy.orm import registry 

2201 

2202 some_registry = registry() 

2203 

2204 

2205 @mapped_as_dataclass(some_registry) 

2206 class Relationships: 

2207 __tablename__ = "relationships" 

2208 

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

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

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

2212 

2213 .. versionadded:: 2.0.44 

2214 

2215 """ 

2216 

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

2218 _generate_dc_transforms( 

2219 init=init, 

2220 repr=repr, 

2221 eq=eq, 

2222 order=order, 

2223 unsafe_hash=unsafe_hash, 

2224 match_args=match_args, 

2225 kw_only=kw_only, 

2226 dataclass_callable=dataclass_callable, 

2227 cls_=cls, 

2228 ) 

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

2230 return cls 

2231 

2232 return decorate 

2233 

2234 

2235@inspection._inspects( 

2236 DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept 

2237) 

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

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

2240 if mp is None: 

2241 if _DeferredDeclarativeConfig.has_cls(cls): 

2242 _DeferredDeclarativeConfig.raise_unmapped_for_cls(cls) 

2243 return mp 

2244 

2245 

2246@compat_typing.dataclass_transform( 

2247 field_specifiers=( 

2248 MappedColumn, 

2249 RelationshipProperty, 

2250 Composite, 

2251 Synonym, 

2252 mapped_column, 

2253 relationship, 

2254 composite, 

2255 synonym, 

2256 deferred, 

2257 ), 

2258) 

2259@overload 

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

2261 

2262 

2263@overload 

2264def unmapped_dataclass( 

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

2266 /, 

2267 *, 

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

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

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

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

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

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

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

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

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

2277 

2278 

2279def unmapped_dataclass( 

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

2281 /, 

2282 *, 

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

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

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

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

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

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

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

2290 dataclass_callable: Union[ 

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

2292 ] = _NoArg.NO_ARG, 

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

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

2295 within mapped class hierarchies based on the 

2296 :func:`_orm.mapped_as_dataclass` decorator. 

2297 

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

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

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

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

2302 specific directives, but not actually mapping the class. 

2303 

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

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

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

2307 effect. 

2308 

2309 .. versionadded:: 2.1 

2310 

2311 .. seealso:: 

2312 

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

2314 

2315 """ 

2316 

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

2318 _generate_dc_transforms( 

2319 init=init, 

2320 repr=repr, 

2321 eq=eq, 

2322 order=order, 

2323 unsafe_hash=unsafe_hash, 

2324 match_args=match_args, 

2325 kw_only=kw_only, 

2326 dataclass_callable=dataclass_callable, 

2327 cls_=cls, 

2328 ) 

2329 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

2330 return cls 

2331 

2332 if __cls: 

2333 return decorate(__cls) 

2334 else: 

2335 return decorate