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

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

294 statements  

1# orm/base.py 

2# Copyright (C) 2005-2024 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_SET_DEFERRED_EXPIRED = util.symbol("SET_DEFERRED_EXPIRED") 

287 

288_DEFER_FOR_STATE = util.symbol("DEFER_FOR_STATE") 

289 

290_RAISE_FOR_STATE = util.symbol("RAISE_FOR_STATE") 

291 

292 

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

294_Self = TypeVar("_Self") 

295 

296 

297def _assertions( 

298 *assertions: Any, 

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

300 @util.decorator 

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

302 for assertion in assertions: 

303 assertion(self, fn.__name__) 

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

305 return self 

306 

307 return generate 

308 

309 

310if TYPE_CHECKING: 

311 

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

313 

314 @overload 

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

316 

317 @overload 

318 def opt_manager_of_class( 

319 cls: _ExternalEntityType[_O], 

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

321 

322 def opt_manager_of_class( 

323 cls: _ExternalEntityType[_O], 

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

325 

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

327 

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

329 

330else: 

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

332 # if augmented class instrumentation is enabled. 

333 

334 def manager_of_class(cls): 

335 try: 

336 return cls.__dict__[DEFAULT_MANAGER_ATTR] 

337 except KeyError as ke: 

338 raise exc.UnmappedClassError( 

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

340 ) from ke 

341 

342 def opt_manager_of_class(cls): 

343 return cls.__dict__.get(DEFAULT_MANAGER_ATTR) 

344 

345 instance_state = operator.attrgetter(DEFAULT_STATE_ATTR) 

346 

347 instance_dict = operator.attrgetter("__dict__") 

348 

349 

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

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

352 

353 return state_str(instance_state(instance)) 

354 

355 

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

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

358 

359 if state is None: 

360 return "None" 

361 else: 

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

363 

364 

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

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

367 InstanceState. 

368 """ 

369 

370 if state is None: 

371 return "None" 

372 else: 

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

374 

375 

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

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

378 

379 

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

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

382 

383 

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

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

386 instance. 

387 

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

389 if no mapping is configured. 

390 

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

392 

393 inspect(instance).mapper 

394 

395 Using the inspection system will raise 

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

397 not part of a mapping. 

398 

399 """ 

400 return object_state(instance).mapper 

401 

402 

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

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

405 associated with the object. 

406 

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

408 if no mapping is configured. 

409 

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

411 function as:: 

412 

413 inspect(instance) 

414 

415 Using the inspection system will raise 

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

417 not part of a mapping. 

418 

419 """ 

420 state = _inspect_mapped_object(instance) 

421 if state is None: 

422 raise exc.UnmappedInstanceError(instance) 

423 else: 

424 return state 

425 

426 

427@inspection._inspects(object) 

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

429 try: 

430 return instance_state(instance) 

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

432 return None 

433 

434 

435def _class_to_mapper( 

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

437) -> Mapper[_T]: 

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

439 insp = inspection.inspect(class_or_mapper, False) 

440 if insp is not None: 

441 return insp.mapper # type: ignore 

442 else: 

443 assert isinstance(class_or_mapper, type) 

444 raise exc.UnmappedClassError(class_or_mapper) 

445 

446 

447def _mapper_or_none( 

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

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

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

451 class is not mapped. 

452 """ 

453 

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

455 insp = inspection.inspect(entity, False) 

456 if insp is not None: 

457 return insp.mapper # type: ignore 

458 else: 

459 return None 

460 

461 

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

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

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

465 """ 

466 

467 insp = inspection.inspect(entity, False) 

468 return ( 

469 insp is not None 

470 and not insp.is_clause_element 

471 and (insp.is_mapper or insp.is_aliased_class) 

472 ) 

473 

474 

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

476 insp = inspection.inspect(entity, False) 

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

478 

479 

480@no_type_check 

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

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

483 

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

485 attribute. 

486 

487 """ 

488 insp = inspection.inspect(entity) 

489 if insp.is_selectable: 

490 description = entity 

491 entity = insp.c 

492 elif insp.is_aliased_class: 

493 entity = insp.entity 

494 description = entity 

495 elif hasattr(insp, "mapper"): 

496 description = entity = insp.mapper.class_ 

497 else: 

498 description = entity 

499 

500 try: 

501 return getattr(entity, key) 

502 except AttributeError as err: 

503 raise sa_exc.InvalidRequestError( 

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

505 ) from err 

506 

507 

508if TYPE_CHECKING: 

509 

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

511 

512else: 

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

514 

515 

516def _inspect_mapped_class( 

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

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

519 try: 

520 class_manager = opt_manager_of_class(class_) 

521 if class_manager is None or not class_manager.is_mapped: 

522 return None 

523 mapper = class_manager.mapper 

524 except exc.NO_STATE: 

525 return None 

526 else: 

527 if configure: 

528 mapper._check_configure() 

529 return mapper 

530 

531 

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

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

534 if insp_is_mapper(insp): 

535 return insp 

536 

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

538 

539 

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

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

542 with the key. 

543 

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

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

546 object is passed. 

547 

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

549 function as:: 

550 

551 inspect(some_mapped_class) 

552 

553 Using the inspection system will raise 

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

555 

556 """ 

557 mapper = _inspect_mapped_class(class_, configure=configure) 

558 if mapper is None: 

559 if not isinstance(class_, type): 

560 raise sa_exc.ArgumentError( 

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

562 ) 

563 raise exc.UnmappedClassError(class_) 

564 else: 

565 return mapper 

566 

567 

568class InspectionAttr: 

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

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

571 

572 The attributes defined here allow the usage of simple boolean 

573 checks to test basic facts about the object returned. 

574 

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

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

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

578 the SQLAlchemy class system can change while leaving the flags 

579 here intact for forwards-compatibility. 

580 

581 """ 

582 

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

584 

585 is_selectable = False 

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

587 :class:`_expression.Selectable`.""" 

588 

589 is_aliased_class = False 

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

591 

592 is_instance = False 

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

594 

595 is_mapper = False 

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

597 

598 is_bundle = False 

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

600 

601 is_property = False 

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

603 

604 is_attribute = False 

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

606 

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

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

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

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

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

612 identifying the specific subtype. 

613 

614 .. seealso:: 

615 

616 :attr:`_orm.Mapper.all_orm_descriptors` 

617 

618 """ 

619 

620 _is_internal_proxy = False 

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

622 

623 .. versionadded:: 1.2.12 

624 

625 """ 

626 

627 is_clause_element = False 

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

629 :class:`_expression.ClauseElement`.""" 

630 

631 extension_type: InspectionAttrExtensionType = NotExtension.NOT_EXTENSION 

632 """The extension type, if any. 

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

634 

635 .. seealso:: 

636 

637 :class:`.HybridExtensionType` 

638 

639 :class:`.AssociationProxyExtensionType` 

640 

641 """ 

642 

643 

644class InspectionAttrInfo(InspectionAttr): 

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

646 

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

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

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

650 

651 """ 

652 

653 __slots__ = () 

654 

655 @util.ro_memoized_property 

656 def info(self) -> _InfoType: 

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

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

659 

660 The dictionary is generated when first accessed. Alternatively, 

661 it can be specified as a constructor argument to the 

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

663 :func:`.composite` 

664 functions. 

665 

666 .. seealso:: 

667 

668 :attr:`.QueryableAttribute.info` 

669 

670 :attr:`.SchemaItem.info` 

671 

672 """ 

673 return {} 

674 

675 

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

677 __slots__ = () 

678 

679 if typing.TYPE_CHECKING: 

680 

681 def of_type( 

682 self, class_: _EntityType[Any] 

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

684 

685 def and_( 

686 self, *criteria: _ColumnExpressionArgument[bool] 

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

688 

689 def any( # noqa: A001 

690 self, 

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

692 **kwargs: Any, 

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

694 

695 def has( 

696 self, 

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

698 **kwargs: Any, 

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

700 

701 

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

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

704 construct at the class level.""" 

705 

706 __slots__ = () 

707 

708 if typing.TYPE_CHECKING: 

709 

710 @overload 

711 def __get__( 

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

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

714 

715 @overload 

716 def __get__( 

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

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

719 

720 @overload 

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

722 

723 def __get__( 

724 self, instance: object, owner: Any 

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

726 

727 

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

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

730 

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

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

733 surrounding a mapped class. 

734 

735 """ 

736 

737 __slots__ = () 

738 

739 

740class SQLORMExpression( 

741 SQLORMOperations[_T_co], SQLColumnExpression[_T_co], TypingOnly 

742): 

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

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

745 construction. 

746 

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

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

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

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

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

752 attribute expressions. 

753 

754 .. versionadded:: 2.0.0b4 

755 

756 

757 """ 

758 

759 __slots__ = () 

760 

761 

762class Mapped( 

763 SQLORMExpression[_T_co], 

764 ORMDescriptor[_T_co], 

765 _MappedAnnotationBase[_T_co], 

766 roles.DDLConstraintColumnRole, 

767): 

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

769 

770 This class represents the complete descriptor interface for any class 

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

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

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

774 are correctly typed. 

775 

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

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

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

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

780 and :func:`_orm.relationship`. 

781 

782 .. seealso:: 

783 

784 :ref:`orm_explicit_declarative_base` 

785 

786 :ref:`orm_declarative_table` 

787 

788 .. tip:: 

789 

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

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

792 Python descriptor classes that are provided as extensions, including 

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

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

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

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

797 when they are accessed on a class. 

798 

799 .. versionadded:: 1.4 

800 

801 

802 """ 

803 

804 __slots__ = () 

805 

806 if typing.TYPE_CHECKING: 

807 

808 @overload 

809 def __get__( 

810 self, instance: None, owner: Any 

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

812 

813 @overload 

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

815 

816 def __get__( 

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

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

819 

820 @classmethod 

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

822 

823 def __set__( 

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

825 ) -> None: ... 

826 

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

828 

829 

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

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

832 attributes. 

833 

834 """ 

835 

836 __slots__ = () 

837 

838 

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

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

841 be compatible with ORM-annotated declarative mappings. 

842 

843 """ 

844 

845 __slots__ = () 

846 

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

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

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

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

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

852 # to normal comparison behavior. 

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

854 return NotImplemented 

855 

856 __sa_operate__ = operate 

857 

858 def reverse_operate( 

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

860 ) -> Any: 

861 return NotImplemented 

862 

863 

864class DynamicMapped(_MappedAnnotationBase[_T_co]): 

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

866 

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

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

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

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

871 

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

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

874 :ref:`write_only_relationship`. 

875 

876 E.g.:: 

877 

878 class User(Base): 

879 __tablename__ = "user" 

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

881 addresses: DynamicMapped[Address] = relationship( 

882 cascade="all,delete-orphan" 

883 ) 

884 

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

886 

887 .. versionadded:: 2.0 

888 

889 .. seealso:: 

890 

891 :ref:`dynamic_relationship` - complete background 

892 

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

894 

895 """ 

896 

897 __slots__ = () 

898 

899 if TYPE_CHECKING: 

900 

901 @overload 

902 def __get__( 

903 self, instance: None, owner: Any 

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

905 

906 @overload 

907 def __get__( 

908 self, instance: object, owner: Any 

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

910 

911 def __get__( 

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

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

914 

915 def __set__( 

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

917 ) -> None: ... 

918 

919 

920class WriteOnlyMapped(_MappedAnnotationBase[_T_co]): 

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

922 

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

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

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

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

927 

928 E.g.:: 

929 

930 class User(Base): 

931 __tablename__ = "user" 

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

933 addresses: WriteOnlyMapped[Address] = relationship( 

934 cascade="all,delete-orphan" 

935 ) 

936 

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

938 

939 .. versionadded:: 2.0 

940 

941 .. seealso:: 

942 

943 :ref:`write_only_relationship` - complete background 

944 

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

946 

947 """ 

948 

949 __slots__ = () 

950 

951 if TYPE_CHECKING: 

952 

953 @overload 

954 def __get__( 

955 self, instance: None, owner: Any 

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

957 

958 @overload 

959 def __get__( 

960 self, instance: object, owner: Any 

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

962 

963 def __get__( 

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

965 ) -> Union[ 

966 InstrumentedAttribute[_T_co], WriteOnlyCollection[_T_co] 

967 ]: ... 

968 

969 def __set__( 

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

971 ) -> None: ...