1# orm/scoping.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 
    7 
    8from __future__ import annotations 
    9 
    10from typing import Any 
    11from typing import Callable 
    12from typing import Dict 
    13from typing import Generic 
    14from typing import Iterable 
    15from typing import Iterator 
    16from typing import Optional 
    17from typing import overload 
    18from typing import Protocol 
    19from typing import Sequence 
    20from typing import Tuple 
    21from typing import Type 
    22from typing import TYPE_CHECKING 
    23from typing import TypeVar 
    24from typing import Union 
    25 
    26from .session import _S 
    27from .session import Session 
    28from .. import exc as sa_exc 
    29from .. import util 
    30from ..util import create_proxy_methods 
    31from ..util import ScopedRegistry 
    32from ..util import ThreadLocalRegistry 
    33from ..util import warn 
    34from ..util import warn_deprecated 
    35from ..util.typing import TupleAny 
    36from ..util.typing import TypeVarTuple 
    37from ..util.typing import Unpack 
    38 
    39if TYPE_CHECKING: 
    40    from ._typing import _EntityType 
    41    from ._typing import _IdentityKeyType 
    42    from ._typing import OrmExecuteOptionsParameter 
    43    from .identity import IdentityMap 
    44    from .interfaces import ORMOption 
    45    from .mapper import Mapper 
    46    from .query import Query 
    47    from .query import RowReturningQuery 
    48    from .session import _BindArguments 
    49    from .session import _EntityBindKey 
    50    from .session import _PKIdentityArgument 
    51    from .session import _SessionBind 
    52    from .session import sessionmaker 
    53    from .session import SessionTransaction 
    54    from ..engine import Connection 
    55    from ..engine import Engine 
    56    from ..engine import Result 
    57    from ..engine import Row 
    58    from ..engine import RowMapping 
    59    from ..engine.interfaces import _CoreAnyExecuteParams 
    60    from ..engine.interfaces import _CoreSingleExecuteParams 
    61    from ..engine.interfaces import _ExecuteOptions 
    62    from ..engine.interfaces import CoreExecuteOptionsParameter 
    63    from ..engine.result import ScalarResult 
    64    from ..sql._typing import _ColumnsClauseArgument 
    65    from ..sql._typing import _T0 
    66    from ..sql._typing import _T1 
    67    from ..sql._typing import _T2 
    68    from ..sql._typing import _T3 
    69    from ..sql._typing import _T4 
    70    from ..sql._typing import _T5 
    71    from ..sql._typing import _T6 
    72    from ..sql._typing import _T7 
    73    from ..sql._typing import _TypedColumnClauseArgument as _TCCA 
    74    from ..sql.base import Executable 
    75    from ..sql.elements import ClauseElement 
    76    from ..sql.roles import TypedColumnsClauseRole 
    77    from ..sql.selectable import ForUpdateParameter 
    78    from ..sql.selectable import TypedReturnsRows 
    79 
    80 
    81_T = TypeVar("_T", bound=Any) 
    82_Ts = TypeVarTuple("_Ts") 
    83 
    84 
    85class QueryPropertyDescriptor(Protocol): 
    86    """Describes the type applied to a class-level 
    87    :meth:`_orm.scoped_session.query_property` attribute. 
    88 
    89    .. versionadded:: 2.0.5 
    90 
    91    """ 
    92 
    93    def __get__(self, instance: Any, owner: Type[_T]) -> Query[_T]: ... 
    94 
    95 
    96_O = TypeVar("_O", bound=object) 
    97 
    98__all__ = ["scoped_session"] 
    99 
    100 
    101@create_proxy_methods( 
    102    Session, 
    103    ":class:`_orm.Session`", 
    104    ":class:`_orm.scoping.scoped_session`", 
    105    classmethods=["object_session", "identity_key"], 
    106    methods=[ 
    107        "__contains__", 
    108        "__iter__", 
    109        "add", 
    110        "add_all", 
    111        "begin", 
    112        "begin_nested", 
    113        "close", 
    114        "reset", 
    115        "commit", 
    116        "connection", 
    117        "delete", 
    118        "delete_all", 
    119        "execute", 
    120        "expire", 
    121        "expire_all", 
    122        "expunge", 
    123        "expunge_all", 
    124        "flush", 
    125        "get", 
    126        "get_one", 
    127        "get_bind", 
    128        "is_modified", 
    129        "bulk_save_objects", 
    130        "bulk_insert_mappings", 
    131        "bulk_update_mappings", 
    132        "merge", 
    133        "merge_all", 
    134        "query", 
    135        "refresh", 
    136        "rollback", 
    137        "scalar", 
    138        "scalars", 
    139    ], 
    140    attributes=[ 
    141        "bind", 
    142        "dirty", 
    143        "deleted", 
    144        "new", 
    145        "identity_map", 
    146        "is_active", 
    147        "autoflush", 
    148        "no_autoflush", 
    149        "info", 
    150        "execution_options", 
    151    ], 
    152) 
    153class scoped_session(Generic[_S]): 
    154    """Provides scoped management of :class:`.Session` objects. 
    155 
    156    See :ref:`unitofwork_contextual` for a tutorial. 
    157 
    158    .. note:: 
    159 
    160       When using :ref:`asyncio_toplevel`, the async-compatible 
    161       :class:`_asyncio.async_scoped_session` class should be 
    162       used in place of :class:`.scoped_session`. 
    163 
    164    """ 
    165 
    166    _support_async: bool = False 
    167 
    168    session_factory: sessionmaker[_S] 
    169    """The `session_factory` provided to `__init__` is stored in this 
    170    attribute and may be accessed at a later time.  This can be useful when 
    171    a new non-scoped :class:`.Session` is needed.""" 
    172 
    173    registry: ScopedRegistry[_S] 
    174 
    175    def __init__( 
    176        self, 
    177        session_factory: sessionmaker[_S], 
    178        scopefunc: Optional[Callable[[], Any]] = None, 
    179    ): 
    180        """Construct a new :class:`.scoped_session`. 
    181 
    182        :param session_factory: a factory to create new :class:`.Session` 
    183         instances. This is usually, but not necessarily, an instance 
    184         of :class:`.sessionmaker`. 
    185        :param scopefunc: optional function which defines 
    186         the current scope.   If not passed, the :class:`.scoped_session` 
    187         object assumes "thread-local" scope, and will use 
    188         a Python ``threading.local()`` in order to maintain the current 
    189         :class:`.Session`.  If passed, the function should return 
    190         a hashable token; this token will be used as the key in a 
    191         dictionary in order to store and retrieve the current 
    192         :class:`.Session`. 
    193 
    194        """ 
    195        self.session_factory = session_factory 
    196 
    197        if scopefunc: 
    198            self.registry = ScopedRegistry(session_factory, scopefunc) 
    199        else: 
    200            self.registry = ThreadLocalRegistry(session_factory) 
    201 
    202    @property 
    203    def _proxied(self) -> _S: 
    204        return self.registry() 
    205 
    206    def __call__(self, **kw: Any) -> _S: 
    207        r"""Return the current :class:`.Session`, creating it 
    208        using the :attr:`.scoped_session.session_factory` if not present. 
    209 
    210        :param \**kw: Keyword arguments will be passed to the 
    211         :attr:`.scoped_session.session_factory` callable, if an existing 
    212         :class:`.Session` is not present.  If the :class:`.Session` is present 
    213         and keyword arguments have been passed, 
    214         :exc:`~sqlalchemy.exc.InvalidRequestError` is raised. 
    215 
    216        """ 
    217        if kw: 
    218            if self.registry.has(): 
    219                raise sa_exc.InvalidRequestError( 
    220                    "Scoped session is already present; " 
    221                    "no new arguments may be specified." 
    222                ) 
    223            else: 
    224                sess = self.session_factory(**kw) 
    225                self.registry.set(sess) 
    226        else: 
    227            sess = self.registry() 
    228        if not self._support_async and sess._is_asyncio: 
    229            warn_deprecated( 
    230                "Using `scoped_session` with asyncio is deprecated and " 
    231                "will raise an error in a future version. " 
    232                "Please use `async_scoped_session` instead.", 
    233                "1.4.23", 
    234            ) 
    235        return sess 
    236 
    237    def configure(self, **kwargs: Any) -> None: 
    238        """reconfigure the :class:`.sessionmaker` used by this 
    239        :class:`.scoped_session`. 
    240 
    241        See :meth:`.sessionmaker.configure`. 
    242 
    243        """ 
    244 
    245        if self.registry.has(): 
    246            warn( 
    247                "At least one scoped session is already present. " 
    248                " configure() can not affect sessions that have " 
    249                "already been created." 
    250            ) 
    251 
    252        self.session_factory.configure(**kwargs) 
    253 
    254    def remove(self) -> None: 
    255        """Dispose of the current :class:`.Session`, if present. 
    256 
    257        This will first call :meth:`.Session.close` method 
    258        on the current :class:`.Session`, which releases any existing 
    259        transactional/connection resources still being held; transactions 
    260        specifically are rolled back.  The :class:`.Session` is then 
    261        discarded.   Upon next usage within the same scope, 
    262        the :class:`.scoped_session` will produce a new 
    263        :class:`.Session` object. 
    264 
    265        """ 
    266 
    267        if self.registry.has(): 
    268            self.registry().close() 
    269        self.registry.clear() 
    270 
    271    def query_property( 
    272        self, query_cls: Optional[Type[Query[_T]]] = None 
    273    ) -> QueryPropertyDescriptor: 
    274        """return a class property which produces a legacy 
    275        :class:`_query.Query` object against the class and the current 
    276        :class:`.Session` when called. 
    277 
    278        .. legacy:: The :meth:`_orm.scoped_session.query_property` accessor 
    279           is specific to the legacy :class:`.Query` object and is not 
    280           considered to be part of :term:`2.0-style` ORM use. 
    281 
    282        e.g.:: 
    283 
    284            from sqlalchemy.orm import QueryPropertyDescriptor 
    285            from sqlalchemy.orm import scoped_session 
    286            from sqlalchemy.orm import sessionmaker 
    287 
    288            Session = scoped_session(sessionmaker()) 
    289 
    290 
    291            class MyClass: 
    292                query: QueryPropertyDescriptor = Session.query_property() 
    293 
    294 
    295            # after mappers are defined 
    296            result = MyClass.query.filter(MyClass.name == "foo").all() 
    297 
    298        Produces instances of the session's configured query class by 
    299        default.  To override and use a custom implementation, provide 
    300        a ``query_cls`` callable.  The callable will be invoked with 
    301        the class's mapper as a positional argument and a session 
    302        keyword argument. 
    303 
    304        There is no limit to the number of query properties placed on 
    305        a class. 
    306 
    307        """ 
    308 
    309        class query: 
    310            def __get__(s, instance: Any, owner: Type[_O]) -> Query[_O]: 
    311                if query_cls: 
    312                    # custom query class 
    313                    return query_cls(owner, session=self.registry())  # type: ignore  # noqa: E501 
    314                else: 
    315                    # session's configured query class 
    316                    return self.registry().query(owner) 
    317 
    318        return query() 
    319 
    320    # START PROXY METHODS scoped_session 
    321 
    322    # code within this block is **programmatically, 
    323    # statically generated** by tools/generate_proxy_methods.py 
    324 
    325    def __contains__(self, instance: object) -> bool: 
    326        r"""Return True if the instance is associated with this session. 
    327 
    328        .. container:: class_bases 
    329 
    330            Proxied for the :class:`_orm.Session` class on 
    331            behalf of the :class:`_orm.scoping.scoped_session` class. 
    332 
    333        The instance may be pending or persistent within the Session for a 
    334        result of True. 
    335 
    336 
    337        """  # noqa: E501 
    338 
    339        return self._proxied.__contains__(instance) 
    340 
    341    def __iter__(self) -> Iterator[object]: 
    342        r"""Iterate over all pending or persistent instances within this 
    343        Session. 
    344 
    345        .. container:: class_bases 
    346 
    347            Proxied for the :class:`_orm.Session` class on 
    348            behalf of the :class:`_orm.scoping.scoped_session` class. 
    349 
    350 
    351        """  # noqa: E501 
    352 
    353        return self._proxied.__iter__() 
    354 
    355    def add(self, instance: object, *, _warn: bool = True) -> None: 
    356        r"""Place an object into this :class:`_orm.Session`. 
    357 
    358        .. container:: class_bases 
    359 
    360            Proxied for the :class:`_orm.Session` class on 
    361            behalf of the :class:`_orm.scoping.scoped_session` class. 
    362 
    363        Objects that are in the :term:`transient` state when passed to the 
    364        :meth:`_orm.Session.add` method will move to the 
    365        :term:`pending` state, until the next flush, at which point they 
    366        will move to the :term:`persistent` state. 
    367 
    368        Objects that are in the :term:`detached` state when passed to the 
    369        :meth:`_orm.Session.add` method will move to the :term:`persistent` 
    370        state directly. 
    371 
    372        If the transaction used by the :class:`_orm.Session` is rolled back, 
    373        objects which were transient when they were passed to 
    374        :meth:`_orm.Session.add` will be moved back to the 
    375        :term:`transient` state, and will no longer be present within this 
    376        :class:`_orm.Session`. 
    377 
    378        .. seealso:: 
    379 
    380            :meth:`_orm.Session.add_all` 
    381 
    382            :ref:`session_adding` - at :ref:`session_basics` 
    383 
    384 
    385        """  # noqa: E501 
    386 
    387        return self._proxied.add(instance, _warn=_warn) 
    388 
    389    def add_all(self, instances: Iterable[object]) -> None: 
    390        r"""Add the given collection of instances to this :class:`_orm.Session`. 
    391 
    392        .. container:: class_bases 
    393 
    394            Proxied for the :class:`_orm.Session` class on 
    395            behalf of the :class:`_orm.scoping.scoped_session` class. 
    396 
    397        See the documentation for :meth:`_orm.Session.add` for a general 
    398        behavioral description. 
    399 
    400        .. seealso:: 
    401 
    402            :meth:`_orm.Session.add` 
    403 
    404            :ref:`session_adding` - at :ref:`session_basics` 
    405 
    406 
    407        """  # noqa: E501 
    408 
    409        return self._proxied.add_all(instances) 
    410 
    411    def begin(self, nested: bool = False) -> SessionTransaction: 
    412        r"""Begin a transaction, or nested transaction, 
    413        on this :class:`.Session`, if one is not already begun. 
    414 
    415        .. container:: class_bases 
    416 
    417            Proxied for the :class:`_orm.Session` class on 
    418            behalf of the :class:`_orm.scoping.scoped_session` class. 
    419 
    420        The :class:`_orm.Session` object features **autobegin** behavior, 
    421        so that normally it is not necessary to call the 
    422        :meth:`_orm.Session.begin` 
    423        method explicitly. However, it may be used in order to control 
    424        the scope of when the transactional state is begun. 
    425 
    426        When used to begin the outermost transaction, an error is raised 
    427        if this :class:`.Session` is already inside of a transaction. 
    428 
    429        :param nested: if True, begins a SAVEPOINT transaction and is 
    430         equivalent to calling :meth:`~.Session.begin_nested`. For 
    431         documentation on SAVEPOINT transactions, please see 
    432         :ref:`session_begin_nested`. 
    433 
    434        :return: the :class:`.SessionTransaction` object.  Note that 
    435         :class:`.SessionTransaction` 
    436         acts as a Python context manager, allowing :meth:`.Session.begin` 
    437         to be used in a "with" block.  See :ref:`session_explicit_begin` for 
    438         an example. 
    439 
    440        .. seealso:: 
    441 
    442            :ref:`session_autobegin` 
    443 
    444            :ref:`unitofwork_transaction` 
    445 
    446            :meth:`.Session.begin_nested` 
    447 
    448 
    449 
    450        """  # noqa: E501 
    451 
    452        return self._proxied.begin(nested=nested) 
    453 
    454    def begin_nested(self) -> SessionTransaction: 
    455        r"""Begin a "nested" transaction on this Session, e.g. SAVEPOINT. 
    456 
    457        .. container:: class_bases 
    458 
    459            Proxied for the :class:`_orm.Session` class on 
    460            behalf of the :class:`_orm.scoping.scoped_session` class. 
    461 
    462        The target database(s) and associated drivers must support SQL 
    463        SAVEPOINT for this method to function correctly. 
    464 
    465        For documentation on SAVEPOINT 
    466        transactions, please see :ref:`session_begin_nested`. 
    467 
    468        :return: the :class:`.SessionTransaction` object.  Note that 
    469         :class:`.SessionTransaction` acts as a context manager, allowing 
    470         :meth:`.Session.begin_nested` to be used in a "with" block. 
    471         See :ref:`session_begin_nested` for a usage example. 
    472 
    473        .. seealso:: 
    474 
    475            :ref:`session_begin_nested` 
    476 
    477            :ref:`pysqlite_serializable` - special workarounds required 
    478            with the SQLite driver in order for SAVEPOINT to work 
    479            correctly. For asyncio use cases, see the section 
    480            :ref:`aiosqlite_serializable`. 
    481 
    482 
    483        """  # noqa: E501 
    484 
    485        return self._proxied.begin_nested() 
    486 
    487    def close(self) -> None: 
    488        r"""Close out the transactional resources and ORM objects used by this 
    489        :class:`_orm.Session`. 
    490 
    491        .. container:: class_bases 
    492 
    493            Proxied for the :class:`_orm.Session` class on 
    494            behalf of the :class:`_orm.scoping.scoped_session` class. 
    495 
    496        This expunges all ORM objects associated with this 
    497        :class:`_orm.Session`, ends any transaction in progress and 
    498        :term:`releases` any :class:`_engine.Connection` objects which this 
    499        :class:`_orm.Session` itself has checked out from associated 
    500        :class:`_engine.Engine` objects. The operation then leaves the 
    501        :class:`_orm.Session` in a state which it may be used again. 
    502 
    503        .. tip:: 
    504 
    505            In the default running mode the :meth:`_orm.Session.close` 
    506            method **does not prevent the Session from being used again**. 
    507            The :class:`_orm.Session` itself does not actually have a 
    508            distinct "closed" state; it merely means 
    509            the :class:`_orm.Session` will release all database connections 
    510            and ORM objects. 
    511 
    512            Setting the parameter :paramref:`_orm.Session.close_resets_only` 
    513            to ``False`` will instead make the ``close`` final, meaning that 
    514            any further action on the session will be forbidden. 
    515 
    516        .. versionchanged:: 1.4  The :meth:`.Session.close` method does not 
    517           immediately create a new :class:`.SessionTransaction` object; 
    518           instead, the new :class:`.SessionTransaction` is created only if 
    519           the :class:`.Session` is used again for a database operation. 
    520 
    521        .. seealso:: 
    522 
    523            :ref:`session_closing` - detail on the semantics of 
    524            :meth:`_orm.Session.close` and :meth:`_orm.Session.reset`. 
    525 
    526            :meth:`_orm.Session.reset` - a similar method that behaves like 
    527            ``close()`` with  the parameter 
    528            :paramref:`_orm.Session.close_resets_only` set to ``True``. 
    529 
    530 
    531        """  # noqa: E501 
    532 
    533        return self._proxied.close() 
    534 
    535    def reset(self) -> None: 
    536        r"""Close out the transactional resources and ORM objects used by this 
    537        :class:`_orm.Session`, resetting the session to its initial state. 
    538 
    539        .. container:: class_bases 
    540 
    541            Proxied for the :class:`_orm.Session` class on 
    542            behalf of the :class:`_orm.scoping.scoped_session` class. 
    543 
    544        This method provides for same "reset-only" behavior that the 
    545        :meth:`_orm.Session.close` method has provided historically, where the 
    546        state of the :class:`_orm.Session` is reset as though the object were 
    547        brand new, and ready to be used again. 
    548        This method may then be useful for :class:`_orm.Session` objects 
    549        which set :paramref:`_orm.Session.close_resets_only` to ``False``, 
    550        so that "reset only" behavior is still available. 
    551 
    552        .. versionadded:: 2.0.22 
    553 
    554        .. seealso:: 
    555 
    556            :ref:`session_closing` - detail on the semantics of 
    557            :meth:`_orm.Session.close` and :meth:`_orm.Session.reset`. 
    558 
    559            :meth:`_orm.Session.close` - a similar method will additionally 
    560            prevent re-use of the Session when the parameter 
    561            :paramref:`_orm.Session.close_resets_only` is set to ``False``. 
    562 
    563        """  # noqa: E501 
    564 
    565        return self._proxied.reset() 
    566 
    567    def commit(self) -> None: 
    568        r"""Flush pending changes and commit the current transaction. 
    569 
    570        .. container:: class_bases 
    571 
    572            Proxied for the :class:`_orm.Session` class on 
    573            behalf of the :class:`_orm.scoping.scoped_session` class. 
    574 
    575        When the COMMIT operation is complete, all objects are fully 
    576        :term:`expired`, erasing their internal contents, which will be 
    577        automatically re-loaded when the objects are next accessed. In the 
    578        interim, these objects are in an expired state and will not function if 
    579        they are :term:`detached` from the :class:`.Session`. Additionally, 
    580        this re-load operation is not supported when using asyncio-oriented 
    581        APIs. The :paramref:`.Session.expire_on_commit` parameter may be used 
    582        to disable this behavior. 
    583 
    584        When there is no transaction in place for the :class:`.Session`, 
    585        indicating that no operations were invoked on this :class:`.Session` 
    586        since the previous call to :meth:`.Session.commit`, the method will 
    587        begin and commit an internal-only "logical" transaction, that does not 
    588        normally affect the database unless pending flush changes were 
    589        detected, but will still invoke event handlers and object expiration 
    590        rules. 
    591 
    592        The outermost database transaction is committed unconditionally, 
    593        automatically releasing any SAVEPOINTs in effect. 
    594 
    595        .. seealso:: 
    596 
    597            :ref:`session_committing` 
    598 
    599            :ref:`unitofwork_transaction` 
    600 
    601            :ref:`asyncio_orm_avoid_lazyloads` 
    602 
    603 
    604        """  # noqa: E501 
    605 
    606        return self._proxied.commit() 
    607 
    608    def connection( 
    609        self, 
    610        bind_arguments: Optional[_BindArguments] = None, 
    611        execution_options: Optional[CoreExecuteOptionsParameter] = None, 
    612    ) -> Connection: 
    613        r"""Return a :class:`_engine.Connection` object corresponding to this 
    614        :class:`.Session` object's transactional state. 
    615 
    616        .. container:: class_bases 
    617 
    618            Proxied for the :class:`_orm.Session` class on 
    619            behalf of the :class:`_orm.scoping.scoped_session` class. 
    620 
    621        Either the :class:`_engine.Connection` corresponding to the current 
    622        transaction is returned, or if no transaction is in progress, a new 
    623        one is begun and the :class:`_engine.Connection` 
    624        returned (note that no 
    625        transactional state is established with the DBAPI until the first 
    626        SQL statement is emitted). 
    627 
    628        Ambiguity in multi-bind or unbound :class:`.Session` objects can be 
    629        resolved through any of the optional keyword arguments.   This 
    630        ultimately makes usage of the :meth:`.get_bind` method for resolution. 
    631 
    632        :param bind_arguments: dictionary of bind arguments.  May include 
    633         "mapper", "bind", "clause", other custom arguments that are passed 
    634         to :meth:`.Session.get_bind`. 
    635 
    636        :param execution_options: a dictionary of execution options that will 
    637         be passed to :meth:`_engine.Connection.execution_options`, **when the 
    638         connection is first procured only**.   If the connection is already 
    639         present within the :class:`.Session`, a warning is emitted and 
    640         the arguments are ignored. 
    641 
    642         .. seealso:: 
    643 
    644            :ref:`session_transaction_isolation` 
    645 
    646 
    647        """  # noqa: E501 
    648 
    649        return self._proxied.connection( 
    650            bind_arguments=bind_arguments, execution_options=execution_options 
    651        ) 
    652 
    653    def delete(self, instance: object) -> None: 
    654        r"""Mark an instance as deleted. 
    655 
    656        .. container:: class_bases 
    657 
    658            Proxied for the :class:`_orm.Session` class on 
    659            behalf of the :class:`_orm.scoping.scoped_session` class. 
    660 
    661        The object is assumed to be either :term:`persistent` or 
    662        :term:`detached` when passed; after the method is called, the 
    663        object will remain in the :term:`persistent` state until the next 
    664        flush proceeds.  During this time, the object will also be a member 
    665        of the :attr:`_orm.Session.deleted` collection. 
    666 
    667        When the next flush proceeds, the object will move to the 
    668        :term:`deleted` state, indicating a ``DELETE`` statement was emitted 
    669        for its row within the current transaction.   When the transaction 
    670        is successfully committed, 
    671        the deleted object is moved to the :term:`detached` state and is 
    672        no longer present within this :class:`_orm.Session`. 
    673 
    674        .. seealso:: 
    675 
    676            :ref:`session_deleting` - at :ref:`session_basics` 
    677 
    678            :meth:`.Session.delete_all` - multiple instance version 
    679 
    680 
    681        """  # noqa: E501 
    682 
    683        return self._proxied.delete(instance) 
    684 
    685    def delete_all(self, instances: Iterable[object]) -> None: 
    686        r"""Calls :meth:`.Session.delete` on multiple instances. 
    687 
    688        .. container:: class_bases 
    689 
    690            Proxied for the :class:`_orm.Session` class on 
    691            behalf of the :class:`_orm.scoping.scoped_session` class. 
    692 
    693        .. seealso:: 
    694 
    695            :meth:`.Session.delete` - main documentation on delete 
    696 
    697        .. versionadded:: 2.1 
    698 
    699 
    700        """  # noqa: E501 
    701 
    702        return self._proxied.delete_all(instances) 
    703 
    704    @overload 
    705    def execute( 
    706        self, 
    707        statement: TypedReturnsRows[Unpack[_Ts]], 
    708        params: Optional[_CoreAnyExecuteParams] = None, 
    709        *, 
    710        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    711        bind_arguments: Optional[_BindArguments] = None, 
    712        _parent_execute_state: Optional[Any] = None, 
    713        _add_event: Optional[Any] = None, 
    714    ) -> Result[Unpack[_Ts]]: ... 
    715 
    716    @overload 
    717    def execute( 
    718        self, 
    719        statement: Executable, 
    720        params: Optional[_CoreAnyExecuteParams] = None, 
    721        *, 
    722        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    723        bind_arguments: Optional[_BindArguments] = None, 
    724        _parent_execute_state: Optional[Any] = None, 
    725        _add_event: Optional[Any] = None, 
    726    ) -> Result[Unpack[TupleAny]]: ... 
    727 
    728    def execute( 
    729        self, 
    730        statement: Executable, 
    731        params: Optional[_CoreAnyExecuteParams] = None, 
    732        *, 
    733        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    734        bind_arguments: Optional[_BindArguments] = None, 
    735        _parent_execute_state: Optional[Any] = None, 
    736        _add_event: Optional[Any] = None, 
    737    ) -> Result[Unpack[TupleAny]]: 
    738        r"""Execute a SQL expression construct. 
    739 
    740        .. container:: class_bases 
    741 
    742            Proxied for the :class:`_orm.Session` class on 
    743            behalf of the :class:`_orm.scoping.scoped_session` class. 
    744 
    745        Returns a :class:`_engine.Result` object representing 
    746        results of the statement execution. 
    747 
    748        E.g.:: 
    749 
    750            from sqlalchemy import select 
    751 
    752            result = session.execute(select(User).where(User.id == 5)) 
    753 
    754        The API contract of :meth:`_orm.Session.execute` is similar to that 
    755        of :meth:`_engine.Connection.execute`, the :term:`2.0 style` version 
    756        of :class:`_engine.Connection`. 
    757 
    758        .. versionchanged:: 1.4 the :meth:`_orm.Session.execute` method is 
    759           now the primary point of ORM statement execution when using 
    760           :term:`2.0 style` ORM usage. 
    761 
    762        :param statement: 
    763            An executable statement (i.e. an :class:`.Executable` expression 
    764            such as :func:`_expression.select`). 
    765 
    766        :param params: 
    767            Optional dictionary, or list of dictionaries, containing 
    768            bound parameter values.   If a single dictionary, single-row 
    769            execution occurs; if a list of dictionaries, an 
    770            "executemany" will be invoked.  The keys in each dictionary 
    771            must correspond to parameter names present in the statement. 
    772 
    773        :param execution_options: optional dictionary of execution options, 
    774         which will be associated with the statement execution.  This 
    775         dictionary can provide a subset of the options that are accepted 
    776         by :meth:`_engine.Connection.execution_options`, and may also 
    777         provide additional options understood only in an ORM context. 
    778 
    779         The execution_options are passed along to methods like 
    780         :meth:`.Connection.execute` on :class:`.Connection` giving the 
    781         highest priority to execution_options that are passed to this 
    782         method explicitly, then the options that are present on the 
    783         statement object if any, and finally those options present 
    784         session-wide. 
    785 
    786         .. seealso:: 
    787 
    788            :ref:`orm_queryguide_execution_options` - ORM-specific execution 
    789            options 
    790 
    791        :param bind_arguments: dictionary of additional arguments to determine 
    792         the bind.  May include "mapper", "bind", or other custom arguments. 
    793         Contents of this dictionary are passed to the 
    794         :meth:`.Session.get_bind` method. 
    795 
    796        :return: a :class:`_engine.Result` object. 
    797 
    798 
    799 
    800        """  # noqa: E501 
    801 
    802        return self._proxied.execute( 
    803            statement, 
    804            params=params, 
    805            execution_options=execution_options, 
    806            bind_arguments=bind_arguments, 
    807            _parent_execute_state=_parent_execute_state, 
    808            _add_event=_add_event, 
    809        ) 
    810 
    811    def expire( 
    812        self, instance: object, attribute_names: Optional[Iterable[str]] = None 
    813    ) -> None: 
    814        r"""Expire the attributes on an instance. 
    815 
    816        .. container:: class_bases 
    817 
    818            Proxied for the :class:`_orm.Session` class on 
    819            behalf of the :class:`_orm.scoping.scoped_session` class. 
    820 
    821        Marks the attributes of an instance as out of date. When an expired 
    822        attribute is next accessed, a query will be issued to the 
    823        :class:`.Session` object's current transactional context in order to 
    824        load all expired attributes for the given instance.   Note that 
    825        a highly isolated transaction will return the same values as were 
    826        previously read in that same transaction, regardless of changes 
    827        in database state outside of that transaction. 
    828 
    829        To expire all objects in the :class:`.Session` simultaneously, 
    830        use :meth:`Session.expire_all`. 
    831 
    832        The :class:`.Session` object's default behavior is to 
    833        expire all state whenever the :meth:`Session.rollback` 
    834        or :meth:`Session.commit` methods are called, so that new 
    835        state can be loaded for the new transaction.   For this reason, 
    836        calling :meth:`Session.expire` only makes sense for the specific 
    837        case that a non-ORM SQL statement was emitted in the current 
    838        transaction. 
    839 
    840        :param instance: The instance to be refreshed. 
    841        :param attribute_names: optional list of string attribute names 
    842          indicating a subset of attributes to be expired. 
    843 
    844        .. seealso:: 
    845 
    846            :ref:`session_expire` - introductory material 
    847 
    848            :meth:`.Session.expire` 
    849 
    850            :meth:`.Session.refresh` 
    851 
    852            :meth:`_orm.Query.populate_existing` 
    853 
    854 
    855        """  # noqa: E501 
    856 
    857        return self._proxied.expire(instance, attribute_names=attribute_names) 
    858 
    859    def expire_all(self) -> None: 
    860        r"""Expires all persistent instances within this Session. 
    861 
    862        .. container:: class_bases 
    863 
    864            Proxied for the :class:`_orm.Session` class on 
    865            behalf of the :class:`_orm.scoping.scoped_session` class. 
    866 
    867        When any attributes on a persistent instance is next accessed, 
    868        a query will be issued using the 
    869        :class:`.Session` object's current transactional context in order to 
    870        load all expired attributes for the given instance.   Note that 
    871        a highly isolated transaction will return the same values as were 
    872        previously read in that same transaction, regardless of changes 
    873        in database state outside of that transaction. 
    874 
    875        To expire individual objects and individual attributes 
    876        on those objects, use :meth:`Session.expire`. 
    877 
    878        The :class:`.Session` object's default behavior is to 
    879        expire all state whenever the :meth:`Session.rollback` 
    880        or :meth:`Session.commit` methods are called, so that new 
    881        state can be loaded for the new transaction.   For this reason, 
    882        calling :meth:`Session.expire_all` is not usually needed, 
    883        assuming the transaction is isolated. 
    884 
    885        .. seealso:: 
    886 
    887            :ref:`session_expire` - introductory material 
    888 
    889            :meth:`.Session.expire` 
    890 
    891            :meth:`.Session.refresh` 
    892 
    893            :meth:`_orm.Query.populate_existing` 
    894 
    895 
    896        """  # noqa: E501 
    897 
    898        return self._proxied.expire_all() 
    899 
    900    def expunge(self, instance: object) -> None: 
    901        r"""Remove the `instance` from this ``Session``. 
    902 
    903        .. container:: class_bases 
    904 
    905            Proxied for the :class:`_orm.Session` class on 
    906            behalf of the :class:`_orm.scoping.scoped_session` class. 
    907 
    908        This will free all internal references to the instance.  Cascading 
    909        will be applied according to the *expunge* cascade rule. 
    910 
    911 
    912        """  # noqa: E501 
    913 
    914        return self._proxied.expunge(instance) 
    915 
    916    def expunge_all(self) -> None: 
    917        r"""Remove all object instances from this ``Session``. 
    918 
    919        .. container:: class_bases 
    920 
    921            Proxied for the :class:`_orm.Session` class on 
    922            behalf of the :class:`_orm.scoping.scoped_session` class. 
    923 
    924        This is equivalent to calling ``expunge(obj)`` on all objects in this 
    925        ``Session``. 
    926 
    927 
    928        """  # noqa: E501 
    929 
    930        return self._proxied.expunge_all() 
    931 
    932    def flush(self, objects: Optional[Sequence[Any]] = None) -> None: 
    933        r"""Flush all the object changes to the database. 
    934 
    935        .. container:: class_bases 
    936 
    937            Proxied for the :class:`_orm.Session` class on 
    938            behalf of the :class:`_orm.scoping.scoped_session` class. 
    939 
    940        Writes out all pending object creations, deletions and modifications 
    941        to the database as INSERTs, DELETEs, UPDATEs, etc.  Operations are 
    942        automatically ordered by the Session's unit of work dependency 
    943        solver. 
    944 
    945        Database operations will be issued in the current transactional 
    946        context and do not affect the state of the transaction, unless an 
    947        error occurs, in which case the entire transaction is rolled back. 
    948        You may flush() as often as you like within a transaction to move 
    949        changes from Python to the database's transaction buffer. 
    950 
    951        :param objects: Optional; restricts the flush operation to operate 
    952          only on elements that are in the given collection. 
    953 
    954          This feature is for an extremely narrow set of use cases where 
    955          particular objects may need to be operated upon before the 
    956          full flush() occurs.  It is not intended for general use. 
    957 
    958          .. deprecated:: 2.1 
    959 
    960 
    961        """  # noqa: E501 
    962 
    963        return self._proxied.flush(objects=objects) 
    964 
    965    def get( 
    966        self, 
    967        entity: _EntityBindKey[_O], 
    968        ident: _PKIdentityArgument, 
    969        *, 
    970        options: Optional[Sequence[ORMOption]] = None, 
    971        populate_existing: bool = False, 
    972        with_for_update: ForUpdateParameter = None, 
    973        identity_token: Optional[Any] = None, 
    974        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    975        bind_arguments: Optional[_BindArguments] = None, 
    976    ) -> Optional[_O]: 
    977        r"""Return an instance based on the given primary key identifier, 
    978        or ``None`` if not found. 
    979 
    980        .. container:: class_bases 
    981 
    982            Proxied for the :class:`_orm.Session` class on 
    983            behalf of the :class:`_orm.scoping.scoped_session` class. 
    984 
    985        E.g.:: 
    986 
    987            my_user = session.get(User, 5) 
    988 
    989            some_object = session.get(VersionedFoo, (5, 10)) 
    990 
    991            some_object = session.get(VersionedFoo, {"id": 5, "version_id": 10}) 
    992 
    993        .. versionadded:: 1.4 Added :meth:`_orm.Session.get`, which is moved 
    994           from the now legacy :meth:`_orm.Query.get` method. 
    995 
    996        :meth:`_orm.Session.get` is special in that it provides direct 
    997        access to the identity map of the :class:`.Session`. 
    998        If the given primary key identifier is present 
    999        in the local identity map, the object is returned 
    1000        directly from this collection and no SQL is emitted, 
    1001        unless the object has been marked fully expired. 
    1002        If not present, 
    1003        a SELECT is performed in order to locate the object. 
    1004 
    1005        :meth:`_orm.Session.get` also will perform a check if 
    1006        the object is present in the identity map and 
    1007        marked as expired - a SELECT 
    1008        is emitted to refresh the object as well as to 
    1009        ensure that the row is still present. 
    1010        If not, :class:`~sqlalchemy.orm.exc.ObjectDeletedError` is raised. 
    1011 
    1012        :param entity: a mapped class or :class:`.Mapper` indicating the 
    1013         type of entity to be loaded. 
    1014 
    1015        :param ident: A scalar, tuple, or dictionary representing the 
    1016         primary key.  For a composite (e.g. multiple column) primary key, 
    1017         a tuple or dictionary should be passed. 
    1018 
    1019         For a single-column primary key, the scalar calling form is typically 
    1020         the most expedient.  If the primary key of a row is the value "5", 
    1021         the call looks like:: 
    1022 
    1023            my_object = session.get(SomeClass, 5) 
    1024 
    1025         The tuple form contains primary key values typically in 
    1026         the order in which they correspond to the mapped 
    1027         :class:`_schema.Table` 
    1028         object's primary key columns, or if the 
    1029         :paramref:`_orm.Mapper.primary_key` configuration parameter were 
    1030         used, in 
    1031         the order used for that parameter. For example, if the primary key 
    1032         of a row is represented by the integer 
    1033         digits "5, 10" the call would look like:: 
    1034 
    1035             my_object = session.get(SomeClass, (5, 10)) 
    1036 
    1037         The dictionary form should include as keys the mapped attribute names 
    1038         corresponding to each element of the primary key.  If the mapped class 
    1039         has the attributes ``id``, ``version_id`` as the attributes which 
    1040         store the object's primary key value, the call would look like:: 
    1041 
    1042            my_object = session.get(SomeClass, {"id": 5, "version_id": 10}) 
    1043 
    1044        :param options: optional sequence of loader options which will be 
    1045         applied to the query, if one is emitted. 
    1046 
    1047        :param populate_existing: causes the method to unconditionally emit 
    1048         a SQL query and refresh the object with the newly loaded data, 
    1049         regardless of whether or not the object is already present. 
    1050 
    1051        :param with_for_update: optional boolean ``True`` indicating FOR UPDATE 
    1052          should be used, or may be a dictionary containing flags to 
    1053          indicate a more specific set of FOR UPDATE flags for the SELECT; 
    1054          flags should match the parameters of 
    1055          :meth:`_query.Query.with_for_update`. 
    1056          Supersedes the :paramref:`.Session.refresh.lockmode` parameter. 
    1057 
    1058        :param execution_options: optional dictionary of execution options, 
    1059         which will be associated with the query execution if one is emitted. 
    1060         This dictionary can provide a subset of the options that are 
    1061         accepted by :meth:`_engine.Connection.execution_options`, and may 
    1062         also provide additional options understood only in an ORM context. 
    1063 
    1064         .. versionadded:: 1.4.29 
    1065 
    1066         .. seealso:: 
    1067 
    1068            :ref:`orm_queryguide_execution_options` - ORM-specific execution 
    1069            options 
    1070 
    1071        :param bind_arguments: dictionary of additional arguments to determine 
    1072         the bind.  May include "mapper", "bind", or other custom arguments. 
    1073         Contents of this dictionary are passed to the 
    1074         :meth:`.Session.get_bind` method. 
    1075 
    1076         .. versionadded:: 2.0.0rc1 
    1077 
    1078        :return: The object instance, or ``None``. 
    1079 
    1080 
    1081        """  # noqa: E501 
    1082 
    1083        return self._proxied.get( 
    1084            entity, 
    1085            ident, 
    1086            options=options, 
    1087            populate_existing=populate_existing, 
    1088            with_for_update=with_for_update, 
    1089            identity_token=identity_token, 
    1090            execution_options=execution_options, 
    1091            bind_arguments=bind_arguments, 
    1092        ) 
    1093 
    1094    def get_one( 
    1095        self, 
    1096        entity: _EntityBindKey[_O], 
    1097        ident: _PKIdentityArgument, 
    1098        *, 
    1099        options: Optional[Sequence[ORMOption]] = None, 
    1100        populate_existing: bool = False, 
    1101        with_for_update: ForUpdateParameter = None, 
    1102        identity_token: Optional[Any] = None, 
    1103        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    1104        bind_arguments: Optional[_BindArguments] = None, 
    1105    ) -> _O: 
    1106        r"""Return exactly one instance based on the given primary key 
    1107        identifier, or raise an exception if not found. 
    1108 
    1109        .. container:: class_bases 
    1110 
    1111            Proxied for the :class:`_orm.Session` class on 
    1112            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1113 
    1114        Raises :class:`_exc.NoResultFound` if the query selects no rows. 
    1115 
    1116        For a detailed documentation of the arguments see the 
    1117        method :meth:`.Session.get`. 
    1118 
    1119        .. versionadded:: 2.0.22 
    1120 
    1121        :return: The object instance. 
    1122 
    1123        .. seealso:: 
    1124 
    1125            :meth:`.Session.get` - equivalent method that instead 
    1126              returns ``None`` if no row was found with the provided primary 
    1127              key 
    1128 
    1129 
    1130        """  # noqa: E501 
    1131 
    1132        return self._proxied.get_one( 
    1133            entity, 
    1134            ident, 
    1135            options=options, 
    1136            populate_existing=populate_existing, 
    1137            with_for_update=with_for_update, 
    1138            identity_token=identity_token, 
    1139            execution_options=execution_options, 
    1140            bind_arguments=bind_arguments, 
    1141        ) 
    1142 
    1143    def get_bind( 
    1144        self, 
    1145        mapper: Optional[_EntityBindKey[_O]] = None, 
    1146        *, 
    1147        clause: Optional[ClauseElement] = None, 
    1148        bind: Optional[_SessionBind] = None, 
    1149        _sa_skip_events: Optional[bool] = None, 
    1150        _sa_skip_for_implicit_returning: bool = False, 
    1151        **kw: Any, 
    1152    ) -> Union[Engine, Connection]: 
    1153        r"""Return a "bind" to which this :class:`.Session` is bound. 
    1154 
    1155        .. container:: class_bases 
    1156 
    1157            Proxied for the :class:`_orm.Session` class on 
    1158            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1159 
    1160        The "bind" is usually an instance of :class:`_engine.Engine`, 
    1161        except in the case where the :class:`.Session` has been 
    1162        explicitly bound directly to a :class:`_engine.Connection`. 
    1163 
    1164        For a multiply-bound or unbound :class:`.Session`, the 
    1165        ``mapper`` or ``clause`` arguments are used to determine the 
    1166        appropriate bind to return. 
    1167 
    1168        Note that the "mapper" argument is usually present 
    1169        when :meth:`.Session.get_bind` is called via an ORM 
    1170        operation such as a :meth:`.Session.query`, each 
    1171        individual INSERT/UPDATE/DELETE operation within a 
    1172        :meth:`.Session.flush`, call, etc. 
    1173 
    1174        The order of resolution is: 
    1175 
    1176        1. if mapper given and :paramref:`.Session.binds` is present, 
    1177           locate a bind based first on the mapper in use, then 
    1178           on the mapped class in use, then on any base classes that are 
    1179           present in the ``__mro__`` of the mapped class, from more specific 
    1180           superclasses to more general. 
    1181        2. if clause given and ``Session.binds`` is present, 
    1182           locate a bind based on :class:`_schema.Table` objects 
    1183           found in the given clause present in ``Session.binds``. 
    1184        3. if ``Session.binds`` is present, return that. 
    1185        4. if clause given, attempt to return a bind 
    1186           linked to the :class:`_schema.MetaData` ultimately 
    1187           associated with the clause. 
    1188        5. if mapper given, attempt to return a bind 
    1189           linked to the :class:`_schema.MetaData` ultimately 
    1190           associated with the :class:`_schema.Table` or other 
    1191           selectable to which the mapper is mapped. 
    1192        6. No bind can be found, :exc:`~sqlalchemy.exc.UnboundExecutionError` 
    1193           is raised. 
    1194 
    1195        Note that the :meth:`.Session.get_bind` method can be overridden on 
    1196        a user-defined subclass of :class:`.Session` to provide any kind 
    1197        of bind resolution scheme.  See the example at 
    1198        :ref:`session_custom_partitioning`. 
    1199 
    1200        :param mapper: 
    1201          Optional mapped class or corresponding :class:`_orm.Mapper` instance. 
    1202          The bind can be derived from a :class:`_orm.Mapper` first by 
    1203          consulting the "binds" map associated with this :class:`.Session`, 
    1204          and secondly by consulting the :class:`_schema.MetaData` associated 
    1205          with the :class:`_schema.Table` to which the :class:`_orm.Mapper` is 
    1206          mapped for a bind. 
    1207 
    1208        :param clause: 
    1209            A :class:`_expression.ClauseElement` (i.e. 
    1210            :func:`_expression.select`, 
    1211            :func:`_expression.text`, 
    1212            etc.).  If the ``mapper`` argument is not present or could not 
    1213            produce a bind, the given expression construct will be searched 
    1214            for a bound element, typically a :class:`_schema.Table` 
    1215            associated with 
    1216            bound :class:`_schema.MetaData`. 
    1217 
    1218        .. seealso:: 
    1219 
    1220             :ref:`session_partitioning` 
    1221 
    1222             :paramref:`.Session.binds` 
    1223 
    1224             :meth:`.Session.bind_mapper` 
    1225 
    1226             :meth:`.Session.bind_table` 
    1227 
    1228 
    1229        """  # noqa: E501 
    1230 
    1231        return self._proxied.get_bind( 
    1232            mapper=mapper, 
    1233            clause=clause, 
    1234            bind=bind, 
    1235            _sa_skip_events=_sa_skip_events, 
    1236            _sa_skip_for_implicit_returning=_sa_skip_for_implicit_returning, 
    1237            **kw, 
    1238        ) 
    1239 
    1240    def is_modified( 
    1241        self, instance: object, include_collections: bool = True 
    1242    ) -> bool: 
    1243        r"""Return ``True`` if the given instance has locally 
    1244        modified attributes. 
    1245 
    1246        .. container:: class_bases 
    1247 
    1248            Proxied for the :class:`_orm.Session` class on 
    1249            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1250 
    1251        This method retrieves the history for each instrumented 
    1252        attribute on the instance and performs a comparison of the current 
    1253        value to its previously flushed or committed value, if any. 
    1254 
    1255        It is in effect a more expensive and accurate 
    1256        version of checking for the given instance in the 
    1257        :attr:`.Session.dirty` collection; a full test for 
    1258        each attribute's net "dirty" status is performed. 
    1259 
    1260        E.g.:: 
    1261 
    1262            return session.is_modified(someobject) 
    1263 
    1264        A few caveats to this method apply: 
    1265 
    1266        * Instances present in the :attr:`.Session.dirty` collection may 
    1267          report ``False`` when tested with this method.  This is because 
    1268          the object may have received change events via attribute mutation, 
    1269          thus placing it in :attr:`.Session.dirty`, but ultimately the state 
    1270          is the same as that loaded from the database, resulting in no net 
    1271          change here. 
    1272        * Scalar attributes may not have recorded the previously set 
    1273          value when a new value was applied, if the attribute was not loaded, 
    1274          or was expired, at the time the new value was received - in these 
    1275          cases, the attribute is assumed to have a change, even if there is 
    1276          ultimately no net change against its database value. SQLAlchemy in 
    1277          most cases does not need the "old" value when a set event occurs, so 
    1278          it skips the expense of a SQL call if the old value isn't present, 
    1279          based on the assumption that an UPDATE of the scalar value is 
    1280          usually needed, and in those few cases where it isn't, is less 
    1281          expensive on average than issuing a defensive SELECT. 
    1282 
    1283          The "old" value is fetched unconditionally upon set only if the 
    1284          attribute container has the ``active_history`` flag set to ``True``. 
    1285          This flag is set typically for primary key attributes and scalar 
    1286          object references that are not a simple many-to-one.  To set this 
    1287          flag for any arbitrary mapped column, use the ``active_history`` 
    1288          argument with :func:`.column_property`. 
    1289 
    1290        :param instance: mapped instance to be tested for pending changes. 
    1291        :param include_collections: Indicates if multivalued collections 
    1292         should be included in the operation.  Setting this to ``False`` is a 
    1293         way to detect only local-column based properties (i.e. scalar columns 
    1294         or many-to-one foreign keys) that would result in an UPDATE for this 
    1295         instance upon flush. 
    1296 
    1297 
    1298        """  # noqa: E501 
    1299 
    1300        return self._proxied.is_modified( 
    1301            instance, include_collections=include_collections 
    1302        ) 
    1303 
    1304    def bulk_save_objects( 
    1305        self, 
    1306        objects: Iterable[object], 
    1307        return_defaults: bool = False, 
    1308        update_changed_only: bool = True, 
    1309        preserve_order: bool = True, 
    1310    ) -> None: 
    1311        r"""Perform a bulk save of the given list of objects. 
    1312 
    1313        .. container:: class_bases 
    1314 
    1315            Proxied for the :class:`_orm.Session` class on 
    1316            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1317 
    1318        .. legacy:: 
    1319 
    1320            This method is a legacy feature as of the 2.0 series of 
    1321            SQLAlchemy.   For modern bulk INSERT and UPDATE, see 
    1322            the sections :ref:`orm_queryguide_bulk_insert` and 
    1323            :ref:`orm_queryguide_bulk_update`. 
    1324 
    1325            For general INSERT and UPDATE of existing ORM mapped objects, 
    1326            prefer standard :term:`unit of work` data management patterns, 
    1327            introduced in the :ref:`unified_tutorial` at 
    1328            :ref:`tutorial_orm_data_manipulation`.  SQLAlchemy 2.0 
    1329            now uses :ref:`engine_insertmanyvalues` with modern dialects 
    1330            which solves previous issues of bulk INSERT slowness. 
    1331 
    1332        :param objects: a sequence of mapped object instances.  The mapped 
    1333         objects are persisted as is, and are **not** associated with the 
    1334         :class:`.Session` afterwards. 
    1335 
    1336         For each object, whether the object is sent as an INSERT or an 
    1337         UPDATE is dependent on the same rules used by the :class:`.Session` 
    1338         in traditional operation; if the object has the 
    1339         :attr:`.InstanceState.key` 
    1340         attribute set, then the object is assumed to be "detached" and 
    1341         will result in an UPDATE.  Otherwise, an INSERT is used. 
    1342 
    1343         In the case of an UPDATE, statements are grouped based on which 
    1344         attributes have changed, and are thus to be the subject of each 
    1345         SET clause.  If ``update_changed_only`` is False, then all 
    1346         attributes present within each object are applied to the UPDATE 
    1347         statement, which may help in allowing the statements to be grouped 
    1348         together into a larger executemany(), and will also reduce the 
    1349         overhead of checking history on attributes. 
    1350 
    1351        :param return_defaults: when True, rows that are missing values which 
    1352         generate defaults, namely integer primary key defaults and sequences, 
    1353         will be inserted **one at a time**, so that the primary key value 
    1354         is available.  In particular this will allow joined-inheritance 
    1355         and other multi-table mappings to insert correctly without the need 
    1356         to provide primary key values ahead of time; however, 
    1357         :paramref:`.Session.bulk_save_objects.return_defaults` **greatly 
    1358         reduces the performance gains** of the method overall.  It is strongly 
    1359         advised to please use the standard :meth:`_orm.Session.add_all` 
    1360         approach. 
    1361 
    1362        :param update_changed_only: when True, UPDATE statements are rendered 
    1363         based on those attributes in each state that have logged changes. 
    1364         When False, all attributes present are rendered into the SET clause 
    1365         with the exception of primary key attributes. 
    1366 
    1367        :param preserve_order: when True, the order of inserts and updates 
    1368         matches exactly the order in which the objects are given.   When 
    1369         False, common types of objects are grouped into inserts 
    1370         and updates, to allow for more batching opportunities. 
    1371 
    1372        .. seealso:: 
    1373 
    1374            :doc:`queryguide/dml` 
    1375 
    1376            :meth:`.Session.bulk_insert_mappings` 
    1377 
    1378            :meth:`.Session.bulk_update_mappings` 
    1379 
    1380 
    1381        """  # noqa: E501 
    1382 
    1383        return self._proxied.bulk_save_objects( 
    1384            objects, 
    1385            return_defaults=return_defaults, 
    1386            update_changed_only=update_changed_only, 
    1387            preserve_order=preserve_order, 
    1388        ) 
    1389 
    1390    def bulk_insert_mappings( 
    1391        self, 
    1392        mapper: Mapper[Any], 
    1393        mappings: Iterable[Dict[str, Any]], 
    1394        return_defaults: bool = False, 
    1395        render_nulls: bool = False, 
    1396    ) -> None: 
    1397        r"""Perform a bulk insert of the given list of mapping dictionaries. 
    1398 
    1399        .. container:: class_bases 
    1400 
    1401            Proxied for the :class:`_orm.Session` class on 
    1402            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1403 
    1404        .. legacy:: 
    1405 
    1406            This method is a legacy feature as of the 2.0 series of 
    1407            SQLAlchemy.   For modern bulk INSERT and UPDATE, see 
    1408            the sections :ref:`orm_queryguide_bulk_insert` and 
    1409            :ref:`orm_queryguide_bulk_update`.  The 2.0 API shares 
    1410            implementation details with this method and adds new features 
    1411            as well. 
    1412 
    1413        :param mapper: a mapped class, or the actual :class:`_orm.Mapper` 
    1414         object, 
    1415         representing the single kind of object represented within the mapping 
    1416         list. 
    1417 
    1418        :param mappings: a sequence of dictionaries, each one containing the 
    1419         state of the mapped row to be inserted, in terms of the attribute 
    1420         names on the mapped class.   If the mapping refers to multiple tables, 
    1421         such as a joined-inheritance mapping, each dictionary must contain all 
    1422         keys to be populated into all tables. 
    1423 
    1424        :param return_defaults: when True, the INSERT process will be altered 
    1425         to ensure that newly generated primary key values will be fetched. 
    1426         The rationale for this parameter is typically to enable 
    1427         :ref:`Joined Table Inheritance <joined_inheritance>` mappings to 
    1428         be bulk inserted. 
    1429 
    1430         .. note:: for backends that don't support RETURNING, the 
    1431            :paramref:`_orm.Session.bulk_insert_mappings.return_defaults` 
    1432            parameter can significantly decrease performance as INSERT 
    1433            statements can no longer be batched.   See 
    1434            :ref:`engine_insertmanyvalues` 
    1435            for background on which backends are affected. 
    1436 
    1437        :param render_nulls: When True, a value of ``None`` will result 
    1438         in a NULL value being included in the INSERT statement, rather 
    1439         than the column being omitted from the INSERT.   This allows all 
    1440         the rows being INSERTed to have the identical set of columns which 
    1441         allows the full set of rows to be batched to the DBAPI.  Normally, 
    1442         each column-set that contains a different combination of NULL values 
    1443         than the previous row must omit a different series of columns from 
    1444         the rendered INSERT statement, which means it must be emitted as a 
    1445         separate statement.   By passing this flag, the full set of rows 
    1446         are guaranteed to be batchable into one batch; the cost however is 
    1447         that server-side defaults which are invoked by an omitted column will 
    1448         be skipped, so care must be taken to ensure that these are not 
    1449         necessary. 
    1450 
    1451         .. warning:: 
    1452 
    1453            When this flag is set, **server side default SQL values will 
    1454            not be invoked** for those columns that are inserted as NULL; 
    1455            the NULL value will be sent explicitly.   Care must be taken 
    1456            to ensure that no server-side default functions need to be 
    1457            invoked for the operation as a whole. 
    1458 
    1459        .. seealso:: 
    1460 
    1461            :doc:`queryguide/dml` 
    1462 
    1463            :meth:`.Session.bulk_save_objects` 
    1464 
    1465            :meth:`.Session.bulk_update_mappings` 
    1466 
    1467 
    1468        """  # noqa: E501 
    1469 
    1470        return self._proxied.bulk_insert_mappings( 
    1471            mapper, 
    1472            mappings, 
    1473            return_defaults=return_defaults, 
    1474            render_nulls=render_nulls, 
    1475        ) 
    1476 
    1477    def bulk_update_mappings( 
    1478        self, mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]] 
    1479    ) -> None: 
    1480        r"""Perform a bulk update of the given list of mapping dictionaries. 
    1481 
    1482        .. container:: class_bases 
    1483 
    1484            Proxied for the :class:`_orm.Session` class on 
    1485            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1486 
    1487        .. legacy:: 
    1488 
    1489            This method is a legacy feature as of the 2.0 series of 
    1490            SQLAlchemy.   For modern bulk INSERT and UPDATE, see 
    1491            the sections :ref:`orm_queryguide_bulk_insert` and 
    1492            :ref:`orm_queryguide_bulk_update`.  The 2.0 API shares 
    1493            implementation details with this method and adds new features 
    1494            as well. 
    1495 
    1496        :param mapper: a mapped class, or the actual :class:`_orm.Mapper` 
    1497         object, 
    1498         representing the single kind of object represented within the mapping 
    1499         list. 
    1500 
    1501        :param mappings: a sequence of dictionaries, each one containing the 
    1502         state of the mapped row to be updated, in terms of the attribute names 
    1503         on the mapped class.   If the mapping refers to multiple tables, such 
    1504         as a joined-inheritance mapping, each dictionary may contain keys 
    1505         corresponding to all tables.   All those keys which are present and 
    1506         are not part of the primary key are applied to the SET clause of the 
    1507         UPDATE statement; the primary key values, which are required, are 
    1508         applied to the WHERE clause. 
    1509 
    1510 
    1511        .. seealso:: 
    1512 
    1513            :doc:`queryguide/dml` 
    1514 
    1515            :meth:`.Session.bulk_insert_mappings` 
    1516 
    1517            :meth:`.Session.bulk_save_objects` 
    1518 
    1519 
    1520        """  # noqa: E501 
    1521 
    1522        return self._proxied.bulk_update_mappings(mapper, mappings) 
    1523 
    1524    def merge( 
    1525        self, 
    1526        instance: _O, 
    1527        *, 
    1528        load: bool = True, 
    1529        options: Optional[Sequence[ORMOption]] = None, 
    1530    ) -> _O: 
    1531        r"""Copy the state of a given instance into a corresponding instance 
    1532        within this :class:`.Session`. 
    1533 
    1534        .. container:: class_bases 
    1535 
    1536            Proxied for the :class:`_orm.Session` class on 
    1537            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1538 
    1539        :meth:`.Session.merge` examines the primary key attributes of the 
    1540        source instance, and attempts to reconcile it with an instance of the 
    1541        same primary key in the session.   If not found locally, it attempts 
    1542        to load the object from the database based on primary key, and if 
    1543        none can be located, creates a new instance.  The state of each 
    1544        attribute on the source instance is then copied to the target 
    1545        instance.  The resulting target instance is then returned by the 
    1546        method; the original source instance is left unmodified, and 
    1547        un-associated with the :class:`.Session` if not already. 
    1548 
    1549        This operation cascades to associated instances if the association is 
    1550        mapped with ``cascade="merge"``. 
    1551 
    1552        See :ref:`unitofwork_merging` for a detailed discussion of merging. 
    1553 
    1554        :param instance: Instance to be merged. 
    1555        :param load: Boolean, when False, :meth:`.merge` switches into 
    1556         a "high performance" mode which causes it to forego emitting history 
    1557         events as well as all database access.  This flag is used for 
    1558         cases such as transferring graphs of objects into a :class:`.Session` 
    1559         from a second level cache, or to transfer just-loaded objects 
    1560         into the :class:`.Session` owned by a worker thread or process 
    1561         without re-querying the database. 
    1562 
    1563         The ``load=False`` use case adds the caveat that the given 
    1564         object has to be in a "clean" state, that is, has no pending changes 
    1565         to be flushed - even if the incoming object is detached from any 
    1566         :class:`.Session`.   This is so that when 
    1567         the merge operation populates local attributes and 
    1568         cascades to related objects and 
    1569         collections, the values can be "stamped" onto the 
    1570         target object as is, without generating any history or attribute 
    1571         events, and without the need to reconcile the incoming data with 
    1572         any existing related objects or collections that might not 
    1573         be loaded.  The resulting objects from ``load=False`` are always 
    1574         produced as "clean", so it is only appropriate that the given objects 
    1575         should be "clean" as well, else this suggests a mis-use of the 
    1576         method. 
    1577        :param options: optional sequence of loader options which will be 
    1578         applied to the :meth:`_orm.Session.get` method when the merge 
    1579         operation loads the existing version of the object from the database. 
    1580 
    1581         .. versionadded:: 1.4.24 
    1582 
    1583 
    1584        .. seealso:: 
    1585 
    1586            :func:`.make_transient_to_detached` - provides for an alternative 
    1587            means of "merging" a single object into the :class:`.Session` 
    1588 
    1589            :meth:`.Session.merge_all` - multiple instance version 
    1590 
    1591 
    1592        """  # noqa: E501 
    1593 
    1594        return self._proxied.merge(instance, load=load, options=options) 
    1595 
    1596    def merge_all( 
    1597        self, 
    1598        instances: Iterable[_O], 
    1599        *, 
    1600        load: bool = True, 
    1601        options: Optional[Sequence[ORMOption]] = None, 
    1602    ) -> Sequence[_O]: 
    1603        r"""Calls :meth:`.Session.merge` on multiple instances. 
    1604 
    1605        .. container:: class_bases 
    1606 
    1607            Proxied for the :class:`_orm.Session` class on 
    1608            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1609 
    1610        .. seealso:: 
    1611 
    1612            :meth:`.Session.merge` - main documentation on merge 
    1613 
    1614        .. versionadded:: 2.1 
    1615 
    1616 
    1617        """  # noqa: E501 
    1618 
    1619        return self._proxied.merge_all(instances, load=load, options=options) 
    1620 
    1621    @overload 
    1622    def query(self, _entity: _EntityType[_O]) -> Query[_O]: ... 
    1623 
    1624    @overload 
    1625    def query( 
    1626        self, _colexpr: TypedColumnsClauseRole[_T] 
    1627    ) -> RowReturningQuery[_T]: ... 
    1628 
    1629    # START OVERLOADED FUNCTIONS self.query RowReturningQuery 2-8 
    1630 
    1631    # code within this block is **programmatically, 
    1632    # statically generated** by tools/generate_tuple_map_overloads.py 
    1633 
    1634    @overload 
    1635    def query( 
    1636        self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], / 
    1637    ) -> RowReturningQuery[_T0, _T1]: ... 
    1638 
    1639    @overload 
    1640    def query( 
    1641        self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2], / 
    1642    ) -> RowReturningQuery[_T0, _T1, _T2]: ... 
    1643 
    1644    @overload 
    1645    def query( 
    1646        self, 
    1647        __ent0: _TCCA[_T0], 
    1648        __ent1: _TCCA[_T1], 
    1649        __ent2: _TCCA[_T2], 
    1650        __ent3: _TCCA[_T3], 
    1651        /, 
    1652    ) -> RowReturningQuery[_T0, _T1, _T2, _T3]: ... 
    1653 
    1654    @overload 
    1655    def query( 
    1656        self, 
    1657        __ent0: _TCCA[_T0], 
    1658        __ent1: _TCCA[_T1], 
    1659        __ent2: _TCCA[_T2], 
    1660        __ent3: _TCCA[_T3], 
    1661        __ent4: _TCCA[_T4], 
    1662        /, 
    1663    ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4]: ... 
    1664 
    1665    @overload 
    1666    def query( 
    1667        self, 
    1668        __ent0: _TCCA[_T0], 
    1669        __ent1: _TCCA[_T1], 
    1670        __ent2: _TCCA[_T2], 
    1671        __ent3: _TCCA[_T3], 
    1672        __ent4: _TCCA[_T4], 
    1673        __ent5: _TCCA[_T5], 
    1674        /, 
    1675    ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4, _T5]: ... 
    1676 
    1677    @overload 
    1678    def query( 
    1679        self, 
    1680        __ent0: _TCCA[_T0], 
    1681        __ent1: _TCCA[_T1], 
    1682        __ent2: _TCCA[_T2], 
    1683        __ent3: _TCCA[_T3], 
    1684        __ent4: _TCCA[_T4], 
    1685        __ent5: _TCCA[_T5], 
    1686        __ent6: _TCCA[_T6], 
    1687        /, 
    1688    ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4, _T5, _T6]: ... 
    1689 
    1690    @overload 
    1691    def query( 
    1692        self, 
    1693        __ent0: _TCCA[_T0], 
    1694        __ent1: _TCCA[_T1], 
    1695        __ent2: _TCCA[_T2], 
    1696        __ent3: _TCCA[_T3], 
    1697        __ent4: _TCCA[_T4], 
    1698        __ent5: _TCCA[_T5], 
    1699        __ent6: _TCCA[_T6], 
    1700        __ent7: _TCCA[_T7], 
    1701        /, 
    1702        *entities: _ColumnsClauseArgument[Any], 
    1703    ) -> RowReturningQuery[ 
    1704        _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, Unpack[TupleAny] 
    1705    ]: ... 
    1706 
    1707    # END OVERLOADED FUNCTIONS self.query 
    1708 
    1709    @overload 
    1710    def query( 
    1711        self, *entities: _ColumnsClauseArgument[Any], **kwargs: Any 
    1712    ) -> Query[Any]: ... 
    1713 
    1714    def query( 
    1715        self, *entities: _ColumnsClauseArgument[Any], **kwargs: Any 
    1716    ) -> Query[Any]: 
    1717        r"""Return a new :class:`_query.Query` object corresponding to this 
    1718        :class:`_orm.Session`. 
    1719 
    1720        .. container:: class_bases 
    1721 
    1722            Proxied for the :class:`_orm.Session` class on 
    1723            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1724 
    1725        Note that the :class:`_query.Query` object is legacy as of 
    1726        SQLAlchemy 2.0; the :func:`_sql.select` construct is now used 
    1727        to construct ORM queries. 
    1728 
    1729        .. seealso:: 
    1730 
    1731            :ref:`unified_tutorial` 
    1732 
    1733            :ref:`queryguide_toplevel` 
    1734 
    1735            :ref:`query_api_toplevel` - legacy API doc 
    1736 
    1737 
    1738        """  # noqa: E501 
    1739 
    1740        return self._proxied.query(*entities, **kwargs) 
    1741 
    1742    def refresh( 
    1743        self, 
    1744        instance: object, 
    1745        attribute_names: Optional[Iterable[str]] = None, 
    1746        with_for_update: ForUpdateParameter = None, 
    1747    ) -> None: 
    1748        r"""Expire and refresh attributes on the given instance. 
    1749 
    1750        .. container:: class_bases 
    1751 
    1752            Proxied for the :class:`_orm.Session` class on 
    1753            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1754 
    1755        The selected attributes will first be expired as they would when using 
    1756        :meth:`_orm.Session.expire`; then a SELECT statement will be issued to 
    1757        the database to refresh column-oriented attributes with the current 
    1758        value available in the current transaction. 
    1759 
    1760        :func:`_orm.relationship` oriented attributes will also be immediately 
    1761        loaded if they were already eagerly loaded on the object, using the 
    1762        same eager loading strategy that they were loaded with originally. 
    1763 
    1764        .. versionadded:: 1.4 - the :meth:`_orm.Session.refresh` method 
    1765           can also refresh eagerly loaded attributes. 
    1766 
    1767        :func:`_orm.relationship` oriented attributes that would normally 
    1768        load using the ``select`` (or "lazy") loader strategy will also 
    1769        load **if they are named explicitly in the attribute_names 
    1770        collection**, emitting a SELECT statement for the attribute using the 
    1771        ``immediate`` loader strategy.  If lazy-loaded relationships are not 
    1772        named in :paramref:`_orm.Session.refresh.attribute_names`, then 
    1773        they remain as "lazy loaded" attributes and are not implicitly 
    1774        refreshed. 
    1775 
    1776        .. versionchanged:: 2.0.4  The :meth:`_orm.Session.refresh` method 
    1777           will now refresh lazy-loaded :func:`_orm.relationship` oriented 
    1778           attributes for those which are named explicitly in the 
    1779           :paramref:`_orm.Session.refresh.attribute_names` collection. 
    1780 
    1781        .. tip:: 
    1782 
    1783            While the :meth:`_orm.Session.refresh` method is capable of 
    1784            refreshing both column and relationship oriented attributes, its 
    1785            primary focus is on refreshing of local column-oriented attributes 
    1786            on a single instance. For more open ended "refresh" functionality, 
    1787            including the ability to refresh the attributes on many objects at 
    1788            once while having explicit control over relationship loader 
    1789            strategies, use the 
    1790            :ref:`populate existing <orm_queryguide_populate_existing>` feature 
    1791            instead. 
    1792 
    1793        Note that a highly isolated transaction will return the same values as 
    1794        were previously read in that same transaction, regardless of changes 
    1795        in database state outside of that transaction.   Refreshing 
    1796        attributes usually only makes sense at the start of a transaction 
    1797        where database rows have not yet been accessed. 
    1798 
    1799        :param attribute_names: optional.  An iterable collection of 
    1800          string attribute names indicating a subset of attributes to 
    1801          be refreshed. 
    1802 
    1803        :param with_for_update: optional boolean ``True`` indicating FOR UPDATE 
    1804          should be used, or may be a dictionary containing flags to 
    1805          indicate a more specific set of FOR UPDATE flags for the SELECT; 
    1806          flags should match the parameters of 
    1807          :meth:`_query.Query.with_for_update`. 
    1808          Supersedes the :paramref:`.Session.refresh.lockmode` parameter. 
    1809 
    1810        .. seealso:: 
    1811 
    1812            :ref:`session_expire` - introductory material 
    1813 
    1814            :meth:`.Session.expire` 
    1815 
    1816            :meth:`.Session.expire_all` 
    1817 
    1818            :ref:`orm_queryguide_populate_existing` - allows any ORM query 
    1819            to refresh objects as they would be loaded normally. 
    1820 
    1821 
    1822        """  # noqa: E501 
    1823 
    1824        return self._proxied.refresh( 
    1825            instance, 
    1826            attribute_names=attribute_names, 
    1827            with_for_update=with_for_update, 
    1828        ) 
    1829 
    1830    def rollback(self) -> None: 
    1831        r"""Rollback the current transaction in progress. 
    1832 
    1833        .. container:: class_bases 
    1834 
    1835            Proxied for the :class:`_orm.Session` class on 
    1836            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1837 
    1838        If no transaction is in progress, this method is a pass-through. 
    1839 
    1840        The method always rolls back 
    1841        the topmost database transaction, discarding any nested 
    1842        transactions that may be in progress. 
    1843 
    1844        .. seealso:: 
    1845 
    1846            :ref:`session_rollback` 
    1847 
    1848            :ref:`unitofwork_transaction` 
    1849 
    1850 
    1851        """  # noqa: E501 
    1852 
    1853        return self._proxied.rollback() 
    1854 
    1855    @overload 
    1856    def scalar( 
    1857        self, 
    1858        statement: TypedReturnsRows[_T], 
    1859        params: Optional[_CoreSingleExecuteParams] = None, 
    1860        *, 
    1861        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    1862        bind_arguments: Optional[_BindArguments] = None, 
    1863        **kw: Any, 
    1864    ) -> Optional[_T]: ... 
    1865 
    1866    @overload 
    1867    def scalar( 
    1868        self, 
    1869        statement: Executable, 
    1870        params: Optional[_CoreSingleExecuteParams] = None, 
    1871        *, 
    1872        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    1873        bind_arguments: Optional[_BindArguments] = None, 
    1874        **kw: Any, 
    1875    ) -> Any: ... 
    1876 
    1877    def scalar( 
    1878        self, 
    1879        statement: Executable, 
    1880        params: Optional[_CoreSingleExecuteParams] = None, 
    1881        *, 
    1882        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    1883        bind_arguments: Optional[_BindArguments] = None, 
    1884        **kw: Any, 
    1885    ) -> Any: 
    1886        r"""Execute a statement and return a scalar result. 
    1887 
    1888        .. container:: class_bases 
    1889 
    1890            Proxied for the :class:`_orm.Session` class on 
    1891            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1892 
    1893        Usage and parameters are the same as that of 
    1894        :meth:`_orm.Session.execute`; the return result is a scalar Python 
    1895        value. 
    1896 
    1897 
    1898        """  # noqa: E501 
    1899 
    1900        return self._proxied.scalar( 
    1901            statement, 
    1902            params=params, 
    1903            execution_options=execution_options, 
    1904            bind_arguments=bind_arguments, 
    1905            **kw, 
    1906        ) 
    1907 
    1908    @overload 
    1909    def scalars( 
    1910        self, 
    1911        statement: TypedReturnsRows[_T], 
    1912        params: Optional[_CoreAnyExecuteParams] = None, 
    1913        *, 
    1914        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    1915        bind_arguments: Optional[_BindArguments] = None, 
    1916        **kw: Any, 
    1917    ) -> ScalarResult[_T]: ... 
    1918 
    1919    @overload 
    1920    def scalars( 
    1921        self, 
    1922        statement: Executable, 
    1923        params: Optional[_CoreAnyExecuteParams] = None, 
    1924        *, 
    1925        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    1926        bind_arguments: Optional[_BindArguments] = None, 
    1927        **kw: Any, 
    1928    ) -> ScalarResult[Any]: ... 
    1929 
    1930    def scalars( 
    1931        self, 
    1932        statement: Executable, 
    1933        params: Optional[_CoreAnyExecuteParams] = None, 
    1934        *, 
    1935        execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 
    1936        bind_arguments: Optional[_BindArguments] = None, 
    1937        **kw: Any, 
    1938    ) -> ScalarResult[Any]: 
    1939        r"""Execute a statement and return the results as scalars. 
    1940 
    1941        .. container:: class_bases 
    1942 
    1943            Proxied for the :class:`_orm.Session` class on 
    1944            behalf of the :class:`_orm.scoping.scoped_session` class. 
    1945 
    1946        Usage and parameters are the same as that of 
    1947        :meth:`_orm.Session.execute`; the return result is a 
    1948        :class:`_result.ScalarResult` filtering object which 
    1949        will return single elements rather than :class:`_row.Row` objects. 
    1950 
    1951        :return:  a :class:`_result.ScalarResult` object 
    1952 
    1953        .. versionadded:: 1.4.24 Added :meth:`_orm.Session.scalars` 
    1954 
    1955        .. versionadded:: 1.4.26 Added :meth:`_orm.scoped_session.scalars` 
    1956 
    1957        .. seealso:: 
    1958 
    1959            :ref:`orm_queryguide_select_orm_entities` - contrasts the behavior 
    1960            of :meth:`_orm.Session.execute` to :meth:`_orm.Session.scalars` 
    1961 
    1962 
    1963        """  # noqa: E501 
    1964 
    1965        return self._proxied.scalars( 
    1966            statement, 
    1967            params=params, 
    1968            execution_options=execution_options, 
    1969            bind_arguments=bind_arguments, 
    1970            **kw, 
    1971        ) 
    1972 
    1973    @property 
    1974    def bind(self) -> Optional[Union[Engine, Connection]]: 
    1975        r"""Proxy for the :attr:`_orm.Session.bind` attribute 
    1976        on behalf of the :class:`_orm.scoping.scoped_session` class. 
    1977 
    1978        """  # noqa: E501 
    1979 
    1980        return self._proxied.bind 
    1981 
    1982    @bind.setter 
    1983    def bind(self, attr: Optional[Union[Engine, Connection]]) -> None: 
    1984        self._proxied.bind = attr 
    1985 
    1986    @property 
    1987    def dirty(self) -> Any: 
    1988        r"""The set of all persistent instances considered dirty. 
    1989 
    1990        .. container:: class_bases 
    1991 
    1992            Proxied for the :class:`_orm.Session` class 
    1993            on behalf of the :class:`_orm.scoping.scoped_session` class. 
    1994 
    1995        E.g.:: 
    1996 
    1997            some_mapped_object in session.dirty 
    1998 
    1999        Instances are considered dirty when they were modified but not 
    2000        deleted. 
    2001 
    2002        Note that this 'dirty' calculation is 'optimistic'; most 
    2003        attribute-setting or collection modification operations will 
    2004        mark an instance as 'dirty' and place it in this set, even if 
    2005        there is no net change to the attribute's value.  At flush 
    2006        time, the value of each attribute is compared to its 
    2007        previously saved value, and if there's no net change, no SQL 
    2008        operation will occur (this is a more expensive operation so 
    2009        it's only done at flush time). 
    2010 
    2011        To check if an instance has actionable net changes to its 
    2012        attributes, use the :meth:`.Session.is_modified` method. 
    2013 
    2014 
    2015        """  # noqa: E501 
    2016 
    2017        return self._proxied.dirty 
    2018 
    2019    @property 
    2020    def deleted(self) -> Any: 
    2021        r"""The set of all instances marked as 'deleted' within this ``Session`` 
    2022 
    2023        .. container:: class_bases 
    2024 
    2025            Proxied for the :class:`_orm.Session` class 
    2026            on behalf of the :class:`_orm.scoping.scoped_session` class. 
    2027 
    2028        """  # noqa: E501 
    2029 
    2030        return self._proxied.deleted 
    2031 
    2032    @property 
    2033    def new(self) -> Any: 
    2034        r"""The set of all instances marked as 'new' within this ``Session``. 
    2035 
    2036        .. container:: class_bases 
    2037 
    2038            Proxied for the :class:`_orm.Session` class 
    2039            on behalf of the :class:`_orm.scoping.scoped_session` class. 
    2040 
    2041        """  # noqa: E501 
    2042 
    2043        return self._proxied.new 
    2044 
    2045    @property 
    2046    def identity_map(self) -> IdentityMap: 
    2047        r"""Proxy for the :attr:`_orm.Session.identity_map` attribute 
    2048        on behalf of the :class:`_orm.scoping.scoped_session` class. 
    2049 
    2050        """  # noqa: E501 
    2051 
    2052        return self._proxied.identity_map 
    2053 
    2054    @identity_map.setter 
    2055    def identity_map(self, attr: IdentityMap) -> None: 
    2056        self._proxied.identity_map = attr 
    2057 
    2058    @property 
    2059    def is_active(self) -> Any: 
    2060        r"""True if this :class:`.Session` not in "partial rollback" state. 
    2061 
    2062        .. container:: class_bases 
    2063 
    2064            Proxied for the :class:`_orm.Session` class 
    2065            on behalf of the :class:`_orm.scoping.scoped_session` class. 
    2066 
    2067        .. versionchanged:: 1.4 The :class:`_orm.Session` no longer begins 
    2068           a new transaction immediately, so this attribute will be False 
    2069           when the :class:`_orm.Session` is first instantiated. 
    2070 
    2071        "partial rollback" state typically indicates that the flush process 
    2072        of the :class:`_orm.Session` has failed, and that the 
    2073        :meth:`_orm.Session.rollback` method must be emitted in order to 
    2074        fully roll back the transaction. 
    2075 
    2076        If this :class:`_orm.Session` is not in a transaction at all, the 
    2077        :class:`_orm.Session` will autobegin when it is first used, so in this 
    2078        case :attr:`_orm.Session.is_active` will return True. 
    2079 
    2080        Otherwise, if this :class:`_orm.Session` is within a transaction, 
    2081        and that transaction has not been rolled back internally, the 
    2082        :attr:`_orm.Session.is_active` will also return True. 
    2083 
    2084        .. seealso:: 
    2085 
    2086            :ref:`faq_session_rollback` 
    2087 
    2088            :meth:`_orm.Session.in_transaction` 
    2089 
    2090 
    2091        """  # noqa: E501 
    2092 
    2093        return self._proxied.is_active 
    2094 
    2095    @property 
    2096    def autoflush(self) -> bool: 
    2097        r"""Proxy for the :attr:`_orm.Session.autoflush` attribute 
    2098        on behalf of the :class:`_orm.scoping.scoped_session` class. 
    2099 
    2100        """  # noqa: E501 
    2101 
    2102        return self._proxied.autoflush 
    2103 
    2104    @autoflush.setter 
    2105    def autoflush(self, attr: bool) -> None: 
    2106        self._proxied.autoflush = attr 
    2107 
    2108    @property 
    2109    def no_autoflush(self) -> Any: 
    2110        r"""Return a context manager that disables autoflush. 
    2111 
    2112        .. container:: class_bases 
    2113 
    2114            Proxied for the :class:`_orm.Session` class 
    2115            on behalf of the :class:`_orm.scoping.scoped_session` class. 
    2116 
    2117        e.g.:: 
    2118 
    2119            with session.no_autoflush: 
    2120 
    2121                some_object = SomeClass() 
    2122                session.add(some_object) 
    2123                # won't autoflush 
    2124                some_object.related_thing = session.query(SomeRelated).first() 
    2125 
    2126        Operations that proceed within the ``with:`` block 
    2127        will not be subject to flushes occurring upon query 
    2128        access.  This is useful when initializing a series 
    2129        of objects which involve existing database queries, 
    2130        where the uncompleted object should not yet be flushed. 
    2131 
    2132 
    2133        """  # noqa: E501 
    2134 
    2135        return self._proxied.no_autoflush 
    2136 
    2137    @property 
    2138    def info(self) -> Any: 
    2139        r"""A user-modifiable dictionary. 
    2140 
    2141        .. container:: class_bases 
    2142 
    2143            Proxied for the :class:`_orm.Session` class 
    2144            on behalf of the :class:`_orm.scoping.scoped_session` class. 
    2145 
    2146        The initial value of this dictionary can be populated using the 
    2147        ``info`` argument to the :class:`.Session` constructor or 
    2148        :class:`.sessionmaker` constructor or factory methods.  The dictionary 
    2149        here is always local to this :class:`.Session` and can be modified 
    2150        independently of all other :class:`.Session` objects. 
    2151 
    2152 
    2153        """  # noqa: E501 
    2154 
    2155        return self._proxied.info 
    2156 
    2157    @property 
    2158    def execution_options(self) -> _ExecuteOptions: 
    2159        r"""Proxy for the :attr:`_orm.Session.execution_options` attribute 
    2160        on behalf of the :class:`_orm.scoping.scoped_session` class. 
    2161 
    2162        """  # noqa: E501 
    2163 
    2164        return self._proxied.execution_options 
    2165 
    2166    @execution_options.setter 
    2167    def execution_options(self, attr: _ExecuteOptions) -> None: 
    2168        self._proxied.execution_options = attr 
    2169 
    2170    @classmethod 
    2171    def object_session(cls, instance: object) -> Optional[Session]: 
    2172        r"""Return the :class:`.Session` to which an object belongs. 
    2173 
    2174        .. container:: class_bases 
    2175 
    2176            Proxied for the :class:`_orm.Session` class on 
    2177            behalf of the :class:`_orm.scoping.scoped_session` class. 
    2178 
    2179        This is an alias of :func:`.object_session`. 
    2180 
    2181 
    2182        """  # noqa: E501 
    2183 
    2184        return Session.object_session(instance) 
    2185 
    2186    @classmethod 
    2187    def identity_key( 
    2188        cls, 
    2189        class_: Optional[Type[Any]] = None, 
    2190        ident: Union[Any, Tuple[Any, ...]] = None, 
    2191        *, 
    2192        instance: Optional[Any] = None, 
    2193        row: Optional[Union[Row[Unpack[TupleAny]], RowMapping]] = None, 
    2194        identity_token: Optional[Any] = None, 
    2195    ) -> _IdentityKeyType[Any]: 
    2196        r"""Return an identity key. 
    2197 
    2198        .. container:: class_bases 
    2199 
    2200            Proxied for the :class:`_orm.Session` class on 
    2201            behalf of the :class:`_orm.scoping.scoped_session` class. 
    2202 
    2203        This is an alias of :func:`.util.identity_key`. 
    2204 
    2205 
    2206        """  # noqa: E501 
    2207 
    2208        return Session.identity_key( 
    2209            class_=class_, 
    2210            ident=ident, 
    2211            instance=instance, 
    2212            row=row, 
    2213            identity_token=identity_token, 
    2214        ) 
    2215 
    2216    # END PROXY METHODS scoped_session 
    2217 
    2218 
    2219ScopedSession = scoped_session 
    2220"""Old name for backwards compatibility."""