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