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

506 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 ClassVar 

17from typing import Dict 

18from typing import FrozenSet 

19from typing import Generic 

20from typing import Iterable 

21from typing import Iterator 

22from typing import Literal 

23from typing import Mapping 

24from typing import Optional 

25from typing import overload 

26from typing import Protocol 

27from typing import Set 

28from typing import Tuple 

29from typing import Type 

30from typing import TYPE_CHECKING 

31from typing import TypeVar 

32from typing import Union 

33import weakref 

34 

35from . import attributes 

36from . import clsregistry 

37from . import instrumentation 

38from . import interfaces 

39from . import mapperlib 

40from ._orm_constructors import composite 

41from ._orm_constructors import deferred 

42from ._orm_constructors import mapped_column 

43from ._orm_constructors import relationship 

44from ._orm_constructors import synonym 

45from .attributes import InstrumentedAttribute 

46from .base import _inspect_mapped_class 

47from .base import _is_mapped_class 

48from .base import Mapped 

49from .base import ORMDescriptor 

50from .decl_base import _add_attribute 

51from .decl_base import _declarative_constructor 

52from .decl_base import _DeclarativeMapperConfig 

53from .decl_base import _DeferredDeclarativeConfig 

54from .decl_base import _del_attribute 

55from .decl_base import _ORMClassConfigurator 

56from .decl_base import MappedClassProtocol 

57from .descriptor_props import Composite 

58from .descriptor_props import Synonym 

59from .descriptor_props import Synonym as _orm_synonym 

60from .mapper import Mapper 

61from .properties import MappedColumn 

62from .relationships import RelationshipProperty 

63from .state import InstanceState 

64from .. import exc 

65from .. import inspection 

66from .. import util 

67from ..event import dispatcher 

68from ..event import EventTarget 

69from ..sql import sqltypes 

70from ..sql._annotated_cols import _TC 

71from ..sql.base import _NoArg 

72from ..sql.elements import SQLCoreOperations 

73from ..sql.schema import MetaData 

74from ..sql.selectable import FromClause 

75from ..util import hybridmethod 

76from ..util import hybridproperty 

77from ..util import typing as compat_typing 

78from ..util import TypingOnly 

79from ..util.typing import CallableReference 

80from ..util.typing import de_optionalize_union_types 

81from ..util.typing import GenericProtocol 

82from ..util.typing import is_generic 

83from ..util.typing import is_literal 

84from ..util.typing import LITERAL_TYPES 

85from ..util.typing import Self 

86from ..util.typing import TypeAliasType 

87 

88if TYPE_CHECKING: 

89 from ._typing import _O 

90 from ._typing import _RegistryType 

91 from .instrumentation import ClassManager 

92 from .interfaces import _DataclassArguments 

93 from .interfaces import MapperProperty 

94 from .state import InstanceState # noqa 

95 from ..sql._typing import _TypeEngineArgument 

96 from ..util.typing import _MatchedOnType 

97 

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

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

100 

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

102 

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

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

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

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

107 

108_DeclaredAttrDecorated = Callable[ 

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

110] 

111 

112 

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

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

115 mapped table, otherwise return False. 

116 

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

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

119 hierarchy. 

120 

121 .. seealso:: 

122 

123 :ref:`decl_mixin_inheritance` 

124 

125 """ 

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

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

128 return True 

129 return False 

130 

131 

132class _DynamicAttributesType(type): 

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

134 if "__mapper__" in cls.__dict__: 

135 _add_attribute(cls, key, value) 

136 else: 

137 type.__setattr__(cls, key, value) 

138 

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

140 if "__mapper__" in cls.__dict__: 

141 _del_attribute(cls, key) 

142 else: 

143 type.__delattr__(cls, key) 

144 

145 

146class DeclarativeAttributeIntercept( 

147 _DynamicAttributesType, 

148 # Inspectable is used only by the mypy plugin 

149 inspection.Inspectable[Mapper[Any]], 

150): 

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

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

153 attributes dynamically. 

154 

155 """ 

156 

157 

158@compat_typing.dataclass_transform( 

159 field_specifiers=( 

160 MappedColumn, 

161 RelationshipProperty, 

162 Composite, 

163 Synonym, 

164 mapped_column, 

165 relationship, 

166 composite, 

167 synonym, 

168 deferred, 

169 ), 

170) 

171class DCTransformDeclarative(DeclarativeAttributeIntercept): 

172 """metaclass that includes @dataclass_transforms""" 

173 

174 

175class DeclarativeMeta(DeclarativeAttributeIntercept): 

176 metadata: MetaData 

177 registry: RegistryType 

178 

179 def __init__( 

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

181 ) -> None: 

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

183 # __init_subclass__() method (#7900) 

184 dict_ = cls.__dict__ 

185 

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

187 # assign privately to not conflict with subclass attributes named 

188 # "registry" 

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

190 if reg is None: 

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

192 if not isinstance(reg, registry): 

193 raise exc.InvalidRequestError( 

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

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

196 ) 

197 else: 

198 cls._sa_registry = reg 

199 

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

201 _ORMClassConfigurator._as_declarative(reg, cls, dict_) 

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

203 

204 

