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

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

329 statements  

1# orm/base.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"""Constants and rudimental functions used throughout the ORM.""" 

9 

10from __future__ import annotations 

11 

12from enum import Enum 

13import operator 

14import typing 

15from typing import Any 

16from typing import Callable 

17from typing import Dict 

18from typing import Generic 

19from typing import no_type_check 

20from typing import Optional 

21from typing import overload 

22from typing import Tuple 

23from typing import Type 

24from typing import TYPE_CHECKING 

25from typing import TypeVar 

26from typing import Union 

27 

28from . import exc 

29from ._typing import insp_is_mapper 

30from .. import exc as sa_exc 

31from .. import inspection 

32from .. import util 

33from ..sql import roles 

34from ..sql.elements import SQLColumnExpression 

35from ..sql.elements import SQLCoreOperations 

36from ..util import FastIntFlag 

37from ..util.langhelpers import TypingOnly 

38from ..util.typing import Literal 

39 

40if typing.TYPE_CHECKING: 

41 from ._typing import _EntityType 

42 from ._typing import _ExternalEntityType 

43 from ._typing import _InternalEntityType 

44 from .attributes import InstrumentedAttribute 

45 from .dynamic import AppenderQuery 

46 from .instrumentation import ClassManager 

47 from .interfaces import PropComparator 

48 from .mapper import Mapper 

49 from .state import InstanceState 

50 from .util import AliasedClass 

51 from .writeonly import WriteOnlyCollection 

52 from ..sql._typing import _ColumnExpressionArgument 

53 from ..sql._typing import _InfoType 

54 from ..sql.elements import ColumnElement 

55 from ..sql.operators import OperatorType 

56 

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

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

59 

60_O = TypeVar("_O", bound=object) 

61 

62 

63class LoaderCallableStatus(Enum): 

64 PASSIVE_NO_RESULT = 0 

65 """Symbol returned by a loader callable or other attribute/history 

66 retrieval operation when a value could not be determined, based 

67 on loader callable flags. 

68 """ 

69 

70 PASSIVE_CLASS_MISMATCH = 1 

71 """Symbol indicating that an object is locally present for a given 

72 primary key identity but it is not of the requested class. The 

73 return value is therefore None and no SQL should be emitted.""" 

74 

75 ATTR_WAS_SET = 2 

76 """Symbol returned by a loader callable to indicate the 

77 retrieved value, or values, were assigned to their attributes 

78 on the target object. 

79 """ 

80 

81 ATTR_EMPTY = 3 

82 """Symbol used internally to indicate an attribute had no callable.""" 

83 

84 NO_VALUE = 4 

85 """Symbol which may be placed as the 'previous' value of an attribute, 

86 indicating no value was loaded for an attribute when it was modified, 

87 and flags indicated we were not to load it. 

88 """ 

89 

90 NEVER_SET = NO_VALUE 

91 """ 

92 Synonymous with NO_VALUE 

93 

94 .. versionchanged:: 1.4 NEVER_SET was merged with NO_VALUE 

95 

96 """ 

97 

98 DONT_SET = 5 

99 

100 

101( 

102 PASSIVE_NO_RESULT, 

103 PASSIVE_CLASS_MISMATCH, 

104 ATTR_WAS_SET, 

105 ATTR_EMPTY, 

106 NO_VALUE, 

107 DONT_SET, 

108) = tuple(LoaderCallableStatus) 

109 

110NEVER_SET = NO_VALUE 

111 

112 

113class PassiveFlag(FastIntFlag): 

114 """Bitflag interface that passes options onto loader callables""" 

115 

116 NO_CHANGE = 0 

117 """No callables or SQL should be emitted on attribute access 

118 and no state should change 

119 """ 

120 

121 CALLABLES_OK = 1 

122 """Loader callables can be fired off if a value 

123 is not present. 

124 """ 

125 

126 SQL_OK = 2 

127 """Loader callables can emit SQL at least on scalar value attributes.""" 

128 

129 RELATED_OBJECT_OK = 4 

130 """Callables can use SQL to load related objects as well 

131 as scalar value attributes. 

132 """ 

133 

134 INIT_OK = 8 

