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

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

510 statements  

1# orm/decl_api.py 

2# Copyright (C) 2005-2025 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 Set 

27from typing import Tuple 

28from typing import Type 

29from typing import TYPE_CHECKING 

30from typing import TypeVar 

31from typing import Union 

32import weakref 

33 

34from . import attributes 

35from . import clsregistry 

36from . import instrumentation 

37from . import interfaces 

38from . import mapperlib 

39from ._orm_constructors import composite 

40from ._orm_constructors import deferred 

41from ._orm_constructors import mapped_column 

42from ._orm_constructors import relationship 

43from ._orm_constructors import synonym 

44from .attributes import InstrumentedAttribute 

45from .base import _inspect_mapped_class 

46from .base import _is_mapped_class 

47from .base import Mapped 

48from .base import ORMDescriptor 

49from .decl_base import _add_attribute 

50from .decl_base import _declarative_constructor 

51from .decl_base import _DeclarativeMapperConfig 

52from .decl_base import _DeferredDeclarativeConfig 

53from .decl_base import _del_attribute 

54from .decl_base import _ORMClassConfigurator 

55from .descriptor_props import Composite 

56from .descriptor_props import Synonym 

57from .descriptor_props import Synonym as _orm_synonym 

58from .mapper import Mapper 

59from .properties import MappedColumn 

60from .relationships import RelationshipProperty 

61from .state import InstanceState 

62from .. import exc 

63from .. import inspection 

64from .. import util 

65from ..event import dispatcher 

66from ..event import EventTarget 

67from ..sql import sqltypes 

68from ..sql.base import _NoArg 

69from ..sql.elements import SQLCoreOperations 

70from ..sql.schema import MetaData 

71from ..sql.selectable import FromClause 

72from ..util import hybridmethod 

73from ..util import hybridproperty 

74from ..util import typing as compat_typing 

75from ..util.typing import CallableReference 

76from ..util.typing import de_optionalize_union_types 

77from ..util.typing import GenericProtocol 

78from ..util.typing import is_generic 

79from ..util.typing import is_literal 

80from ..util.typing import LITERAL_TYPES 

81from ..util.typing import Self 

82from ..util.typing import TypeAliasType 

83 

84if TYPE_CHECKING: 

85 from ._typing import _O 

86 from ._typing import _RegistryType 

87 from .instrumentation import ClassManager 

88 from .interfaces import _DataclassArguments 

89 from .interfaces import MapperProperty 

90 from .state import InstanceState # noqa 

91 from ..sql._typing import _TypeEngineArgument 

92 from ..util.typing import _MatchedOnType 

93 

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

95 

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

97 

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

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

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

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

102 

103_DeclaredAttrDecorated = Callable[ 

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

105] 

106 

107 

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

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

110 mapped table, otherwise return False. 

111 

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

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

114 hierarchy. 

115 

116 .. seealso:: 

117 

118 :ref:`decl_mixin_inheritance` 

119 

120 """ 

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

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

123 return True 

124 return False 

125 

126 

127class _DynamicAttributesType(type): 

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

129 if "__mapper__" in cls.__dict__: 

130 _add_attribute(cls, key, value) 

131 else: 

132 type.__setattr__(cls, key, value) 

133 

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

135 if "__mapper__" in cls.__dict__: 

136 _del_attribute(cls, key) 

137 else: 

138 type.__delattr__(cls, key) 

139 

140 

141class DeclarativeAttributeIntercept( 

142 _DynamicAttributesType, 

143 # Inspectable is used only by the mypy plugin 

144 inspection.Inspectable[Mapper[Any]], 

145): 

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

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

148 attributes dynamically. 

149 

150 """ 

151 

152 

153@compat_typing.dataclass_transform( 

154 field_specifiers=( 

155 MappedColumn, 

156 RelationshipProperty, 

157 Composite, 

158 Synonym, 

159 mapped_column, 

160 relationship, 

161 composite, 

162 synonym, 

163 deferred, 

164 ), 

165) 

166class DCTransformDeclarative(DeclarativeAttributeIntercept): 

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

168 

169 

170class DeclarativeMeta(DeclarativeAttributeIntercept): 

171 metadata: MetaData 

172 registry: RegistryType 

173 

174 def __init__( 

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

176 ) -> None: 

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

178 # __init_subclass__() method (#7900) 

179 dict_ = cls.__dict__ 

180 

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

182 # assign privately to not conflict with subclass attributes named 

183 # "registry" 

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

185 if reg is None: 

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

187 if not isinstance(reg, registry): 

188 raise exc.InvalidRequestError( 

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

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

191 ) 

192 else: 

193 cls._sa_registry = reg 

194 

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

196 _ORMClassConfigurator._as_declarative(reg, cls, dict_) 

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

198 

199 

