Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
base.py972 linesDownload Raw Back to orm
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: ...
972 
codekingpro/portable-devtools · Team Ai