135 """Attributes should be initialized with a blank 

136 value (None or an empty collection) upon get, if no other 

137 value can be obtained. 

138 """ 

139 

140 NON_PERSISTENT_OK = 16 

141 """Callables can be emitted if the parent is not persistent.""" 

142 

143 LOAD_AGAINST_COMMITTED = 32 

144 """Callables should use committed values as primary/foreign keys during a 

145 load. 

146 """ 

147 

148 NO_AUTOFLUSH = 64 

149 """Loader callables should disable autoflush.""" 

150 

151 NO_RAISE = 128 

152 """Loader callables should not raise any assertions""" 

153 

154 DEFERRED_HISTORY_LOAD = 256 

155 """indicates special load of the previous value of an attribute""" 

156 

157 INCLUDE_PENDING_MUTATIONS = 512 

158 

159 # pre-packaged sets of flags used as inputs 

160 PASSIVE_OFF = ( 

161 RELATED_OBJECT_OK | NON_PERSISTENT_OK | INIT_OK | CALLABLES_OK | SQL_OK 

162 ) 

163 "Callables can be emitted in all cases." 

164 

165 PASSIVE_RETURN_NO_VALUE = PASSIVE_OFF ^ INIT_OK 

166 """PASSIVE_OFF ^ INIT_OK""" 

167 

168 PASSIVE_NO_INITIALIZE = PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK 

169 "PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK" 

170 

171 PASSIVE_NO_FETCH = PASSIVE_OFF ^ SQL_OK 

172 "PASSIVE_OFF ^ SQL_OK" 

173 

174 PASSIVE_NO_FETCH_RELATED = PASSIVE_OFF ^ RELATED_OBJECT_OK 

175 "PASSIVE_OFF ^ RELATED_OBJECT_OK" 

176 

177 PASSIVE_ONLY_PERSISTENT = PASSIVE_OFF ^ NON_PERSISTENT_OK 

178 "PASSIVE_OFF ^ NON_PERSISTENT_OK" 

179 

180 PASSIVE_MERGE = PASSIVE_OFF | NO_RAISE 

181 """PASSIVE_OFF | NO_RAISE 

182 

183 Symbol used specifically for session.merge() and similar cases 

184 

185 """ 

186 

187 

188( 

189 NO_CHANGE, 

190 CALLABLES_OK, 

191 SQL_OK, 

192 RELATED_OBJECT_OK, 

193 INIT_OK, 

194 NON_PERSISTENT_OK, 

195 LOAD_AGAINST_COMMITTED, 

196 NO_AUTOFLUSH, 

197 NO_RAISE, 

198 DEFERRED_HISTORY_LOAD, 

199 INCLUDE_PENDING_MUTATIONS, 

200 PASSIVE_OFF, 

201 PASSIVE_RETURN_NO_VALUE, 

202 PASSIVE_NO_INITIALIZE, 

203 PASSIVE_NO_FETCH, 

204 PASSIVE_NO_FETCH_RELATED, 

205 PASSIVE_ONLY_PERSISTENT, 

206 PASSIVE_MERGE, 

207) = PassiveFlag.__members__.values() 

208 

209DEFAULT_MANAGER_ATTR = "_sa_class_manager" 

210DEFAULT_STATE_ATTR = "_sa_instance_state" 

211 

212 

213class EventConstants(Enum): 

214 EXT_CONTINUE = 1 

215 EXT_STOP = 2 

216 EXT_SKIP = 3 

217 NO_KEY = 4 

218 """indicates an :class:`.AttributeEvent` event that did not have any 

219 key argument. 

220 

221 .. versionadded:: 2.0 

222 

223 """ 

224 

225 

226EXT_CONTINUE, EXT_STOP, EXT_SKIP, NO_KEY = tuple(EventConstants) 

227 

228 

229class RelationshipDirection(Enum): 

230 """enumeration which indicates the 'direction' of a 

231 :class:`_orm.RelationshipProperty`. 

232 

233 :class:`.RelationshipDirection` is accessible from the 

234 :attr:`_orm.Relationship.direction` attribute of 

235 :class:`_orm.RelationshipProperty`. 

236 

237 """ 

