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

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

334 statements  

1# orm/base.py 

2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: https://www.opensource.org/licenses/mit-license.php 

7 

8"""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 Literal 

20from typing import no_type_check 

21from typing import Optional 

22from typing import overload 

23from typing import Tuple 

24from typing import Type 

25from typing import TYPE_CHECKING 

26from typing import TypeVar 

27from typing import Union 

28 

29from . import exc 

30from ._typing import _O 

31from ._typing import insp_is_mapper 

32from .. import exc as sa_exc 

33from .. import inspection 

34from .. import util 

35from ..sql import roles 

36from ..sql._typing import _T 

37from ..sql._typing import _T_co 

38from ..sql.elements import SQLColumnExpression 

39from ..sql.elements import SQLCoreOperations 

40from ..util import FastIntFlag 

41from ..util.langhelpers import TypingOnly 

42 

43if typing.TYPE_CHECKING: 

44 from ._typing import _EntityType 

45 from ._typing import _ExternalEntityType 

46 from ._typing import _InternalEntityType 

47 from .attributes import InstrumentedAttribute 

48 from .dynamic import AppenderQuery 

49 from .instrumentation import ClassManager 

50 from .interfaces import PropComparator 

51 from .mapper import Mapper 

52 from .properties import MappedColumn 

53 from .state import InstanceState 

54 from .util import AliasedClass 

55 from .writeonly import WriteOnlyCollection 

56 from ..sql._annotated_cols import TypedColumns 

57 from ..sql._typing import _ColumnExpressionArgument 

58 from ..sql._typing import _InfoType 

59 from ..sql.elements import ColumnElement 

60 from ..sql.operators import OperatorType 

61 from ..sql.schema import Column 

62 

63 

64class LoaderCallableStatus(Enum): 

65 PASSIVE_NO_RESULT = 0 

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

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

68 on loader callable flags. 

69 """ 

70 

71 PASSIVE_CLASS_MISMATCH = 1 

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

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

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

75 

76 ATTR_WAS_SET = 2 

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

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

79 on the target object. 

80 """ 

81 

82 ATTR_EMPTY = 3 

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

84 

85 NO_VALUE = 4 

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

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

88 and flags indicated we were not to load it. 

89 """ 

90 

91 NEVER_SET = NO_VALUE 

92 """ 

93 Synonymous with NO_VALUE 

94 

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

96 

97 """ 

98 

99 DONT_SET = 5 

100 

101 

102( 

103 PASSIVE_NO_RESULT, 

104 PASSIVE_CLASS_MISMATCH, 

105 ATTR_WAS_SET, 

106 ATTR_EMPTY, 

107 NO_VALUE, 

108 DONT_SET, 

109) = tuple(LoaderCallableStatus) 

110 

111NEVER_SET = NO_VALUE 

112 

113 

114class PassiveFlag(FastIntFlag): 

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

116 

117 NO_CHANGE = 0 

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

119 and no state should change 

120 """ 

121 

122 CALLABLES_OK = 1 

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

124 is not present. 

125 """ 

126 

127 SQL_OK = 2 

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

129 

130 RELATED_OBJECT_OK = 4 

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

132 as scalar value attributes. 

133 """ 

134 

135 INIT_OK = 8 

136 """Attributes should be initialized with a blank 

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

138 value can be obtained. 

139 """ 

140 

141 NON_PERSISTENT_OK = 16 

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

143 

144 LOAD_AGAINST_COMMITTED = 32 

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

146 load. 

147 """ 

148 

149 NO_AUTOFLUSH = 64 

150 """Loader callables should disable autoflush.""" 

151 

152 NO_RAISE = 128 

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

154 

155 DEFERRED_HISTORY_LOAD = 256 

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

157 

158 INCLUDE_PENDING_MUTATIONS = 512 

159 

160 # pre-packaged sets of flags used as inputs 

161 PASSIVE_OFF = ( 

162 RELATED_OBJECT_OK | NON_PERSISTENT_OK | INIT_OK | CALLABLES_OK | SQL_OK 

163 ) 

164 "Callables can be emitted in all cases." 

165 

166 PASSIVE_RETURN_NO_VALUE = PASSIVE_OFF ^ INIT_OK 

167 """PASSIVE_OFF ^ INIT_OK""" 

