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

505 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 

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

101 

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

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

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

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

106 

107_DeclaredAttrDecorated = Callable[ 

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

109] 

110 

111 

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

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

114 mapped table, otherwise return False. 

115 

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

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

118 hierarchy. 

119 

120 .. seealso:: 

121 

122 :ref:`decl_mixin_inheritance` 

123 

124 """ 

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

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

127 return True 

128 return False 

129 

130 

131class _DynamicAttributesType(type): 

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

133 if "__mapper__" in cls.__dict__: 

134 _add_attribute(cls, key, value) 

135 else: 

136 type.__setattr__(cls, key, value) 

137 

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

139 if "__mapper__" in cls.__dict__: 

140 _del_attribute(cls, key) 

141 else: 

142 type.__delattr__(cls, key) 

143 

144 

145class DeclarativeAttributeIntercept( 

146 _DynamicAttributesType, 

147 # Inspectable is used only by the mypy plugin 

148 inspection.Inspectable[Mapper[Any]], 

149): 

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

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

152 attributes dynamically. 

153 

154 """ 

155 

156 

157@compat_typing.dataclass_transform( 

158 field_specifiers=( 

159 MappedColumn, 

160 RelationshipProperty, 

161 Composite, 

162 Synonym, 

163 mapped_column, 

164 relationship, 

165 composite, 

166 synonym, 

167 deferred, 

168 ), 

169) 

170class DCTransformDeclarative(DeclarativeAttributeIntercept): 

171 """metaclass that includes @dataclass_transforms""" 

172 

173 

174class DeclarativeMeta(DeclarativeAttributeIntercept): 

175 metadata: MetaData 

176 registry: RegistryType 

177 

178 def __init__( 

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

180 ) -> None: 

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

182 # __init_subclass__() method (#7900) 

183 dict_ = cls.__dict__ 

184 

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

186 # assign privately to not conflict with subclass attributes named 

187 # "registry" 

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

189 if reg is None: 

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

191 if not isinstance(reg, registry): 

192 raise exc.InvalidRequestError( 

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

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

195 ) 

196 else: 

197 cls._sa_registry = reg 

198 

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

200 _ORMClassConfigurator._as_declarative(reg, cls, dict_) 

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

202 

203 