238 

239 ONETOMANY = 1 

240 """Indicates the one-to-many direction for a :func:`_orm.relationship`. 

241 

242 This symbol is typically used by the internals but may be exposed within 

243 certain API features. 

244 

245 """ 

246 

247 MANYTOONE = 2 

248 """Indicates the many-to-one direction for a :func:`_orm.relationship`. 

249 

250 This symbol is typically used by the internals but may be exposed within 

251 certain API features. 

252 

253 """ 

254 

255 MANYTOMANY = 3 

256 """Indicates the many-to-many direction for a :func:`_orm.relationship`. 

257 

258 This symbol is typically used by the internals but may be exposed within 

259 certain API features. 

260 

261 """ 

262 

263 

264ONETOMANY, MANYTOONE, MANYTOMANY = tuple(RelationshipDirection) 

265 

266 

267class InspectionAttrExtensionType(Enum): 

268 """Symbols indicating the type of extension that a 

269 :class:`.InspectionAttr` is part of.""" 

270 

271 

272class NotExtension(InspectionAttrExtensionType): 

273 NOT_EXTENSION = "not_extension" 

274 """Symbol indicating an :class:`InspectionAttr` that's 

275 not part of sqlalchemy.ext. 

276 

277 Is assigned to the :attr:`.InspectionAttr.extension_type` 

278 attribute. 

279 

280 """ 

281 

282 

283_never_set = frozenset([NEVER_SET]) 

284 

285_none_set = frozenset([None, NEVER_SET, PASSIVE_NO_RESULT]) 

286 

287_none_only_set = frozenset([None]) 

288 

289_SET_DEFERRED_EXPIRED = util.symbol("SET_DEFERRED_EXPIRED") 

290 

291_DEFER_FOR_STATE = util.symbol("DEFER_FOR_STATE") 

292 

293_RAISE_FOR_STATE = util.symbol("RAISE_FOR_STATE") 

294 

295 

296_F = TypeVar("_F", bound=Callable[..., Any]) 

297_Self = TypeVar("_Self") 

298 

299 

300def _assertions( 

301 *assertions: Any, 

302) -> Callable[[_F], _F]: 

303 @util.decorator 

304 def generate(fn: _F, self: _Self, *args: Any, **kw: Any) -> _Self: 

305 for assertion in assertions: 

306 assertion(self, fn.__name__) 

307 fn(self, *args, **kw) 

308 return self 

309 

310 return generate 

311 

312 

313if TYPE_CHECKING: 

314 

315 def manager_of_class(cls: Type[_O]) -> ClassManager[_O]: ... 

316 

317 @overload 

318 def opt_manager_of_class(cls: AliasedClass[Any]) -> None: ... 

319 

320 @overload 

321 def opt_manager_of_class( 

322 cls: _ExternalEntityType[_O], 

323 ) -> Optional[ClassManager[_O]]: ... 

324 

325 def opt_manager_of_class( 

326 cls: _ExternalEntityType[_O], 

327 ) -> Optional[ClassManager[_O]]: ... 

328 

329 def instance_state(instance: _O) -> InstanceState[_O]: ... 

330 

331 def instance_dict(instance: object) -> Dict[str, Any]: ... 

332 

333else: 

334 # these can be replaced by sqlalchemy.ext.instrumentation 

335 # if augmented class instrumentation is enabled. 

336 

337 def manager_of_class(cls): 

338 try: 

339 return cls.__dict__[DEFAULT_MANAGER_ATTR] 

340 except KeyError as ke: 

341 raise exc.UnmappedClassError( 

342 cls, f"Can't locate an instrumentation manager for class {cls}" 

343 ) from ke 

344 

345 def opt_manager_of_class(cls): 

346 return cls.__dict__.get(DEFAULT_MANAGER_ATTR) 

347 

348 instance_state = operator.attrgetter(DEFAULT_STATE_ATTR) 

349 

350 instance_dict = operator.attrgetter("__dict__") 

351 

352 

353def instance_str(instance: object) -> str: 

354 """Return a string describing an instance.""" 

355 

356 return state_str(instance_state(instance)) 

357 

