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
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
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
8"""Constants and rudimental functions used throughout the ORM.
10"""
12from __future__ import annotations
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
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
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
59_T = TypeVar("_T", bound=Any)
60_T_co = TypeVar("_T_co", bound=Any, covariant=True)
62_O = TypeVar("_O", bound=object)
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 """
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."""
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 """
83 ATTR_EMPTY = 3
84 """Symbol used internally to indicate an attribute had no callable."""
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 """
92 NEVER_SET = NO_VALUE
93 """
94 Synonymous with NO_VALUE
96 .. versionchanged:: 1.4 NEVER_SET was merged with NO_VALUE
98 """
101(
102 PASSIVE_NO_RESULT,
103 PASSIVE_CLASS_MISMATCH,
104 ATTR_WAS_SET,
105 ATTR_EMPTY,
106 NO_VALUE,
107) = tuple(LoaderCallableStatus)
109NEVER_SET = NO_VALUE
112class PassiveFlag(FastIntFlag):
113 """Bitflag interface that passes options onto loader callables"""
115 NO_CHANGE = 0
116 """No callables or SQL should be emitted on attribute access
117 and no state should change
118 """
120 CALLABLES_OK = 1
121 """Loader callables can be fired off if a value
122 is not present.
123 """
125 SQL_OK = 2
126 """Loader callables can emit SQL at least on scalar value attributes."""
128 RELATED_OBJECT_OK = 4
129 """Callables can use SQL to load related objects as well
130 as scalar value attributes.
131 """
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 """
139 NON_PERSISTENT_OK = 16
140 """Callables can be emitted if the parent is not persistent."""
142 LOAD_AGAINST_COMMITTED = 32
143 """Callables should use committed values as primary/foreign keys during a
144 load.
145 """
147 NO_AUTOFLUSH = 64
148 """Loader callables should disable autoflush.""",
150 NO_RAISE = 128
151 """Loader callables should not raise any assertions"""
153 DEFERRED_HISTORY_LOAD = 256
154 """indicates special load of the previous value of an attribute"""
156 INCLUDE_PENDING_MUTATIONS = 512
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."
164 PASSIVE_RETURN_NO_VALUE = PASSIVE_OFF ^ INIT_OK
165 """PASSIVE_OFF ^ INIT_OK"""
167 PASSIVE_NO_INITIALIZE = PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK
168 "PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK"
170 PASSIVE_NO_FETCH = PASSIVE_OFF ^ SQL_OK
171 "PASSIVE_OFF ^ SQL_OK"
173 PASSIVE_NO_FETCH_RELATED = PASSIVE_OFF ^ RELATED_OBJECT_OK
174 "PASSIVE_OFF ^ RELATED_OBJECT_OK"
176 PASSIVE_ONLY_PERSISTENT = PASSIVE_OFF ^ NON_PERSISTENT_OK
177 "PASSIVE_OFF ^ NON_PERSISTENT_OK"
179 PASSIVE_MERGE = PASSIVE_OFF | NO_RAISE
180 """PASSIVE_OFF | NO_RAISE
182 Symbol used specifically for session.merge() and similar cases
184 """
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()
208DEFAULT_MANAGER_ATTR = "_sa_class_manager"
209DEFAULT_STATE_ATTR = "_sa_instance_state"
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.
220 .. versionadded:: 2.0
222 """
225EXT_CONTINUE, EXT_STOP, EXT_SKIP, NO_KEY = tuple(EventConstants)
228class RelationshipDirection(Enum):
229 """enumeration which indicates the 'direction' of a
230 :class:`_orm.RelationshipProperty`.
232 :class:`.RelationshipDirection` is accessible from the
233 :attr:`_orm.Relationship.direction` attribute of
234 :class:`_orm.RelationshipProperty`.
236 """
238 ONETOMANY = 1
239 """Indicates the one-to-many direction for a :func:`_orm.relationship`.
241 This symbol is typically used by the internals but may be exposed within
242 certain API features.
244 """
246 MANYTOONE = 2
247 """Indicates the many-to-one direction for a :func:`_orm.relationship`.
249 This symbol is typically used by the internals but may be exposed within
250 certain API features.
252 """
254 MANYTOMANY = 3
255 """Indicates the many-to-many direction for a :func:`_orm.relationship`.
257 This symbol is typically used by the internals but may be exposed within
258 certain API features.
260 """
263ONETOMANY, MANYTOONE, MANYTOMANY = tuple(RelationshipDirection)
266class InspectionAttrExtensionType(Enum):
267 """Symbols indicating the type of extension that a
268 :class:`.InspectionAttr` is part of."""
271class NotExtension(InspectionAttrExtensionType):
272 NOT_EXTENSION = "not_extension"
273 """Symbol indicating an :class:`InspectionAttr` that's
274 not part of sqlalchemy.ext.
276 Is assigned to the :attr:`.InspectionAttr.extension_type`
277 attribute.
279 """
282_never_set = frozenset([NEVER_SET])
284_none_set = frozenset([None, NEVER_SET, PASSIVE_NO_RESULT])
286_SET_DEFERRED_EXPIRED = util.symbol("SET_DEFERRED_EXPIRED")
288_DEFER_FOR_STATE = util.symbol("DEFER_FOR_STATE")
290_RAISE_FOR_STATE = util.symbol("RAISE_FOR_STATE")
293_F = TypeVar("_F", bound=Callable[..., Any])
294_Self = TypeVar("_Self")
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
307 return generate
310if TYPE_CHECKING:
312 def manager_of_class(cls: Type[_O]) -> ClassManager[_O]: ...
314 @overload
315 def opt_manager_of_class(cls: AliasedClass[Any]) -> None: ...
317 @overload
318 def opt_manager_of_class(
319 cls: _ExternalEntityType[_O],
320 ) -> Optional[ClassManager[_O]]: ...
322 def opt_manager_of_class(
323 cls: _ExternalEntityType[_O],
324 ) -> Optional[ClassManager[_O]]: ...
326 def instance_state(instance: _O) -> InstanceState[_O]: ...
328 def instance_dict(instance: object) -> Dict[str, Any]: ...
330else:
331 # these can be replaced by sqlalchemy.ext.instrumentation
332 # if augmented class instrumentation is enabled.
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
342 def opt_manager_of_class(cls):
343 return cls.__dict__.get(DEFAULT_MANAGER_ATTR)
345 instance_state = operator.attrgetter(DEFAULT_STATE_ATTR)
347 instance_dict = operator.attrgetter("__dict__")
350def instance_str(instance: object) -> str:
351 """Return a string describing an instance."""
353 return state_str(instance_state(instance))
356def state_str(state: InstanceState[Any]) -> str:
357 """Return a string describing an instance via its InstanceState."""
359 if state is None:
360 return "None"
361 else:
362 return "<%s at 0x%x>" % (state.class_.__name__, id(state.obj()))
365def state_class_str(state: InstanceState[Any]) -> str:
366 """Return a string describing an instance's class via its
367 InstanceState.
368 """
370 if state is None:
371 return "None"
372 else:
373 return "<%s>" % (state.class_.__name__,)
376def attribute_str(instance: object, attribute: str) -> str:
377 return instance_str(instance) + "." + attribute
380def state_attribute_str(state: InstanceState[Any], attribute: str) -> str:
381 return state_str(state) + "." + attribute
384def object_mapper(instance: _T) -> Mapper[_T]:
385 """Given an object, return the primary Mapper associated with the object
386 instance.
388 Raises :class:`sqlalchemy.orm.exc.UnmappedInstanceError`
389 if no mapping is configured.
391 This function is available via the inspection system as::
393 inspect(instance).mapper
395 Using the inspection system will raise
396 :class:`sqlalchemy.exc.NoInspectionAvailable` if the instance is
397 not part of a mapping.
399 """
400 return object_state(instance).mapper
403def object_state(instance: _T) -> InstanceState[_T]:
404 """Given an object, return the :class:`.InstanceState`
405 associated with the object.
407 Raises :class:`sqlalchemy.orm.exc.UnmappedInstanceError`
408 if no mapping is configured.
410 Equivalent functionality is available via the :func:`_sa.inspect`
411 function as::
413 inspect(instance)
415 Using the inspection system will raise
416 :class:`sqlalchemy.exc.NoInspectionAvailable` if the instance is
417 not part of a mapping.
419 """
420 state = _inspect_mapped_object(instance)
421 if state is None:
422 raise exc.UnmappedInstanceError(instance)
423 else:
424 return state
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
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)
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 """
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
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 """
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 )
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)
480@no_type_check
481def _entity_descriptor(entity: _EntityType[Any], key: str) -> Any:
482 """Return a class attribute given an entity and string name.
484 May return :class:`.InstrumentedAttribute` or user-defined
485 attribute.
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
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
508if TYPE_CHECKING:
510 def _state_mapper(state: InstanceState[_O]) -> Mapper[_O]: ...
512else:
513 _state_mapper = util.dottedgetter("manager.mapper")
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
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
537 raise sa_exc.ArgumentError(f"Mapper or mapped class expected, got {arg!r}")
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.
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.
548 Equivalent functionality is available via the :func:`_sa.inspect`
549 function as::
551 inspect(some_mapped_class)
553 Using the inspection system will raise
554 :class:`sqlalchemy.exc.NoInspectionAvailable` if the class is not mapped.
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
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.
572 The attributes defined here allow the usage of simple boolean
573 checks to test basic facts about the object returned.
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.
581 """
583 __slots__: Tuple[str, ...] = ()
585 is_selectable = False
586 """Return True if this object is an instance of
587 :class:`_expression.Selectable`."""
589 is_aliased_class = False
590 """True if this object is an instance of :class:`.AliasedClass`."""
592 is_instance = False
593 """True if this object is an instance of :class:`.InstanceState`."""
595 is_mapper = False
596 """True if this object is an instance of :class:`_orm.Mapper`."""
598 is_bundle = False
599 """True if this object is an instance of :class:`.Bundle`."""
601 is_property = False
602 """True if this object is an instance of :class:`.MapperProperty`."""
604 is_attribute = False
605 """True if this object is a Python :term:`descriptor`.
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.
614 .. seealso::
616 :attr:`_orm.Mapper.all_orm_descriptors`
618 """
620 _is_internal_proxy = False
621 """True if this object is an internal proxy object.
623 .. versionadded:: 1.2.12
625 """
627 is_clause_element = False
628 """True if this object is an instance of
629 :class:`_expression.ClauseElement`."""
631 extension_type: InspectionAttrExtensionType = NotExtension.NOT_EXTENSION
632 """The extension type, if any.
633 Defaults to :attr:`.interfaces.NotExtension.NOT_EXTENSION`
635 .. seealso::
637 :class:`.HybridExtensionType`
639 :class:`.AssociationProxyExtensionType`
641 """
644class InspectionAttrInfo(InspectionAttr):
645 """Adds the ``.info`` attribute to :class:`.InspectionAttr`.
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.
651 """
653 __slots__ = ()
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`.
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.
666 .. seealso::
668 :attr:`.QueryableAttribute.info`
670 :attr:`.SchemaItem.info`
672 """
673 return {}
676class SQLORMOperations(SQLCoreOperations[_T_co], TypingOnly):
677 __slots__ = ()
679 if typing.TYPE_CHECKING:
681 def of_type(
682 self, class_: _EntityType[Any]
683 ) -> PropComparator[_T_co]: ...
685 def and_(
686 self, *criteria: _ColumnExpressionArgument[bool]
687 ) -> PropComparator[bool]: ...
689 def any( # noqa: A001
690 self,
691 criterion: Optional[_ColumnExpressionArgument[bool]] = None,
692 **kwargs: Any,
693 ) -> ColumnElement[bool]: ...
695 def has(
696 self,
697 criterion: Optional[_ColumnExpressionArgument[bool]] = None,
698 **kwargs: Any,
699 ) -> ColumnElement[bool]: ...
702class ORMDescriptor(Generic[_T_co], TypingOnly):
703 """Represent any Python descriptor that provides a SQL expression
704 construct at the class level."""
706 __slots__ = ()
708 if typing.TYPE_CHECKING:
710 @overload
711 def __get__(
712 self, instance: Any, owner: Literal[None]
713 ) -> ORMDescriptor[_T_co]: ...
715 @overload
716 def __get__(
717 self, instance: Literal[None], owner: Any
718 ) -> SQLCoreOperations[_T_co]: ...
720 @overload
721 def __get__(self, instance: object, owner: Any) -> _T_co: ...
723 def __get__(
724 self, instance: object, owner: Any
725 ) -> Union[ORMDescriptor[_T_co], SQLCoreOperations[_T_co], _T_co]: ...
728class _MappedAnnotationBase(Generic[_T_co], TypingOnly):
729 """common class for Mapped and similar ORM container classes.
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.
735 """
737 __slots__ = ()
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.
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.
754 .. versionadded:: 2.0.0b4
757 """
759 __slots__ = ()
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.
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.
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`.
782 .. seealso::
784 :ref:`orm_explicit_declarative_base`
786 :ref:`orm_declarative_table`
788 .. tip::
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.
799 .. versionadded:: 1.4
802 """
804 __slots__ = ()
806 if typing.TYPE_CHECKING:
808 @overload
809 def __get__(
810 self, instance: None, owner: Any
811 ) -> InstrumentedAttribute[_T_co]: ...
813 @overload
814 def __get__(self, instance: object, owner: Any) -> _T_co: ...
816 def __get__(
817 self, instance: Optional[object], owner: Any
818 ) -> Union[InstrumentedAttribute[_T_co], _T_co]: ...
820 @classmethod
821 def _empty_constructor(cls, arg1: Any) -> Mapped[_T_co]: ...
823 def __set__(
824 self, instance: Any, value: Union[SQLCoreOperations[_T_co], _T_co]
825 ) -> None: ...
827 def __delete__(self, instance: Any) -> None: ...
830class _MappedAttribute(Generic[_T_co], TypingOnly):
831 """Mixin for attributes which should be replaced by mapper-assigned
832 attributes.
834 """
836 __slots__ = ()
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.
843 """
845 __slots__ = ()
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
856 __sa_operate__ = operate
858 def reverse_operate(
859 self, op: OperatorType, other: Any, **kwargs: Any
860 ) -> Any:
861 return NotImplemented
864class DynamicMapped(_MappedAnnotationBase[_T_co]):
865 """Represent the ORM mapped attribute type for a "dynamic" relationship.
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`.
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`.
876 E.g.::
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 )
885 See the section :ref:`dynamic_relationship` for background.
887 .. versionadded:: 2.0
889 .. seealso::
891 :ref:`dynamic_relationship` - complete background
893 :class:`.WriteOnlyMapped` - fully 2.0 style version
895 """
897 __slots__ = ()
899 if TYPE_CHECKING:
901 @overload
902 def __get__(
903 self, instance: None, owner: Any
904 ) -> InstrumentedAttribute[_T_co]: ...
906 @overload
907 def __get__(
908 self, instance: object, owner: Any
909 ) -> AppenderQuery[_T_co]: ...
911 def __get__(
912 self, instance: Optional[object], owner: Any
913 ) -> Union[InstrumentedAttribute[_T_co], AppenderQuery[_T_co]]: ...
915 def __set__(
916 self, instance: Any, value: typing.Collection[_T_co]
917 ) -> None: ...
920class WriteOnlyMapped(_MappedAnnotationBase[_T_co]):
921 """Represent the ORM mapped attribute type for a "write only" relationship.
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`.
928 E.g.::
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 )
937 See the section :ref:`write_only_relationship` for background.
939 .. versionadded:: 2.0
941 .. seealso::
943 :ref:`write_only_relationship` - complete background
945 :class:`.DynamicMapped` - includes legacy :class:`_orm.Query` support
947 """
949 __slots__ = ()
951 if TYPE_CHECKING:
953 @overload
954 def __get__(
955 self, instance: None, owner: Any
956 ) -> InstrumentedAttribute[_T_co]: ...
958 @overload
959 def __get__(
960 self, instance: object, owner: Any
961 ) -> WriteOnlyCollection[_T_co]: ...
963 def __get__(
964 self, instance: Optional[object], owner: Any
965 ) -> Union[
966 InstrumentedAttribute[_T_co], WriteOnlyCollection[_T_co]
967 ]: ...
969 def __set__(
970 self, instance: Any, value: typing.Collection[_T_co]
971 ) -> None: ...