scoping.py 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613
  1. # ext/asyncio/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. from __future__ import annotations
  8. from typing import Any
  9. from typing import Callable
  10. from typing import Generic
  11. from typing import Iterable
  12. from typing import Iterator
  13. from typing import Optional
  14. from typing import overload
  15. from typing import Sequence
  16. from typing import Tuple
  17. from typing import Type
  18. from typing import TYPE_CHECKING
  19. from typing import TypeVar
  20. from typing import Union
  21. from .session import _AS
  22. from .session import async_sessionmaker
  23. from .session import AsyncSession
  24. from ... import exc as sa_exc
  25. from ... import util
  26. from ...orm.session import Session
  27. from ...util import create_proxy_methods
  28. from ...util import ScopedRegistry
  29. from ...util import warn
  30. from ...util import warn_deprecated
  31. if TYPE_CHECKING:
  32. from .engine import AsyncConnection
  33. from .result import AsyncResult
  34. from .result import AsyncScalarResult
  35. from .session import AsyncSessionTransaction
  36. from ...engine import Connection
  37. from ...engine import CursorResult
  38. from ...engine import Engine
  39. from ...engine import Result
  40. from ...engine import Row
  41. from ...engine import RowMapping
  42. from ...engine.interfaces import _CoreAnyExecuteParams
  43. from ...engine.interfaces import CoreExecuteOptionsParameter
  44. from ...engine.result import ScalarResult
  45. from ...orm._typing import _IdentityKeyType
  46. from ...orm._typing import _O
  47. from ...orm._typing import OrmExecuteOptionsParameter
  48. from ...orm.interfaces import ORMOption
  49. from ...orm.session import _BindArguments
  50. from ...orm.session import _EntityBindKey
  51. from ...orm.session import _PKIdentityArgument
  52. from ...orm.session import _SessionBind
  53. from ...sql.base import Executable
  54. from ...sql.dml import UpdateBase
  55. from ...sql.elements import ClauseElement
  56. from ...sql.selectable import ForUpdateParameter
  57. from ...sql.selectable import TypedReturnsRows
  58. _T = TypeVar("_T", bound=Any)
  59. @create_proxy_methods(
  60. AsyncSession,
  61. ":class:`_asyncio.AsyncSession`",
  62. ":class:`_asyncio.scoping.async_scoped_session`",
  63. classmethods=["close_all", "object_session", "identity_key"],
  64. methods=[
  65. "__contains__",
  66. "__iter__",
  67. "aclose",
  68. "add",
  69. "add_all",
  70. "begin",
  71. "begin_nested",
  72. "close",
  73. "reset",
  74. "commit",
  75. "connection",
  76. "delete",
  77. "execute",
  78. "expire",
  79. "expire_all",
  80. "expunge",
  81. "expunge_all",
  82. "flush",
  83. "get_bind",
  84. "is_modified",
  85. "invalidate",
  86. "merge",
  87. "refresh",
  88. "rollback",
  89. "scalar",
  90. "scalars",
  91. "get",
  92. "get_one",
  93. "stream",
  94. "stream_scalars",
  95. ],
  96. attributes=[
  97. "bind",
  98. "dirty",
  99. "deleted",
  100. "new",
  101. "identity_map",
  102. "is_active",
  103. "autoflush",
  104. "no_autoflush",
  105. "info",
  106. ],
  107. use_intermediate_variable=["get"],
  108. )
  109. class async_scoped_session(Generic[_AS]):
  110. """Provides scoped management of :class:`.AsyncSession` objects.
  111. See the section :ref:`asyncio_scoped_session` for usage details.
  112. .. versionadded:: 1.4.19
  113. """
  114. _support_async = True
  115. session_factory: async_sessionmaker[_AS]
  116. """The `session_factory` provided to `__init__` is stored in this
  117. attribute and may be accessed at a later time. This can be useful when
  118. a new non-scoped :class:`.AsyncSession` is needed."""
  119. registry: ScopedRegistry[_AS]
  120. def __init__(
  121. self,
  122. session_factory: async_sessionmaker[_AS],
  123. scopefunc: Callable[[], Any],
  124. ):
  125. """Construct a new :class:`_asyncio.async_scoped_session`.
  126. :param session_factory: a factory to create new :class:`_asyncio.AsyncSession`
  127. instances. This is usually, but not necessarily, an instance
  128. of :class:`_asyncio.async_sessionmaker`.
  129. :param scopefunc: function which defines
  130. the current scope. A function such as ``asyncio.current_task``
  131. may be useful here.
  132. """ # noqa: E501
  133. self.session_factory = session_factory
  134. self.registry = ScopedRegistry(session_factory, scopefunc)
  135. @property
  136. def _proxied(self) -> _AS:
  137. return self.registry()
  138. def __call__(self, **kw: Any) -> _AS:
  139. r"""Return the current :class:`.AsyncSession`, creating it
  140. using the :attr:`.scoped_session.session_factory` if not present.
  141. :param \**kw: Keyword arguments will be passed to the
  142. :attr:`.scoped_session.session_factory` callable, if an existing
  143. :class:`.AsyncSession` is not present. If the
  144. :class:`.AsyncSession` is present
  145. and keyword arguments have been passed,
  146. :exc:`~sqlalchemy.exc.InvalidRequestError` is raised.
  147. """
  148. if kw:
  149. if self.registry.has():
  150. raise sa_exc.InvalidRequestError(
  151. "Scoped session is already present; "
  152. "no new arguments may be specified."
  153. )
  154. else:
  155. sess = self.session_factory(**kw)
  156. self.registry.set(sess)
  157. else:
  158. sess = self.registry()
  159. if not self._support_async and sess._is_asyncio:
  160. warn_deprecated(
  161. "Using `scoped_session` with asyncio is deprecated and "
  162. "will raise an error in a future version. "
  163. "Please use `async_scoped_session` instead.",
  164. "1.4.23",
  165. )
  166. return sess
  167. def configure(self, **kwargs: Any) -> None:
  168. """reconfigure the :class:`.sessionmaker` used by this
  169. :class:`.scoped_session`.
  170. See :meth:`.sessionmaker.configure`.
  171. """
  172. if self.registry.has():
  173. warn(
  174. "At least one scoped session is already present. "
  175. " configure() can not affect sessions that have "
  176. "already been created."
  177. )
  178. self.session_factory.configure(**kwargs)
  179. async def remove(self) -> None:
  180. """Dispose of the current :class:`.AsyncSession`, if present.
  181. Different from scoped_session's remove method, this method would use
  182. await to wait for the close method of AsyncSession.
  183. """
  184. if self.registry.has():
  185. await self.registry().close()
  186. self.registry.clear()
  187. # START PROXY METHODS async_scoped_session
  188. # code within this block is **programmatically,
  189. # statically generated** by tools/generate_proxy_methods.py
  190. def __contains__(self, instance: object) -> bool:
  191. r"""Return True if the instance is associated with this session.
  192. .. container:: class_bases
  193. Proxied for the :class:`_asyncio.AsyncSession` class on
  194. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  195. .. container:: class_bases
  196. Proxied for the :class:`_orm.Session` class on
  197. behalf of the :class:`_asyncio.AsyncSession` class.
  198. The instance may be pending or persistent within the Session for a
  199. result of True.
  200. """ # noqa: E501
  201. return self._proxied.__contains__(instance)
  202. def __iter__(self) -> Iterator[object]:
  203. r"""Iterate over all pending or persistent instances within this
  204. Session.
  205. .. container:: class_bases
  206. Proxied for the :class:`_asyncio.AsyncSession` class on
  207. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  208. .. container:: class_bases
  209. Proxied for the :class:`_orm.Session` class on
  210. behalf of the :class:`_asyncio.AsyncSession` class.
  211. """ # noqa: E501
  212. return self._proxied.__iter__()
  213. async def aclose(self) -> None:
  214. r"""A synonym for :meth:`_asyncio.AsyncSession.close`.
  215. .. container:: class_bases
  216. Proxied for the :class:`_asyncio.AsyncSession` class on
  217. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  218. The :meth:`_asyncio.AsyncSession.aclose` name is specifically
  219. to support the Python standard library ``@contextlib.aclosing``
  220. context manager function.
  221. .. versionadded:: 2.0.20
  222. """ # noqa: E501
  223. return await self._proxied.aclose()
  224. def add(self, instance: object, _warn: bool = True) -> None:
  225. r"""Place an object into this :class:`_orm.Session`.
  226. .. container:: class_bases
  227. Proxied for the :class:`_asyncio.AsyncSession` class on
  228. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  229. .. container:: class_bases
  230. Proxied for the :class:`_orm.Session` class on
  231. behalf of the :class:`_asyncio.AsyncSession` class.
  232. Objects that are in the :term:`transient` state when passed to the
  233. :meth:`_orm.Session.add` method will move to the
  234. :term:`pending` state, until the next flush, at which point they
  235. will move to the :term:`persistent` state.
  236. Objects that are in the :term:`detached` state when passed to the
  237. :meth:`_orm.Session.add` method will move to the :term:`persistent`
  238. state directly.
  239. If the transaction used by the :class:`_orm.Session` is rolled back,
  240. objects which were transient when they were passed to
  241. :meth:`_orm.Session.add` will be moved back to the
  242. :term:`transient` state, and will no longer be present within this
  243. :class:`_orm.Session`.
  244. .. seealso::
  245. :meth:`_orm.Session.add_all`
  246. :ref:`session_adding` - at :ref:`session_basics`
  247. """ # noqa: E501
  248. return self._proxied.add(instance, _warn=_warn)
  249. def add_all(self, instances: Iterable[object]) -> None:
  250. r"""Add the given collection of instances to this :class:`_orm.Session`.
  251. .. container:: class_bases
  252. Proxied for the :class:`_asyncio.AsyncSession` class on
  253. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  254. .. container:: class_bases
  255. Proxied for the :class:`_orm.Session` class on
  256. behalf of the :class:`_asyncio.AsyncSession` class.
  257. See the documentation for :meth:`_orm.Session.add` for a general
  258. behavioral description.
  259. .. seealso::
  260. :meth:`_orm.Session.add`
  261. :ref:`session_adding` - at :ref:`session_basics`
  262. """ # noqa: E501
  263. return self._proxied.add_all(instances)
  264. def begin(self) -> AsyncSessionTransaction:
  265. r"""Return an :class:`_asyncio.AsyncSessionTransaction` object.
  266. .. container:: class_bases
  267. Proxied for the :class:`_asyncio.AsyncSession` class on
  268. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  269. The underlying :class:`_orm.Session` will perform the
  270. "begin" action when the :class:`_asyncio.AsyncSessionTransaction`
  271. object is entered::
  272. async with async_session.begin():
  273. ... # ORM transaction is begun
  274. Note that database IO will not normally occur when the session-level
  275. transaction is begun, as database transactions begin on an
  276. on-demand basis. However, the begin block is async to accommodate
  277. for a :meth:`_orm.SessionEvents.after_transaction_create`
  278. event hook that may perform IO.
  279. For a general description of ORM begin, see
  280. :meth:`_orm.Session.begin`.
  281. """ # noqa: E501
  282. return self._proxied.begin()
  283. def begin_nested(self) -> AsyncSessionTransaction:
  284. r"""Return an :class:`_asyncio.AsyncSessionTransaction` object
  285. which will begin a "nested" transaction, e.g. SAVEPOINT.
  286. .. container:: class_bases
  287. Proxied for the :class:`_asyncio.AsyncSession` class on
  288. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  289. Behavior is the same as that of :meth:`_asyncio.AsyncSession.begin`.
  290. For a general description of ORM begin nested, see
  291. :meth:`_orm.Session.begin_nested`.
  292. .. seealso::
  293. :ref:`aiosqlite_serializable` - special workarounds required
  294. with the SQLite asyncio driver in order for SAVEPOINT to work
  295. correctly.
  296. """ # noqa: E501
  297. return self._proxied.begin_nested()
  298. async def close(self) -> None:
  299. r"""Close out the transactional resources and ORM objects used by this
  300. :class:`_asyncio.AsyncSession`.
  301. .. container:: class_bases
  302. Proxied for the :class:`_asyncio.AsyncSession` class on
  303. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  304. .. seealso::
  305. :meth:`_orm.Session.close` - main documentation for
  306. "close"
  307. :ref:`session_closing` - detail on the semantics of
  308. :meth:`_asyncio.AsyncSession.close` and
  309. :meth:`_asyncio.AsyncSession.reset`.
  310. """ # noqa: E501
  311. return await self._proxied.close()
  312. async def reset(self) -> None:
  313. r"""Close out the transactional resources and ORM objects used by this
  314. :class:`_orm.Session`, resetting the session to its initial state.
  315. .. container:: class_bases
  316. Proxied for the :class:`_asyncio.AsyncSession` class on
  317. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  318. .. versionadded:: 2.0.22
  319. .. seealso::
  320. :meth:`_orm.Session.reset` - main documentation for
  321. "reset"
  322. :ref:`session_closing` - detail on the semantics of
  323. :meth:`_asyncio.AsyncSession.close` and
  324. :meth:`_asyncio.AsyncSession.reset`.
  325. """ # noqa: E501
  326. return await self._proxied.reset()
  327. async def commit(self) -> None:
  328. r"""Commit the current transaction in progress.
  329. .. container:: class_bases
  330. Proxied for the :class:`_asyncio.AsyncSession` class on
  331. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  332. .. seealso::
  333. :meth:`_orm.Session.commit` - main documentation for
  334. "commit"
  335. """ # noqa: E501
  336. return await self._proxied.commit()
  337. async def connection(
  338. self,
  339. bind_arguments: Optional[_BindArguments] = None,
  340. execution_options: Optional[CoreExecuteOptionsParameter] = None,
  341. **kw: Any,
  342. ) -> AsyncConnection:
  343. r"""Return a :class:`_asyncio.AsyncConnection` object corresponding to
  344. this :class:`.Session` object's transactional state.
  345. .. container:: class_bases
  346. Proxied for the :class:`_asyncio.AsyncSession` class on
  347. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  348. This method may also be used to establish execution options for the
  349. database connection used by the current transaction.
  350. .. versionadded:: 1.4.24 Added \**kw arguments which are passed
  351. through to the underlying :meth:`_orm.Session.connection` method.
  352. .. seealso::
  353. :meth:`_orm.Session.connection` - main documentation for
  354. "connection"
  355. """ # noqa: E501
  356. return await self._proxied.connection(
  357. bind_arguments=bind_arguments,
  358. execution_options=execution_options,
  359. **kw,
  360. )
  361. async def delete(self, instance: object) -> None:
  362. r"""Mark an instance as deleted.
  363. .. container:: class_bases
  364. Proxied for the :class:`_asyncio.AsyncSession` class on
  365. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  366. The database delete operation occurs upon ``flush()``.
  367. As this operation may need to cascade along unloaded relationships,
  368. it is awaitable to allow for those queries to take place.
  369. .. seealso::
  370. :meth:`_orm.Session.delete` - main documentation for delete
  371. """ # noqa: E501
  372. return await self._proxied.delete(instance)
  373. @overload
  374. async def execute(
  375. self,
  376. statement: TypedReturnsRows[_T],
  377. params: Optional[_CoreAnyExecuteParams] = None,
  378. *,
  379. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  380. bind_arguments: Optional[_BindArguments] = None,
  381. _parent_execute_state: Optional[Any] = None,
  382. _add_event: Optional[Any] = None,
  383. ) -> Result[_T]: ...
  384. @overload
  385. async def execute(
  386. self,
  387. statement: UpdateBase,
  388. params: Optional[_CoreAnyExecuteParams] = None,
  389. *,
  390. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  391. bind_arguments: Optional[_BindArguments] = None,
  392. _parent_execute_state: Optional[Any] = None,
  393. _add_event: Optional[Any] = None,
  394. ) -> CursorResult[Any]: ...
  395. @overload
  396. async def execute(
  397. self,
  398. statement: Executable,
  399. params: Optional[_CoreAnyExecuteParams] = None,
  400. *,
  401. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  402. bind_arguments: Optional[_BindArguments] = None,
  403. _parent_execute_state: Optional[Any] = None,
  404. _add_event: Optional[Any] = None,
  405. ) -> Result[Any]: ...
  406. async def execute(
  407. self,
  408. statement: Executable,
  409. params: Optional[_CoreAnyExecuteParams] = None,
  410. *,
  411. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  412. bind_arguments: Optional[_BindArguments] = None,
  413. **kw: Any,
  414. ) -> Result[Any]:
  415. r"""Execute a statement and return a buffered
  416. :class:`_engine.Result` object.
  417. .. container:: class_bases
  418. Proxied for the :class:`_asyncio.AsyncSession` class on
  419. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  420. .. seealso::
  421. :meth:`_orm.Session.execute` - main documentation for execute
  422. """ # noqa: E501
  423. return await self._proxied.execute(
  424. statement,
  425. params=params,
  426. execution_options=execution_options,
  427. bind_arguments=bind_arguments,
  428. **kw,
  429. )
  430. def expire(
  431. self, instance: object, attribute_names: Optional[Iterable[str]] = None
  432. ) -> None:
  433. r"""Expire the attributes on an instance.
  434. .. container:: class_bases
  435. Proxied for the :class:`_asyncio.AsyncSession` class on
  436. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  437. .. container:: class_bases
  438. Proxied for the :class:`_orm.Session` class on
  439. behalf of the :class:`_asyncio.AsyncSession` class.
  440. Marks the attributes of an instance as out of date. When an expired
  441. attribute is next accessed, a query will be issued to the
  442. :class:`.Session` object's current transactional context in order to
  443. load all expired attributes for the given instance. Note that
  444. a highly isolated transaction will return the same values as were
  445. previously read in that same transaction, regardless of changes
  446. in database state outside of that transaction.
  447. To expire all objects in the :class:`.Session` simultaneously,
  448. use :meth:`Session.expire_all`.
  449. The :class:`.Session` object's default behavior is to
  450. expire all state whenever the :meth:`Session.rollback`
  451. or :meth:`Session.commit` methods are called, so that new
  452. state can be loaded for the new transaction. For this reason,
  453. calling :meth:`Session.expire` only makes sense for the specific
  454. case that a non-ORM SQL statement was emitted in the current
  455. transaction.
  456. :param instance: The instance to be refreshed.
  457. :param attribute_names: optional list of string attribute names
  458. indicating a subset of attributes to be expired.
  459. .. seealso::
  460. :ref:`session_expire` - introductory material
  461. :meth:`.Session.expire`
  462. :meth:`.Session.refresh`
  463. :meth:`_orm.Query.populate_existing`
  464. """ # noqa: E501
  465. return self._proxied.expire(instance, attribute_names=attribute_names)
  466. def expire_all(self) -> None:
  467. r"""Expires all persistent instances within this Session.
  468. .. container:: class_bases
  469. Proxied for the :class:`_asyncio.AsyncSession` class on
  470. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  471. .. container:: class_bases
  472. Proxied for the :class:`_orm.Session` class on
  473. behalf of the :class:`_asyncio.AsyncSession` class.
  474. When any attributes on a persistent instance is next accessed,
  475. a query will be issued using the
  476. :class:`.Session` object's current transactional context in order to
  477. load all expired attributes for the given instance. Note that
  478. a highly isolated transaction will return the same values as were
  479. previously read in that same transaction, regardless of changes
  480. in database state outside of that transaction.
  481. To expire individual objects and individual attributes
  482. on those objects, use :meth:`Session.expire`.
  483. The :class:`.Session` object's default behavior is to
  484. expire all state whenever the :meth:`Session.rollback`
  485. or :meth:`Session.commit` methods are called, so that new
  486. state can be loaded for the new transaction. For this reason,
  487. calling :meth:`Session.expire_all` is not usually needed,
  488. assuming the transaction is isolated.
  489. .. seealso::
  490. :ref:`session_expire` - introductory material
  491. :meth:`.Session.expire`
  492. :meth:`.Session.refresh`
  493. :meth:`_orm.Query.populate_existing`
  494. """ # noqa: E501
  495. return self._proxied.expire_all()
  496. def expunge(self, instance: object) -> None:
  497. r"""Remove the `instance` from this ``Session``.
  498. .. container:: class_bases
  499. Proxied for the :class:`_asyncio.AsyncSession` class on
  500. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  501. .. container:: class_bases
  502. Proxied for the :class:`_orm.Session` class on
  503. behalf of the :class:`_asyncio.AsyncSession` class.
  504. This will free all internal references to the instance. Cascading
  505. will be applied according to the *expunge* cascade rule.
  506. """ # noqa: E501
  507. return self._proxied.expunge(instance)
  508. def expunge_all(self) -> None:
  509. r"""Remove all object instances from this ``Session``.
  510. .. container:: class_bases
  511. Proxied for the :class:`_asyncio.AsyncSession` class on
  512. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  513. .. container:: class_bases
  514. Proxied for the :class:`_orm.Session` class on
  515. behalf of the :class:`_asyncio.AsyncSession` class.
  516. This is equivalent to calling ``expunge(obj)`` on all objects in this
  517. ``Session``.
  518. """ # noqa: E501
  519. return self._proxied.expunge_all()
  520. async def flush(self, objects: Optional[Sequence[Any]] = None) -> None:
  521. r"""Flush all the object changes to the database.
  522. .. container:: class_bases
  523. Proxied for the :class:`_asyncio.AsyncSession` class on
  524. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  525. .. seealso::
  526. :meth:`_orm.Session.flush` - main documentation for flush
  527. """ # noqa: E501
  528. return await self._proxied.flush(objects=objects)
  529. def get_bind(
  530. self,
  531. mapper: Optional[_EntityBindKey[_O]] = None,
  532. clause: Optional[ClauseElement] = None,
  533. bind: Optional[_SessionBind] = None,
  534. **kw: Any,
  535. ) -> Union[Engine, Connection]:
  536. r"""Return a "bind" to which the synchronous proxied :class:`_orm.Session`
  537. is bound.
  538. .. container:: class_bases
  539. Proxied for the :class:`_asyncio.AsyncSession` class on
  540. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  541. Unlike the :meth:`_orm.Session.get_bind` method, this method is
  542. currently **not** used by this :class:`.AsyncSession` in any way
  543. in order to resolve engines for requests.
  544. .. note::
  545. This method proxies directly to the :meth:`_orm.Session.get_bind`
  546. method, however is currently **not** useful as an override target,
  547. in contrast to that of the :meth:`_orm.Session.get_bind` method.
  548. The example below illustrates how to implement custom
  549. :meth:`_orm.Session.get_bind` schemes that work with
  550. :class:`.AsyncSession` and :class:`.AsyncEngine`.
  551. The pattern introduced at :ref:`session_custom_partitioning`
  552. illustrates how to apply a custom bind-lookup scheme to a
  553. :class:`_orm.Session` given a set of :class:`_engine.Engine` objects.
  554. To apply a corresponding :meth:`_orm.Session.get_bind` implementation
  555. for use with a :class:`.AsyncSession` and :class:`.AsyncEngine`
  556. objects, continue to subclass :class:`_orm.Session` and apply it to
  557. :class:`.AsyncSession` using
  558. :paramref:`.AsyncSession.sync_session_class`. The inner method must
  559. continue to return :class:`_engine.Engine` instances, which can be
  560. acquired from a :class:`_asyncio.AsyncEngine` using the
  561. :attr:`_asyncio.AsyncEngine.sync_engine` attribute::
  562. # using example from "Custom Vertical Partitioning"
  563. import random
  564. from sqlalchemy.ext.asyncio import AsyncSession
  565. from sqlalchemy.ext.asyncio import create_async_engine
  566. from sqlalchemy.ext.asyncio import async_sessionmaker
  567. from sqlalchemy.orm import Session
  568. # construct async engines w/ async drivers
  569. engines = {
  570. "leader": create_async_engine("sqlite+aiosqlite:///leader.db"),
  571. "other": create_async_engine("sqlite+aiosqlite:///other.db"),
  572. "follower1": create_async_engine("sqlite+aiosqlite:///follower1.db"),
  573. "follower2": create_async_engine("sqlite+aiosqlite:///follower2.db"),
  574. }
  575. class RoutingSession(Session):
  576. def get_bind(self, mapper=None, clause=None, **kw):
  577. # within get_bind(), return sync engines
  578. if mapper and issubclass(mapper.class_, MyOtherClass):
  579. return engines["other"].sync_engine
  580. elif self._flushing or isinstance(clause, (Update, Delete)):
  581. return engines["leader"].sync_engine
  582. else:
  583. return engines[
  584. random.choice(["follower1", "follower2"])
  585. ].sync_engine
  586. # apply to AsyncSession using sync_session_class
  587. AsyncSessionMaker = async_sessionmaker(sync_session_class=RoutingSession)
  588. The :meth:`_orm.Session.get_bind` method is called in a non-asyncio,
  589. implicitly non-blocking context in the same manner as ORM event hooks
  590. and functions that are invoked via :meth:`.AsyncSession.run_sync`, so
  591. routines that wish to run SQL commands inside of
  592. :meth:`_orm.Session.get_bind` can continue to do so using
  593. blocking-style code, which will be translated to implicitly async calls
  594. at the point of invoking IO on the database drivers.
  595. """ # noqa: E501
  596. return self._proxied.get_bind(
  597. mapper=mapper, clause=clause, bind=bind, **kw
  598. )
  599. def is_modified(
  600. self, instance: object, include_collections: bool = True
  601. ) -> bool:
  602. r"""Return ``True`` if the given instance has locally
  603. modified attributes.
  604. .. container:: class_bases
  605. Proxied for the :class:`_asyncio.AsyncSession` class on
  606. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  607. .. container:: class_bases
  608. Proxied for the :class:`_orm.Session` class on
  609. behalf of the :class:`_asyncio.AsyncSession` class.
  610. This method retrieves the history for each instrumented
  611. attribute on the instance and performs a comparison of the current
  612. value to its previously flushed or committed value, if any.
  613. It is in effect a more expensive and accurate
  614. version of checking for the given instance in the
  615. :attr:`.Session.dirty` collection; a full test for
  616. each attribute's net "dirty" status is performed.
  617. E.g.::
  618. return session.is_modified(someobject)
  619. A few caveats to this method apply:
  620. * Instances present in the :attr:`.Session.dirty` collection may
  621. report ``False`` when tested with this method. This is because
  622. the object may have received change events via attribute mutation,
  623. thus placing it in :attr:`.Session.dirty`, but ultimately the state
  624. is the same as that loaded from the database, resulting in no net
  625. change here.
  626. * Scalar attributes may not have recorded the previously set
  627. value when a new value was applied, if the attribute was not loaded,
  628. or was expired, at the time the new value was received - in these
  629. cases, the attribute is assumed to have a change, even if there is
  630. ultimately no net change against its database value. SQLAlchemy in
  631. most cases does not need the "old" value when a set event occurs, so
  632. it skips the expense of a SQL call if the old value isn't present,
  633. based on the assumption that an UPDATE of the scalar value is
  634. usually needed, and in those few cases where it isn't, is less
  635. expensive on average than issuing a defensive SELECT.
  636. The "old" value is fetched unconditionally upon set only if the
  637. attribute container has the ``active_history`` flag set to ``True``.
  638. This flag is set typically for primary key attributes and scalar
  639. object references that are not a simple many-to-one. To set this
  640. flag for any arbitrary mapped column, use the ``active_history``
  641. argument with :func:`.column_property`.
  642. :param instance: mapped instance to be tested for pending changes.
  643. :param include_collections: Indicates if multivalued collections
  644. should be included in the operation. Setting this to ``False`` is a
  645. way to detect only local-column based properties (i.e. scalar columns
  646. or many-to-one foreign keys) that would result in an UPDATE for this
  647. instance upon flush.
  648. """ # noqa: E501
  649. return self._proxied.is_modified(
  650. instance, include_collections=include_collections
  651. )
  652. async def invalidate(self) -> None:
  653. r"""Close this Session, using connection invalidation.
  654. .. container:: class_bases
  655. Proxied for the :class:`_asyncio.AsyncSession` class on
  656. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  657. For a complete description, see :meth:`_orm.Session.invalidate`.
  658. """ # noqa: E501
  659. return await self._proxied.invalidate()
  660. async def merge(
  661. self,
  662. instance: _O,
  663. *,
  664. load: bool = True,
  665. options: Optional[Sequence[ORMOption]] = None,
  666. ) -> _O:
  667. r"""Copy the state of a given instance into a corresponding instance
  668. within this :class:`_asyncio.AsyncSession`.
  669. .. container:: class_bases
  670. Proxied for the :class:`_asyncio.AsyncSession` class on
  671. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  672. .. seealso::
  673. :meth:`_orm.Session.merge` - main documentation for merge
  674. """ # noqa: E501
  675. return await self._proxied.merge(instance, load=load, options=options)
  676. async def refresh(
  677. self,
  678. instance: object,
  679. attribute_names: Optional[Iterable[str]] = None,
  680. with_for_update: ForUpdateParameter = None,
  681. ) -> None:
  682. r"""Expire and refresh the attributes on the given instance.
  683. .. container:: class_bases
  684. Proxied for the :class:`_asyncio.AsyncSession` class on
  685. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  686. A query will be issued to the database and all attributes will be
  687. refreshed with their current database value.
  688. This is the async version of the :meth:`_orm.Session.refresh` method.
  689. See that method for a complete description of all options.
  690. .. seealso::
  691. :meth:`_orm.Session.refresh` - main documentation for refresh
  692. """ # noqa: E501
  693. return await self._proxied.refresh(
  694. instance,
  695. attribute_names=attribute_names,
  696. with_for_update=with_for_update,
  697. )
  698. async def rollback(self) -> None:
  699. r"""Rollback the current transaction in progress.
  700. .. container:: class_bases
  701. Proxied for the :class:`_asyncio.AsyncSession` class on
  702. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  703. .. seealso::
  704. :meth:`_orm.Session.rollback` - main documentation for
  705. "rollback"
  706. """ # noqa: E501
  707. return await self._proxied.rollback()
  708. @overload
  709. async def scalar(
  710. self,
  711. statement: TypedReturnsRows[Tuple[_T]],
  712. params: Optional[_CoreAnyExecuteParams] = None,
  713. *,
  714. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  715. bind_arguments: Optional[_BindArguments] = None,
  716. **kw: Any,
  717. ) -> Optional[_T]: ...
  718. @overload
  719. async def scalar(
  720. self,
  721. statement: Executable,
  722. params: Optional[_CoreAnyExecuteParams] = None,
  723. *,
  724. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  725. bind_arguments: Optional[_BindArguments] = None,
  726. **kw: Any,
  727. ) -> Any: ...
  728. async def scalar(
  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. **kw: Any,
  736. ) -> Any:
  737. r"""Execute a statement and return a scalar result.
  738. .. container:: class_bases
  739. Proxied for the :class:`_asyncio.AsyncSession` class on
  740. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  741. .. seealso::
  742. :meth:`_orm.Session.scalar` - main documentation for scalar
  743. """ # noqa: E501
  744. return await self._proxied.scalar(
  745. statement,
  746. params=params,
  747. execution_options=execution_options,
  748. bind_arguments=bind_arguments,
  749. **kw,
  750. )
  751. @overload
  752. async def scalars(
  753. self,
  754. statement: TypedReturnsRows[Tuple[_T]],
  755. params: Optional[_CoreAnyExecuteParams] = None,
  756. *,
  757. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  758. bind_arguments: Optional[_BindArguments] = None,
  759. **kw: Any,
  760. ) -> ScalarResult[_T]: ...
  761. @overload
  762. async def scalars(
  763. self,
  764. statement: Executable,
  765. params: Optional[_CoreAnyExecuteParams] = None,
  766. *,
  767. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  768. bind_arguments: Optional[_BindArguments] = None,
  769. **kw: Any,
  770. ) -> ScalarResult[Any]: ...
  771. async def scalars(
  772. self,
  773. statement: Executable,
  774. params: Optional[_CoreAnyExecuteParams] = None,
  775. *,
  776. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  777. bind_arguments: Optional[_BindArguments] = None,
  778. **kw: Any,
  779. ) -> ScalarResult[Any]:
  780. r"""Execute a statement and return scalar results.
  781. .. container:: class_bases
  782. Proxied for the :class:`_asyncio.AsyncSession` class on
  783. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  784. :return: a :class:`_result.ScalarResult` object
  785. .. versionadded:: 1.4.24 Added :meth:`_asyncio.AsyncSession.scalars`
  786. .. versionadded:: 1.4.26 Added
  787. :meth:`_asyncio.async_scoped_session.scalars`
  788. .. seealso::
  789. :meth:`_orm.Session.scalars` - main documentation for scalars
  790. :meth:`_asyncio.AsyncSession.stream_scalars` - streaming version
  791. """ # noqa: E501
  792. return await self._proxied.scalars(
  793. statement,
  794. params=params,
  795. execution_options=execution_options,
  796. bind_arguments=bind_arguments,
  797. **kw,
  798. )
  799. async def get(
  800. self,
  801. entity: _EntityBindKey[_O],
  802. ident: _PKIdentityArgument,
  803. *,
  804. options: Optional[Sequence[ORMOption]] = None,
  805. populate_existing: bool = False,
  806. with_for_update: ForUpdateParameter = None,
  807. identity_token: Optional[Any] = None,
  808. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  809. ) -> Union[_O, None]:
  810. r"""Return an instance based on the given primary key identifier,
  811. or ``None`` if not found.
  812. .. container:: class_bases
  813. Proxied for the :class:`_asyncio.AsyncSession` class on
  814. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  815. .. seealso::
  816. :meth:`_orm.Session.get` - main documentation for get
  817. """ # noqa: E501
  818. result = await self._proxied.get(
  819. entity,
  820. ident,
  821. options=options,
  822. populate_existing=populate_existing,
  823. with_for_update=with_for_update,
  824. identity_token=identity_token,
  825. execution_options=execution_options,
  826. )
  827. return result
  828. async def get_one(
  829. self,
  830. entity: _EntityBindKey[_O],
  831. ident: _PKIdentityArgument,
  832. *,
  833. options: Optional[Sequence[ORMOption]] = None,
  834. populate_existing: bool = False,
  835. with_for_update: ForUpdateParameter = None,
  836. identity_token: Optional[Any] = None,
  837. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  838. ) -> _O:
  839. r"""Return an instance based on the given primary key identifier,
  840. or raise an exception if not found.
  841. .. container:: class_bases
  842. Proxied for the :class:`_asyncio.AsyncSession` class on
  843. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  844. Raises :class:`_exc.NoResultFound` if the query selects no rows.
  845. ..versionadded: 2.0.22
  846. .. seealso::
  847. :meth:`_orm.Session.get_one` - main documentation for get_one
  848. """ # noqa: E501
  849. return await self._proxied.get_one(
  850. entity,
  851. ident,
  852. options=options,
  853. populate_existing=populate_existing,
  854. with_for_update=with_for_update,
  855. identity_token=identity_token,
  856. execution_options=execution_options,
  857. )
  858. @overload
  859. async def stream(
  860. self,
  861. statement: TypedReturnsRows[_T],
  862. params: Optional[_CoreAnyExecuteParams] = None,
  863. *,
  864. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  865. bind_arguments: Optional[_BindArguments] = None,
  866. **kw: Any,
  867. ) -> AsyncResult[_T]: ...
  868. @overload
  869. async def stream(
  870. self,
  871. statement: Executable,
  872. params: Optional[_CoreAnyExecuteParams] = None,
  873. *,
  874. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  875. bind_arguments: Optional[_BindArguments] = None,
  876. **kw: Any,
  877. ) -> AsyncResult[Any]: ...
  878. async def stream(
  879. self,
  880. statement: Executable,
  881. params: Optional[_CoreAnyExecuteParams] = None,
  882. *,
  883. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  884. bind_arguments: Optional[_BindArguments] = None,
  885. **kw: Any,
  886. ) -> AsyncResult[Any]:
  887. r"""Execute a statement and return a streaming
  888. :class:`_asyncio.AsyncResult` object.
  889. .. container:: class_bases
  890. Proxied for the :class:`_asyncio.AsyncSession` class on
  891. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  892. """ # noqa: E501
  893. return await self._proxied.stream(
  894. statement,
  895. params=params,
  896. execution_options=execution_options,
  897. bind_arguments=bind_arguments,
  898. **kw,
  899. )
  900. @overload
  901. async def stream_scalars(
  902. self,
  903. statement: TypedReturnsRows[Tuple[_T]],
  904. params: Optional[_CoreAnyExecuteParams] = None,
  905. *,
  906. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  907. bind_arguments: Optional[_BindArguments] = None,
  908. **kw: Any,
  909. ) -> AsyncScalarResult[_T]: ...
  910. @overload
  911. async def stream_scalars(
  912. self,
  913. statement: Executable,
  914. params: Optional[_CoreAnyExecuteParams] = None,
  915. *,
  916. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  917. bind_arguments: Optional[_BindArguments] = None,
  918. **kw: Any,
  919. ) -> AsyncScalarResult[Any]: ...
  920. async def stream_scalars(
  921. self,
  922. statement: Executable,
  923. params: Optional[_CoreAnyExecuteParams] = None,
  924. *,
  925. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  926. bind_arguments: Optional[_BindArguments] = None,
  927. **kw: Any,
  928. ) -> AsyncScalarResult[Any]:
  929. r"""Execute a statement and return a stream of scalar results.
  930. .. container:: class_bases
  931. Proxied for the :class:`_asyncio.AsyncSession` class on
  932. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  933. :return: an :class:`_asyncio.AsyncScalarResult` object
  934. .. versionadded:: 1.4.24
  935. .. seealso::
  936. :meth:`_orm.Session.scalars` - main documentation for scalars
  937. :meth:`_asyncio.AsyncSession.scalars` - non streaming version
  938. """ # noqa: E501
  939. return await self._proxied.stream_scalars(
  940. statement,
  941. params=params,
  942. execution_options=execution_options,
  943. bind_arguments=bind_arguments,
  944. **kw,
  945. )
  946. @property
  947. def bind(self) -> Any:
  948. r"""Proxy for the :attr:`_asyncio.AsyncSession.bind` attribute
  949. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  950. """ # noqa: E501
  951. return self._proxied.bind
  952. @bind.setter
  953. def bind(self, attr: Any) -> None:
  954. self._proxied.bind = attr
  955. @property
  956. def dirty(self) -> Any:
  957. r"""The set of all persistent instances considered dirty.
  958. .. container:: class_bases
  959. Proxied for the :class:`_asyncio.AsyncSession` class
  960. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  961. .. container:: class_bases
  962. Proxied for the :class:`_orm.Session` class
  963. on behalf of the :class:`_asyncio.AsyncSession` class.
  964. E.g.::
  965. some_mapped_object in session.dirty
  966. Instances are considered dirty when they were modified but not
  967. deleted.
  968. Note that this 'dirty' calculation is 'optimistic'; most
  969. attribute-setting or collection modification operations will
  970. mark an instance as 'dirty' and place it in this set, even if
  971. there is no net change to the attribute's value. At flush
  972. time, the value of each attribute is compared to its
  973. previously saved value, and if there's no net change, no SQL
  974. operation will occur (this is a more expensive operation so
  975. it's only done at flush time).
  976. To check if an instance has actionable net changes to its
  977. attributes, use the :meth:`.Session.is_modified` method.
  978. """ # noqa: E501
  979. return self._proxied.dirty
  980. @property
  981. def deleted(self) -> Any:
  982. r"""The set of all instances marked as 'deleted' within this ``Session``
  983. .. container:: class_bases
  984. Proxied for the :class:`_asyncio.AsyncSession` class
  985. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  986. .. container:: class_bases
  987. Proxied for the :class:`_orm.Session` class
  988. on behalf of the :class:`_asyncio.AsyncSession` class.
  989. """ # noqa: E501
  990. return self._proxied.deleted
  991. @property
  992. def new(self) -> Any:
  993. r"""The set of all instances marked as 'new' within this ``Session``.
  994. .. container:: class_bases
  995. Proxied for the :class:`_asyncio.AsyncSession` class
  996. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  997. .. container:: class_bases
  998. Proxied for the :class:`_orm.Session` class
  999. on behalf of the :class:`_asyncio.AsyncSession` class.
  1000. """ # noqa: E501
  1001. return self._proxied.new
  1002. @property
  1003. def identity_map(self) -> Any:
  1004. r"""Proxy for the :attr:`_orm.Session.identity_map` attribute
  1005. on behalf of the :class:`_asyncio.AsyncSession` class.
  1006. .. container:: class_bases
  1007. Proxied for the :class:`_asyncio.AsyncSession` class
  1008. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1009. """ # noqa: E501
  1010. return self._proxied.identity_map
  1011. @identity_map.setter
  1012. def identity_map(self, attr: Any) -> None:
  1013. self._proxied.identity_map = attr
  1014. @property
  1015. def is_active(self) -> Any:
  1016. r"""True if this :class:`.Session` not in "partial rollback" state.
  1017. .. container:: class_bases
  1018. Proxied for the :class:`_asyncio.AsyncSession` class
  1019. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1020. .. container:: class_bases
  1021. Proxied for the :class:`_orm.Session` class
  1022. on behalf of the :class:`_asyncio.AsyncSession` class.
  1023. .. versionchanged:: 1.4 The :class:`_orm.Session` no longer begins
  1024. a new transaction immediately, so this attribute will be False
  1025. when the :class:`_orm.Session` is first instantiated.
  1026. "partial rollback" state typically indicates that the flush process
  1027. of the :class:`_orm.Session` has failed, and that the
  1028. :meth:`_orm.Session.rollback` method must be emitted in order to
  1029. fully roll back the transaction.
  1030. If this :class:`_orm.Session` is not in a transaction at all, the
  1031. :class:`_orm.Session` will autobegin when it is first used, so in this
  1032. case :attr:`_orm.Session.is_active` will return True.
  1033. Otherwise, if this :class:`_orm.Session` is within a transaction,
  1034. and that transaction has not been rolled back internally, the
  1035. :attr:`_orm.Session.is_active` will also return True.
  1036. .. seealso::
  1037. :ref:`faq_session_rollback`
  1038. :meth:`_orm.Session.in_transaction`
  1039. """ # noqa: E501
  1040. return self._proxied.is_active
  1041. @property
  1042. def autoflush(self) -> Any:
  1043. r"""Proxy for the :attr:`_orm.Session.autoflush` attribute
  1044. on behalf of the :class:`_asyncio.AsyncSession` class.
  1045. .. container:: class_bases
  1046. Proxied for the :class:`_asyncio.AsyncSession` class
  1047. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1048. """ # noqa: E501
  1049. return self._proxied.autoflush
  1050. @autoflush.setter
  1051. def autoflush(self, attr: Any) -> None:
  1052. self._proxied.autoflush = attr
  1053. @property
  1054. def no_autoflush(self) -> Any:
  1055. r"""Return a context manager that disables autoflush.
  1056. .. container:: class_bases
  1057. Proxied for the :class:`_asyncio.AsyncSession` class
  1058. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1059. .. container:: class_bases
  1060. Proxied for the :class:`_orm.Session` class
  1061. on behalf of the :class:`_asyncio.AsyncSession` class.
  1062. e.g.::
  1063. with session.no_autoflush:
  1064. some_object = SomeClass()
  1065. session.add(some_object)
  1066. # won't autoflush
  1067. some_object.related_thing = session.query(SomeRelated).first()
  1068. Operations that proceed within the ``with:`` block
  1069. will not be subject to flushes occurring upon query
  1070. access. This is useful when initializing a series
  1071. of objects which involve existing database queries,
  1072. where the uncompleted object should not yet be flushed.
  1073. """ # noqa: E501
  1074. return self._proxied.no_autoflush
  1075. @property
  1076. def info(self) -> Any:
  1077. r"""A user-modifiable dictionary.
  1078. .. container:: class_bases
  1079. Proxied for the :class:`_asyncio.AsyncSession` class
  1080. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1081. .. container:: class_bases
  1082. Proxied for the :class:`_orm.Session` class
  1083. on behalf of the :class:`_asyncio.AsyncSession` class.
  1084. The initial value of this dictionary can be populated using the
  1085. ``info`` argument to the :class:`.Session` constructor or
  1086. :class:`.sessionmaker` constructor or factory methods. The dictionary
  1087. here is always local to this :class:`.Session` and can be modified
  1088. independently of all other :class:`.Session` objects.
  1089. """ # noqa: E501
  1090. return self._proxied.info
  1091. @classmethod
  1092. async def close_all(cls) -> None:
  1093. r"""Close all :class:`_asyncio.AsyncSession` sessions.
  1094. .. container:: class_bases
  1095. Proxied for the :class:`_asyncio.AsyncSession` class on
  1096. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1097. .. deprecated:: 2.0 The :meth:`.AsyncSession.close_all` method is deprecated and will be removed in a future release. Please refer to :func:`_asyncio.close_all_sessions`.
  1098. """ # noqa: E501
  1099. return await AsyncSession.close_all()
  1100. @classmethod
  1101. def object_session(cls, instance: object) -> Optional[Session]:
  1102. r"""Return the :class:`.Session` to which an object belongs.
  1103. .. container:: class_bases
  1104. Proxied for the :class:`_asyncio.AsyncSession` class on
  1105. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1106. .. container:: class_bases
  1107. Proxied for the :class:`_orm.Session` class on
  1108. behalf of the :class:`_asyncio.AsyncSession` class.
  1109. This is an alias of :func:`.object_session`.
  1110. """ # noqa: E501
  1111. return AsyncSession.object_session(instance)
  1112. @classmethod
  1113. def identity_key(
  1114. cls,
  1115. class_: Optional[Type[Any]] = None,
  1116. ident: Union[Any, Tuple[Any, ...]] = None,
  1117. *,
  1118. instance: Optional[Any] = None,
  1119. row: Optional[Union[Row[Any], RowMapping]] = None,
  1120. identity_token: Optional[Any] = None,
  1121. ) -> _IdentityKeyType[Any]:
  1122. r"""Return an identity key.
  1123. .. container:: class_bases
  1124. Proxied for the :class:`_asyncio.AsyncSession` class on
  1125. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1126. .. container:: class_bases
  1127. Proxied for the :class:`_orm.Session` class on
  1128. behalf of the :class:`_asyncio.AsyncSession` class.
  1129. This is an alias of :func:`.util.identity_key`.
  1130. """ # noqa: E501
  1131. return AsyncSession.identity_key(
  1132. class_=class_,
  1133. ident=ident,
  1134. instance=instance,
  1135. row=row,
  1136. identity_token=identity_token,
  1137. )
  1138. # END PROXY METHODS async_scoped_session