358 

359def state_str(state: InstanceState[Any]) -> str: 

360 """Return a string describing an instance via its InstanceState.""" 

361 

362 if state is None: 

363 return "None" 

364 else: 

365 return "<%s at 0x%x>" % (state.class_.__name__, id(state.obj())) 

366 

367 

368def state_class_str(state: InstanceState[Any]) -> str: 

369 """Return a string describing an instance's class via its 

370 InstanceState. 

371 """ 

372 

373 if state is None: 

374 return "None" 

375 else: 

376 return "<%s>" % (state.class_.__name__,) 

377 

378 

379def attribute_str(instance: object, attribute: str) -> str: 

380 return instance_str(instance) + "." + attribute 

381 

382 

383def state_attribute_str(state: InstanceState[Any], attribute: str) -> str: 

384 return state_str(state) + "." + attribute 

385 

386 

387def object_mapper(instance: _T) -> Mapper[_T]: 

388 """Given an object, return the primary Mapper associated with the object 

389 instance. 

390 

391 Raises :class:`sqlalchemy.orm.exc.UnmappedInstanceError` 

392 if no mapping is configured. 

393 

394 This function is available via the inspection system as:: 

395 

396 inspect(instance).mapper 

397 

398 Using the inspection system will raise 

399 :class:`sqlalchemy.exc.NoInspectionAvailable` if the instance is 

400 not part of a mapping. 

401 

402 """ 

403 return object_state(instance).mapper 

404 

405 

406def object_state(instance: _T) -> InstanceState[_T]: 

407 """Given an object, return the :class:`.InstanceState` 

408 associated with the object. 

409 

410 Raises :class:`sqlalchemy.orm.exc.UnmappedInstanceError` 

411 if no mapping is configured. 

412 

413 Equivalent functionality is available via the :func:`_sa.inspect` 

414 function as:: 

415 

416 inspect(instance) 

417 

418 Using the inspection system will raise 

419 :class:`sqlalchemy.exc.NoInspectionAvailable` if the instance is 

420 not part of a mapping. 

421 

422 """ 

423 state = _inspect_mapped_object(instance) 

424 if state is None: 

425 raise exc.UnmappedInstanceError(instance) 

426 else: 

427 return state 

428 

429 

430@inspection._inspects(object) 

431def _inspect_mapped_object(instance: _T) -> Optional[InstanceState[_T]]: 

432 try: 

433 return instance_state(instance) 

434 except (exc.UnmappedClassError,) + exc.NO_STATE: 

435 return None 

436 

437 

438def _class_to_mapper( 

439 class_or_mapper: Union[Mapper[_T], Type[_T]], 

440) -> Mapper[_T]: 

441 # can't get mypy to see an overload for this 

442 insp = inspection.inspect(class_or_mapper, False) 

443 if insp is not None: 

444 return insp.mapper # type: ignore 

445 else: 

446 assert isinstance(class_or_mapper, type) 

447 raise exc.UnmappedClassError(class_or_mapper) 

448 

449 

450def _mapper_or_none( 

451 entity: Union[Type[_T], _InternalEntityType[_T]], 

452) -> Optional[Mapper[_T]]: 

453 """Return the :class:`_orm.Mapper` for the given class or None if the 

454 class is not mapped. 

455 """ 

456 

457 # can't get mypy to see an overload for this 

458 insp = inspection.inspect(entity, False) 

459 if insp is not None: 

460 return insp.mapper # type: ignore 

461 else: 

462 return None 

463 

464 

465def _is_mapped_class(entity: Any) -> bool: 

466 """Return True if the given object is a mapped class, 

467 :class:`_orm.Mapper`, or :class:`.AliasedClass`. 

468 """ 

469 

470 insp = inspection.inspect(entity, False) 

471 return ( 

472 insp is not None 

473 and not insp.is_clause_element 

474 and (insp.is_mapper or insp.is_aliased_class) 

475 ) 

476 

477 

478def _is_aliased_class(entity: Any) -> bool: 

479 insp = inspection.inspect(entity, False) 

480 return insp is not None and getattr(insp, "is_aliased_class", False) 

481 

482 