168 

169 PASSIVE_NO_INITIALIZE = PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK 

170 "PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK" 

171 

172 PASSIVE_NO_FETCH = PASSIVE_OFF ^ SQL_OK 

173 "PASSIVE_OFF ^ SQL_OK" 

174 

175 PASSIVE_NO_FETCH_RELATED = PASSIVE_OFF ^ RELATED_OBJECT_OK 

176 "PASSIVE_OFF ^ RELATED_OBJECT_OK" 

177 

178 PASSIVE_ONLY_PERSISTENT = PASSIVE_OFF ^ NON_PERSISTENT_OK 

179 "PASSIVE_OFF ^ NON_PERSISTENT_OK" 

180 

181 PASSIVE_MERGE = PASSIVE_OFF | NO_RAISE 

182 """PASSIVE_OFF | NO_RAISE 

183 

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

185 

186 """ 

187 

188 

189( 

190 NO_CHANGE, 

191 CALLABLES_OK, 

192 SQL_OK, 

193 RELATED_OBJECT_OK, 

194 INIT_OK, 

195 NON_PERSISTENT_OK, 

196 LOAD_AGAINST_COMMITTED, 

197 NO_AUTOFLUSH, 

198 NO_RAISE, 

199 DEFERRED_HISTORY_LOAD, 

200 INCLUDE_PENDING_MUTATIONS, 

201 PASSIVE_OFF, 

202 PASSIVE_RETURN_NO_VALUE, 

203 PASSIVE_NO_INITIALIZE, 

204 PASSIVE_NO_FETCH, 

205 PASSIVE_NO_FETCH_RELATED, 

206 PASSIVE_ONLY_PERSISTENT, 

207 PASSIVE_MERGE, 

208) = PassiveFlag.__members__.values() 

209 

210DEFAULT_MANAGER_ATTR = "_sa_class_manager" 

211DEFAULT_STATE_ATTR = "_sa_instance_state" 

212 

213 

214class EventConstants(Enum): 

215 EXT_CONTINUE = 1 

216 EXT_STOP = 2 

217 EXT_SKIP = 3 

218 NO_KEY = 4 

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

220 key argument. 

221 

222 .. versionadded:: 2.0 

223 

224 """ 

225 

226 

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

228 

229 

230class RelationshipDirection(Enum): 

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

232 :class:`_orm.RelationshipProperty`. 

233 

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

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

236 :class:`_orm.RelationshipProperty`. 

237 

238 """ 

239 

240 ONETOMANY = 1 

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

242 

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

244 certain API features. 

245 

246 """ 

247 

248 MANYTOONE = 2 

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

250 

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

252 certain API features. 

253 

254 """ 

255 

256 MANYTOMANY = 3 

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

258 

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

260 certain API features. 

261 

262 """ 

263 

264 

265ONETOMANY, MANYTOONE, MANYTOMANY = tuple(RelationshipDirection) 

266 

267 

268class InspectionAttrExtensionType(Enum): 

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

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

271 

272 

273class NotExtension(InspectionAttrExtensionType): 

274 NOT_EXTENSION = "not_extension" 

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

276 not part of sqlalchemy.ext. 

277 

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

279 attribute. 

280 

281 """ 

282 

283 

284_never_set = frozenset([NEVER_SET]) 

285 

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

287 

288_none_only_set = frozenset([None]) 

289 

290_SET_DEFERRED_EXPIRED = util.symbol("SET_DEFERRED_EXPIRED") 

291 

292_DEFER_FOR_STATE = util.symbol("DEFER_FOR_STATE") 

293 

294_RAISE_FOR_STATE = util.symbol("RAISE_FOR_STATE") 

295 

296 

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

298_Self = TypeVar("_Self") 

299 

300 