200def synonym_for( 

201 name: str, map_column: bool = False 

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

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

204 attribute in conjunction with a Python descriptor. 

205 

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

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

208 

209 class MyClass(Base): 

210 __tablename__ = "my_table" 

211 

212 id = Column(Integer, primary_key=True) 

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

214 

215 @synonym_for("job_status") 

216 @property 

217 def job_status(self): 

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

219 

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

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

222 feature. 

223 

224 .. seealso:: 

225 

226 :ref:`synonyms` - Overview of synonyms 

227 

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

229 

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

231 updated approach to augmenting attribute behavior more flexibly than 

232 can be achieved with synonyms. 

233 

234 """ 

235 

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

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

238 

239 return decorate 

240 

241 

242class _declared_attr_common: 

243 def __init__( 

244 self, 

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

246 cascading: bool = False, 

247 quiet: bool = False, 

248 ): 

249 # suppport 

250 # @declared_attr 

251 # @classmethod 

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

253 # ... 

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

255 # for situations where needed 

256 if isinstance(fn, classmethod): 

257 fn = fn.__func__ 

258 

259 self.fget = fn 

260 self._cascading = cascading 

261 self._quiet = quiet 

262 self.__doc__ = fn.__doc__ 

263 

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

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

266 

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

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

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

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

271 

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

273 # setup phase 

274 

275 cls = owner 

276 manager = attributes.opt_manager_of_class(cls) 

277 if manager is None: 

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

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

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

281 util.warn( 

282 "Unmanaged access of declarative attribute %s from " 

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

284 ) 

285 return self.fget(cls) 

286 elif manager.is_mapped: 

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

288 # scan setup, just run the function. 

289 return self.fget(cls) 

290 

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

292 # that is tracking the values of these attributes. 

293 declarative_scan = manager.declarative_scan() 

294 

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

296 assert declarative_scan is not None 

297 

298 reg = declarative_scan.declared_attr_reg 

299 

300 if self in reg: 

301 return reg[self] 

302 else: 

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

304 return obj 

305 

306 

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

308 # see mapping_api.rst for docstring 

309 

310 if typing.TYPE_CHECKING: 

311 

312 def __init__( 

313 self, 

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

315 cascading: bool = False, 

316 ): ... 

317 

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

319 

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

321 

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

323 

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

325 # extensive fooling of mypy underway... 

326 ... 

327 

328 

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

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

331 a mapped property or Declarative directive. 

332 

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

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

335 invoked from the uninstantiated class. The Declarative mapping process 

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

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

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

339 table configuration. 

340 

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

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

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

344 define dynamically generated column expressions and other Declarative 

345 attributes. 

346 

347 Example:: 

348 

349 class ProvidesUserMixin: 

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

351 

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

353 

354 @declared_attr 

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

356 return relationship("User") 

357 

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

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

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

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

362 

363 class CreateTableName: 

364 @declared_attr.directive 

365 def __tablename__(cls) -> str: 

366 return cls.__name__.lower() 

367 

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

369 classes, to allow for attributes that dynamically configure themselves 

370 on subclasses when using mapped inheritance schemes. Below 

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

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

373 for subclasses:: 

374 

375 class Employee(Base): 

376 __tablename__ = "employee" 

377 

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

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

380 

381 @declared_attr.directive 

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

383 if cls.__name__ == "Employee": 

384 return { 

385 "polymorphic_on": cls.type, 

386 "polymorphic_identity": "Employee", 

387 } 

388 else: 

389 return {"polymorphic_identity": cls.__name__} 

390 

391 

392 class Engineer(Employee): 

393 pass 

394 

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

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

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

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

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

400 

401 class SomethingMixin: 

402 x: Mapped[int] 

403 y: Mapped[int] 

404 

405 @declared_attr 

406 @classmethod 

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

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

409 

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

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

412 integration where needed. 

413 

414 

415 .. seealso:: 

416 

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

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

419 

420 """ # noqa: E501 

421 

422 if typing.TYPE_CHECKING: 

423 

424 def __init__( 

425 self, 

426 fn: _DeclaredAttrDecorated[_T], 

427 cascading: bool = False, 

428 ): ... 

429 

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

431 

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

433 

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

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

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

437 # declarative function that does not return InstrumentedAttribute 

438 @overload 

439 def __get__( 

440 self, instance: None, owner: Any 

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

442 

443 @overload 

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

445 

446 def __get__( 

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

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

449 

450 @hybridmethod 

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

452 return _stateful_declared_attr(**kw) 

453 

454 @hybridproperty 

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

456 # see mapping_api.rst for docstring 

457 return _declared_directive # type: ignore 

458 

459 @hybridproperty 

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

461 # see mapping_api.rst for docstring 

462 return cls._stateful(cascading=True) 

463 

464 

465class _stateful_declared_attr(declared_attr[_T]): 

466 kw: Dict[str, Any] 

467 

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

469 self.kw = kw 

470 

471 @hybridmethod 

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

473 new_kw = self.kw.copy() 

474 new_kw.update(kw) 

475 return _stateful_declared_attr(**new_kw) 

476 

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

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

479 

480 

481@util.deprecated( 

482 "2.1", 

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

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

485) 

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

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

488 

489 E.g.:: 

490 

491 from sqlalchemy.orm import declared_attr 

492 from sqlalchemy.orm import declarative_mixin 

493 

494 

495 @declarative_mixin 

496 class MyMixin: 

497 

498 @declared_attr 

499 def __tablename__(cls): 

500 return cls.__name__.lower() 

501 

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

503 __mapper_args__ = {"always_refresh": True} 

504 

505 id = Column(Integer, primary_key=True) 

506 

507 

508 class MyModel(MyMixin, Base): 

509 name = Column(String(1000)) 

510 

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

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

513 the Mypy plugin in being able to identify 

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

515 

516 .. versionadded:: 1.4.6 

517 

518 .. seealso:: 

519 

520 :ref:`orm_mixins_toplevel` 

521 

522 """ # noqa: E501 

523 

524 return cls 

525 

526 

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

528 if "metadata" in cls.__dict__: 

529 metadata = cls.__dict__["metadata"] 

530 else: 

531 metadata = None 

532 

533 if "type_annotation_map" in cls.__dict__: 

534 type_annotation_map = cls.__dict__["type_annotation_map"] 

535 else: 

536 type_annotation_map = None 

537 

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

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 DeclarativeBase( 

659 # Inspectable is used only by the mypy plugin 

660 inspection.Inspectable[InstanceState[Any]], 

661 metaclass=DeclarativeAttributeIntercept, 

662): 

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

664 

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

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

667 

668 

669 from sqlalchemy.orm import DeclarativeBase 

670 

671 

672 class Base(DeclarativeBase): 

673 pass 

674 

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

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

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

678 

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

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

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

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

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

684 collection as well as a specific value for 

685 :paramref:`_orm.registry.type_annotation_map`:: 

686 

687 from typing import Annotated 

688 

689 from sqlalchemy import BigInteger 

690 from sqlalchemy import MetaData 

691 from sqlalchemy import String 

692 from sqlalchemy.orm import DeclarativeBase 

693 

694 bigint = Annotated[int, "bigint"] 

695 my_metadata = MetaData() 

696 

697 

698 class Base(DeclarativeBase): 

699 metadata = my_metadata 

700 type_annotation_map = { 

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

702 bigint: BigInteger(), 

703 } 

704 

705 Class-level attributes which may be specified include: 

706 

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

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

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

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

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

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

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

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

715 :paramref:`_orm.registry.type_annotation_map`. 

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

717 

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

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

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

721 and other subclassing-oriented APIs should be seen as 

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

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

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

725 without using plugins. 

726 

727 **__init__ behavior** 

728 

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

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

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

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

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

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

735 constructor that will assign keyword arguments as attributes on the 

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

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

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

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

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

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

742 method does. 

743 

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

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

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

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

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

749 ``object.__init__()``. 

750 

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

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

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

754 

755 class Base(DeclarativeBase): 

756 def __init__(self, id=None): 

757 self.id = id 

758 

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

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

761 

762 class MyClass(Base): 

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

764 self.name = name 

765 super().__init__(id=id) 

766 

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

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

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

770 ``__init__()``. 

771 

772 

773 """ 

774 

775 if typing.TYPE_CHECKING: 

776 

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

778 

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

780 

781 _sa_registry: ClassVar[_RegistryType] 

782 

783 registry: ClassVar[_RegistryType] 

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

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

786 

787 metadata: ClassVar[MetaData] 

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

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

790 

791 .. seealso:: 

792 

793 :ref:`orm_declarative_metadata` 

794 

795 """ 

796 

797 __name__: ClassVar[str] 

798 

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

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

801 # ok with it. 

802 __mapper__: ClassVar[Mapper[Any]] 

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

804 mapped. 

805 

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

807 ``inspect(klass)``. 

808 

809 """ 

810 

811 __table__: ClassVar[FromClause] 

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

813 mapped. 

814 

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

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

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

818 

819 .. seealso:: 

820 

821 :ref:`orm_declarative_metadata` 

822 

823 """ 

824 

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

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

827 __tablename__: Any 

828 """String name to assign to the generated 

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

830 :attr:`_orm.DeclarativeBase.__table__`. 

831 

832 .. seealso:: 

833 

834 :ref:`orm_declarative_table` 

835 

836 """ 

837 

838 __mapper_args__: Any 

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

840 :class:`_orm.Mapper` constructor. 

841 

842 .. seealso:: 

843 

844 :ref:`orm_declarative_mapper_options` 

845 

846 """ 

847 

848 __table_args__: Any 

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

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

851 :ref:`orm_declarative_table_configuration` 

852 for background on the specific structure of this collection. 

853 

854 .. seealso:: 

855 

856 :ref:`orm_declarative_table_configuration` 

857 

858 """ 

859 

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

861 

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

863 if DeclarativeBase in cls.__bases__: 

864 _check_not_declarative(cls, DeclarativeBase) 

865 _setup_declarative_base(cls) 

866 else: 

867 _ORMClassConfigurator._as_declarative( 

868 cls._sa_registry, cls, cls.__dict__ 

869 ) 

870 super().__init_subclass__(**kw) 

871 

872 

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

874 cls_dict = cls.__dict__ 

875 if ( 

876 "__table__" in cls_dict 

877 and not ( 

878 callable(cls_dict["__table__"]) 

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

880 ) 

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

882 raise exc.InvalidRequestError( 

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

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

885 ) 

886 

887 

888class DeclarativeBaseNoMeta( 

889 # Inspectable is used only by the mypy plugin 

890 inspection.Inspectable[InstanceState[Any]] 

891): 

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

893 to intercept new attributes. 

894 

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

896 custom metaclasses is desirable. 

897 

898 .. versionadded:: 2.0 

899 

900 

901 """ 

902 

903 _sa_registry: ClassVar[_RegistryType] 

904 

905 registry: ClassVar[_RegistryType] 

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

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

908 

909 metadata: ClassVar[MetaData] 

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

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

912 

913 .. seealso:: 

914 

915 :ref:`orm_declarative_metadata` 

916 

917 """ 

918 

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

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

921 # ok with it. 

922 __mapper__: ClassVar[Mapper[Any]] 

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

924 mapped. 

925 

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

927 ``inspect(klass)``. 

928 

929 """ 

930 

931 __table__: Optional[FromClause] 

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

933 mapped. 

934 

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

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

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

938 

939 .. seealso:: 

940 

941 :ref:`orm_declarative_metadata` 

942 

943 """ 

944 

945 if typing.TYPE_CHECKING: 

946 

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

948 

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

950 

951 __tablename__: Any 

952 """String name to assign to the generated 

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

954 :attr:`_orm.DeclarativeBase.__table__`. 

955 

956 .. seealso:: 

957 

958 :ref:`orm_declarative_table` 

959 

960 """ 

961 

962 __mapper_args__: Any 

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

964 :class:`_orm.Mapper` constructor. 

965 

966 .. seealso:: 

967 

968 :ref:`orm_declarative_mapper_options` 

969 

970 """ 

971 

972 __table_args__: Any 

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

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

975 :ref:`orm_declarative_table_configuration` 

976 for background on the specific structure of this collection. 

977 

978 .. seealso:: 

979 

980 :ref:`orm_declarative_table_configuration` 

981 

982 """ 

983 

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

985 

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

987 if DeclarativeBaseNoMeta in cls.__bases__: 

988 _check_not_declarative(cls, DeclarativeBaseNoMeta) 

989 _setup_declarative_base(cls) 

990 else: 

991 _ORMClassConfigurator._as_declarative( 

992 cls._sa_registry, cls, cls.__dict__ 

993 ) 

994 super().__init_subclass__(**kw) 

995 

996 

997def add_mapped_attribute( 

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

999) -> None: 

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

1001 

1002 E.g.:: 

1003 

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

1005 

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

1007 metaclass that intercepts attribute set operations. 

1008 

1009 .. versionadded:: 2.0 

1010 

1011 

1012 """ 

1013 _add_attribute(target, key, attr) 

1014 

1015 

1016def declarative_base( 

1017 *, 

1018 metadata: Optional[MetaData] = None, 

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

1020 cls: Type[Any] = object, 

1021 name: str = "Base", 

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

1023 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1025 metaclass: Type[Any] = DeclarativeMeta, 

1026) -> Any: 

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

1028 

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

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

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

1032 information provided declaratively in the class and any subclasses 

1033 of the class. 

1034 

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

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

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

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

1039 with :pep:`484` typing tools. 

1040 

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

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

1043 method. That is, the following:: 

1044 

1045 from sqlalchemy.orm import declarative_base 

1046 

1047 Base = declarative_base() 

1048 

1049 Is equivalent to:: 

1050 

1051 from sqlalchemy.orm import registry 

1052 

1053 mapper_registry = registry() 

1054 Base = mapper_registry.generate_base() 

1055 

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

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

1058 for more details. 

1059 

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

1061 function is now a specialization of the more generic 

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

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

1064 

1065 

1066 :param metadata: 

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

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

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

1070 will be created if none is provided. The 

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

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

1073 

1074 :param mapper: 

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

1076 be used to map subclasses to their Tables. 

1077 

1078 :param cls: 

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

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

1081 

1082 :param name: 

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

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

1085 tracebacks and debugging. 

1086 

1087 :param constructor: 

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

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

1090 implementation that assigns \**kwargs for declared 

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

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

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

1094 

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

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

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

1098 and others. Allows two or more declarative base classes 

1099 to share the same registry of class names for simplified 

1100 inter-base relationships. 

1101 

1102 :param type_annotation_map: optional dictionary of Python types to 

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

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

1105 to produce column types based on annotations within the 

1106 :class:`_orm.Mapped` type. 

1107 

1108 

1109 .. versionadded:: 2.0 

1110 

1111 .. seealso:: 

1112 

1113 :ref:`orm_declarative_mapped_column_type_map` 

1114 

1115 :param metaclass: 

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

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

1118 declarative base class. 

1119 

1120 .. seealso:: 

1121 

1122 :class:`_orm.registry` 

1123 

1124 """ 

1125 

1126 return registry( 

1127 metadata=metadata, 

1128 class_registry=class_registry, 

1129 constructor=constructor, 

1130 type_annotation_map=type_annotation_map, 

1131 ).generate_base( 

1132 mapper=mapper, 

1133 cls=cls, 

1134 name=name, 

1135 metaclass=metaclass, 

1136 ) 

1137 

1138 

1139class registry(EventTarget): 

1140 """Generalized registry for mapping classes. 

1141 

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

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

1144 

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

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

1147 styles may be used interchangeably: 

1148 

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

1150 class, and is the underlying implementation of the 

1151 :func:`_orm.declarative_base` function. 

1152 

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

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

1155 base class. 

1156 

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

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

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

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

1161 which is removed as of SQLAlchemy 2.0. 

1162 

1163 .. versionadded:: 1.4 

1164 

1165 .. seealso:: 

1166 

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

1168 styles. 

1169 

1170 """ 

1171 

1172 _class_registry: clsregistry._ClsRegistryType 

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

1174 metadata: MetaData 

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

1176 type_annotation_map: _MutableTypeAnnotationMapType 

1177 _dependents: Set[_RegistryType] 

1178 _dependencies: Set[_RegistryType] 

1179 _new_mappers: bool 

1180 dispatch: dispatcher["registry"] 

1181 

1182 def __init__( 

1183 self, 

1184 *, 

1185 metadata: Optional[MetaData] = None, 

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

1187 type_annotation_map: Optional[_TypeAnnotationMapType] = None, 

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

1189 ): 

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

1191 

1192 :param metadata: 

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

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

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

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

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

1198 

1199 :param constructor: 

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

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

1202 implementation that assigns \**kwargs for declared 

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

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

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

1206 

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

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

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

1210 and others. Allows two or more declarative base classes 

1211 to share the same registry of class names for simplified 

1212 inter-base relationships. 

1213 

1214 :param type_annotation_map: optional dictionary of Python types to 

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

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

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

1218 to produce column types based on annotations within the 

1219 :class:`_orm.Mapped` type. 

1220 

1221 .. versionadded:: 2.0 

1222 

1223 .. seealso:: 

1224 

1225 :ref:`orm_declarative_mapped_column_type_map` 

1226 

1227 

1228 """ 

1229 lcl_metadata = metadata or MetaData() 

1230 

1231 if class_registry is None: 

1232 class_registry = weakref.WeakValueDictionary() 

1233 

1234 self._class_registry = class_registry 

1235 self._managers = weakref.WeakKeyDictionary() 

1236 self.metadata = lcl_metadata 

1237 self.constructor = constructor 

1238 self.type_annotation_map = {} 

1239 if type_annotation_map is not None: 

1240 self.update_type_annotation_map(type_annotation_map) 

1241 self._dependents = set() 

1242 self._dependencies = set() 

1243 

1244 self._new_mappers = False 

1245 

1246 with mapperlib._CONFIGURE_MUTEX: 

1247 mapperlib._mapper_registries[self] = True 

1248 

1249 def update_type_annotation_map( 

1250 self, 

1251 type_annotation_map: _TypeAnnotationMapType, 

1252 ) -> None: 

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

1254 values.""" 

1255 

1256 self.type_annotation_map.update( 

1257 { 

1258 de_optionalize_union_types(typ): sqltype 

1259 for typ, sqltype in type_annotation_map.items() 

1260 } 

1261 ) 

1262 

1263 def _resolve_type_with_events( 

1264 self, 

1265 cls: Any, 

1266 key: str, 

1267 raw_annotation: _MatchedOnType, 

1268 extracted_type: _MatchedOnType, 

1269 *, 

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

1271 pep_593_resolved_argument: Optional[_MatchedOnType] = None, 

1272 raw_pep_695_type: Optional[TypeAliasType] = None, 

1273 pep_695_resolved_value: Optional[_MatchedOnType] = None, 

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

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

1276 

1277 This method fires the resolve_type_annotation event first to allow 

1278 custom resolution, then falls back to normal resolution. 

1279 

1280 """ 

1281 

1282 if self.dispatch.resolve_type_annotation: 

1283 type_resolve = TypeResolve( 

1284 self, 

1285 cls, 

1286 key, 

1287 raw_annotation, 

1288 ( 

1289 pep_593_resolved_argument 

1290 if pep_593_resolved_argument is not None 

1291 else ( 

1292 pep_695_resolved_value 

1293 if pep_695_resolved_value is not None 

1294 else extracted_type 

1295 ) 

1296 ), 

1297 raw_pep_593_type, 

1298 pep_593_resolved_argument, 

1299 raw_pep_695_type, 

1300 pep_695_resolved_value, 

1301 ) 

1302 

1303 for fn in self.dispatch.resolve_type_annotation: 

1304 result = fn(type_resolve) 

1305 if result is not None: 

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

1307 

1308 if raw_pep_695_type is not None: 

1309 sqltype = self._resolve_type(raw_pep_695_type) 

1310 if sqltype is not None: 

1311 return sqltype 

1312 

1313 sqltype = self._resolve_type(extracted_type) 

1314 if sqltype is not None: 

1315 return sqltype 

1316 

1317 if pep_593_resolved_argument is not None: 

1318 sqltype = self._resolve_type(pep_593_resolved_argument) 

1319 

1320 return sqltype 

1321 

1322 def _resolve_type( 

1323 self, python_type: _MatchedOnType 

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

1325 python_type_type: Type[Any] 

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

1327 

1328 if is_generic(python_type): 

1329 if is_literal(python_type): 

1330 python_type_type = python_type # type: ignore[assignment] 

1331 

1332 search = ( 

1333 (python_type, python_type_type), 

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

1335 ) 

1336 else: 

1337 python_type_type = python_type.__origin__ 

1338 search = ((python_type, python_type_type),) 

1339 elif isinstance(python_type, type): 

1340 python_type_type = python_type 

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

1342 else: 

1343 python_type_type = python_type # type: ignore[assignment] 

1344 search = ((python_type, python_type_type),) 

1345 

1346 for pt, flattened in search: 

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

1348 sql_type = self.type_annotation_map.get(pt) 

1349 if sql_type is None: 

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

1351 

1352 if sql_type is not None: 

1353 sql_type_inst = sqltypes.to_instance(sql_type) 

1354 

1355 # ... this additional step will reject most 

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

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

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

1359 # type_annotation_map to be useful 

1360 resolved_sql_type = sql_type_inst._resolve_for_python_type( 

1361 python_type_type, 

1362 pt, 

1363 flattened, 

1364 ) 

1365 if resolved_sql_type is not None: 

1366 return resolved_sql_type 

1367 

1368 return None 

1369 

1370 @property 

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

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

1373 

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

1375 

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

1377 if registry is self: 

1378 return 

1379 registry._dependents.add(self) 

1380 self._dependencies.add(registry) 

1381 

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

1383 mapper._ready_for_configure = True 

1384 if self._new_mappers: 

1385 return 

1386 

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

1388 reg._new_mappers = True 

1389 

1390 @classmethod 

1391 def _recurse_with_dependents( 

1392 cls, registries: Set[RegistryType] 

1393 ) -> Iterator[RegistryType]: 

1394 todo = registries 

1395 done = set() 

1396 while todo: 

1397 reg = todo.pop() 

1398 done.add(reg) 

1399 

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

1401 # them before 

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

1403 yield reg 

1404 

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

1406 # after 

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

1408 

1409 @classmethod 

1410 def _recurse_with_dependencies( 

1411 cls, registries: Set[RegistryType] 

1412 ) -> Iterator[RegistryType]: 

1413 todo = registries 

1414 done = set() 

1415 while todo: 

1416 reg = todo.pop() 

1417 done.add(reg) 

1418 

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

1420 # them before 

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

1422 

1423 yield reg 

1424 

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

1426 # them before 

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

1428 

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

1430 return ( 

1431 manager.mapper 

1432 for manager in list(self._managers) 

1433 if manager.is_mapped 

1434 and not manager.mapper.configured 

1435 and manager.mapper._ready_for_configure 

1436 ) 

1437 

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

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

1440 

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

1442 self._managers[manager] = True 

1443 if manager.is_mapped: 

1444 raise exc.ArgumentError( 

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

1446 % manager.class_ 

1447 ) 

1448 assert manager.registry is None 

1449 manager.registry = self 

1450 

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

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

1453 :class:`_orm.registry`. 

1454 

1455 The configure step is used to reconcile and initialize the 

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

1457 to invoke configuration events such as the 

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

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

1460 extensions or user-defined extension hooks. 

1461 

1462 If one or more mappers in this registry contain 

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

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

1465 registries. In order to configure those dependent registries 

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

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

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

1469 allow an application to programmatically invoke configuration of 

1470 registries while controlling whether or not the process implicitly 

1471 reaches other registries. 

1472 

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

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

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

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

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

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

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

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

1481 

1482 .. seealso:: 

1483 

1484 :func:`_orm.configure_mappers` 

1485 

1486 

1487 .. versionadded:: 1.4.0b2 

1488 

1489 """ 

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

1491 

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

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

1494 

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

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

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

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

1499 

1500 If this registry contains mappers that are dependencies of other 

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

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

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

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

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

1506 were not already disposed. 

1507 

1508 .. versionadded:: 1.4.0b2 

1509 

1510 .. seealso:: 

1511 

1512 :func:`_orm.clear_mappers` 

1513 

1514 """ 

1515 

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

1517 

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

1519 if "mapper" in manager.__dict__: 

1520 mapper = manager.mapper 

1521 

1522 mapper._set_dispose_flags() 

1523 

1524 class_ = manager.class_ 

1525 self._dispose_cls(class_) 

1526 instrumentation._instrumentation_factory.unregister(class_) 

1527 

1528 def generate_base( 

1529 self, 

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

1531 cls: Type[Any] = object, 

1532 name: str = "Base", 

1533 metaclass: Type[Any] = DeclarativeMeta, 

1534 ) -> Any: 

1535 """Generate a declarative base class. 

1536 

1537 Classes that inherit from the returned class object will be 

1538 automatically mapped using declarative mapping. 

1539 

1540 E.g.:: 

1541 

1542 from sqlalchemy.orm import registry 

1543 

1544 mapper_registry = registry() 

1545 

1546 Base = mapper_registry.generate_base() 

1547 

1548 

1549 class MyClass(Base): 

1550 __tablename__ = "my_table" 

1551 id = Column(Integer, primary_key=True) 

1552 

1553 The above dynamically generated class is equivalent to the 

1554 non-dynamic example below:: 

1555 

1556 from sqlalchemy.orm import registry 

1557 from sqlalchemy.orm.decl_api import DeclarativeMeta 

1558 

1559 mapper_registry = registry() 

1560 

1561 

1562 class Base(metaclass=DeclarativeMeta): 

1563 __abstract__ = True 

1564 registry = mapper_registry 

1565 metadata = mapper_registry.metadata 

1566 

1567 __init__ = mapper_registry.constructor 

1568 

1569 .. versionchanged:: 2.0 Note that the 

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

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

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

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

1574 tools. 

1575 

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

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

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

1579 

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

1581 examples. 

1582 

1583 :param mapper: 

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

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

1586 

1587 :param cls: 

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

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

1590 

1591 :param name: 

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

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

1594 tracebacks and debugging. 

1595 

1596 :param metaclass: 

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

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

1599 declarative base class. 

1600 

1601 .. seealso:: 

1602 

1603 :ref:`orm_declarative_mapping` 

1604 

1605 :func:`_orm.declarative_base` 

1606 

1607 """ 

1608 metadata = self.metadata 

1609 

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

1611 

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

1613 if isinstance(cls, type): 

1614 class_dict["__doc__"] = cls.__doc__ 

1615 

1616 if self.constructor is not None: 

1617 class_dict["__init__"] = self.constructor 

1618 

1619 class_dict["__abstract__"] = True 

1620 if mapper: 

1621 class_dict["__mapper_cls__"] = mapper 

1622 

1623 if hasattr(cls, "__class_getitem__"): 

1624 

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

1626 # allow generic classes in py3.9+ 

1627 return cls 

1628 

1629 class_dict["__class_getitem__"] = __class_getitem__ 

1630 

1631 return metaclass(name, bases, class_dict) 

1632 

1633 @compat_typing.dataclass_transform( 

1634 field_specifiers=( 

1635 MappedColumn, 

1636 RelationshipProperty, 

1637 Composite, 

1638 Synonym, 

1639 mapped_column, 

1640 relationship, 

1641 composite, 

1642 synonym, 

1643 deferred, 

1644 ), 

1645 ) 

1646 @overload 

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

1648 

1649 @overload 

1650 def mapped_as_dataclass( 

1651 self, 

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

1653 /, 

1654 *, 

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

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

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

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

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

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

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

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

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

1664 

1665 def mapped_as_dataclass( 

1666 self, 

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

1668 /, 

1669 *, 

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

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

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

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

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

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

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

1677 dataclass_callable: Union[ 

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

1679 ] = _NoArg.NO_ARG, 

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

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

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

1683 Python dataclass. 

1684 

1685 .. seealso:: 

1686 

1687 :ref:`orm_declarative_native_dataclasses` - complete background 

1688 on SQLAlchemy native dataclass mapping 

1689 

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

1691 provide better compatibility with mypy 

1692 

1693 .. versionadded:: 2.0 

1694 

1695 

1696 """ 

1697 

1698 decorate = mapped_as_dataclass( 

1699 self, 

1700 init=init, 

1701 repr=repr, 

1702 eq=eq, 

1703 order=order, 

1704 unsafe_hash=unsafe_hash, 

1705 match_args=match_args, 

1706 kw_only=kw_only, 

1707 dataclass_callable=dataclass_callable, 

1708 ) 

1709 

1710 if __cls: 

1711 return decorate(__cls) 

1712 else: 

1713 return decorate 

1714 

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

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

1717 to a given class. 

1718 

1719 E.g.:: 

1720 

1721 from sqlalchemy.orm import registry 

1722 

1723 mapper_registry = registry() 

1724 

1725 

1726 @mapper_registry.mapped 

1727 class Foo: 

1728 __tablename__ = "some_table" 

1729 

1730 id = Column(Integer, primary_key=True) 

1731 name = Column(String) 

1732 

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

1734 details and examples. 

1735 

1736 :param cls: class to be mapped. 

1737 

1738 :return: the class that was passed. 

1739 

1740 .. seealso:: 

1741 

1742 :ref:`orm_declarative_mapping` 

1743 

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

1745 that will apply Declarative mapping to subclasses automatically 

1746 using a Python metaclass. 

1747 

1748 .. seealso:: 

1749 

1750 :meth:`_orm.registry.mapped_as_dataclass` 

1751 

1752 """ 

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

1754 return cls 

1755 

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

1757 """ 

1758 Class decorator which will invoke 

1759 :meth:`_orm.registry.generate_base` 

1760 for a given base class. 

1761 

1762 E.g.:: 

1763 

1764 from sqlalchemy.orm import registry 

1765 

1766 mapper_registry = registry() 

1767 

1768 

1769 @mapper_registry.as_declarative_base() 

1770 class Base: 

1771 @declared_attr 

1772 def __tablename__(cls): 

1773 return cls.__name__.lower() 

1774 

1775 id = Column(Integer, primary_key=True) 

1776 

1777 

1778 class MyMappedClass(Base): ... 

1779 

1780 All keyword arguments passed to 

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

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

1783 

1784 """ 

1785 

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

1787 kw["cls"] = cls 

1788 kw["name"] = cls.__name__ 

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

1790 

1791 return decorate 

1792 

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

1794 """Map a class declaratively. 

1795 

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

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

1798 actual table object. 

1799 

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

1801 

1802 E.g.:: 

1803 

1804 from sqlalchemy.orm import registry 

1805 

1806 mapper_registry = registry() 

1807 

1808 

1809 class Foo: 

1810 __tablename__ = "some_table" 

1811 

1812 id = Column(Integer, primary_key=True) 

1813 name = Column(String) 

1814 

1815 

1816 mapper = mapper_registry.map_declaratively(Foo) 

1817 

1818 This function is more conveniently invoked indirectly via either the 

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

1820 declarative metaclass generated from 

1821 :meth:`_orm.registry.generate_base`. 

1822 

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

1824 details and examples. 

1825 

1826 :param cls: class to be mapped. 

1827 

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

1829 

1830 .. seealso:: 

1831 

1832 :ref:`orm_declarative_mapping` 

1833 

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

1835 to this function. 

1836 

1837 :meth:`_orm.registry.map_imperatively` 

1838 

1839 """ 

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

1841 return cls.__mapper__ # type: ignore 

1842 

1843 def map_imperatively( 

1844 self, 

1845 class_: Type[_O], 

1846 local_table: Optional[FromClause] = None, 

1847 **kw: Any, 

1848 ) -> Mapper[_O]: 

1849 r"""Map a class imperatively. 

1850 

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

1852 information. Instead, all mapping constructs are passed as 

1853 arguments. 

1854 

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

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

1857 a particular registry. 

1858 

1859 E.g.:: 

1860 

1861 from sqlalchemy.orm import registry 

1862 

1863 mapper_registry = registry() 

1864 

1865 my_table = Table( 

1866 "my_table", 

1867 mapper_registry.metadata, 

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

1869 ) 

1870 

1871 

1872 class MyClass: 

1873 pass 

1874 

1875 

1876 mapper_registry.map_imperatively(MyClass, my_table) 

1877 

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

1879 and usage examples. 

1880 

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

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

1883 

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

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

1886 Corresponds to the 

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

1888 

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

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

1891 

1892 .. seealso:: 

1893 

1894 :ref:`orm_imperative_mapping` 

1895 

1896 :ref:`orm_declarative_mapping` 

1897 

1898 """ 

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

1900 

1901 

1902RegistryType = registry 

1903 

1904if not TYPE_CHECKING: 

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

1906 _RegistryType = registry # noqa 

1907 

1908 

1909class TypeResolve: 

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

1911 event. 

1912 

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

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

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

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

1917 method may be used. 

1918 

1919 .. versionadded:: 2.1 

1920 

1921 """ 

1922 

1923 __slots__ = ( 

1924 "registry", 

1925 "cls", 

1926 "key", 

1927 "raw_type", 

1928 "resolved_type", 

1929 "raw_pep_593_type", 

1930 "raw_pep_695_type", 

1931 "pep_593_resolved_argument", 

1932 "pep_695_resolved_value", 

1933 ) 

1934 

1935 cls: Any 

1936 "The class being processed during declarative mapping" 

1937 

1938 registry: "registry" 

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

1940 

1941 key: str 

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

1943 

1944 raw_type: _MatchedOnType 

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

1946 

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

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

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

1950 the raw type will not be de-optionalized. 

1951 

1952 """ 

1953 

1954 resolved_type: _MatchedOnType 

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

1956 and :pep:`593` indirection: 

1957 

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

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

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

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

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

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

1964 :attr:`.TypeResolve.pep_695_resolved_value`. 

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

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

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

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

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

1970 :attr:`.TypeResolve.pep_593_resolved_argument`. 

1971 

1972 """ 

1973 

1974 raw_pep_593_type: Optional[GenericProtocol[Any]] 

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

1976 

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

1978 

1979 """ 

1980 

1981 pep_593_resolved_argument: Optional[_MatchedOnType] 

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

1983 type referred to one. 

1984 

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

1986 :attr:`.TypeResolve.resolved_type`. 

1987 

1988 """ 

1989 

1990 raw_pep_695_type: Optional[TypeAliasType] 

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

1992 

1993 pep_695_resolved_value: Optional[_MatchedOnType] 

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

1995 raw type referred to one. 

1996 

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

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

1999 

2000 """ 

2001 

2002 def __init__( 

2003 self, 

2004 registry: RegistryType, 

2005 cls: Any, 

2006 key: str, 

2007 raw_type: _MatchedOnType, 

2008 resolved_type: _MatchedOnType, 

2009 raw_pep_593_type: Optional[GenericProtocol[Any]], 

2010 pep_593_resolved_argument: Optional[_MatchedOnType], 

2011 raw_pep_695_type: Optional[TypeAliasType], 

2012 pep_695_resolved_value: Optional[_MatchedOnType], 

2013 ): 

2014 self.registry = registry 

2015 self.cls = cls 

2016 self.key = key 

2017 self.raw_type = raw_type 

2018 self.resolved_type = resolved_type 

2019 self.raw_pep_593_type = raw_pep_593_type 

2020 self.pep_593_resolved_argument = pep_593_resolved_argument 

2021 self.raw_pep_695_type = raw_pep_695_type 

2022 self.pep_695_resolved_value = pep_695_resolved_value 

2023 

2024 def resolve( 

2025 self, python_type: _MatchedOnType 

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

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

2028 the :class:`registry`. 

2029 

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

2031 type object that's present in 

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

2033 non-``None`` result. 

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

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

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

2037 matched. 

2038 

2039 """ 

2040 return self.registry._resolve_type(python_type) 

2041 

2042 

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

2044 """ 

2045 Class decorator which will adapt a given class into a 

2046 :func:`_orm.declarative_base`. 

2047 

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

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

2050 and then invoking the decorator. 

2051 

2052 E.g.:: 

2053 

2054 from sqlalchemy.orm import as_declarative 

2055 

2056 

2057 @as_declarative() 

2058 class Base: 

2059 @declared_attr 

2060 def __tablename__(cls): 

2061 return cls.__name__.lower() 

2062 

2063 id = Column(Integer, primary_key=True) 

2064 

2065 

2066 class MyMappedClass(Base): ... 

2067 

2068 .. seealso:: 

2069 

2070 :meth:`_orm.registry.as_declarative_base` 

2071 

2072 """ 

2073 metadata, class_registry = ( 

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

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

2076 ) 

2077 

2078 return registry( 

2079 metadata=metadata, class_registry=class_registry 

2080 ).as_declarative_base(**kw) 

2081 

2082 

2083@compat_typing.dataclass_transform( 

2084 field_specifiers=( 

2085 MappedColumn, 

2086 RelationshipProperty, 

2087 Composite, 

2088 Synonym, 

2089 mapped_column, 

2090 relationship, 

2091 composite, 

2092 synonym, 

2093 deferred, 

2094 ), 

2095) 

2096def mapped_as_dataclass( 

2097 registry: RegistryType, 

2098 /, 

2099 *, 

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

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

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

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

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

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

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

2107 dataclass_callable: Union[ 

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

2109 ] = _NoArg.NO_ARG, 

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

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

2112 which may have better compatibility with mypy. 

2113 

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

2115 decorator. 

2116 

2117 e.g.:: 

2118 

2119 from sqlalchemy.orm import Mapped 

2120 from sqlalchemy.orm import mapped_as_dataclass 

2121 from sqlalchemy.orm import mapped_column 

2122 from sqlalchemy.orm import registry 

2123 

2124 some_registry = registry() 

2125 

2126 

2127 @mapped_as_dataclass(some_registry) 

2128 class Relationships: 

2129 __tablename__ = "relationships" 

2130 

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

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

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

2134 

2135 .. versionadded:: 2.0.44 

2136 

2137 """ 

2138 

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

2140 _generate_dc_transforms( 

2141 init=init, 

2142 repr=repr, 

2143 eq=eq, 

2144 order=order, 

2145 unsafe_hash=unsafe_hash, 

2146 match_args=match_args, 

2147 kw_only=kw_only, 

2148 dataclass_callable=dataclass_callable, 

2149 cls_=cls, 

2150 ) 

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

2152 return cls 

2153 

2154 return decorate 

2155 

2156 

2157@inspection._inspects( 

2158 DeclarativeMeta, DeclarativeBase, DeclarativeAttributeIntercept 

2159) 

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

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

2162 if mp is None: 

2163 if _DeferredDeclarativeConfig.has_cls(cls): 

2164 _DeferredDeclarativeConfig.raise_unmapped_for_cls(cls) 

2165 return mp 

2166 

2167 

2168@compat_typing.dataclass_transform( 

2169 field_specifiers=( 

2170 MappedColumn, 

2171 RelationshipProperty, 

2172 Composite, 

2173 Synonym, 

2174 mapped_column, 

2175 relationship, 

2176 composite, 

2177 synonym, 

2178 deferred, 

2179 ), 

2180) 

2181@overload 

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

2183 

2184 

2185@overload 

2186def unmapped_dataclass( 

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

2188 /, 

2189 *, 

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

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

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

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

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

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

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

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

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

2199 

2200 

2201def unmapped_dataclass( 

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

2203 /, 

2204 *, 

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

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

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

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

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

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

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

2212 dataclass_callable: Union[ 

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

2214 ] = _NoArg.NO_ARG, 

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

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

2217 within mapped class hierarchies based on the 

2218 :func:`_orm.mapped_as_dataclass` decorator. 

2219 

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

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

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

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

2224 specific directives, but not actually mapping the class. 

2225 

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

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

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

2229 effect. 

2230 

2231 .. versionadded:: 2.1 

2232 

2233 .. seealso:: 

2234 

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

2236 

2237 """ 

2238 

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

2240 _generate_dc_transforms( 

2241 init=init, 

2242 repr=repr, 

2243 eq=eq, 

2244 order=order, 

2245 unsafe_hash=unsafe_hash, 

2246 match_args=match_args, 

2247 kw_only=kw_only, 

2248 dataclass_callable=dataclass_callable, 

2249 cls_=cls, 

2250 ) 

2251 _ORMClassConfigurator._as_unmapped_dataclass(cls, cls.__dict__) 

2252 return cls 

2253 

2254 if __cls: 

2255 return decorate(__cls) 

2256 else: 

2257 return decorate