483@no_type_check 

484def _entity_descriptor(entity: _EntityType[Any], key: str) -> Any: 

485 """Return a class attribute given an entity and string name. 

486 

487 May return :class:`.InstrumentedAttribute` or user-defined 

488 attribute. 

489 

490 """ 

491 insp = inspection.inspect(entity) 

492 if insp.is_selectable: 

493 description = entity 

494 entity = insp.c 

495 elif insp.is_aliased_class: 

496 entity = insp.entity 

497 description = entity 

498 elif hasattr(insp, "mapper"): 

499 description = entity = insp.mapper.class_ 

500 else: 

501 description = entity 

502 

503 try: 

504 return getattr(entity, key) 

505 except AttributeError as err: 

506 raise sa_exc.InvalidRequestError( 

507 "Entity '%s' has no property '%s'" % (description, key) 

508 ) from err 

509 

510 

511if TYPE_CHECKING: 

512 

513 def _state_mapper(state: InstanceState[_O]) -> Mapper[_O]: ... 

514 

515else: 

516 _state_mapper = util.dottedgetter("manager.mapper") 

517 

518 

519def _inspect_mapped_class( 

520 class_: Type[_O], configure: bool = False 

521) -> Optional[Mapper[_O]]: 

522 try: 

523 class_manager = opt_manager_of_class(class_) 

524 if class_manager is None or not class_manager.is_mapped: 

525 return None 

526 mapper = class_manager.mapper 

527 except exc.NO_STATE: 

528 return None 

529 else: 

530 if configure: 

531 mapper._check_configure() 

532 return mapper 

533 

534 

535def _parse_mapper_argument(arg: Union[Mapper[_O], Type[_O]]) -> Mapper[_O]: 

536 insp = inspection.inspect(arg, raiseerr=False) 

537 if insp_is_mapper(insp): 

538 return insp 

539 

540 raise sa_exc.ArgumentError(f"Mapper or mapped class expected, got {arg!r}") 

541 

542 

543def class_mapper(class_: Type[_O], configure: bool = True) -> Mapper[_O]: 

544 """Given a class, return the primary :class:`_orm.Mapper` associated 

545 with the key. 

546 

547 Raises :exc:`.UnmappedClassError` if no mapping is configured 

548 on the given class, or :exc:`.ArgumentError` if a non-class 

549 object is passed. 

550 

551 Equivalent functionality is available via the :func:`_sa.inspect` 

552 function as:: 

553 

554 inspect(some_mapped_class) 

555 

556 Using the inspection system will raise 

557 :class:`sqlalchemy.exc.NoInspectionAvailable` if the class is not mapped. 

558 

559 """ 

560 mapper = _inspect_mapped_class(class_, configure=configure) 

561 if mapper is None: 

562 if not isinstance(class_, type): 

563 raise sa_exc.ArgumentError( 

564 "Class object expected, got '%r'." % (class_,) 

565 ) 

566 raise exc.UnmappedClassError(class_) 

567 else: 

568 return mapper 

569 

570 

571class InspectionAttr: 

572 """A base class applied to all ORM objects and attributes that are 

573 related to things that can be returned by the :func:`_sa.inspect` function. 

574 

575 The attributes defined here allow the usage of simple boolean 

576 checks to test basic facts about the object returned. 

577 

578 While the boolean checks here are basically the same as using 

579 the Python isinstance() function, the flags here can be used without 

580 the need to import all of these classes, and also such that 

581 the SQLAlchemy class system can change while leaving the flags 

582 here intact for forwards-compatibility. 

583 

584 """ 

585 

586 __slots__: Tuple[str, ...] = () 

587 

588 is_selectable = False 

589 """Return True if this object is an instance of 

590 :class:`_expression.Selectable`.""" 

591 

592 is_aliased_class = False 

593 """True if this object is an instance of :class:`.AliasedClass`.""" 

594 

595 is_instance = False 

596 """True if this object is an instance of :class:`.InstanceState`.""" 

597 

598 is_mapper = False 

599 """True if this object is an instance of :class:`_orm.Mapper`.""" 

600 

601 is_bundle = False 

602 """True if this object is an instance of :class:`.Bundle`.""" 