301def _assertions( 

302 *assertions: Any, 

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

304 @util.decorator 

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

306 for assertion in assertions: 

307 assertion(self, fn.__name__) 

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

309 return self 

310 

311 return generate 

312 

313 

314if TYPE_CHECKING: 

315 

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

317 

318 @overload 

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

320 

321 @overload 

322 def opt_manager_of_class( 

323 cls: _ExternalEntityType[_O], 

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

325 

326 def opt_manager_of_class( 

327 cls: _ExternalEntityType[_O], 

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

329 

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

331 

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

333 

334else: 

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

336 # if augmented class instrumentation is enabled. 

337 

338 def manager_of_class(cls): 

339 try: 

340 return cls.__dict__[DEFAULT_MANAGER_ATTR] 

341 except KeyError as ke: 

342 raise exc.UnmappedClassError( 

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

344 ) from ke 

345 

346 def opt_manager_of_class(cls): 

347 return cls.__dict__.get(DEFAULT_MANAGER_ATTR) 

348 

349 instance_state = operator.attrgetter(DEFAULT_STATE_ATTR) 

350 

351 instance_dict = operator.attrgetter("__dict__") 

352 

353 

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

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

356 

357 return state_str(instance_state(instance)) 

358 

359 

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

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

362 

363 if state is None: 

364 return "None" 

365 else: 

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

367 

368 

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

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

371 InstanceState. 

372 """ 

373 

374 if state is None: 

375 return "None" 

376 else: 

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

378 

379 

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

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

382 

383 

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

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

386 

387 

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

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

390 instance. 

391 

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

393 if no mapping is configured. 

394 

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

396 

397 inspect(instance).mapper 

398 

399 Using the inspection system will raise 

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

401 not part of a mapping. 

402 

403 """ 

404 return object_state(instance).mapper 

405 

406 

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

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

409 associated with the object. 

410 

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

412 if no mapping is configured. 

413 

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

415 function as:: 

416 

417 inspect(instance) 

418 

419 Using the inspection system will raise 

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

421 not part of a mapping. 

422 

423 """ 

424 state = _inspect_mapped_object(instance) 

425 if state is None: 

426 raise exc.UnmappedInstanceError(instance) 

427 else: 

428 return state 

429 

430 

431@inspection._inspects(object) 

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

433 try: 

434 return instance_state(instance) 

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

436 return None 

437 

438 

439def _class_to_mapper( 

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

441) -> Mapper[_T]: 

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

443 insp = inspection.inspect(class_or_mapper, False) 

444 if insp is not None: 

445 return insp.mapper # type: ignore 

446 else: 

447 assert isinstance(class_or_mapper, type) 

448 raise exc.UnmappedClassError(class_or_mapper) 

449 

450 

451def _mapper_or_none( 

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

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

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

455 class is not mapped. 

456 """ 

457 

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

459 insp = inspection.inspect(entity, False) 

460 if insp is not None: 

461 return insp.mapper # type: ignore 

462 else: 

463 return None 

464 

465 

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

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

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

469 """ 

470 

471 insp = inspection.inspect(entity, False) 

472 return ( 

473 insp is not None 

474 and not insp.is_clause_element 

475 and (insp.is_mapper or insp.is_aliased_class) 

476 ) 

477 

478 

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

480 insp = inspection.inspect(entity, False) 

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

482 

483 

484@no_type_check 

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

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

487 

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

489 attribute. 

490 

491 """ 

492 insp = inspection.inspect(entity) 

493 if insp.is_selectable: 

494 description = entity 

495 entity = insp.c 

496 elif insp.is_aliased_class: 

497 entity = insp.entity 

498 description = entity 

499 elif hasattr(insp, "mapper"): 

500 description = entity = insp.mapper.class_ 

501 else: 

502 description = entity 

503 

504 try: 

505 return getattr(entity, key) 

506 except AttributeError as err: 

507 raise sa_exc.InvalidRequestError( 

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

509 ) from err 

510 

511 

512if TYPE_CHECKING: 

513 

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

515 

516else: 

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

518 

519 

520def _inspect_mapped_class( 

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

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

523 try: 

524 class_manager = opt_manager_of_class(class_) 

525 if class_manager is None or not class_manager.is_mapped: 

526 return None 

527 mapper = class_manager.mapper 

528 except exc.NO_STATE: 

529 return None 

530 else: 

531 if configure: 

532 mapper._check_configure() 

533 return mapper 

534 

535 

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

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

538 if insp_is_mapper(insp): 

539 return insp 

540 

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

542 

543 

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

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

546 with the key. 

547 

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

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

550 object is passed. 

551 

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

553 function as:: 

554 

555 inspect(some_mapped_class) 

556 

557 Using the inspection system will raise 

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

559 

560 """ 

561 mapper = _inspect_mapped_class(class_, configure=configure) 

562 if mapper is None: 

563 if not isinstance(class_, type): 

564 raise sa_exc.ArgumentError( 

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

566 ) 

567 raise exc.UnmappedClassError(class_) 

568 else: 

569 return mapper 

570 

571 

572class InspectionAttr: 

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

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

575 

576 The attributes defined here allow the usage of simple boolean 

577 checks to test basic facts about the object returned. 

578 

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

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

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

582 the SQLAlchemy class system can change while leaving the flags 

583 here intact for forwards-compatibility. 

584 

585 """ 

586 

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

588 

589 is_selectable = False 

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

591 :class:`_expression.Selectable`.""" 

592 

593 is_aliased_class = False 

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

595 

596 is_instance = False 

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

598 

599 is_mapper = False 

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

601 

602 is_bundle = False 

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

604 

605 is_property = False 

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

607 

608 is_attribute = False 

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

610 

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

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

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

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

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

616 identifying the specific subtype. 

617 

618 .. seealso:: 

619 

620 :attr:`_orm.Mapper.all_orm_descriptors` 

621 

622 """ 

623 

624 _is_internal_proxy = False 

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

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__( # type: ignore[misc] 

810 self: MappedColumn[_T_co], instance: TypedColumns, owner: Any 

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

812 

813 @overload 

814 def __get__( 

815 self, instance: None, owner: Any 

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

817 

818 @overload 

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

820 

821 def __get__( 

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

823 ) -> Union[InstrumentedAttribute[_T_co], Column[_T_co], _T_co]: ... 

824 

825 @classmethod 

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

827 

828 def __set__( 

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

830 ) -> None: ... 

831 

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

833 

834 

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

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

837 attributes. 

838 

839 """ 

840 

841 __slots__ = () 

842 

843 

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

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

846 be compatible with ORM-annotated declarative mappings. 

847 

848 """ 

849 

850 __slots__ = () 

851 

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

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

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

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

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

857 # to normal comparison behavior. 

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

859 return NotImplemented 

860 

861 __sa_operate__ = operate 

862 

863 def reverse_operate( 

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

865 ) -> Any: 

866 return NotImplemented 

867 

868 

869class DynamicMapped(_MappedAnnotationBase[_T_co]): 

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

871 

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

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

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

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

876 

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

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

879 :ref:`write_only_relationship`. 

880 

881 E.g.:: 

882 

883 class User(Base): 

884 __tablename__ = "user" 

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

886 addresses: DynamicMapped[Address] = relationship( 

887 cascade="all,delete-orphan" 

888 ) 

889 

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

891 

892 .. versionadded:: 2.0 

893 

894 .. seealso:: 

895 

896 :ref:`dynamic_relationship` - complete background 

897 

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

899 

900 """ 

901 

902 __slots__ = () 

903 

904 if TYPE_CHECKING: 

905 

906 @overload 

907 def __get__( 

908 self, instance: None, owner: Any 

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

910 

911 @overload 

912 def __get__( 

913 self, instance: object, owner: Any 

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

915 

916 def __get__( 

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

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

919 

920 def __set__( 

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

922 ) -> None: ... 

923 

924 

925class WriteOnlyMapped(_MappedAnnotationBase[_T_co]): 

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

927 

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

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

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

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

932 

933 E.g.:: 

934 

935 class User(Base): 

936 __tablename__ = "user" 

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

938 addresses: WriteOnlyMapped[Address] = relationship( 

939 cascade="all,delete-orphan" 

940 ) 

941 

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

943 

944 .. versionadded:: 2.0 

945 

946 .. seealso:: 

947 

948 :ref:`write_only_relationship` - complete background 

949 

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

951 

952 """ 

953 

954 __slots__ = () 

955 

956 if TYPE_CHECKING: 

957 

958 @overload 

959 def __get__( 

960 self, instance: None, owner: Any 

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

962 

963 @overload 

964 def __get__( 

965 self, instance: object, owner: Any 

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

967 

968 def __get__( 

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

970 ) -> Union[ 

971 InstrumentedAttribute[_T_co], WriteOnlyCollection[_T_co] 

972 ]: ... 

973 

974 def __set__( 

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

976 ) -> None: ...