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

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

328 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 

10""" 

11 

12from __future__ import annotations 

13 

14from enum import Enum 

15import operator 

16import typing 

17from typing import Any 

18from typing import Callable 

19from typing import Dict 

20from typing import Generic 

21from typing import no_type_check 

22from typing import Optional 

23from typing import overload 

24from typing import Tuple 

25from typing import Type 

26from typing import TYPE_CHECKING 

27from typing import TypeVar 

28from typing import Union 

29 

30from . import exc 

31from ._typing import insp_is_mapper 

32from .. import exc as sa_exc 

33from .. import inspection 

34from .. import util 

35from ..sql import roles 

36from ..sql.elements import SQLColumnExpression 

37from ..sql.elements import SQLCoreOperations 

38from ..util import FastIntFlag 

39from ..util.langhelpers import TypingOnly 

40from ..util.typing import Literal 

41 

42if typing.TYPE_CHECKING: 

43 from ._typing import _EntityType 

44 from ._typing import _ExternalEntityType 

45 from ._typing import _InternalEntityType 

46 from .attributes import InstrumentedAttribute 

47 from .dynamic import AppenderQuery 

48 from .instrumentation import ClassManager 

49 from .interfaces import PropComparator 

50 from .mapper import Mapper 

51 from .state import InstanceState 

52 from .util import AliasedClass 

53 from .writeonly import WriteOnlyCollection 

54 from ..sql._typing import _ColumnExpressionArgument 

55 from ..sql._typing import _InfoType 

56 from ..sql.elements import ColumnElement 

57 from ..sql.operators import OperatorType 

58 

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

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

61 

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

63 

64 

65class LoaderCallableStatus(Enum): 

66 PASSIVE_NO_RESULT = 0 

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

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

69 on loader callable flags. 

70 """ 

71 

72 PASSIVE_CLASS_MISMATCH = 1 

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

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

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

76 

77 ATTR_WAS_SET = 2 

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

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

80 on the target object. 

81 """ 

82 

83 ATTR_EMPTY = 3 

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

85 

86 NO_VALUE = 4 

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

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

89 and flags indicated we were not to load it. 

90 """ 

91 

92 NEVER_SET = NO_VALUE 

93 """ 

94 Synonymous with NO_VALUE 

95 

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

97 

98 """ 

99 

100 

101( 

102 PASSIVE_NO_RESULT, 

103 PASSIVE_CLASS_MISMATCH, 

104 ATTR_WAS_SET, 

105 ATTR_EMPTY, 

106 NO_VALUE, 

107) = tuple(LoaderCallableStatus) 

108 

109NEVER_SET = NO_VALUE 

110 

111 

112class PassiveFlag(FastIntFlag): 

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

114 

115 NO_CHANGE = 0 

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

117 and no state should change 

118 """ 

119 

120 CALLABLES_OK = 1 

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

122 is not present. 

123 """ 

124 

125 SQL_OK = 2 

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

127 

128 RELATED_OBJECT_OK = 4 

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

130 as scalar value attributes. 

131 """ 

132 

133 INIT_OK = 8 

134 """Attributes should be initialized with a blank 

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

136 value can be obtained. 

137 """ 

138 

139 NON_PERSISTENT_OK = 16 

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

141 

142 LOAD_AGAINST_COMMITTED = 32 

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

144 load. 

145 """ 

146 

147 NO_AUTOFLUSH = 64 

148 """Loader callables should disable autoflush.""" 

149 

150 NO_RAISE = 128 

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

152 

153 DEFERRED_HISTORY_LOAD = 256 

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

155 

156 INCLUDE_PENDING_MUTATIONS = 512 

157 

158 # pre-packaged sets of flags used as inputs 

159 PASSIVE_OFF = ( 

160 RELATED_OBJECT_OK | NON_PERSISTENT_OK | INIT_OK | CALLABLES_OK | SQL_OK 

161 ) 

162 "Callables can be emitted in all cases." 

163 