603 

604 is_property = False 

605 """True if this object is an instance of :class:`.MapperProperty`.""" 

606 

607 is_attribute = False 

608 """True if this object is a Python :term:`descriptor`. 

609 

610 This can refer to one of many types. Usually a 

611 :class:`.QueryableAttribute` which handles attributes events on behalf 

612 of a :class:`.MapperProperty`. But can also be an extension type 

613 such as :class:`.AssociationProxy` or :class:`.hybrid_property`. 

614 The :attr:`.InspectionAttr.extension_type` will refer to a constant 

615 identifying the specific subtype. 

616 

617 .. seealso:: 

618 

619 :attr:`_orm.Mapper.all_orm_descriptors` 

620 

621 """ 

622 

623 _is_internal_proxy = False 

624 """True if this object is an internal proxy object.""" 

625 

626 is_clause_element = False 

627 """True if this object is an instance of 

628 :class:`_expression.ClauseElement`.""" 

629 

630 extension_type: InspectionAttrExtensionType = NotExtension.NOT_EXTENSION 

631 """The extension type, if any. 

632 Defaults to :attr:`.interfaces.NotExtension.NOT_EXTENSION` 

633 

634 .. seealso:: 

635 

636 :class:`.HybridExtensionType` 

637 

638 :class:`.AssociationProxyExtensionType` 

639 

640 """ 

641 

642 

643class InspectionAttrInfo(InspectionAttr): 

644 """Adds the ``.info`` attribute to :class:`.InspectionAttr`. 

645 

646 The rationale for :class:`.InspectionAttr` vs. :class:`.InspectionAttrInfo` 

647 is that the former is compatible as a mixin for classes that specify 

648 ``__slots__``; this is essentially an implementation artifact. 

649 

650 """ 

651 

652 __slots__ = () 

653 

654 @util.ro_memoized_property 

655 def info(self) -> _InfoType: 

656 """Info dictionary associated with the object, allowing user-defined 

657 data to be associated with this :class:`.InspectionAttr`. 

658 

659 The dictionary is generated when first accessed. Alternatively, 

660 it can be specified as a constructor argument to the 

661 :func:`.column_property`, :func:`_orm.relationship`, or 

662 :func:`.composite` 

663 functions. 

664 

665 .. seealso:: 

666 

667 :attr:`.QueryableAttribute.info` 

668 

669 :attr:`.SchemaItem.info` 

670 

671 """ 

672 return {} 

673 

674 

675class SQLORMOperations(SQLCoreOperations[_T_co], TypingOnly): 

676 __slots__ = () 

677 

678 if typing.TYPE_CHECKING: 

679 

680 def of_type( 

681 self, class_: _EntityType[Any] 

682 ) -> PropComparator[_T_co]: ... 

683 

684 def and_( 

685 self, *criteria: _ColumnExpressionArgument[bool] 

686 ) -> PropComparator[bool]: ... 

687 

688 def any( # noqa: A001 

689 self, 

690 criterion: Optional[_ColumnExpressionArgument[bool]] = None, 

691 **kwargs: Any, 

692 ) -> ColumnElement[bool]: ... 

693 

694 def has( 

695 self, 

696 criterion: Optional[_ColumnExpressionArgument[bool]] = None, 

697 **kwargs: Any, 

698 ) -> ColumnElement[bool]: ... 

699 

700 

701class ORMDescriptor(Generic[_T_co], TypingOnly): 

702 """Represent any Python descriptor that provides a SQL expression 

703 construct at the class level.""" 

704 

705 __slots__ = () 

706 

707 if typing.TYPE_CHECKING: 

708 

709 @overload 

710 def __get__( 

711 self, instance: Any, owner: Literal[None] 

712 ) -> ORMDescriptor[_T_co]: ... 

713 

714 @overload 

715 def __get__( 

716 self, instance: Literal[None], owner: Any 

717 ) -> SQLCoreOperations[_T_co]: ... 

718 

719 @overload 

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

721 

722 def __get__( 

723 self, instance: object, owner: Any 

724 ) -> Union[ORMDescriptor[_T_co], SQLCoreOperations[_T_co], _T_co]: ... 