205def synonym_for( 

206 name: str, map_column: bool = False 

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

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

209 attribute in conjunction with a Python descriptor. 

210 

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

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

213 

214 class MyClass(Base): 

215 __tablename__ = "my_table" 

216 

217 id = Column(Integer, primary_key=True) 

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

219 

220 @synonym_for("job_status") 

221 @property 

222 def job_status(self): 

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

224 

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

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

227 feature. 

228 

229 .. seealso:: 

230 

231 :ref:`synonyms` - Overview of synonyms 

232 

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

234 

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

236 updated approach to augmenting attribute behavior more flexibly than 

237 can be achieved with synonyms. 

238 

239 """ 

240 

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

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

243 

244 return decorate 

245 

246 

247class _declared_attr_common: 

248 def __init__( 

249 self, 

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

251 cascading: bool = False, 

252 quiet: bool = False, 

253 ): 

254 # support 

255 # @declared_attr 

256 # @classmethod 

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

258 # ... 

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

260 # for situations where needed 

261 if isinstance(fn, classmethod): 

262 fn = fn.__func__ 

263 

264 self.fget = fn 

265 self._cascading = cascading 

266 self._quiet = quiet 

267 self.__doc__ = fn.__doc__ 

268 

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

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

271 

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

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

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

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

276 

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

278 # setup phase 

279 

280 cls = owner 

281 manager = attributes.opt_manager_of_class(cls) 

282 if manager is None: 

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

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

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

286 util.warn( 

287 "Unmanaged access of declarative attribute %s from " 

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

289 ) 

290 return self.fget(cls) 

291 elif manager.is_mapped: 

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

293 # scan setup, just run the function. 

294 return self.fget(cls) 

295 

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

297 # that is tracking the values of these attributes. 

298 declarative_scan = manager.declarative_scan() 

299 

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

301 assert declarative_scan is not None 

302 

303 reg = declarative_scan.declared_attr_reg 

304 

305 if self in reg: 

306 return reg[self] 

307 else: 

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

309 return obj 

310 

311 

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

313 # see mapping_api.rst for docstring 

314 

315 if typing.TYPE_CHECKING: 

316 

317 def __init__( 

318 self, 

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

320 cascading: bool = False, 

321 ): ... 

322 

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

324 

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

326 

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

328 

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

330 # extensive fooling of mypy underway... 

331 ... 

332 

333 

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

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

336 a mapped property or Declarative directive. 

337 

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

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

340 invoked from the uninstantiated class. The Declarative mapping process 

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

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

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

344 table configuration. 

345 

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

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

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

349 define dynamically generated column expressions and other Declarative 

350 attributes. 

351 

352 Example:: 

353 

354 class ProvidesUserMixin: 

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

356 

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

358 

359 @declared_attr 

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

361 return relationship("User") 

362 

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

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

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

366 :class:`_orm.Mapped` attributes:: 

367 

368 class CreateTableName: 

369 @declared_attr.directive 

370 def __tablename__(cls) -> str: 

371 return cls.__name__.lower() 

372 

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

374 classes, to allow for attributes that dynamically configure themselves 

375 on subclasses when using mapped inheritance schemes. Below 

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

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

378 for subclasses:: 

379 

380 class Employee(Base): 

381 __tablename__ = "employee" 

382 

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

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

385 

386 @declared_attr.directive 

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

388 if cls.__name__ == "Employee": 

389 return { 

390 "polymorphic_on": cls.type, 

391 "polymorphic_identity": "Employee", 

392 } 

393 else: 

394 return {"polymorphic_identity": cls.__name__} 

395 

396 

397 class Engineer(Employee): 

398 pass 

399 

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

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

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

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

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

405 

406 class SomethingMixin: 

407 x: Mapped[int] 

408 y: Mapped[int] 

409 

410 @declared_attr 

411 @classmethod 

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

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

414 

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

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

417 integration where needed. 

418 

419 

420 .. seealso:: 

421 

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

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

424 

425 """ # noqa: E501 

426 

427 if typing.TYPE_CHECKING: 

428 

429 def __init__( 

430 self, 

431 fn: _DeclaredAttrDecorated[_T_co], 

432 cascading: bool = False, 

433 ): ... 

434 

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

436 

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

438 

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

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

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

442 # declarative function that does not return InstrumentedAttribute 

443 @overload 

444 def __get__( 

445 self, instance: None, owner: Any 

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

447 

448 @overload 

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

450 

451 def __get__( 

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

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

454 

455 @hybridmethod 

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

457 return _stateful_declared_attr(**kw) 

458 

459 @hybridproperty 

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

461 # see mapping_api.rst for docstring 

462 return _declared_directive # type: ignore 

463 

464 @hybridproperty 

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

466 # see mapping_api.rst for docstring 

467 return cls._stateful(cascading=True) 

468 

469 

470class _stateful_declared_attr(declared_attr[_T_co]): 

471 kw: Dict[str, Any] 

472 

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

474 self.kw = kw 

475 

476 @hybridmethod 

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

478 new_kw = self.kw.copy() 

479 new_kw.update(kw) 

480 return _stateful_declared_attr(**new_kw) 

481 

482 def __call__( 

483 self, fn: _DeclaredAttrDecorated[_T_co] 

484 ) -> declared_attr[_T_co]: 

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

486 

487 

488@util.deprecated( 

489 "2.1", 

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

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

492) 

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

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

495 

496 E.g.:: 

497 

498 from sqlalchemy.orm import declared_attr 

499 from sqlalchemy.orm import declarative_mixin 

500 

501 

502 @declarative_mixin 

503 class MyMixin: 

504 

505 @declared_attr 

506 def __tablename__(cls): 

507 return cls.__name__.lower() 

508 

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

510 __mapper_args__ = {"always_refresh": True} 

511 

512 id = Column(Integer, primary_key=True) 

513 

514 

515 class MyModel(MyMixin, Base): 

516 name = Column(String(1000)) 

517 

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

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

520 the Mypy plugin in being able to identify 

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

522 

523 .. versionadded:: 1.4.6 

524 

525 .. seealso:: 

526 

527 :ref:`orm_mixins_toplevel` 

528 

529 """ # noqa: E501 

530 

531 return cls 

532 

533 

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

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

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

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

538 

539 if reg is not None: 

540 if not isinstance(reg, registry): 

541 raise exc.InvalidRequestError( 

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

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

544 ) 

545 elif type_annotation_map is not None: 

546 raise exc.InvalidRequestError( 

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

548 "type_annotation_map entry. Per-base type_annotation_maps " 

549 "are not supported. Please apply the type_annotation_map " 

550 "to this registry directly." 

551 ) 

552 

553 else: 

554 reg = registry( 

555 metadata=metadata, type_annotation_map=type_annotation_map 

556 ) 

557 cls.registry = reg 

558 

559 cls._sa_registry = reg 

560 

561 if "metadata" not in cls.__dict__: 

562 cls.metadata = cls.registry.metadata 

563 

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

565 cls.__init__ = cls.registry.constructor 

566 

567 

568def _generate_dc_transforms( 

569 cls_: Type[_O], 

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

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

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

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

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

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

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

577 dataclass_callable: Union[ 

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

579 ] = _NoArg.NO_ARG, 

580) -> None: 

581 apply_dc_transforms: _DataclassArguments = { 

582 "init": init, 

583 "repr": repr, 

584 "eq": eq, 

585 "order": order, 

586 "unsafe_hash": unsafe_hash, 

587 "match_args": match_args, 

588 "kw_only": kw_only, 

589 "dataclass_callable": dataclass_callable, 

590 } 

591 

592 if hasattr(cls_, "_sa_apply_dc_transforms"): 

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

594 

595 _DeclarativeMapperConfig._assert_dc_arguments(current) 

596 

597 cls_._sa_apply_dc_transforms = { # type: ignore # noqa: E501 

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

599 for k, v in apply_dc_transforms.items() 

600 } 

601 else: 

602 setattr(cls_, "_sa_apply_dc_transforms", apply_dc_transforms) 

603 

604 

605class MappedAsDataclass(metaclass=DCTransformDeclarative): 

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

607 a dataclass. 

608 

609 .. seealso:: 

610 

611 :ref:`orm_declarative_native_dataclasses` - complete background 

612 on SQLAlchemy native dataclass mapping with 

613 :class:`_orm.MappedAsDataclass`. 

614 

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

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

617 

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

619 decorator versions with equivalent functionality 

620 

621 .. versionadded:: 2.0 

622 

623 """ 

624 

625 def __init_subclass__( 

626 cls, 

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

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

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

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

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

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

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

634 dataclass_callable: Union[ 

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

636 ] = _NoArg.NO_ARG, 

637 **kw: Any, 

638 ) -> None: 

639 _generate_dc_transforms( 

640 init=init, 

641 repr=repr, 

642 eq=eq, 

643 order=order, 

644 unsafe_hash=unsafe_hash, 

645 match_args=match_args, 

646 kw_only=kw_only, 

647 dataclass_callable=dataclass_callable, 

648 cls_=cls, 

649 ) 

650 super().__init_subclass__(**kw) 

651 

652 if not _is_mapped_class(cls): 

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

654 # as a base or a mixin 

655 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

656 

657 

658class _DeclarativeTyping(TypingOnly): 

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

660 DeclarativeBaseNoMeta classes. 

661 """ 

662 

663 __slots__ = () 

664 

665 if typing.TYPE_CHECKING: 

666 # protocols for inspection 

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

668 

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

670 

671 # internal stuff 

672 _sa_registry: ClassVar[_RegistryType] 

673 

674 # public interface 

675 registry: ClassVar[_RegistryType] 

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

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

678 

679 metadata: ClassVar[MetaData] 

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

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

682 

683 .. seealso:: 

684 

685 :ref:`orm_declarative_metadata` 

686 

687 """ 

688 

689 __name__: ClassVar[str] 

690 

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

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

693 # ok with it. 

694 __mapper__: ClassVar[Mapper[Any]] 

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

696 mapped. 

697 

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

699 ``inspect(klass)``. 

700 

701 """ 

702 

703 __table__: ClassVar[FromClause] 

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

705 mapped. 

706 

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

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

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

710 

711 .. seealso:: 

712 

713 :ref:`orm_declarative_metadata` 

714 

715 """ 

716 

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

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

719 __tablename__: Any 

720 """String name to assign to the generated 

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

722 :attr:`_orm.DeclarativeBase.__table__`. 

723 

724 .. seealso:: 

725 

726 :ref:`orm_declarative_table` 

727 

728 """ 

729 

730 __mapper_args__: Any 

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

732 :class:`_orm.Mapper` constructor. 

733 

734 .. seealso:: 

735 

736 :ref:`orm_declarative_mapper_options` 

737 

738 """ 

739 

740 __table_args__: Any 

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

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

743 :ref:`orm_declarative_table_configuration` 

744 for background on the specific structure of this collection. 

745 

746 .. seealso:: 

747 

748 :ref:`orm_declarative_table_configuration` 

749 

750 """ 

751 

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

753 

754 

755class MappedClassWithTypedColumnsProtocol(Protocol[_TC]): 

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

757 attribute its typed columns. 

758 

759 .. versionadded:: 2.1.0b2 

760 """ 

761 

762 __typed_cols__: _TC 

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

764 

765 __name__: ClassVar[str] 

766 __mapper__: ClassVar[Mapper[Any]] 

767 __table__: ClassVar[FromClause] 

768 

769 

770@overload 

771def as_typed_table( 

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

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

774 

775 

776@overload 

777def as_typed_table( 

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

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

780 

781 

782def as_typed_table( 

783 cls: ( 

784 MappedClassProtocol[Any] 

785 | type[MappedClassWithTypedColumnsProtocol[Any]] 

786 ), 

787 typed_columns_cls: Any = None, 

788 /, 

789) -> FromClause[Any]: 

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

791 

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

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

794 

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

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

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

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

799 

800 

801 Example usage:: 

802 

803 from sqlalchemy import TypedColumns 

804 from sqlalchemy.orm import DeclarativeBase, mapped_column 

805 from sqlalchemy.orm import MappedColumn, as_typed_table 

806 

807 

808 class Base(DeclarativeBase): 

809 pass 

810 

811 

812 class A(Base): 

813 __tablename__ = "a" 

814 

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

816 data: MappedColumn[str] 

817 

818 

819 class a_cols(A, TypedColumns): 

820 pass 

821 

822 

823 # table_a is annotated as FromClause[a_cols] 

824 table_a = as_typed_table(A, a_cols) 

825 

826 

827 class B(Base): 

828 __tablename__ = "b" 

829 __typed_cols__: "b_cols" 

830 

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

832 b: Mapped[str] 

833 

834 

835 class b_cols(B, TypedColumns): 

836 pass 

837 

838 

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

840 # provides the __typed_cols__ annotation 

841 table_b = as_typed_table(B) 

842 

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

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

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

846 

847 .. versionadded:: 2.1.0b2 

848 """ 

849 return cls.__table__ 

850 

851 

852class DeclarativeBase( 

853 # Inspectable is used only by the mypy plugin 

854 inspection.Inspectable[InstanceState[Any]], 

855 _DeclarativeTyping, 

856 metaclass=DeclarativeAttributeIntercept, 

857): 

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

859 

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

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

862 

863 

864 from sqlalchemy.orm import DeclarativeBase 

865 

866 

867 class Base(DeclarativeBase): 

868 pass 

869 

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

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

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

873 

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

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

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

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

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

879 collection as well as a specific value for 

880 :paramref:`_orm.registry.type_annotation_map`:: 

881 

882 from typing import Annotated 

883 

884 from sqlalchemy import BigInteger 

885 from sqlalchemy import MetaData 

886 from sqlalchemy import String 

887 from sqlalchemy.orm import DeclarativeBase 

888 

889 bigint = Annotated[int, "bigint"] 

890 my_metadata = MetaData() 

891 

892 

893 class Base(DeclarativeBase): 

894 metadata = my_metadata 

895 type_annotation_map = { 

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

897 bigint: BigInteger(), 

898 } 

899 

900 Class-level attributes which may be specified include: 

901 

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

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

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

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

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

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

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

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

910 :paramref:`_orm.registry.type_annotation_map`. 

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

912 

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

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

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

916 and other subclassing-oriented APIs should be seen as 

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

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

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

920 without using plugins. 

921 

922 **__init__ behavior** 

923 

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

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

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

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

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

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

930 constructor that will assign keyword arguments as attributes on the 

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

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

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

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

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

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

937 method does. 

938 

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

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

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

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

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

944 ``object.__init__()``. 

945 

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

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

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

949 

950 class Base(DeclarativeBase): 

951 def __init__(self, id=None): 

952 self.id = id 

953 

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

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

956 

957 class MyClass(Base): 

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

959 self.name = name 

960 super().__init__(id=id) 

961 

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

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

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

965 ``__init__()``. 

966 

967 

968 """ 

969 

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

971 if DeclarativeBase in cls.__bases__: 

972 _check_not_declarative(cls, DeclarativeBase) 

973 _setup_declarative_base(cls) 

974 else: 

975 _ORMClassConfigurator._as_declarative( 

976 cls._sa_registry, cls, cls.__dict__ 

977 ) 

978 super().__init_subclass__(**kw) 

979 

980 

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

982 cls_dict = cls.__dict__ 

983 if ( 

984 "__table__" in cls_dict 

985 and not ( 

986 callable(cls_dict["__table__"]) 

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

988 ) 

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

990 raise exc.InvalidRequestError( 

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

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

993 ) 

994 

995 

996class DeclarativeBaseNoMeta( 

997 # Inspectable is used only by the mypy plugin 

998 inspection.Inspectable[InstanceState[Any]], 

999 _DeclarativeTyping, 

1000): 

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

1002 to intercept new attributes. 

1003 

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

1005 custom metaclasses is desirable. 

1006 

1007 .. versionadded:: 2.0 

1008 

1009 

1010 """ 

1011 

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

1013 if DeclarativeBaseNoMeta in cls.__bases__: 

1014 _check_not_declarative(cls, DeclarativeBaseNoMeta) 

1015 _setup_declarative_base(cls) 

1016 else: 

1017 _ORMClassConfigurator._as_declarative( 

1018 cls._sa_registry, cls, cls.__dict__ 

1019 ) 

1020 super().__init_subclass__(**kw) 

1021 

1022 

1023def add_mapped_attribute( 

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

1025) -> None: 

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

1027 

1028 E.g.:: 

1029 

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

1031 

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

1033 metaclass that intercepts attribute set operations. 

1034 

1035 .. versionadded:: 2.0 

1036 

1037 

1038 """ 

1039 _add_attribute(target, key, attr) 

1040 

1041 

1042def declarative_base( 

1043 *, 

1044 metadata: Optional[MetaData] = None, 

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

1046 cls: Type[Any] = object, 

1047 name: str = "Base", 

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

1049 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1051 metaclass: Type[Any] = DeclarativeMeta, 

1052) -> Any: 

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

1054 

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

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

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

1058 information provided declaratively in the class and any subclasses 

1059 of the class. 

1060 

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

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

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

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

1065 with :pep:`484` typing tools. 

1066 

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

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

1069 method. That is, the following:: 

1070 

1071 from sqlalchemy.orm import declarative_base 

1072 

1073 Base = declarative_base() 

1074 

1075 Is equivalent to:: 

1076 

1077 from sqlalchemy.orm import registry 

1078 

1079 mapper_registry = registry() 

1080 Base = mapper_registry.generate_base() 

1081 

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

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

1084 for more details. 

1085 

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

1087 function is now a specialization of the more generic 

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

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

1090 

1091 

1092 :param metadata: 

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

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

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

1096 will be created if none is provided. The 

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

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

1099 

1100 :param mapper: 

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

1102 be used to map subclasses to their Tables. 

1103 

1104 :param cls: 

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

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

1107 

1108 :param name: 

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

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

1111 tracebacks and debugging. 

1112 

1113 :param constructor: 

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

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

1116 implementation that assigns \**kwargs for declared 

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

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

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

1120 

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

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

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

1124 and others. Allows two or more declarative base classes 

1125 to share the same registry of class names for simplified 

1126 inter-base relationships. 

1127 

1128 :param type_annotation_map: optional dictionary of Python types to 

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

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

1131 to produce column types based on annotations within the 

1132 :class:`_orm.Mapped` type. 

1133 

1134 

1135 .. versionadded:: 2.0 

1136 

1137 .. seealso:: 

1138 

1139 :ref:`orm_declarative_mapped_column_type_map` 

1140 

1141 :param metaclass: 

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

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

1144 declarative base class. 

1145 

1146 .. seealso:: 

1147 

1148 :class:`_orm.registry` 

1149 

1150 """ 

1151 

1152 return registry( 

1153 metadata=metadata, 

1154 class_registry=class_registry, 

1155 constructor=constructor, 

1156 type_annotation_map=type_annotation_map, 

1157 ).generate_base( 

1158 mapper=mapper, 

1159 cls=cls, 

1160 name=name, 

1161 metaclass=metaclass, 

1162 ) 

1163 

1164 

1165class registry(EventTarget): 

1166 """Generalized registry for mapping classes. 

1167 

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

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

1170 

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

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

1173 styles may be used interchangeably: 

1174 

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

1176 class, and is the underlying implementation of the 

1177 :func:`_orm.declarative_base` function. 

1178 

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

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

1181 base class. 

1182 

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

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

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

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

1187 which is removed as of SQLAlchemy 2.0. 

1188 

1189 .. versionadded:: 1.4 

1190 

1191 .. seealso:: 

1192 

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

1194 styles. 

1195 

1196 """ 

1197 

1198 _class_registry: clsregistry._ClsRegistryType 

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

1200 metadata: MetaData 

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

1202 type_annotation_map: _MutableTypeAnnotationMapType 

1203 _dependents: Set[_RegistryType] 

1204 _dependencies: Set[_RegistryType] 

1205 _new_mappers: bool 

1206 dispatch: dispatcher["registry"] 

1207 

1208 def __init__( 

1209 self, 

1210 *, 

1211 metadata: Optional[MetaData] = None, 

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

1213 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1215 ): 

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

1217 

1218 :param metadata: 

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

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

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

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

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

1224 

1225 :param constructor: 

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

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

1228 implementation that assigns \**kwargs for declared 

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

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

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

1232 

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

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

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

1236 and others. Allows two or more declarative base classes 

1237 to share the same registry of class names for simplified 

1238 inter-base relationships. 

1239 

1240 :param type_annotation_map: optional dictionary of Python types to 

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

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

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

1244 to produce column types based on annotations within the 

1245 :class:`_orm.Mapped` type. 

1246 

1247 .. versionadded:: 2.0 

1248 

1249 .. seealso:: 

1250 

1251 :ref:`orm_declarative_mapped_column_type_map` 

1252 

1253 

1254 """ 

1255 lcl_metadata = metadata or MetaData() 

1256 

1257 if class_registry is None: 

1258 class_registry = weakref.WeakValueDictionary() 

1259 

1260 self._class_registry = class_registry 

1261 self._managers = weakref.WeakKeyDictionary() 

1262 self.metadata = lcl_metadata 

1263 self.constructor = constructor 

1264 self.type_annotation_map = {} 

1265 if type_annotation_map is not None: 

1266 self.update_type_annotation_map(type_annotation_map) 

1267 self._dependents = set() 

1268 self._dependencies = set() 

1269 

1270 self._new_mappers = False 

1271 

1272 with mapperlib._CONFIGURE_MUTEX: 

1273 mapperlib._mapper_registries[self] = True 

1274 

1275 def update_type_annotation_map( 

1276 self, 

1277 type_annotation_map: _TypeAnnotationMapType, 

1278 ) -> None: 

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

1280 values.""" 

1281 

1282 self.type_annotation_map.update( 

1283 { 

1284 de_optionalize_union_types(typ): sqltype 

1285 for typ, sqltype in type_annotation_map.items() 

1286 } 

1287 ) 

1288 

1289 def _resolve_type_with_events( 

1290 self, 

1291 cls: Any, 

1292 key: str, 

1293 raw_annotation: _MatchedOnType, 

1294 extracted_type: _MatchedOnType, 

1295 *, 

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

1297 pep_593_resolved_argument: Optional[_MatchedOnType] = None, 

1298 raw_pep_695_type: Optional[TypeAliasType] = None, 

1299 pep_695_resolved_value: Optional[_MatchedOnType] = None, 

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

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

1302 

1303 This method fires the resolve_type_annotation event first to allow 

1304 custom resolution, then falls back to normal resolution. 

1305 

1306 """ 

1307 

1308 if self.dispatch.resolve_type_annotation: 

1309 type_resolve = TypeResolve( 

1310 self, 

1311 cls, 

1312 key, 

1313 raw_annotation, 

1314 ( 

1315 pep_593_resolved_argument 

1316 if pep_593_resolved_argument is not None 

1317 else ( 

1318 pep_695_resolved_value 

1319 if pep_695_resolved_value is not None 

1320 else extracted_type 

1321 ) 

1322 ), 

1323 raw_pep_593_type, 

1324 pep_593_resolved_argument, 

1325 raw_pep_695_type, 

1326 pep_695_resolved_value, 

1327 ) 

1328 

1329 for fn in self.dispatch.resolve_type_annotation: 

1330 result = fn(type_resolve) 

1331 if result is not None: 

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

1333 

1334 if raw_pep_695_type is not None: 

1335 sqltype = self._resolve_type(raw_pep_695_type) 

1336 if sqltype is not None: 

1337 return sqltype 

1338 

1339 sqltype = self._resolve_type(extracted_type) 

1340 if sqltype is not None: 

1341 return sqltype 

1342 

1343 if pep_593_resolved_argument is not None: 

1344 sqltype = self._resolve_type(pep_593_resolved_argument) 

1345 

1346 return sqltype 

1347 

1348 def _resolve_type( 

1349 self, python_type: _MatchedOnType 

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

1351 python_type_type: Type[Any] 

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

1353 

1354 if is_generic(python_type): 

1355 if is_literal(python_type): 

1356 python_type_type = python_type # type: ignore[assignment] 

1357 

1358 search = ( 

1359 (python_type, python_type_type), 

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

1361 ) 

1362 else: 

1363 python_type_type = python_type.__origin__ 

1364 search = ((python_type, python_type_type),) 

1365 elif isinstance(python_type, type): 

1366 python_type_type = python_type 

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

1368 else: 

1369 python_type_type = python_type # type: ignore[assignment] 

1370 search = ((python_type, python_type_type),) 

1371 

1372 for pt, flattened in search: 

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

1374 sql_type = self.type_annotation_map.get(pt) 

1375 if sql_type is None: 

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

1377 

1378 if sql_type is not None: 

1379 sql_type_inst = sqltypes.to_instance(sql_type) 

1380 

1381 # ... this additional step will reject most 

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

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

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

1385 # type_annotation_map to be useful 

1386 resolved_sql_type = sql_type_inst._resolve_for_python_type( 

1387 python_type_type, 

1388 pt, 

1389 flattened, 

1390 ) 

1391 if resolved_sql_type is not None: 

1392 return resolved_sql_type 

1393 

1394 return None 

1395 

1396 @property 

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

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

1399 

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

1401 

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

1403 if registry is self: 

1404 return 

1405 registry._dependents.add(self) 

1406 self._dependencies.add(registry) 

1407 

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

1409 mapper._ready_for_configure = True 

1410 if self._new_mappers: 

1411 return 

1412 

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

1414 reg._new_mappers = True 

1415 

1416 @classmethod 

1417 def _recurse_with_dependents( 

1418 cls, registries: Set[RegistryType] 

1419 ) -> Iterator[RegistryType]: 

1420 todo = registries 

1421 done = set() 

1422 while todo: 

1423 reg = todo.pop() 

1424 done.add(reg) 

1425 

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

1427 # them before 

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

1429 yield reg 

1430 

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

1432 # after 

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

1434 

1435 @classmethod 

1436 def _recurse_with_dependencies( 

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 dependencies, make sure we have 

1446 # them before 

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

1448 

1449 yield reg 

1450 

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

1452 # them before 

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

1454 

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

1456 return ( 

1457 manager.mapper 

1458 for manager in list(self._managers) 

1459 if manager.is_mapped 

1460 and not manager.mapper.configured 

1461 and manager.mapper._ready_for_configure 

1462 ) 

1463 

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

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

1466 

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

1468 self._managers[manager] = True 

1469 if manager.is_mapped: 

1470 raise exc.ArgumentError( 

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

1472 % manager.class_ 

1473 ) 

1474 assert manager.registry is None 

1475 manager.registry = self 

1476 

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

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

1479 :class:`_orm.registry`. 

1480 

1481 The configure step is used to reconcile and initialize the 

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

1483 to invoke configuration events such as the 

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

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

1486 extensions or user-defined extension hooks. 

1487 

1488 If one or more mappers in this registry contain 

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

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

1491 registries. In order to configure those dependent registries 

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

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

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

1495 allow an application to programmatically invoke configuration of 

1496 registries while controlling whether or not the process implicitly 

1497 reaches other registries. 

1498 

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

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

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

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

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

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

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

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

1507 

1508 .. seealso:: 

1509 

1510 :func:`_orm.configure_mappers` 

1511 

1512 

1513 .. versionadded:: 1.4.0b2 

1514 

1515 """ 

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

1517 

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

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

1520 

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

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

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

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

1525 

1526 If this registry contains mappers that are dependencies of other 

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

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

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

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

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

1532 were not already disposed. 

1533 

1534 .. versionadded:: 1.4.0b2 

1535 

1536 .. seealso:: 

1537 

1538 :func:`_orm.clear_mappers` 

1539 

1540 """ 

1541 

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

1543 

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

1545 if "mapper" in manager.__dict__: 

1546 mapper = manager.mapper 

1547 

1548 mapper._set_dispose_flags() 

1549 

1550 class_ = manager.class_ 

1551 self._dispose_cls(class_) 

1552 instrumentation._instrumentation_factory.unregister(class_) 

1553 

1554 def generate_base( 

1555 self, 

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

1557 cls: Type[Any] = object, 

1558 name: str = "Base", 

1559 metaclass: Type[Any] = DeclarativeMeta, 

1560 ) -> Any: 

1561 """Generate a declarative base class. 

1562 

1563 Classes that inherit from the returned class object will be 

1564 automatically mapped using declarative mapping. 

1565 

1566 E.g.:: 

1567 

1568 from sqlalchemy.orm import registry 

1569 

1570 mapper_registry = registry() 

1571 

1572 Base = mapper_registry.generate_base() 

1573 

1574 

1575 class MyClass(Base): 

1576 __tablename__ = "my_table" 

1577 id = Column(Integer, primary_key=True) 

1578 

1579 The above dynamically generated class is equivalent to the 

1580 non-dynamic example below:: 

1581 

1582 from sqlalchemy.orm import registry 

1583 from sqlalchemy.orm.decl_api import DeclarativeMeta 

1584 

1585 mapper_registry = registry() 

1586 

1587 

1588 class Base(metaclass=DeclarativeMeta): 

1589 __abstract__ = True 

1590 registry = mapper_registry 

1591 metadata = mapper_registry.metadata 

1592 

1593 __init__ = mapper_registry.constructor 

1594 

1595 .. versionchanged:: 2.0 Note that the 

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

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

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

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

1600 tools. 

1601 

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

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

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

1605 

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

1607 examples. 

1608 

1609 :param mapper: 

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

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

1612 

1613 :param cls: 

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

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

1616 

1617 :param name: 

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

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

1620 tracebacks and debugging. 

1621 

1622 :param metaclass: 

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

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

1625 declarative base class. 

1626 

1627 .. seealso:: 

1628 

1629 :ref:`orm_declarative_mapping` 

1630 

1631 :func:`_orm.declarative_base` 

1632 

1633 """ 

1634 metadata = self.metadata 

1635 

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

1637 

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

1639 if isinstance(cls, type): 

1640 class_dict["__doc__"] = cls.__doc__ 

1641 

1642 if self.constructor is not None: 

1643 class_dict["__init__"] = self.constructor 

1644 

1645 class_dict["__abstract__"] = True 

1646 if mapper: 

1647 class_dict["__mapper_cls__"] = mapper 

1648 

1649 if hasattr(cls, "__class_getitem__"): 

1650 

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

1652 # allow generic classes in py3.9+ 

1653 return cls 

1654 

1655 class_dict["__class_getitem__"] = __class_getitem__ 

1656 

1657 return metaclass(name, bases, class_dict) 

1658 

1659 @compat_typing.dataclass_transform( 

1660 field_specifiers=( 

1661 MappedColumn, 

1662 RelationshipProperty, 

1663 Composite, 

1664 Synonym, 

1665 mapped_column, 

1666 relationship, 

1667 composite, 

1668 synonym, 

1669 deferred, 

1670 ), 

1671 ) 

1672 @overload 

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

1674 

1675 @overload 

1676 def mapped_as_dataclass( 

1677 self, 

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

1679 /, 

1680 *, 

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

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

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

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

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

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

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

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

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

1690 

1691 def mapped_as_dataclass( 

1692 self, 

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

1694 /, 

1695 *, 

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

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

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

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

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

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

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

1703 dataclass_callable: Union[ 

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

1705 ] = _NoArg.NO_ARG, 

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

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

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

1709 Python dataclass. 

1710 

1711 .. seealso:: 

1712 

1713 :ref:`orm_declarative_native_dataclasses` - complete background 

1714 on SQLAlchemy native dataclass mapping 

1715 

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

1717 provide better compatibility with mypy 

1718 

1719 .. versionadded:: 2.0 

1720 

1721 

1722 """ 

1723 

1724 decorate = mapped_as_dataclass( 

1725 self, 

1726 init=init, 

1727 repr=repr, 

1728 eq=eq, 

1729 order=order, 

1730 unsafe_hash=unsafe_hash, 

1731 match_args=match_args, 

1732 kw_only=kw_only, 

1733 dataclass_callable=dataclass_callable, 

1734 ) 

1735 

1736 if __cls: 

1737 return decorate(__cls) 

1738 else: 

1739 return decorate 

1740 

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

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

1743 to a given class. 

1744 

1745 E.g.:: 

1746 

1747 from sqlalchemy.orm import registry 

1748 

1749 mapper_registry = registry() 

1750 

1751 

1752 @mapper_registry.mapped 

1753 class Foo: 

1754 __tablename__ = "some_table" 

1755 

1756 id = Column(Integer, primary_key=True) 

1757 name = Column(String) 

1758 

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

1760 details and examples. 

1761 

1762 :param cls: class to be mapped. 

1763 

1764 :return: the class that was passed. 

1765 

1766 .. seealso:: 

1767 

1768 :ref:`orm_declarative_mapping` 

1769 

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

1771 that will apply Declarative mapping to subclasses automatically 

1772 using a Python metaclass. 

1773 

1774 .. seealso:: 

1775 

1776 :meth:`_orm.registry.mapped_as_dataclass` 

1777 

1778 """ 

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

1780 return cls 

1781 

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

1783 """ 

1784 Class decorator which will invoke 

1785 :meth:`_orm.registry.generate_base` 

1786 for a given base class. 

1787 

1788 E.g.:: 

1789 

1790 from sqlalchemy.orm import registry 

1791 

1792 mapper_registry = registry() 

1793 

1794 

1795 @mapper_registry.as_declarative_base() 

1796 class Base: 

1797 @declared_attr 

1798 def __tablename__(cls): 

1799 return cls.__name__.lower() 

1800 

1801 id = Column(Integer, primary_key=True) 

1802 

1803 

1804 class MyMappedClass(Base): ... 

1805 

1806 All keyword arguments passed to 

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

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

1809 

1810 """ 

1811 

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

1813 kw["cls"] = cls 

1814 kw["name"] = cls.__name__ 

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

1816 

1817 return decorate 

1818 

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

1820 """Map a class declaratively. 

1821 

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

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

1824 actual table object. 

1825 

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

1827 

1828 E.g.:: 

1829 

1830 from sqlalchemy.orm import registry 

1831 

1832 mapper_registry = registry() 

1833 

1834 

1835 class Foo: 

1836 __tablename__ = "some_table" 

1837 

1838 id = Column(Integer, primary_key=True) 

1839 name = Column(String) 

1840 

1841 

1842 mapper = mapper_registry.map_declaratively(Foo) 

1843 

1844 This function is more conveniently invoked indirectly via either the 

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

1846 declarative metaclass generated from 

1847 :meth:`_orm.registry.generate_base`. 

1848 

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

1850 details and examples. 

1851 

1852 :param cls: class to be mapped. 

1853 

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

1855 

1856 .. seealso:: 

1857 

1858 :ref:`orm_declarative_mapping` 

1859 

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

1861 to this function. 

1862 

1863 :meth:`_orm.registry.map_imperatively` 

1864 

1865 """ 

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

1867 return cls.__mapper__ # type: ignore 

1868 

1869 def map_imperatively( 

1870 self, 

1871 class_: Type[_O], 

1872 local_table: Optional[FromClause] = None, 

1873 **kw: Any, 

1874 ) -> Mapper[_O]: 

1875 r"""Map a class imperatively. 

1876 

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

1878 information. Instead, all mapping constructs are passed as 

1879 arguments. 

1880 

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

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

1883 a particular registry. 

1884 

1885 E.g.:: 

1886 

1887 from sqlalchemy.orm import registry 

1888 

1889 mapper_registry = registry() 

1890 

1891 my_table = Table( 

1892 "my_table", 

1893 mapper_registry.metadata, 

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

1895 ) 

1896 

1897 

1898 class MyClass: 

1899 pass 

1900 

1901 

1902 mapper_registry.map_imperatively(MyClass, my_table) 

1903 

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

1905 and usage examples. 

1906 

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

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

1909 

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

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

1912 Corresponds to the 

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

1914 

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

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

1917 

1918 .. seealso:: 

1919 

1920 :ref:`orm_imperative_mapping` 

1921 

1922 :ref:`orm_declarative_mapping` 

1923 

1924 """ 

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

1926 

1927 

1928RegistryType = registry 

1929 

1930if not TYPE_CHECKING: 

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

1932 _RegistryType = registry # noqa 

1933 

1934 

1935class TypeResolve: 

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

1937 event. 

1938 

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

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

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

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

1943 method may be used. 

1944 

1945 .. versionadded:: 2.1 

1946 

1947 """ 

1948 

1949 __slots__ = ( 

1950 "registry", 

1951 "cls", 

1952 "key", 

1953 "raw_type", 

1954 "resolved_type", 

1955 "raw_pep_593_type", 

1956 "raw_pep_695_type", 

1957 "pep_593_resolved_argument", 

1958 "pep_695_resolved_value", 

1959 ) 

1960 

1961 cls: Any 

1962 "The class being processed during declarative mapping" 

1963 

1964 registry: "registry" 

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

1966 

1967 key: str 

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

1969 

1970 raw_type: _MatchedOnType 

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

1972 

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

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

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

1976 the raw type will not be de-optionalized. 

1977 

1978 """ 

1979 

1980 resolved_type: _MatchedOnType 

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

1982 and :pep:`593` indirection: 

1983 

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

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

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

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

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

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

1990 :attr:`.TypeResolve.pep_695_resolved_value`. 

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

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

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

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

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

1996 :attr:`.TypeResolve.pep_593_resolved_argument`. 

1997 

1998 """ 

1999 

2000 raw_pep_593_type: Optional[GenericProtocol[Any]] 

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

2002 

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

2004 

2005 """ 

2006 

2007 pep_593_resolved_argument: Optional[_MatchedOnType] 

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

2009 type referred to one. 

2010 

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

2012 :attr:`.TypeResolve.resolved_type`. 

2013 

2014 """ 

2015 

2016 raw_pep_695_type: Optional[TypeAliasType] 

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

2018 

2019 pep_695_resolved_value: Optional[_MatchedOnType] 

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

2021 raw type referred to one. 

2022 

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

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

2025 

2026 """ 

2027 

2028 def __init__( 

2029 self, 

2030 registry: RegistryType, 

2031 cls: Any, 

2032 key: str, 

2033 raw_type: _MatchedOnType, 

2034 resolved_type: _MatchedOnType, 

2035 raw_pep_593_type: Optional[GenericProtocol[Any]], 

2036 pep_593_resolved_argument: Optional[_MatchedOnType], 

2037 raw_pep_695_type: Optional[TypeAliasType], 

2038 pep_695_resolved_value: Optional[_MatchedOnType], 

2039 ): 

2040 self.registry = registry 

2041 self.cls = cls 

2042 self.key = key 

2043 self.raw_type = raw_type 

2044 self.resolved_type = resolved_type 

2045 self.raw_pep_593_type = raw_pep_593_type 

2046 self.pep_593_resolved_argument = pep_593_resolved_argument 

2047 self.raw_pep_695_type = raw_pep_695_type 

2048 self.pep_695_resolved_value = pep_695_resolved_value 

2049 

2050 def resolve( 

2051 self, python_type: _MatchedOnType 

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

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

2054 the :class:`registry`. 

2055 

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

2057 type object that's present in 

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

2059 non-``None`` result. 

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

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

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

2063 matched. 

2064 

2065 """ 

2066 return self.registry._resolve_type(python_type) 

2067 

2068 

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

2070 """ 

2071 Class decorator which will adapt a given class into a 

2072 :func:`_orm.declarative_base`. 

2073 

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

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

2076 and then invoking the decorator. 

2077 

2078 E.g.:: 

2079 

2080 from sqlalchemy.orm import as_declarative 

2081 

2082 

2083 @as_declarative() 

2084 class Base: 

2085 @declared_attr 

2086 def __tablename__(cls): 

2087 return cls.__name__.lower() 

2088 

2089 id = Column(Integer, primary_key=True) 

2090 

2091 

2092 class MyMappedClass(Base): ... 

2093 

2094 .. seealso:: 

2095 

2096 :meth:`_orm.registry.as_declarative_base` 

2097 

2098 """ 

2099 metadata, class_registry = ( 

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

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

2102 ) 

2103 

2104 return registry( 

2105 metadata=metadata, class_registry=class_registry 

2106 ).as_declarative_base(**kw) 

2107 

2108 

2109@compat_typing.dataclass_transform( 

2110 field_specifiers=( 

2111 MappedColumn, 

2112 RelationshipProperty, 

2113 Composite, 

2114 Synonym, 

2115 mapped_column, 

2116 relationship, 

2117 composite, 

2118 synonym, 

2119 deferred, 

2120 ), 

2121) 

2122def mapped_as_dataclass( 

2123 registry: RegistryType, 

2124 /, 

2125 *, 

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

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

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

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

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

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

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

2133 dataclass_callable: Union[ 

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

2135 ] = _NoArg.NO_ARG, 

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

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

2138 which may have better compatibility with mypy. 

2139 

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

2141 decorator. 

2142 

2143 e.g.:: 

2144 

2145 from sqlalchemy.orm import Mapped 

2146 from sqlalchemy.orm import mapped_as_dataclass 

2147 from sqlalchemy.orm import mapped_column 

2148 from sqlalchemy.orm import registry 

2149 

2150 some_registry = registry() 

2151 

2152 

2153 @mapped_as_dataclass(some_registry) 

2154 class Relationships: 

2155 __tablename__ = "relationships" 

2156 

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

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

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

2160 

2161 .. versionadded:: 2.0.44 

2162 

2163 """ 

2164 

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

2166 _generate_dc_transforms( 

2167 init=init, 

2168 repr=repr, 

2169 eq=eq, 

2170 order=order, 

2171 unsafe_hash=unsafe_hash, 

2172 match_args=match_args, 

2173 kw_only=kw_only, 

2174 dataclass_callable=dataclass_callable, 

2175 cls_=cls, 

2176 ) 

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

2178 return cls 

2179 

2180 return decorate 

2181 

2182 

2183@inspection._inspects( 

2184 DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept 

2185) 

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

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

2188 if mp is None: 

2189 if _DeferredDeclarativeConfig.has_cls(cls): 

2190 _DeferredDeclarativeConfig.raise_unmapped_for_cls(cls) 

2191 return mp 

2192 

2193 

2194@compat_typing.dataclass_transform( 

2195 field_specifiers=( 

2196 MappedColumn, 

2197 RelationshipProperty, 

2198 Composite, 

2199 Synonym, 

2200 mapped_column, 

2201 relationship, 

2202 composite, 

2203 synonym, 

2204 deferred, 

2205 ), 

2206) 

2207@overload 

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

2209 

2210 

2211@overload 

2212def unmapped_dataclass( 

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

2214 /, 

2215 *, 

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

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

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

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

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

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

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

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

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

2225 

2226 

2227def unmapped_dataclass( 

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

2229 /, 

2230 *, 

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

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

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

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

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

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

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

2238 dataclass_callable: Union[ 

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

2240 ] = _NoArg.NO_ARG, 

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

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

2243 within mapped class hierarchies based on the 

2244 :func:`_orm.mapped_as_dataclass` decorator. 

2245 

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

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

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

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

2250 specific directives, but not actually mapping the class. 

2251 

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

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

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

2255 effect. 

2256 

2257 .. versionadded:: 2.1 

2258 

2259 .. seealso:: 

2260 

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

2262 

2263 """ 

2264 

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

2266 _generate_dc_transforms( 

2267 init=init, 

2268 repr=repr, 

2269 eq=eq, 

2270 order=order, 

2271 unsafe_hash=unsafe_hash, 

2272 match_args=match_args, 

2273 kw_only=kw_only, 

2274 dataclass_callable=dataclass_callable, 

2275 cls_=cls, 

2276 ) 

2277 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

2278 return cls 

2279 

2280 if __cls: 

2281 return decorate(__cls) 

2282 else: 

2283 return decorate