164 PASSIVE_RETURN_NO_VALUE = PASSIVE_OFF ^ INIT_OK 

165 """PASSIVE_OFF ^ INIT_OK""" 

166 

167 PASSIVE_NO_INITIALIZE = PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK 

168 "PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK" 

169 

170 PASSIVE_NO_FETCH = PASSIVE_OFF ^ SQL_OK 

171 "PASSIVE_OFF ^ SQL_OK" 

172 

173 PASSIVE_NO_FETCH_RELATED = PASSIVE_OFF ^ RELATED_OBJECT_OK 

174 "PASSIVE_OFF ^ RELATED_OBJECT_OK" 

175 

176 PASSIVE_ONLY_PERSISTENT = PASSIVE_OFF ^ NON_PERSISTENT_OK 

177 "PASSIVE_OFF ^ NON_PERSISTENT_OK" 

178 

179 PASSIVE_MERGE = PASSIVE_OFF | NO_RAISE 

180 """PASSIVE_OFF | NO_RAISE 

181 

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

183 

184 """ 

185 

186 

187( 

188 NO_CHANGE, 

189 CALLABLES_OK, 

190 SQL_OK, 

191 RELATED_OBJECT_OK, 

192 INIT_OK, 

193 NON_PERSISTENT_OK, 

194 LOAD_AGAINST_COMMITTED, 

195 NO_AUTOFLUSH, 

196 NO_RAISE, 

197 DEFERRED_HISTORY_LOAD, 

198 INCLUDE_PENDING_MUTATIONS, 

199 PASSIVE_OFF, 

200 PASSIVE_RETURN_NO_VALUE, 

201 PASSIVE_NO_INITIALIZE, 

202 PASSIVE_NO_FETCH, 

203 PASSIVE_NO_FETCH_RELATED, 

204 PASSIVE_ONLY_PERSISTENT, 

205 PASSIVE_MERGE, 

206) = PassiveFlag.__members__.values() 

207 

208DEFAULT_MANAGER_ATTR = "_sa_class_manager" 

209DEFAULT_STATE_ATTR = "_sa_instance_state" 

210 

211 

212class EventConstants(Enum): 

213 EXT_CONTINUE = 1 

214 EXT_STOP = 2 

215 EXT_SKIP = 3 

216 NO_KEY = 4 

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

218 key argument. 

219 

220 .. versionadded:: 2.0 

221 

222 """ 

223 

224 

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

226 

227 

228class RelationshipDirection(Enum): 

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

230 :class:`_orm.RelationshipProperty`. 

231 

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

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

234 :class:`_orm.RelationshipProperty`. 

235 

236 """ 

237 

238 ONETOMANY = 1 

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

240 

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

242 certain API features. 

243 

244 """ 

245 

246 MANYTOONE = 2 

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

248 

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

250 certain API features. 

251 

252 """ 

253 

254 MANYTOMANY = 3 

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

256 

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

258 certain API features. 

259 

260 """ 

261 

262 

263ONETOMANY, MANYTOONE, MANYTOMANY = tuple(RelationshipDirection) 

264 

265 

266class InspectionAttrExtensionType(Enum): 

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

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

269 

270 

271class NotExtension(InspectionAttrExtensionType): 

272 NOT_EXTENSION = "not_extension" 

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

274 not part of sqlalchemy.ext. 

275 

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

277 attribute. 

278 

279 """ 

280 

281 

282_never_set = frozenset([NEVER_SET]) 

283 

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

285 

286_none_only_set = frozenset([None]) 

287 

288_SET_DEFERRED_EXPIRED = util.symbol("SET_DEFERRED_EXPIRED") 

289 

290_DEFER_FOR_STATE = util.symbol("DEFER_FOR_STATE") 

291 

292_RAISE_FOR_STATE = util.symbol("RAISE_FOR_STATE") 

293 

294 

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

296_Self = TypeVar("_Self") 

297 

298 