204def synonym_for( 

205 name: str, map_column: bool = False 

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

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

208 attribute in conjunction with a Python descriptor. 

209 

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

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

212 

213 class MyClass(Base): 

214 __tablename__ = "my_table" 

215 

216 id = Column(Integer, primary_key=True) 

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

218 

219 @synonym_for("job_status") 

220 @property 

221 def job_status(self): 

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

223 

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

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

226 feature. 

227 

228 .. seealso:: 

229 

230 :ref:`synonyms` - Overview of synonyms 

231 

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

233 

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

235 updated approach to augmenting attribute behavior more flexibly than 

236 can be achieved with synonyms. 

237 

238 """ 

239 

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

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

242 

243 return decorate 

244 

245 

246class _declared_attr_common: 

247 def __init__( 

248 self, 

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

250 cascading: bool = False, 

251 quiet: bool = False, 

252 ): 

253 # support 

254 # @declared_attr 

255 # @classmethod 

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

257 # ... 

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

259 # for situations where needed 

260 if isinstance(fn, classmethod): 

261 fn = fn.__func__ 

262 

263 self.fget = fn 

264 self._cascading = cascading 

265 self._quiet = quiet 

266 self.__doc__ = fn.__doc__ 

267 

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

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

270 

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

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

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

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

275 

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

277 # setup phase 

278 

279 cls = owner 

280 manager = attributes.opt_manager_of_class(cls) 

281 if manager is None: 

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

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

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

285 util.warn( 

286 "Unmanaged access of declarative attribute %s from " 

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

288 ) 

289 return self.fget(cls) 

290 elif manager.is_mapped: 

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

292 # scan setup, just run the function. 

293 return self.fget(cls) 

294 

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

296 # that is tracking the values of these attributes. 

297 declarative_scan = manager.declarative_scan() 

298 

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

300 assert declarative_scan is not None 

301 

302 reg = declarative_scan.declared_attr_reg 

303 

304 if self in reg: 

305 return reg[self] 

306 else: 

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

308 return obj 

309 

310 

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

312 # see mapping_api.rst for docstring 

313 

314 if typing.TYPE_CHECKING: 

315 

316 def __init__( 

317 self, 

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

319 cascading: bool = False, 

320 ): ... 

321 

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

323 

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

325 

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

327 

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

329 # extensive fooling of mypy underway... 

330 ... 

331 

332 

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

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

335 a mapped property or Declarative directive. 

336 

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

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

339 invoked from the uninstantiated class. The Declarative mapping process 

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

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

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

343 table configuration. 

344 

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

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

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

348 define dynamically generated column expressions and other Declarative 

349 attributes. 

350 

351 Example:: 

352 

353 class ProvidesUserMixin: 

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

355 

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

357 

358 @declared_attr 

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

360 return relationship("User") 

361 

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

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

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

365 :class:`_orm.Mapped` attributes:: 

366 

367 class CreateTableName: 

368 @declared_attr.directive 

369 def __tablename__(cls) -> str: 

370 return cls.__name__.lower() 

371 

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

373 classes, to allow for attributes that dynamically configure themselves 

374 on subclasses when using mapped inheritance schemes. Below 

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

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

377 for subclasses:: 

378 

379 class Employee(Base): 

380 __tablename__ = "employee" 

381 

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

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

384 

385 @declared_attr.directive 

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

387 if cls.__name__ == "Employee": 

388 return { 

389 "polymorphic_on": cls.type, 

390 "polymorphic_identity": "Employee", 

391 } 

392 else: 

393 return {"polymorphic_identity": cls.__name__} 

394 

395 

396 class Engineer(Employee): 

397 pass 

398 

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

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

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

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

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

404 

405 class SomethingMixin: 

406 x: Mapped[int] 

407 y: Mapped[int] 

408 

409 @declared_attr 

410 @classmethod 

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

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

413 

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

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

416 integration where needed. 

417 

418 

419 .. seealso:: 

420 

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

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

423 

424 """ # noqa: E501 

425 

426 if typing.TYPE_CHECKING: 

427 

428 def __init__( 

429 self, 

430 fn: _DeclaredAttrDecorated[_T], 

431 cascading: bool = False, 

432 ): ... 

433 

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

435 

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

437 

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

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

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

441 # declarative function that does not return InstrumentedAttribute 

442 @overload 

443 def __get__( 

444 self, instance: None, owner: Any 

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

446 

447 @overload 

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

449 

450 def __get__( 

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

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

453 

454 @hybridmethod 

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

456 return _stateful_declared_attr(**kw) 

457 

458 @hybridproperty 

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

460 # see mapping_api.rst for docstring 

461 return _declared_directive # type: ignore 

462 

463 @hybridproperty 

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

465 # see mapping_api.rst for docstring 

466 return cls._stateful(cascading=True) 

467 

468 

469class _stateful_declared_attr(declared_attr[_T]): 

470 kw: Dict[str, Any] 

471 

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

473 self.kw = kw 

474 

475 @hybridmethod 

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

477 new_kw = self.kw.copy() 

478 new_kw.update(kw) 

479 return _stateful_declared_attr(**new_kw) 

480 

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

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

483 

484 

485@util.deprecated( 

486 "2.1", 

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

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

489) 

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

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

492 

493 E.g.:: 

494 

495 from sqlalchemy.orm import declared_attr 

496 from sqlalchemy.orm import declarative_mixin 

497 

498 

499 @declarative_mixin 

500 class MyMixin: 

501 

502 @declared_attr 

503 def __tablename__(cls): 

504 return cls.__name__.lower() 

505 

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

507 __mapper_args__ = {"always_refresh": True} 

508 

509 id = Column(Integer, primary_key=True) 

510 

511 

512 class MyModel(MyMixin, Base): 

513 name = Column(String(1000)) 

514 

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

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

517 the Mypy plugin in being able to identify 

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

519 

520 .. versionadded:: 1.4.6 

521 

522 .. seealso:: 

523 

524 :ref:`orm_mixins_toplevel` 

525 

526 """ # noqa: E501 

527 

528 return cls 

529 

530 

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

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

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

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

535 

536 if reg is not None: 

537 if not isinstance(reg, registry): 

538 raise exc.InvalidRequestError( 

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

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

541 ) 

542 elif type_annotation_map is not None: 

543 raise exc.InvalidRequestError( 

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

545 "type_annotation_map entry. Per-base type_annotation_maps " 

546 "are not supported. Please apply the type_annotation_map " 

547 "to this registry directly." 

548 ) 

549 

550 else: 

551 reg = registry( 

552 metadata=metadata, type_annotation_map=type_annotation_map 

553 ) 

554 cls.registry = reg 

555 

556 cls._sa_registry = reg 

557 

558 if "metadata" not in cls.__dict__: 

559 cls.metadata = cls.registry.metadata 

560 

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

562 cls.__init__ = cls.registry.constructor 

563 

564 

565def _generate_dc_transforms( 

566 cls_: Type[_O], 

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

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

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

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

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

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

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

574 dataclass_callable: Union[ 

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

576 ] = _NoArg.NO_ARG, 

577) -> None: 

578 apply_dc_transforms: _DataclassArguments = { 

579 "init": init, 

580 "repr": repr, 

581 "eq": eq, 

582 "order": order, 

583 "unsafe_hash": unsafe_hash, 

584 "match_args": match_args, 

585 "kw_only": kw_only, 

586 "dataclass_callable": dataclass_callable, 

587 } 

588 

589 if hasattr(cls_, "_sa_apply_dc_transforms"): 

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

591 

592 _DeclarativeMapperConfig._assert_dc_arguments(current) 

593 

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

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

596 for k, v in apply_dc_transforms.items() 

597 } 

598 else: 

599 setattr(cls_, "_sa_apply_dc_transforms", apply_dc_transforms) 

600 

601 

602class MappedAsDataclass(metaclass=DCTransformDeclarative): 

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

604 a dataclass. 

605 

606 .. seealso:: 

607 

608 :ref:`orm_declarative_native_dataclasses` - complete background 

609 on SQLAlchemy native dataclass mapping with 

610 :class:`_orm.MappedAsDataclass`. 

611 

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

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

614 

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

616 decorator versions with equivalent functionality 

617 

618 .. versionadded:: 2.0 

619 

620 """ 

621 

622 def __init_subclass__( 

623 cls, 

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

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

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

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

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

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

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

631 dataclass_callable: Union[ 

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

633 ] = _NoArg.NO_ARG, 

634 **kw: Any, 

635 ) -> None: 

636 _generate_dc_transforms( 

637 init=init, 

638 repr=repr, 

639 eq=eq, 

640 order=order, 

641 unsafe_hash=unsafe_hash, 

642 match_args=match_args, 

643 kw_only=kw_only, 

644 dataclass_callable=dataclass_callable, 

645 cls_=cls, 

646 ) 

647 super().__init_subclass__(**kw) 

648 

649 if not _is_mapped_class(cls): 

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

651 # as a base or a mixin 

652 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

653 

654 

655class _DeclarativeTyping(TypingOnly): 

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

657 DeclarativeBaseNoMeta classes. 

658 """ 

659 

660 __slots__ = () 

661 

662 if typing.TYPE_CHECKING: 

663 # protocols for inspection 

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

665 

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

667 

668 # internal stuff 

669 _sa_registry: ClassVar[_RegistryType] 

670 

671 # public interface 

672 registry: ClassVar[_RegistryType] 

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

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

675 

676 metadata: ClassVar[MetaData] 

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

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

679 

680 .. seealso:: 

681 

682 :ref:`orm_declarative_metadata` 

683 

684 """ 

685 

686 __name__: ClassVar[str] 

687 

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

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

690 # ok with it. 

691 __mapper__: ClassVar[Mapper[Any]] 

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

693 mapped. 

694 

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

696 ``inspect(klass)``. 

697 

698 """ 

699 

700 __table__: ClassVar[FromClause] 

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

702 mapped. 

703 

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

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

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

707 

708 .. seealso:: 

709 

710 :ref:`orm_declarative_metadata` 

711 

712 """ 

713 

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

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

716 __tablename__: Any 

717 """String name to assign to the generated 

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

719 :attr:`_orm.DeclarativeBase.__table__`. 

720 

721 .. seealso:: 

722 

723 :ref:`orm_declarative_table` 

724 

725 """ 

726 

727 __mapper_args__: Any 

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

729 :class:`_orm.Mapper` constructor. 

730 

731 .. seealso:: 

732 

733 :ref:`orm_declarative_mapper_options` 

734 

735 """ 

736 

737 __table_args__: Any 

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

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

740 :ref:`orm_declarative_table_configuration` 

741 for background on the specific structure of this collection. 

742 

743 .. seealso:: 

744 

745 :ref:`orm_declarative_table_configuration` 

746 

747 """ 

748 

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

750 

751 

752class MappedClassWithTypedColumnsProtocol(Protocol[_TC]): 

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

754 attribute its . 

755 """ 

756 

757 __typed_cols__: _TC 

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

759 

760 __name__: ClassVar[str] 

761 __mapper__: ClassVar[Mapper[Any]] 

762 __table__: ClassVar[FromClause] 

763 

764 

765@overload 

766def as_typed_table( 

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

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

769 

770 

771@overload 

772def as_typed_table( 

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

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

775 

776 

777def as_typed_table( 

778 cls: ( 

779 MappedClassProtocol[Any] 

780 | type[MappedClassWithTypedColumnsProtocol[Any]] 

781 ), 

782 typed_columns_cls: Any = None, 

783 /, 

784) -> FromClause[Any]: 

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

786 

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

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

789 

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

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

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

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

794 

795 

796 Example usage:: 

797 

798 from sqlalchemy import TypedColumns 

799 from sqlalchemy.orm import DeclarativeBase, mapped_column 

800 from sqlalchemy.orm import MappedColumn, as_typed_table 

801 

802 

803 class Base(DeclarativeBase): 

804 pass 

805 

806 

807 class A(Base): 

808 __tablename__ = "a" 

809 

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

811 data: MappedColumn[str] 

812 

813 

814 class a_cols(A, TypedColumns): 

815 pass 

816 

817 

818 # table_a is annotated as FromClause[a_cols] 

819 table_a = as_typed_table(A, a_cols) 

820 

821 

822 class B(Base): 

823 __tablename__ = "b" 

824 __typed_cols__: "b_cols" 

825 

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

827 b: Mapped[str] 

828 

829 

830 class b_cols(B, TypedColumns): 

831 pass 

832 

833 

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

835 # provides the __typed_cols__ annotation 

836 table_b = as_typed_table(B) 

837 

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

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

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

841 

842 """ 

843 return cls.__table__ 

844 

845 

846class DeclarativeBase( 

847 # Inspectable is used only by the mypy plugin 

848 inspection.Inspectable[InstanceState[Any]], 

849 _DeclarativeTyping, 

850 metaclass=DeclarativeAttributeIntercept, 

851): 

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

853 

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

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

856 

857 

858 from sqlalchemy.orm import DeclarativeBase 

859 

860 

861 class Base(DeclarativeBase): 

862 pass 

863 

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

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

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

867 

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

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

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

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

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

873 collection as well as a specific value for 

874 :paramref:`_orm.registry.type_annotation_map`:: 

875 

876 from typing import Annotated 

877 

878 from sqlalchemy import BigInteger 

879 from sqlalchemy import MetaData 

880 from sqlalchemy import String 

881 from sqlalchemy.orm import DeclarativeBase 

882 

883 bigint = Annotated[int, "bigint"] 

884 my_metadata = MetaData() 

885 

886 

887 class Base(DeclarativeBase): 

888 metadata = my_metadata 

889 type_annotation_map = { 

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

891 bigint: BigInteger(), 

892 } 

893 

894 Class-level attributes which may be specified include: 

895 

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

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

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

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

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

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

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

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

904 :paramref:`_orm.registry.type_annotation_map`. 

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

906 

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

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

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

910 and other subclassing-oriented APIs should be seen as 

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

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

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

914 without using plugins. 

915 

916 **__init__ behavior** 

917 

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

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

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

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

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

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

924 constructor that will assign keyword arguments as attributes on the 

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

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

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

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

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

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

931 method does. 

932 

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

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

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

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

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

938 ``object.__init__()``. 

939 

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

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

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

943 

944 class Base(DeclarativeBase): 

945 def __init__(self, id=None): 

946 self.id = id 

947 

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

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

950 

951 class MyClass(Base): 

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

953 self.name = name 

954 super().__init__(id=id) 

955 

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

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

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

959 ``__init__()``. 

960 

961 

962 """ 

963 

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

965 if DeclarativeBase in cls.__bases__: 

966 _check_not_declarative(cls, DeclarativeBase) 

967 _setup_declarative_base(cls) 

968 else: 

969 _ORMClassConfigurator._as_declarative( 

970 cls._sa_registry, cls, cls.__dict__ 

971 ) 

972 super().__init_subclass__(**kw) 

973 

974 

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

976 cls_dict = cls.__dict__ 

977 if ( 

978 "__table__" in cls_dict 

979 and not ( 

980 callable(cls_dict["__table__"]) 

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

982 ) 

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

984 raise exc.InvalidRequestError( 

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

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

987 ) 

988 

989 

990class DeclarativeBaseNoMeta( 

991 # Inspectable is used only by the mypy plugin 

992 inspection.Inspectable[InstanceState[Any]], 

993 _DeclarativeTyping, 

994): 

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

996 to intercept new attributes. 

997 

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

999 custom metaclasses is desirable. 

1000 

1001 .. versionadded:: 2.0 

1002 

1003 

1004 """ 

1005 

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

1007 if DeclarativeBaseNoMeta in cls.__bases__: 

1008 _check_not_declarative(cls, DeclarativeBaseNoMeta) 

1009 _setup_declarative_base(cls) 

1010 else: 

1011 _ORMClassConfigurator._as_declarative( 

1012 cls._sa_registry, cls, cls.__dict__ 

1013 ) 

1014 super().__init_subclass__(**kw) 

1015 

1016 

1017def add_mapped_attribute( 

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

1019) -> None: 

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

1021 

1022 E.g.:: 

1023 

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

1025 

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

1027 metaclass that intercepts attribute set operations. 

1028 

1029 .. versionadded:: 2.0 

1030 

1031 

1032 """ 

1033 _add_attribute(target, key, attr) 

1034 

1035 

1036def declarative_base( 

1037 *, 

1038 metadata: Optional[MetaData] = None, 

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

1040 cls: Type[Any] = object, 

1041 name: str = "Base", 

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

1043 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1045 metaclass: Type[Any] = DeclarativeMeta, 

1046) -> Any: 

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

1048 

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

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

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

1052 information provided declaratively in the class and any subclasses 

1053 of the class. 

1054 

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

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

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

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

1059 with :pep:`484` typing tools. 

1060 

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

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

1063 method. That is, the following:: 

1064 

1065 from sqlalchemy.orm import declarative_base 

1066 

1067 Base = declarative_base() 

1068 

1069 Is equivalent to:: 

1070 

1071 from sqlalchemy.orm import registry 

1072 

1073 mapper_registry = registry() 

1074 Base = mapper_registry.generate_base() 

1075 

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

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

1078 for more details. 

1079 

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

1081 function is now a specialization of the more generic 

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

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

1084 

1085 

1086 :param metadata: 

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

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

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

1090 will be created if none is provided. The 

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

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

1093 

1094 :param mapper: 

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

1096 be used to map subclasses to their Tables. 

1097 

1098 :param cls: 

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

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

1101 

1102 :param name: 

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

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

1105 tracebacks and debugging. 

1106 

1107 :param constructor: 

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

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

1110 implementation that assigns \**kwargs for declared 

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

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

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

1114 

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

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

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

1118 and others. Allows two or more declarative base classes 

1119 to share the same registry of class names for simplified 

1120 inter-base relationships. 

1121 

1122 :param type_annotation_map: optional dictionary of Python types to 

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

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

1125 to produce column types based on annotations within the 

1126 :class:`_orm.Mapped` type. 

1127 

1128 

1129 .. versionadded:: 2.0 

1130 

1131 .. seealso:: 

1132 

1133 :ref:`orm_declarative_mapped_column_type_map` 

1134 

1135 :param metaclass: 

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

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

1138 declarative base class. 

1139 

1140 .. seealso:: 

1141 

1142 :class:`_orm.registry` 

1143 

1144 """ 

1145 

1146 return registry( 

1147 metadata=metadata, 

1148 class_registry=class_registry, 

1149 constructor=constructor, 

1150 type_annotation_map=type_annotation_map, 

1151 ).generate_base( 

1152 mapper=mapper, 

1153 cls=cls, 

1154 name=name, 

1155 metaclass=metaclass, 

1156 ) 

1157 

1158 

1159class registry(EventTarget): 

1160 """Generalized registry for mapping classes. 

1161 

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

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

1164 

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

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

1167 styles may be used interchangeably: 

1168 

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

1170 class, and is the underlying implementation of the 

1171 :func:`_orm.declarative_base` function. 

1172 

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

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

1175 base class. 

1176 

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

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

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

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

1181 which is removed as of SQLAlchemy 2.0. 

1182 

1183 .. versionadded:: 1.4 

1184 

1185 .. seealso:: 

1186 

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

1188 styles. 

1189 

1190 """ 

1191 

1192 _class_registry: clsregistry._ClsRegistryType 

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

1194 metadata: MetaData 

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

1196 type_annotation_map: _MutableTypeAnnotationMapType 

1197 _dependents: Set[_RegistryType] 

1198 _dependencies: Set[_RegistryType] 

1199 _new_mappers: bool 

1200 dispatch: dispatcher["registry"] 

1201 

1202 def __init__( 

1203 self, 

1204 *, 

1205 metadata: Optional[MetaData] = None, 

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

1207 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1209 ): 

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

1211 

1212 :param metadata: 

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

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

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

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

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

1218 

1219 :param constructor: 

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

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

1222 implementation that assigns \**kwargs for declared 

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

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

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

1226 

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

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

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

1230 and others. Allows two or more declarative base classes 

1231 to share the same registry of class names for simplified 

1232 inter-base relationships. 

1233 

1234 :param type_annotation_map: optional dictionary of Python types to 

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

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

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

1238 to produce column types based on annotations within the 

1239 :class:`_orm.Mapped` type. 

1240 

1241 .. versionadded:: 2.0 

1242 

1243 .. seealso:: 

1244 

1245 :ref:`orm_declarative_mapped_column_type_map` 

1246 

1247 

1248 """ 

1249 lcl_metadata = metadata or MetaData() 

1250 

1251 if class_registry is None: 

1252 class_registry = weakref.WeakValueDictionary() 

1253 

1254 self._class_registry = class_registry 

1255 self._managers = weakref.WeakKeyDictionary() 

1256 self.metadata = lcl_metadata 

1257 self.constructor = constructor 

1258 self.type_annotation_map = {} 

1259 if type_annotation_map is not None: 

1260 self.update_type_annotation_map(type_annotation_map) 

1261 self._dependents = set() 

1262 self._dependencies = set() 

1263 

1264 self._new_mappers = False 

1265 

1266 with mapperlib._CONFIGURE_MUTEX: 

1267 mapperlib._mapper_registries[self] = True 

1268 

1269 def update_type_annotation_map( 

1270 self, 

1271 type_annotation_map: _TypeAnnotationMapType, 

1272 ) -> None: 

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

1274 values.""" 

1275 

1276 self.type_annotation_map.update( 

1277 { 

1278 de_optionalize_union_types(typ): sqltype 

1279 for typ, sqltype in type_annotation_map.items() 

1280 } 

1281 ) 

1282 

1283 def _resolve_type_with_events( 

1284 self, 

1285 cls: Any, 

1286 key: str, 

1287 raw_annotation: _MatchedOnType, 

1288 extracted_type: _MatchedOnType, 

1289 *, 

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

1291 pep_593_resolved_argument: Optional[_MatchedOnType] = None, 

1292 raw_pep_695_type: Optional[TypeAliasType] = None, 

1293 pep_695_resolved_value: Optional[_MatchedOnType] = None, 

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

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

1296 

1297 This method fires the resolve_type_annotation event first to allow 

1298 custom resolution, then falls back to normal resolution. 

1299 

1300 """ 

1301 

1302 if self.dispatch.resolve_type_annotation: 

1303 type_resolve = TypeResolve( 

1304 self, 

1305 cls, 

1306 key, 

1307 raw_annotation, 

1308 ( 

1309 pep_593_resolved_argument 

1310 if pep_593_resolved_argument is not None 

1311 else ( 

1312 pep_695_resolved_value 

1313 if pep_695_resolved_value is not None 

1314 else extracted_type 

1315 ) 

1316 ), 

1317 raw_pep_593_type, 

1318 pep_593_resolved_argument, 

1319 raw_pep_695_type, 

1320 pep_695_resolved_value, 

1321 ) 

1322 

1323 for fn in self.dispatch.resolve_type_annotation: 

1324 result = fn(type_resolve) 

1325 if result is not None: 

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

1327 

1328 if raw_pep_695_type is not None: 

1329 sqltype = self._resolve_type(raw_pep_695_type) 

1330 if sqltype is not None: 

1331 return sqltype 

1332 

1333 sqltype = self._resolve_type(extracted_type) 

1334 if sqltype is not None: 

1335 return sqltype 

1336 

1337 if pep_593_resolved_argument is not None: 

1338 sqltype = self._resolve_type(pep_593_resolved_argument) 

1339 

1340 return sqltype 

1341 

1342 def _resolve_type( 

1343 self, python_type: _MatchedOnType 

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

1345 python_type_type: Type[Any] 

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

1347 

1348 if is_generic(python_type): 

1349 if is_literal(python_type): 

1350 python_type_type = python_type # type: ignore[assignment] 

1351 

1352 search = ( 

1353 (python_type, python_type_type), 

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

1355 ) 

1356 else: 

1357 python_type_type = python_type.__origin__ 

1358 search = ((python_type, python_type_type),) 

1359 elif isinstance(python_type, type): 

1360 python_type_type = python_type 

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

1362 else: 

1363 python_type_type = python_type # type: ignore[assignment] 

1364 search = ((python_type, python_type_type),) 

1365 

1366 for pt, flattened in search: 

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

1368 sql_type = self.type_annotation_map.get(pt) 

1369 if sql_type is None: 

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

1371 

1372 if sql_type is not None: 

1373 sql_type_inst = sqltypes.to_instance(sql_type) 

1374 

1375 # ... this additional step will reject most 

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

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

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

1379 # type_annotation_map to be useful 

1380 resolved_sql_type = sql_type_inst._resolve_for_python_type( 

1381 python_type_type, 

1382 pt, 

1383 flattened, 

1384 ) 

1385 if resolved_sql_type is not None: 

1386 return resolved_sql_type 

1387 

1388 return None 

1389 

1390 @property 

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

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

1393 

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

1395 

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

1397 if registry is self: 

1398 return 

1399 registry._dependents.add(self) 

1400 self._dependencies.add(registry) 

1401 

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

1403 mapper._ready_for_configure = True 

1404 if self._new_mappers: 

1405 return 

1406 

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

1408 reg._new_mappers = True 

1409 

1410 @classmethod 

1411 def _recurse_with_dependents( 

1412 cls, registries: Set[RegistryType] 

1413 ) -> Iterator[RegistryType]: 

1414 todo = registries 

1415 done = set() 

1416 while todo: 

1417 reg = todo.pop() 

1418 done.add(reg) 

1419 

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

1421 # them before 

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

1423 yield reg 

1424 

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

1426 # after 

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

1428 

1429 @classmethod 

1430 def _recurse_with_dependencies( 

1431 cls, registries: Set[RegistryType] 

1432 ) -> Iterator[RegistryType]: 

1433 todo = registries 

1434 done = set() 

1435 while todo: 

1436 reg = todo.pop() 

1437 done.add(reg) 

1438 

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

1440 # them before 

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

1442 

1443 yield reg 

1444 

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

1446 # them before 

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

1448 

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

1450 return ( 

1451 manager.mapper 

1452 for manager in list(self._managers) 

1453 if manager.is_mapped 

1454 and not manager.mapper.configured 

1455 and manager.mapper._ready_for_configure 

1456 ) 

1457 

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

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

1460 

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

1462 self._managers[manager] = True 

1463 if manager.is_mapped: 

1464 raise exc.ArgumentError( 

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

1466 % manager.class_ 

1467 ) 

1468 assert manager.registry is None 

1469 manager.registry = self 

1470 

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

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

1473 :class:`_orm.registry`. 

1474 

1475 The configure step is used to reconcile and initialize the 

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

1477 to invoke configuration events such as the 

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

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

1480 extensions or user-defined extension hooks. 

1481 

1482 If one or more mappers in this registry contain 

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

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

1485 registries. In order to configure those dependent registries 

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

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

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

1489 allow an application to programmatically invoke configuration of 

1490 registries while controlling whether or not the process implicitly 

1491 reaches other registries. 

1492 

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

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

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

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

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

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

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

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

1501 

1502 .. seealso:: 

1503 

1504 :func:`_orm.configure_mappers` 

1505 

1506 

1507 .. versionadded:: 1.4.0b2 

1508 

1509 """ 

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

1511 

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

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

1514 

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

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

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

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

1519 

1520 If this registry contains mappers that are dependencies of other 

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

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

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

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

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

1526 were not already disposed. 

1527 

1528 .. versionadded:: 1.4.0b2 

1529 

1530 .. seealso:: 

1531 

1532 :func:`_orm.clear_mappers` 

1533 

1534 """ 

1535 

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

1537 

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

1539 if "mapper" in manager.__dict__: 

1540 mapper = manager.mapper 

1541 

1542 mapper._set_dispose_flags() 

1543 

1544 class_ = manager.class_ 

1545 self._dispose_cls(class_) 

1546 instrumentation._instrumentation_factory.unregister(class_) 

1547 

1548 def generate_base( 

1549 self, 

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

1551 cls: Type[Any] = object, 

1552 name: str = "Base", 

1553 metaclass: Type[Any] = DeclarativeMeta, 

1554 ) -> Any: 

1555 """Generate a declarative base class. 

1556 

1557 Classes that inherit from the returned class object will be 

1558 automatically mapped using declarative mapping. 

1559 

1560 E.g.:: 

1561 

1562 from sqlalchemy.orm import registry 

1563 

1564 mapper_registry = registry() 

1565 

1566 Base = mapper_registry.generate_base() 

1567 

1568 

1569 class MyClass(Base): 

1570 __tablename__ = "my_table" 

1571 id = Column(Integer, primary_key=True) 

1572 

1573 The above dynamically generated class is equivalent to the 

1574 non-dynamic example below:: 

1575 

1576 from sqlalchemy.orm import registry 

1577 from sqlalchemy.orm.decl_api import DeclarativeMeta 

1578 

1579 mapper_registry = registry() 

1580 

1581 

1582 class Base(metaclass=DeclarativeMeta): 

1583 __abstract__ = True 

1584 registry = mapper_registry 

1585 metadata = mapper_registry.metadata 

1586 

1587 __init__ = mapper_registry.constructor 

1588 

1589 .. versionchanged:: 2.0 Note that the 

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

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

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

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

1594 tools. 

1595 

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

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

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

1599 

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

1601 examples. 

1602 

1603 :param mapper: 

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

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

1606 

1607 :param cls: 

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

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

1610 

1611 :param name: 

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

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

1614 tracebacks and debugging. 

1615 

1616 :param metaclass: 

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

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

1619 declarative base class. 

1620 

1621 .. seealso:: 

1622 

1623 :ref:`orm_declarative_mapping` 

1624 

1625 :func:`_orm.declarative_base` 

1626 

1627 """ 

1628 metadata = self.metadata 

1629 

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

1631 

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

1633 if isinstance(cls, type): 

1634 class_dict["__doc__"] = cls.__doc__ 

1635 

1636 if self.constructor is not None: 

1637 class_dict["__init__"] = self.constructor 

1638 

1639 class_dict["__abstract__"] = True 

1640 if mapper: 

1641 class_dict["__mapper_cls__"] = mapper 

1642 

1643 if hasattr(cls, "__class_getitem__"): 

1644 

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

1646 # allow generic classes in py3.9+ 

1647 return cls 

1648 

1649 class_dict["__class_getitem__"] = __class_getitem__ 

1650 

1651 return metaclass(name, bases, class_dict) 

1652 

1653 @compat_typing.dataclass_transform( 

1654 field_specifiers=( 

1655 MappedColumn, 

1656 RelationshipProperty, 

1657 Composite, 

1658 Synonym, 

1659 mapped_column, 

1660 relationship, 

1661 composite, 

1662 synonym, 

1663 deferred, 

1664 ), 

1665 ) 

1666 @overload 

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

1668 

1669 @overload 

1670 def mapped_as_dataclass( 

1671 self, 

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

1673 /, 

1674 *, 

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

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

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

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

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

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

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

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

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

1684 

1685 def mapped_as_dataclass( 

1686 self, 

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

1688 /, 

1689 *, 

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

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

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

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

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

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

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

1697 dataclass_callable: Union[ 

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

1699 ] = _NoArg.NO_ARG, 

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

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

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

1703 Python dataclass. 

1704 

1705 .. seealso:: 

1706 

1707 :ref:`orm_declarative_native_dataclasses` - complete background 

1708 on SQLAlchemy native dataclass mapping 

1709 

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

1711 provide better compatibility with mypy 

1712 

1713 .. versionadded:: 2.0 

1714 

1715 

1716 """ 

1717 

1718 decorate = mapped_as_dataclass( 

1719 self, 

1720 init=init, 

1721 repr=repr, 

1722 eq=eq, 

1723 order=order, 

1724 unsafe_hash=unsafe_hash, 

1725 match_args=match_args, 

1726 kw_only=kw_only, 

1727 dataclass_callable=dataclass_callable, 

1728 ) 

1729 

1730 if __cls: 

1731 return decorate(__cls) 

1732 else: 

1733 return decorate 

1734 

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

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

1737 to a given class. 

1738 

1739 E.g.:: 

1740 

1741 from sqlalchemy.orm import registry 

1742 

1743 mapper_registry = registry() 

1744 

1745 

1746 @mapper_registry.mapped 

1747 class Foo: 

1748 __tablename__ = "some_table" 

1749 

1750 id = Column(Integer, primary_key=True) 

1751 name = Column(String) 

1752 

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

1754 details and examples. 

1755 

1756 :param cls: class to be mapped. 

1757 

1758 :return: the class that was passed. 

1759 

1760 .. seealso:: 

1761 

1762 :ref:`orm_declarative_mapping` 

1763 

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

1765 that will apply Declarative mapping to subclasses automatically 

1766 using a Python metaclass. 

1767 

1768 .. seealso:: 

1769 

1770 :meth:`_orm.registry.mapped_as_dataclass` 

1771 

1772 """ 

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

1774 return cls 

1775 

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

1777 """ 

1778 Class decorator which will invoke 

1779 :meth:`_orm.registry.generate_base` 

1780 for a given base class. 

1781 

1782 E.g.:: 

1783 

1784 from sqlalchemy.orm import registry 

1785 

1786 mapper_registry = registry() 

1787 

1788 

1789 @mapper_registry.as_declarative_base() 

1790 class Base: 

1791 @declared_attr 

1792 def __tablename__(cls): 

1793 return cls.__name__.lower() 

1794 

1795 id = Column(Integer, primary_key=True) 

1796 

1797 

1798 class MyMappedClass(Base): ... 

1799 

1800 All keyword arguments passed to 

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

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

1803 

1804 """ 

1805 

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

1807 kw["cls"] = cls 

1808 kw["name"] = cls.__name__ 

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

1810 

1811 return decorate 

1812 

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

1814 """Map a class declaratively. 

1815 

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

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

1818 actual table object. 

1819 

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

1821 

1822 E.g.:: 

1823 

1824 from sqlalchemy.orm import registry 

1825 

1826 mapper_registry = registry() 

1827 

1828 

1829 class Foo: 

1830 __tablename__ = "some_table" 

1831 

1832 id = Column(Integer, primary_key=True) 

1833 name = Column(String) 

1834 

1835 

1836 mapper = mapper_registry.map_declaratively(Foo) 

1837 

1838 This function is more conveniently invoked indirectly via either the 

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

1840 declarative metaclass generated from 

1841 :meth:`_orm.registry.generate_base`. 

1842 

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

1844 details and examples. 

1845 

1846 :param cls: class to be mapped. 

1847 

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

1849 

1850 .. seealso:: 

1851 

1852 :ref:`orm_declarative_mapping` 

1853 

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

1855 to this function. 

1856 

1857 :meth:`_orm.registry.map_imperatively` 

1858 

1859 """ 

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

1861 return cls.__mapper__ # type: ignore 

1862 

1863 def map_imperatively( 

1864 self, 

1865 class_: Type[_O], 

1866 local_table: Optional[FromClause] = None, 

1867 **kw: Any, 

1868 ) -> Mapper[_O]: 

1869 r"""Map a class imperatively. 

1870 

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

1872 information. Instead, all mapping constructs are passed as 

1873 arguments. 

1874 

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

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

1877 a particular registry. 

1878 

1879 E.g.:: 

1880 

1881 from sqlalchemy.orm import registry 

1882 

1883 mapper_registry = registry() 

1884 

1885 my_table = Table( 

1886 "my_table", 

1887 mapper_registry.metadata, 

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

1889 ) 

1890 

1891 

1892 class MyClass: 

1893 pass 

1894 

1895 

1896 mapper_registry.map_imperatively(MyClass, my_table) 

1897 

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

1899 and usage examples. 

1900 

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

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

1903 

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

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

1906 Corresponds to the 

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

1908 

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

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

1911 

1912 .. seealso:: 

1913 

1914 :ref:`orm_imperative_mapping` 

1915 

1916 :ref:`orm_declarative_mapping` 

1917 

1918 """ 

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

1920 

1921 

1922RegistryType = registry 

1923 

1924if not TYPE_CHECKING: 

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

1926 _RegistryType = registry # noqa 

1927 

1928 

1929class TypeResolve: 

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

1931 event. 

1932 

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

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

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

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

1937 method may be used. 

1938 

1939 .. versionadded:: 2.1 

1940 

1941 """ 

1942 

1943 __slots__ = ( 

1944 "registry", 

1945 "cls", 

1946 "key", 

1947 "raw_type", 

1948 "resolved_type", 

1949 "raw_pep_593_type", 

1950 "raw_pep_695_type", 

1951 "pep_593_resolved_argument", 

1952 "pep_695_resolved_value", 

1953 ) 

1954 

1955 cls: Any 

1956 "The class being processed during declarative mapping" 

1957 

1958 registry: "registry" 

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

1960 

1961 key: str 

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

1963 

1964 raw_type: _MatchedOnType 

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

1966 

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

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

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

1970 the raw type will not be de-optionalized. 

1971 

1972 """ 

1973 

1974 resolved_type: _MatchedOnType 

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

1976 and :pep:`593` indirection: 

1977 

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

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

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

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

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

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

1984 :attr:`.TypeResolve.pep_695_resolved_value`. 

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

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

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

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

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

1990 :attr:`.TypeResolve.pep_593_resolved_argument`. 

1991 

1992 """ 

1993 

1994 raw_pep_593_type: Optional[GenericProtocol[Any]] 

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

1996 

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

1998 

1999 """ 

2000 

2001 pep_593_resolved_argument: Optional[_MatchedOnType] 

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

2003 type referred to one. 

2004 

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

2006 :attr:`.TypeResolve.resolved_type`. 

2007 

2008 """ 

2009 

2010 raw_pep_695_type: Optional[TypeAliasType] 

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

2012 

2013 pep_695_resolved_value: Optional[_MatchedOnType] 

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

2015 raw type referred to one. 

2016 

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

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

2019 

2020 """ 

2021 

2022 def __init__( 

2023 self, 

2024 registry: RegistryType, 

2025 cls: Any, 

2026 key: str, 

2027 raw_type: _MatchedOnType, 

2028 resolved_type: _MatchedOnType, 

2029 raw_pep_593_type: Optional[GenericProtocol[Any]], 

2030 pep_593_resolved_argument: Optional[_MatchedOnType], 

2031 raw_pep_695_type: Optional[TypeAliasType], 

2032 pep_695_resolved_value: Optional[_MatchedOnType], 

2033 ): 

2034 self.registry = registry 

2035 self.cls = cls 

2036 self.key = key 

2037 self.raw_type = raw_type 

2038 self.resolved_type = resolved_type 

2039 self.raw_pep_593_type = raw_pep_593_type 

2040 self.pep_593_resolved_argument = pep_593_resolved_argument 

2041 self.raw_pep_695_type = raw_pep_695_type 

2042 self.pep_695_resolved_value = pep_695_resolved_value 

2043 

2044 def resolve( 

2045 self, python_type: _MatchedOnType 

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

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

2048 the :class:`registry`. 

2049 

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

2051 type object that's present in 

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

2053 non-``None`` result. 

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

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

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

2057 matched. 

2058 

2059 """ 

2060 return self.registry._resolve_type(python_type) 

2061 

2062 

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

2064 """ 

2065 Class decorator which will adapt a given class into a 

2066 :func:`_orm.declarative_base`. 

2067 

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

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

2070 and then invoking the decorator. 

2071 

2072 E.g.:: 

2073 

2074 from sqlalchemy.orm import as_declarative 

2075 

2076 

2077 @as_declarative() 

2078 class Base: 

2079 @declared_attr 

2080 def __tablename__(cls): 

2081 return cls.__name__.lower() 

2082 

2083 id = Column(Integer, primary_key=True) 

2084 

2085 

2086 class MyMappedClass(Base): ... 

2087 

2088 .. seealso:: 

2089 

2090 :meth:`_orm.registry.as_declarative_base` 

2091 

2092 """ 

2093 metadata, class_registry = ( 

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

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

2096 ) 

2097 

2098 return registry( 

2099 metadata=metadata, class_registry=class_registry 

2100 ).as_declarative_base(**kw) 

2101 

2102 

2103@compat_typing.dataclass_transform( 

2104 field_specifiers=( 

2105 MappedColumn, 

2106 RelationshipProperty, 

2107 Composite, 

2108 Synonym, 

2109 mapped_column, 

2110 relationship, 

2111 composite, 

2112 synonym, 

2113 deferred, 

2114 ), 

2115) 

2116def mapped_as_dataclass( 

2117 registry: RegistryType, 

2118 /, 

2119 *, 

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

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

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

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

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

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

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

2127 dataclass_callable: Union[ 

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

2129 ] = _NoArg.NO_ARG, 

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

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

2132 which may have better compatibility with mypy. 

2133 

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

2135 decorator. 

2136 

2137 e.g.:: 

2138 

2139 from sqlalchemy.orm import Mapped 

2140 from sqlalchemy.orm import mapped_as_dataclass 

2141 from sqlalchemy.orm import mapped_column 

2142 from sqlalchemy.orm import registry 

2143 

2144 some_registry = registry() 

2145 

2146 

2147 @mapped_as_dataclass(some_registry) 

2148 class Relationships: 

2149 __tablename__ = "relationships" 

2150 

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

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

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

2154 

2155 .. versionadded:: 2.0.44 

2156 

2157 """ 

2158 

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

2160 _generate_dc_transforms( 

2161 init=init, 

2162 repr=repr, 

2163 eq=eq, 

2164 order=order, 

2165 unsafe_hash=unsafe_hash, 

2166 match_args=match_args, 

2167 kw_only=kw_only, 

2168 dataclass_callable=dataclass_callable, 

2169 cls_=cls, 

2170 ) 

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

2172 return cls 

2173 

2174 return decorate 

2175 

2176 

2177@inspection._inspects( 

2178 DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept 

2179) 

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

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

2182 if mp is None: 

2183 if _DeferredDeclarativeConfig.has_cls(cls): 

2184 _DeferredDeclarativeConfig.raise_unmapped_for_cls(cls) 

2185 return mp 

2186 

2187 

2188@compat_typing.dataclass_transform( 

2189 field_specifiers=( 

2190 MappedColumn, 

2191 RelationshipProperty, 

2192 Composite, 

2193 Synonym, 

2194 mapped_column, 

2195 relationship, 

2196 composite, 

2197 synonym, 

2198 deferred, 

2199 ), 

2200) 

2201@overload 

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

2203 

2204 

2205@overload 

2206def unmapped_dataclass( 

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

2208 /, 

2209 *, 

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

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

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

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

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

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

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

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

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

2219 

2220 

2221def unmapped_dataclass( 

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

2223 /, 

2224 *, 

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

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

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

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

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

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

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

2232 dataclass_callable: Union[ 

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

2234 ] = _NoArg.NO_ARG, 

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

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

2237 within mapped class hierarchies based on the 

2238 :func:`_orm.mapped_as_dataclass` decorator. 

2239 

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

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

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

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

2244 specific directives, but not actually mapping the class. 

2245 

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

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

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

2249 effect. 

2250 

2251 .. versionadded:: 2.1 

2252 

2253 .. seealso:: 

2254 

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

2256 

2257 """ 

2258 

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

2260 _generate_dc_transforms( 

2261 init=init, 

2262 repr=repr, 

2263 eq=eq, 

2264 order=order, 

2265 unsafe_hash=unsafe_hash, 

2266 match_args=match_args, 

2267 kw_only=kw_only, 

2268 dataclass_callable=dataclass_callable, 

2269 cls_=cls, 

2270 ) 

2271 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

2272 return cls 

2273 

2274 if __cls: 

2275 return decorate(__cls) 

2276 else: 

2277 return decorate