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
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-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
8"""Constants and rudimental functions used throughout the ORM."""
10from __future__ import annotations
12from enum import Enum
13import operator
14import typing
15from typing import Any
16from typing import Callable
17from typing import Dict
18from typing import Generic
19from typing import no_type_check
20from typing import Optional
21from typing import overload
22from typing import Tuple
23from typing import Type
24from typing import TYPE_CHECKING
25from typing import TypeVar
26from typing import Union
28from . import exc
29from ._typing import insp_is_mapper
30from .. import exc as sa_exc
31from .. import inspection
32from .. import util
33from ..sql import roles
34from ..sql.elements import SQLColumnExpression
35from ..sql.elements import SQLCoreOperations
36from ..util import FastIntFlag
37from ..util.langhelpers import TypingOnly
38from ..util.typing import Literal
40if typing.TYPE_CHECKING:
41 from ._typing import _EntityType
42 from ._typing import _ExternalEntityType
43 from ._typing import _InternalEntityType
44 from .attributes import InstrumentedAttribute
45 from .dynamic import AppenderQuery
46 from .instrumentation import ClassManager
47 from .interfaces import PropComparator
48 from .mapper import Mapper
49 from .state import InstanceState
50 from .util import AliasedClass
51 from .writeonly import WriteOnlyCollection
52 from ..sql._typing import _ColumnExpressionArgument
53 from ..sql._typing import _InfoType
54 from ..sql.elements import ColumnElement
55 from ..sql.operators import OperatorType
57_T = TypeVar("_T", bound=Any)
58_T_co = TypeVar("_T_co", bound=Any, covariant=True)
60_O = TypeVar("_O", bound=object)
63class LoaderCallableStatus(Enum):
64 PASSIVE_NO_RESULT = 0
65 """Symbol returned by a loader callable or other attribute/history
66 retrieval operation when a value could not be determined, based
67 on loader callable flags.
68 """
70 PASSIVE_CLASS_MISMATCH = 1
71 """Symbol indicating that an object is locally present for a given
72 primary key identity but it is not of the requested class. The
73 return value is therefore None and no SQL should be emitted."""
75 ATTR_WAS_SET = 2
76 """Symbol returned by a loader callable to indicate the
77 retrieved value, or values, were assigned to their attributes
78 on the target object.
79 """
81 ATTR_EMPTY = 3
82 """Symbol used internally to indicate an attribute had no callable."""
84 NO_VALUE = 4
85 """Symbol which may be placed as the 'previous' value of an attribute,
86 indicating no value was loaded for an attribute when it was modified,
87 and flags indicated we were not to load it.
88 """
90 NEVER_SET = NO_VALUE
91 """
92 Synonymous with NO_VALUE
94 .. versionchanged:: 1.4 NEVER_SET was merged with NO_VALUE
96 """
99(
100 PASSIVE_NO_RESULT,
101 PASSIVE_CLASS_MISMATCH,
102 ATTR_WAS_SET,
103 ATTR_EMPTY,
104 NO_VALUE,
105) = tuple(LoaderCallableStatus)
107NEVER_SET = NO_VALUE
110class PassiveFlag(FastIntFlag):
111 """Bitflag interface that passes options onto loader callables"""
113 NO_CHANGE = 0
114 """No callables or SQL should be emitted on attribute access
115 and no state should change
116 """
118 CALLABLES_OK = 1
119 """Loader callables can be fired off if a value
120 is not present.
121 """
123 SQL_OK = 2
124 """Loader callables can emit SQL at least on scalar value attributes."""
126 RELATED_OBJECT_OK = 4
127 """Callables can use SQL to load related objects as well
128 as scalar value attributes.
129 """
131 INIT_OK = 8
132 """Attributes should be initialized with a blank
133 value (None or an empty collection) upon get, if no other
134 value can be obtained.
135 """
137 NON_PERSISTENT_OK = 16
138 """Callables can be emitted if the parent is not persistent."""
140 LOAD_AGAINST_COMMITTED = 32
141 """Callables should use committed values as primary/foreign keys during a
142 load.
143 """
145 NO_AUTOFLUSH = 64
146 """Loader callables should disable autoflush."""
148 NO_RAISE = 128
149 """Loader callables should not raise any assertions"""
151 DEFERRED_HISTORY_LOAD = 256
152 """indicates special load of the previous value of an attribute"""
154 INCLUDE_PENDING_MUTATIONS = 512
156 # pre-packaged sets of flags used as inputs
157 PASSIVE_OFF = (
158 RELATED_OBJECT_OK | NON_PERSISTENT_OK | INIT_OK | CALLABLES_OK | SQL_OK
159 )
160 "Callables can be emitted in all cases."
162 PASSIVE_RETURN_NO_VALUE = PASSIVE_OFF ^ INIT_OK
163 """PASSIVE_OFF ^ INIT_OK"""
165 PASSIVE_NO_INITIALIZE = PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK
166 "PASSIVE_RETURN_NO_VALUE ^ CALLABLES_OK"
168 PASSIVE_NO_FETCH = PASSIVE_OFF ^ SQL_OK
169 "PASSIVE_OFF ^ SQL_OK"
171 PASSIVE_NO_FETCH_RELATED = PASSIVE_OFF ^ RELATED_OBJECT_OK
172 "PASSIVE_OFF ^ RELATED_OBJECT_OK"
174 PASSIVE_ONLY_PERSISTENT = PASSIVE_OFF ^ NON_PERSISTENT_OK
175 "PASSIVE_OFF ^ NON_PERSISTENT_OK"
177 PASSIVE_MERGE = PASSIVE_OFF | NO_RAISE
178 """PASSIVE_OFF | NO_RAISE
180 Symbol used specifically for session.merge() and similar cases
182 """
185(
186 NO_CHANGE,
187 CALLABLES_OK,
188 SQL_OK,
189 RELATED_OBJECT_OK,
190 INIT_OK,
191 NON_PERSISTENT_OK,
192 LOAD_AGAINST_COMMITTED,
193 NO_AUTOFLUSH,
194 NO_RAISE,
195 DEFERRED_HISTORY_LOAD,
196 INCLUDE_PENDING_MUTATIONS,
197 PASSIVE_OFF,
198 PASSIVE_RETURN_NO_VALUE,
199 PASSIVE_NO_INITIALIZE,
200 PASSIVE_NO_FETCH,
201 PASSIVE_NO_FETCH_RELATED,
202 PASSIVE_ONLY_PERSISTENT,
203 PASSIVE_MERGE,
204) = PassiveFlag.__members__.values()
206DEFAULT_MANAGER_ATTR = "_sa_class_manager"
207DEFAULT_STATE_ATTR = "_sa_instance_state"
210class EventConstants(Enum):
211 EXT_CONTINUE = 1
212 EXT_STOP = 2
213 EXT_SKIP = 3
214 NO_KEY = 4
215 """indicates an :class:`.AttributeEvent` event that did not have any
216 key argument.
218 .. versionadded:: 2.0
220 """
223EXT_CONTINUE, EXT_STOP, EXT_SKIP, NO_KEY = tuple(EventConstants)
226class RelationshipDirection(Enum):
227 """enumeration which indicates the 'direction' of a
228 :class:`_orm.RelationshipProperty`.
230 :class:`.RelationshipDirection` is accessible from the
231 :attr:`_orm.Relationship.direction` attribute of
232 :class:`_orm.RelationshipProperty`.
234 """
236 ONETOMANY = 1
237 """Indicates the one-to-many direction for a :func:`_orm.relationship`.
239 This symbol is typically used by the internals but may be exposed within
240 certain API features.
242 """
244 MANYTOONE = 2
245 """Indicates the many-to-one direction for a :func:`_orm.relationship`.
247 This symbol is typically used by the internals but may be exposed within
248 certain API features.
250 """
252 MANYTOMANY = 3
253 """Indicates the many-to-many direction for a :func:`_orm.relationship`.
255 This symbol is typically used by the internals but may be exposed within
256 certain API features.
258 """
261ONETOMANY, MANYTOONE, MANYTOMANY = tuple(RelationshipDirection)
264class InspectionAttrExtensionType(Enum):
265 """Symbols indicating the type of extension that a
266 :class:`.InspectionAttr` is part of."""
269class NotExtension(InspectionAttrExtensionType):
270 NOT_EXTENSION = "not_extension"
271 """Symbol indicating an :class:`InspectionAttr` that's
272 not part of sqlalchemy.ext.
274 Is assigned to the :attr:`.InspectionAttr.extension_type`
275 attribute.
277 """
280_never_set = frozenset([NEVER_SET])
282_none_set = frozenset([None, NEVER_SET, PASSIVE_NO_RESULT])
284_none_only_set = frozenset([None])
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: ...