299def _assertions( 

300 *assertions: Any, 

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

302 @util.decorator 

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

304 for assertion in assertions: 

305 assertion(self, fn.__name__) 

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

307 return self 

308 

309 return generate 

310 

311 

312if TYPE_CHECKING: 

313 

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

315 

316 @overload 

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

318 

319 @overload 

320 def opt_manager_of_class( 

321 cls: _ExternalEntityType[_O], 

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

323 

324 def opt_manager_of_class( 

325 cls: _ExternalEntityType[_O], 

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

327 

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

329 

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

331 

332else: 

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

334 # if augmented class instrumentation is enabled. 

335 

336 def manager_of_class(cls): 

337 try: 

338 return cls.__dict__[DEFAULT_MANAGER_ATTR] 

339 except KeyError as ke: 

340 raise exc.UnmappedClassError( 

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

342 ) from ke 

343 

344 def opt_manager_of_class(cls): 

345 return cls.__dict__.get(DEFAULT_MANAGER_ATTR) 

346 

347 instance_state = operator.attrgetter(DEFAULT_STATE_ATTR) 

348 

349 instance_dict = operator.attrgetter("__dict__") 

350 

351 

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

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

354 

355 return state_str(instance_state(instance)) 

356 

357 

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

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

360 

361 if state is None: 

362 return "None" 

363 else: 

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

365 

366 

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

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

369 InstanceState. 

370 """ 

371 

372 if state is None: 

373 return "None" 

374 else: 

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

376 

377 

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

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

380 

381 

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

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

384 

385 

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

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

388 instance. 

389 

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

391 if no mapping is configured. 

392 

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

394 

395 inspect(instance).mapper 

396 

397 Using the inspection system will raise 

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

399 not part of a mapping. 

400 

401 """ 

402 return object_state(instance).mapper 

403 

404 

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

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

407 associated with the object. 

408 

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

410 if no mapping is configured. 

411 

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

413 function as:: 

414 

415 inspect(instance) 

416 

417 Using the inspection system will raise 

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

419 not part of a mapping. 

420 

421 """ 

422 state = _inspect_mapped_object(instance) 

423 if state is None: 

424 raise exc.UnmappedInstanceError(instance) 

425 else: 

426 return state 

427 

428 

429@inspection._inspects(object) 

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

431 try: 

432 return instance_state(instance) 

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

434 return None 

435 

436 

437def _class_to_mapper( 

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

439) -> Mapper[_T]: 

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

441 insp = inspection.inspect(class_or_mapper, False) 

442 if insp is not None: 

443 return insp.mapper # type: ignore 

444 else: 

445 assert isinstance(class_or_mapper, type) 

446 raise exc.UnmappedClassError(class_or_mapper) 

447 

448 

449def _mapper_or_none( 

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

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

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

453 class is not mapped. 

454 """ 

455 

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

457 insp = inspection.inspect(entity, False) 

458 if insp is not None: 

459 return insp.mapper # type: ignore 

460 else: 

461 return None 

462 

463 

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

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

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

467 """ 

468 

469 insp = inspection.inspect(entity, False) 

470 return ( 

471 insp is not None 

472 and not insp.is_clause_element 

473 and (insp.is_mapper or insp.is_aliased_class) 

474 ) 

475 

476 

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

478 insp = inspection.inspect(entity, False) 

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

480 

481 

482@no_type_check 

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

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

485 

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

487 attribute. 

488 

489 """ 

490 insp = inspection.inspect(entity) 

491 if insp.is_selectable: 

492 description = entity 

493 entity = insp.c 

494 elif insp.is_aliased_class: 

495 entity = insp.entity 

496 description = entity 

497 elif hasattr(insp, "mapper"): 

498 description = entity = insp.mapper.class_ 

499 else: 

500 description = entity 

501 

502 try: 

503 return getattr(entity, key) 

504 except AttributeError as err: 

505 raise sa_exc.InvalidRequestError( 

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

507 ) from err 

508 

509 

510if TYPE_CHECKING: 

511 

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

513 

514else: 

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

516 

517 

518def _inspect_mapped_class( 

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

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

521 try: 

522 class_manager = opt_manager_of_class(class_) 

523 if class_manager is None or not class_manager.is_mapped: 

524 return None 

525 mapper = class_manager.mapper 

526 except exc.NO_STATE: 

527 return None 

528 else: 

529 if configure: 

530 mapper._check_configure() 

531 return mapper 

532 

533 

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

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

536 if insp_is_mapper(insp): 

537 return insp 

538 

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

540 

541 

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

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

544 with the key. 

545 

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

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

548 object is passed. 

549 

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

551 function as:: 

552 

553 inspect(some_mapped_class) 

554 

555 Using the inspection system will raise 

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

557 

558 """ 

559 mapper = _inspect_mapped_class(class_, configure=configure) 

560 if mapper is None: 

561 if not isinstance(class_, type): 

562 raise sa_exc.ArgumentError( 

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

564 ) 

565 raise exc.UnmappedClassError(class_) 

566 else: 

567 return mapper 

568 

569 

570class InspectionAttr: 

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

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

573 

574 The attributes defined here allow the usage of simple boolean 

575 checks to test basic facts about the object returned. 

576 

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

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

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

580 the SQLAlchemy class system can change while leaving the flags 

581 here intact for forwards-compatibility. 

582 

583 """ 

584 

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

586 

587 is_selectable = False 

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

589 :class:`_expression.Selectable`.""" 

590 

591 is_aliased_class = False 

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

593 

594 is_instance = False 

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

596 

597 is_mapper = False 

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

599 

600 is_bundle = False 

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

602 

603 is_property = False 

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

605 

606 is_attribute = False 

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

608 

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

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

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

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

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

614 identifying the specific subtype. 

615 

616 .. seealso:: 

617 

618 :attr:`_orm.Mapper.all_orm_descriptors` 

619 

620 """ 

621 

622 _is_internal_proxy = False 

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

624 

625 .. versionadded:: 1.2.12 

626 

627 """ 

628 

629 is_clause_element = False 

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

631 :class:`_expression.ClauseElement`.""" 

632 

633 extension_type: InspectionAttrExtensionType = NotExtension.NOT_EXTENSION 

634 """The extension type, if any. 

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

636 

637 .. seealso:: 

638 

639 :class:`.HybridExtensionType` 

640 

641 :class:`.AssociationProxyExtensionType` 

642 

643 """ 

644 

645 

646class InspectionAttrInfo(InspectionAttr): 

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

648 

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

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

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

652 

653 """ 

654 

655 __slots__ = () 

656 

657 @util.ro_memoized_property 

658 def info(self) -> _InfoType: 

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

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

661 

662 The dictionary is generated when first accessed. Alternatively, 

663 it can be specified as a constructor argument to the 

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

665 :func:`.composite` 

666 functions. 

667 

668 .. seealso:: 

669 

670 :attr:`.QueryableAttribute.info` 

671 

672 :attr:`.SchemaItem.info` 

673 

674 """ 

675 return {} 

676 

677 

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

679 __slots__ = () 

680 

681 if typing.TYPE_CHECKING: 

682 

683 def of_type( 

684 self, class_: _EntityType[Any] 

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

686 

687 def and_( 

688 self, *criteria: _ColumnExpressionArgument[bool] 

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

690 

691 def any( # noqa: A001 

692 self, 

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

694 **kwargs: Any, 

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

696 

697 def has( 

698 self, 

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

700 **kwargs: Any, 

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

702 

703 

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

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

706 construct at the class level.""" 

707 

708 __slots__ = () 

709 

710 if typing.TYPE_CHECKING: 

711 

712 @overload 

713 def __get__( 

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

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

716 

717 @overload 

718 def __get__( 

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

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

721 

722 @overload 

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

724 

725 def __get__( 

726 self, instance: object, owner: Any 

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

728 

729 

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

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

732 

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

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

735 surrounding a mapped class. 

736 

737 """ 

738 

739 __slots__ = () 

740 

741 

742class SQLORMExpression( 

743 SQLORMOperations[_T_co], SQLColumnExpression[_T_co], TypingOnly 

744): 

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

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

747 construction. 

748 

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

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

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

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

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

754 attribute expressions. 

755 

756 .. versionadded:: 2.0.0b4 

757 

758 

759 """ 

760 

761 __slots__ = () 

762 

763 

764class Mapped( 

765 SQLORMExpression[_T_co], 

766 ORMDescriptor[_T_co], 

767 _MappedAnnotationBase[_T_co], 

768 roles.DDLConstraintColumnRole, 

769): 

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

771 

772 This class represents the complete descriptor interface for any class 

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

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

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

776 are correctly typed. 

777 

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

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

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

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

782 and :func:`_orm.relationship`. 

783 

784 .. seealso:: 

785 

786 :ref:`orm_explicit_declarative_base` 

787 

788 :ref:`orm_declarative_table` 

789 

790 .. tip:: 

791 

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

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

794 Python descriptor classes that are provided as extensions, including 

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

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

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

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

799 when they are accessed on a class. 

800 

801 .. versionadded:: 1.4 

802 

803 

804 """ 

805 

806 __slots__ = () 

807 

808 if typing.TYPE_CHECKING: 

809 

810 @overload 

811 def __get__( 

812 self, instance: None, owner: Any 

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

814 

815 @overload 

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

817 

818 def __get__( 

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

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

821 

822 @classmethod 

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

824 

825 def __set__( 

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

827 ) -> None: ... 

828 

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

830 

831 

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

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

834 attributes. 

835 

836 """ 

837 

838 __slots__ = () 

839 

840 

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

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

843 be compatible with ORM-annotated declarative mappings. 

844 

845 """ 

846 

847 __slots__ = () 

848 

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

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

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

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

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

854 # to normal comparison behavior. 

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

856 return NotImplemented 

857 

858 __sa_operate__ = operate 

859 

860 def reverse_operate( 

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

862 ) -> Any: 

863 return NotImplemented 

864 

865 

866class DynamicMapped(_MappedAnnotationBase[_T_co]): 

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

868 

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

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

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

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

873 

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

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

876 :ref:`write_only_relationship`. 

877 

878 E.g.:: 

879 

880 class User(Base): 

881 __tablename__ = "user" 

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

883 addresses: DynamicMapped[Address] = relationship( 

884 cascade="all,delete-orphan" 

885 ) 

886 

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

888 

889 .. versionadded:: 2.0 

890 

891 .. seealso:: 

892 

893 :ref:`dynamic_relationship` - complete background 

894 

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

896 

897 """ 

898 

899 __slots__ = () 

900 

901 if TYPE_CHECKING: 

902 

903 @overload 

904 def __get__( 

905 self, instance: None, owner: Any 

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

907 

908 @overload 

909 def __get__( 

910 self, instance: object, owner: Any 

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

912 

913 def __get__( 

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

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

916 

917 def __set__( 

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

919 ) -> None: ... 

920 

921 

922class WriteOnlyMapped(_MappedAnnotationBase[_T_co]): 

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

924 

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

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

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

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

929 

930 E.g.:: 

931 

932 class User(Base): 

933 __tablename__ = "user" 

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

935 addresses: WriteOnlyMapped[Address] = relationship( 

936 cascade="all,delete-orphan" 

937 ) 

938 

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

940 

941 .. versionadded:: 2.0 

942 

943 .. seealso:: 

944 

945 :ref:`write_only_relationship` - complete background 

946 

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

948 

949 """ 

950 

951 __slots__ = () 

952 

953 if TYPE_CHECKING: 

954 

955 @overload 

956 def __get__( 

957 self, instance: None, owner: Any 

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

959 

960 @overload 

961 def __get__( 

962 self, instance: object, owner: Any 

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

964 

965 def __get__( 

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

967 ) -> Union[ 

968 InstrumentedAttribute[_T_co], WriteOnlyCollection[_T_co] 

969 ]: ... 

970 

971 def __set__( 

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

973 ) -> None: ...