725 

726 

727class _MappedAnnotationBase(Generic[_T_co], TypingOnly): 

728 """common class for Mapped and similar ORM container classes. 

729 

730 these are classes that can appear on the left side of an ORM declarative 

731 mapping, containing a mapped class or in some cases a collection 

732 surrounding a mapped class. 

733 

734 """ 

735 

736 __slots__ = () 

737 

738 

739class SQLORMExpression( 

740 SQLORMOperations[_T_co], SQLColumnExpression[_T_co], TypingOnly 

741): 

742 """A type that may be used to indicate any ORM-level attribute or 

743 object that acts in place of one, in the context of SQL expression 

744 construction. 

745 

746 :class:`.SQLORMExpression` extends from the Core 

747 :class:`.SQLColumnExpression` to add additional SQL methods that are ORM 

748 specific, such as :meth:`.PropComparator.of_type`, and is part of the bases 

749 for :class:`.InstrumentedAttribute`. It may be used in :pep:`484` typing to 

750 indicate arguments or return values that should behave as ORM-level 

751 attribute expressions. 

752 

753 .. versionadded:: 2.0.0b4 

754 

755 

756 """ 

757 

758 __slots__ = () 

759 

760 

761class Mapped( 

762 SQLORMExpression[_T_co], 

763 ORMDescriptor[_T_co], 

764 _MappedAnnotationBase[_T_co], 

765 roles.DDLConstraintColumnRole, 

766): 

767 """Represent an ORM mapped attribute on a mapped class. 

768 

769 This class represents the complete descriptor interface for any class 

770 attribute that will have been :term:`instrumented` by the ORM 

771 :class:`_orm.Mapper` class. Provides appropriate information to type 

772 checkers such as pylance and mypy so that ORM-mapped attributes 

773 are correctly typed. 

774 

775 The most prominent use of :class:`_orm.Mapped` is in 

776 the :ref:`Declarative Mapping <orm_explicit_declarative_base>` form 

777 of :class:`_orm.Mapper` configuration, where used explicitly it drives 

778 the configuration of ORM attributes such as :func:`_orm.mapped_class` 

779 and :func:`_orm.relationship`. 

780 

781 .. seealso:: 

782 

783 :ref:`orm_explicit_declarative_base` 

784 

785 :ref:`orm_declarative_table` 

786 

787 .. tip:: 

788 

789 The :class:`_orm.Mapped` class represents attributes that are handled 

790 directly by the :class:`_orm.Mapper` class. It does not include other 

791 Python descriptor classes that are provided as extensions, including 

792 :ref:`hybrids_toplevel` and the :ref:`associationproxy_toplevel`. 

793 While these systems still make use of ORM-specific superclasses 

794 and structures, they are not :term:`instrumented` by the 

795 :class:`_orm.Mapper` and instead provide their own functionality 

796 when they are accessed on a class. 

797 

798 .. versionadded:: 1.4 

799 

800 

801 """ 

802 

803 __slots__ = () 

804 

805 if typing.TYPE_CHECKING: 

806 

807 @overload 

808 def __get__( 

809 self, instance: None, owner: Any 

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

811 

812 @overload 

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

814 

815 def __get__( 

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

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

818 

819 @classmethod 

820 def _empty_constructor(cls, arg1: Any) -> Mapped[_T_co]: ... 

821 

822 def __set__( 

823 self, instance: Any, value: Union[SQLCoreOperations[_T_co], _T_co] 

824 ) -> None: ... 

825 

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

827 

828 

829class _MappedAttribute(Generic[_T_co], TypingOnly): 

830 """Mixin for attributes which should be replaced by mapper-assigned 

831 attributes. 

832 

833 """ 

834 

835 __slots__ = () 

836 

837 

838class _DeclarativeMapped(Mapped[_T_co], _MappedAttribute[_T_co]): 

839 """Mixin for :class:`.MapperProperty` subclasses that allows them to 

840 be compatible with ORM-annotated declarative mappings. 

841 

842 """ 

843 

844 __slots__ = () 

845 

846 # MappedSQLExpression, Relationship, Composite etc. dont actually do 

847 # SQL expression behavior. yet there is code that compares them with 

848 # __eq__(), __ne__(), etc. Since #8847 made Mapped even more full 

849 # featured including ColumnOperators, we need to have those methods 

850 # be no-ops for these objects, so return NotImplemented to fall back 

851 # to normal comparison behavior. 

852 def operate(self, op: OperatorType, *other: Any, **kwargs: Any) -> Any: 

853 return NotImplemented 

854 

855 __sa_operate__ = operate 

856 

857 def reverse_operate( 

858 self, op: OperatorType, other: Any, **kwargs: Any 

859 ) -> Any: 

860 return NotImplemented 

861 

862 

863class DynamicMapped(_MappedAnnotationBase[_T_co]): 

864 """Represent the ORM mapped attribute type for a "dynamic" relationship. 

865 

866 The :class:`_orm.DynamicMapped` type annotation may be used in an 

867 :ref:`Annotated Declarative Table <orm_declarative_mapped_column>` mapping 

868 to indicate that the ``lazy="dynamic"`` loader strategy should be used 

869 for a particular :func:`_orm.relationship`. 

870 

871 .. legacy:: The "dynamic" lazy loader strategy is the legacy form of what 

872 is now the "write_only" strategy described in the section 

873 :ref:`write_only_relationship`. 

874 

875 E.g.:: 

876 

877 class User(Base): 

878 __tablename__ = "user" 

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

880 addresses: DynamicMapped[Address] = relationship( 

881 cascade="all,delete-orphan" 

882 ) 

883 

884 See the section :ref:`dynamic_relationship` for background. 

885 

886 .. versionadded:: 2.0 

887 

888 .. seealso:: 

889 

890 :ref:`dynamic_relationship` - complete background 

891 

892 :class:`.WriteOnlyMapped` - fully 2.0 style version 

893 

894 """ 

895 

896 __slots__ = () 

897 

898 if TYPE_CHECKING: 

899 

900 @overload 

901 def __get__( 

902 self, instance: None, owner: Any 

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

904 

905 @overload 

906 def __get__( 

907 self, instance: object, owner: Any 

908 ) -> AppenderQuery[_T_co]: ... 

909 

910 def __get__( 

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

912 ) -> Union[InstrumentedAttribute[_T_co], AppenderQuery[_T_co]]: ... 

913 

914 def __set__( 

915 self, instance: Any, value: typing.Collection[_T_co] 

916 ) -> None: ... 

917 

918 

919class WriteOnlyMapped(_MappedAnnotationBase[_T_co]): 

920 """Represent the ORM mapped attribute type for a "write only" relationship. 

921 

922 The :class:`_orm.WriteOnlyMapped` type annotation may be used in an 

923 :ref:`Annotated Declarative Table <orm_declarative_mapped_column>` mapping 

924 to indicate that the ``lazy="write_only"`` loader strategy should be used 

925 for a particular :func:`_orm.relationship`. 

926 

927 E.g.:: 

928 

929 class User(Base): 

930 __tablename__ = "user" 

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

932 addresses: WriteOnlyMapped[Address] = relationship( 

933 cascade="all,delete-orphan" 

934 ) 

935 

936 See the section :ref:`write_only_relationship` for background. 

937 

938 .. versionadded:: 2.0 

939 

940 .. seealso:: 

941 

942 :ref:`write_only_relationship` - complete background 

943 

944 :class:`.DynamicMapped` - includes legacy :class:`_orm.Query` support 

945 

946 """ 

947 

948 __slots__ = () 

949 

950 if TYPE_CHECKING: 

951 

952 @overload 

953 def __get__( 

954 self, instance: None, owner: Any 

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

956 

957 @overload 

958 def __get__( 

959 self, instance: object, owner: Any 

960 ) -> WriteOnlyCollection[_T_co]: ... 

961 

962 def __get__( 

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

964 ) -> Union[ 

965 InstrumentedAttribute[_T_co], WriteOnlyCollection[_T_co] 

966 ]: ... 

967 

968 def __set__( 

969 self, instance: Any, value: typing.Collection[_T_co] 

970 ) -> None: ...