scoping.py 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625
  1. # ext/asyncio/scoping.py
  2. # Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: https://www.opensource.org/licenses/mit-license.php
  7. 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. ...
  385. @overload
  386. async def execute(
  387. self,
  388. statement: UpdateBase,
  389. params: Optional[_CoreAnyExecuteParams] = None,
  390. *,
  391. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  392. bind_arguments: Optional[_BindArguments] = None,
  393. _parent_execute_state: Optional[Any] = None,
  394. _add_event: Optional[Any] = None,
  395. ) -> CursorResult[Any]:
  396. ...
  397. @overload
  398. async def execute(
  399. self,
  400. statement: Executable,
  401. params: Optional[_CoreAnyExecuteParams] = None,
  402. *,
  403. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  404. bind_arguments: Optional[_BindArguments] = None,
  405. _parent_execute_state: Optional[Any] = None,
  406. _add_event: Optional[Any] = None,
  407. ) -> Result[Any]:
  408. ...
  409. async def execute(
  410. self,
  411. statement: Executable,
  412. params: Optional[_CoreAnyExecuteParams] = None,
  413. *,
  414. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  415. bind_arguments: Optional[_BindArguments] = None,
  416. **kw: Any,
  417. ) -> Result[Any]:
  418. r"""Execute a statement and return a buffered
  419. :class:`_engine.Result` object.
  420. .. container:: class_bases
  421. Proxied for the :class:`_asyncio.AsyncSession` class on
  422. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  423. .. seealso::
  424. :meth:`_orm.Session.execute` - main documentation for execute
  425. """ # noqa: E501
  426. return await self._proxied.execute(
  427. statement,
  428. params=params,
  429. execution_options=execution_options,
  430. bind_arguments=bind_arguments,
  431. **kw,
  432. )
  433. def expire(
  434. self, instance: object, attribute_names: Optional[Iterable[str]] = None
  435. ) -> None:
  436. r"""Expire the attributes on an instance.
  437. .. container:: class_bases
  438. Proxied for the :class:`_asyncio.AsyncSession` class on
  439. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  440. .. container:: class_bases
  441. Proxied for the :class:`_orm.Session` class on
  442. behalf of the :class:`_asyncio.AsyncSession` class.
  443. Marks the attributes of an instance as out of date. When an expired
  444. attribute is next accessed, a query will be issued to the
  445. :class:`.Session` object's current transactional context in order to
  446. load all expired attributes for the given instance. Note that
  447. a highly isolated transaction will return the same values as were
  448. previously read in that same transaction, regardless of changes
  449. in database state outside of that transaction.
  450. To expire all objects in the :class:`.Session` simultaneously,
  451. use :meth:`Session.expire_all`.
  452. The :class:`.Session` object's default behavior is to
  453. expire all state whenever the :meth:`Session.rollback`
  454. or :meth:`Session.commit` methods are called, so that new
  455. state can be loaded for the new transaction. For this reason,
  456. calling :meth:`Session.expire` only makes sense for the specific
  457. case that a non-ORM SQL statement was emitted in the current
  458. transaction.
  459. :param instance: The instance to be refreshed.
  460. :param attribute_names: optional list of string attribute names
  461. indicating a subset of attributes to be expired.
  462. .. seealso::
  463. :ref:`session_expire` - introductory material
  464. :meth:`.Session.expire`
  465. :meth:`.Session.refresh`
  466. :meth:`_orm.Query.populate_existing`
  467. """ # noqa: E501
  468. return self._proxied.expire(instance, attribute_names=attribute_names)
  469. def expire_all(self) -> None:
  470. r"""Expires all persistent instances within this Session.
  471. .. container:: class_bases
  472. Proxied for the :class:`_asyncio.AsyncSession` class on
  473. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  474. .. container:: class_bases
  475. Proxied for the :class:`_orm.Session` class on
  476. behalf of the :class:`_asyncio.AsyncSession` class.
  477. When any attributes on a persistent instance is next accessed,
  478. a query will be issued using the
  479. :class:`.Session` object's current transactional context in order to
  480. load all expired attributes for the given instance. Note that
  481. a highly isolated transaction will return the same values as were
  482. previously read in that same transaction, regardless of changes
  483. in database state outside of that transaction.
  484. To expire individual objects and individual attributes
  485. on those objects, use :meth:`Session.expire`.
  486. The :class:`.Session` object's default behavior is to
  487. expire all state whenever the :meth:`Session.rollback`
  488. or :meth:`Session.commit` methods are called, so that new
  489. state can be loaded for the new transaction. For this reason,
  490. calling :meth:`Session.expire_all` is not usually needed,
  491. assuming the transaction is isolated.
  492. .. seealso::
  493. :ref:`session_expire` - introductory material
  494. :meth:`.Session.expire`
  495. :meth:`.Session.refresh`
  496. :meth:`_orm.Query.populate_existing`
  497. """ # noqa: E501
  498. return self._proxied.expire_all()
  499. def expunge(self, instance: object) -> None:
  500. r"""Remove the `instance` from this ``Session``.
  501. .. container:: class_bases
  502. Proxied for the :class:`_asyncio.AsyncSession` class on
  503. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  504. .. container:: class_bases
  505. Proxied for the :class:`_orm.Session` class on
  506. behalf of the :class:`_asyncio.AsyncSession` class.
  507. This will free all internal references to the instance. Cascading
  508. will be applied according to the *expunge* cascade rule.
  509. """ # noqa: E501
  510. return self._proxied.expunge(instance)
  511. def expunge_all(self) -> None:
  512. r"""Remove all object instances from this ``Session``.
  513. .. container:: class_bases
  514. Proxied for the :class:`_asyncio.AsyncSession` class on
  515. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  516. .. container:: class_bases
  517. Proxied for the :class:`_orm.Session` class on
  518. behalf of the :class:`_asyncio.AsyncSession` class.
  519. This is equivalent to calling ``expunge(obj)`` on all objects in this
  520. ``Session``.
  521. """ # noqa: E501
  522. return self._proxied.expunge_all()
  523. async def flush(self, objects: Optional[Sequence[Any]] = None) -> None:
  524. r"""Flush all the object changes to the database.
  525. .. container:: class_bases
  526. Proxied for the :class:`_asyncio.AsyncSession` class on
  527. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  528. .. seealso::
  529. :meth:`_orm.Session.flush` - main documentation for flush
  530. """ # noqa: E501
  531. return await self._proxied.flush(objects=objects)
  532. def get_bind(
  533. self,
  534. mapper: Optional[_EntityBindKey[_O]] = None,
  535. clause: Optional[ClauseElement] = None,
  536. bind: Optional[_SessionBind] = None,
  537. **kw: Any,
  538. ) -> Union[Engine, Connection]:
  539. r"""Return a "bind" to which the synchronous proxied :class:`_orm.Session`
  540. is bound.
  541. .. container:: class_bases
  542. Proxied for the :class:`_asyncio.AsyncSession` class on
  543. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  544. Unlike the :meth:`_orm.Session.get_bind` method, this method is
  545. currently **not** used by this :class:`.AsyncSession` in any way
  546. in order to resolve engines for requests.
  547. .. note::
  548. This method proxies directly to the :meth:`_orm.Session.get_bind`
  549. method, however is currently **not** useful as an override target,
  550. in contrast to that of the :meth:`_orm.Session.get_bind` method.
  551. The example below illustrates how to implement custom
  552. :meth:`_orm.Session.get_bind` schemes that work with
  553. :class:`.AsyncSession` and :class:`.AsyncEngine`.
  554. The pattern introduced at :ref:`session_custom_partitioning`
  555. illustrates how to apply a custom bind-lookup scheme to a
  556. :class:`_orm.Session` given a set of :class:`_engine.Engine` objects.
  557. To apply a corresponding :meth:`_orm.Session.get_bind` implementation
  558. for use with a :class:`.AsyncSession` and :class:`.AsyncEngine`
  559. objects, continue to subclass :class:`_orm.Session` and apply it to
  560. :class:`.AsyncSession` using
  561. :paramref:`.AsyncSession.sync_session_class`. The inner method must
  562. continue to return :class:`_engine.Engine` instances, which can be
  563. acquired from a :class:`_asyncio.AsyncEngine` using the
  564. :attr:`_asyncio.AsyncEngine.sync_engine` attribute::
  565. # using example from "Custom Vertical Partitioning"
  566. import random
  567. from sqlalchemy.ext.asyncio import AsyncSession
  568. from sqlalchemy.ext.asyncio import create_async_engine
  569. from sqlalchemy.ext.asyncio import async_sessionmaker
  570. from sqlalchemy.orm import Session
  571. # construct async engines w/ async drivers
  572. engines = {
  573. 'leader':create_async_engine("sqlite+aiosqlite:///leader.db"),
  574. 'other':create_async_engine("sqlite+aiosqlite:///other.db"),
  575. 'follower1':create_async_engine("sqlite+aiosqlite:///follower1.db"),
  576. 'follower2':create_async_engine("sqlite+aiosqlite:///follower2.db"),
  577. }
  578. class RoutingSession(Session):
  579. def get_bind(self, mapper=None, clause=None, **kw):
  580. # within get_bind(), return sync engines
  581. if mapper and issubclass(mapper.class_, MyOtherClass):
  582. return engines['other'].sync_engine
  583. elif self._flushing or isinstance(clause, (Update, Delete)):
  584. return engines['leader'].sync_engine
  585. else:
  586. return engines[
  587. random.choice(['follower1','follower2'])
  588. ].sync_engine
  589. # apply to AsyncSession using sync_session_class
  590. AsyncSessionMaker = async_sessionmaker(
  591. sync_session_class=RoutingSession
  592. )
  593. The :meth:`_orm.Session.get_bind` method is called in a non-asyncio,
  594. implicitly non-blocking context in the same manner as ORM event hooks
  595. and functions that are invoked via :meth:`.AsyncSession.run_sync`, so
  596. routines that wish to run SQL commands inside of
  597. :meth:`_orm.Session.get_bind` can continue to do so using
  598. blocking-style code, which will be translated to implicitly async calls
  599. at the point of invoking IO on the database drivers.
  600. """ # noqa: E501
  601. return self._proxied.get_bind(
  602. mapper=mapper, clause=clause, bind=bind, **kw
  603. )
  604. def is_modified(
  605. self, instance: object, include_collections: bool = True
  606. ) -> bool:
  607. r"""Return ``True`` if the given instance has locally
  608. modified attributes.
  609. .. container:: class_bases
  610. Proxied for the :class:`_asyncio.AsyncSession` class on
  611. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  612. .. container:: class_bases
  613. Proxied for the :class:`_orm.Session` class on
  614. behalf of the :class:`_asyncio.AsyncSession` class.
  615. This method retrieves the history for each instrumented
  616. attribute on the instance and performs a comparison of the current
  617. value to its previously committed value, if any.
  618. It is in effect a more expensive and accurate
  619. version of checking for the given instance in the
  620. :attr:`.Session.dirty` collection; a full test for
  621. each attribute's net "dirty" status is performed.
  622. E.g.::
  623. return session.is_modified(someobject)
  624. A few caveats to this method apply:
  625. * Instances present in the :attr:`.Session.dirty` collection may
  626. report ``False`` when tested with this method. This is because
  627. the object may have received change events via attribute mutation,
  628. thus placing it in :attr:`.Session.dirty`, but ultimately the state
  629. is the same as that loaded from the database, resulting in no net
  630. change here.
  631. * Scalar attributes may not have recorded the previously set
  632. value when a new value was applied, if the attribute was not loaded,
  633. or was expired, at the time the new value was received - in these
  634. cases, the attribute is assumed to have a change, even if there is
  635. ultimately no net change against its database value. SQLAlchemy in
  636. most cases does not need the "old" value when a set event occurs, so
  637. it skips the expense of a SQL call if the old value isn't present,
  638. based on the assumption that an UPDATE of the scalar value is
  639. usually needed, and in those few cases where it isn't, is less
  640. expensive on average than issuing a defensive SELECT.
  641. The "old" value is fetched unconditionally upon set only if the
  642. attribute container has the ``active_history`` flag set to ``True``.
  643. This flag is set typically for primary key attributes and scalar
  644. object references that are not a simple many-to-one. To set this
  645. flag for any arbitrary mapped column, use the ``active_history``
  646. argument with :func:`.column_property`.
  647. :param instance: mapped instance to be tested for pending changes.
  648. :param include_collections: Indicates if multivalued collections
  649. should be included in the operation. Setting this to ``False`` is a
  650. way to detect only local-column based properties (i.e. scalar columns
  651. or many-to-one foreign keys) that would result in an UPDATE for this
  652. instance upon flush.
  653. """ # noqa: E501
  654. return self._proxied.is_modified(
  655. instance, include_collections=include_collections
  656. )
  657. async def invalidate(self) -> None:
  658. r"""Close this Session, using connection invalidation.
  659. .. container:: class_bases
  660. Proxied for the :class:`_asyncio.AsyncSession` class on
  661. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  662. For a complete description, see :meth:`_orm.Session.invalidate`.
  663. """ # noqa: E501
  664. return await self._proxied.invalidate()
  665. async def merge(
  666. self,
  667. instance: _O,
  668. *,
  669. load: bool = True,
  670. options: Optional[Sequence[ORMOption]] = None,
  671. ) -> _O:
  672. r"""Copy the state of a given instance into a corresponding instance
  673. within this :class:`_asyncio.AsyncSession`.
  674. .. container:: class_bases
  675. Proxied for the :class:`_asyncio.AsyncSession` class on
  676. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  677. .. seealso::
  678. :meth:`_orm.Session.merge` - main documentation for merge
  679. """ # noqa: E501
  680. return await self._proxied.merge(instance, load=load, options=options)
  681. async def refresh(
  682. self,
  683. instance: object,
  684. attribute_names: Optional[Iterable[str]] = None,
  685. with_for_update: ForUpdateParameter = None,
  686. ) -> None:
  687. r"""Expire and refresh the attributes on the given instance.
  688. .. container:: class_bases
  689. Proxied for the :class:`_asyncio.AsyncSession` class on
  690. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  691. A query will be issued to the database and all attributes will be
  692. refreshed with their current database value.
  693. This is the async version of the :meth:`_orm.Session.refresh` method.
  694. See that method for a complete description of all options.
  695. .. seealso::
  696. :meth:`_orm.Session.refresh` - main documentation for refresh
  697. """ # noqa: E501
  698. return await self._proxied.refresh(
  699. instance,
  700. attribute_names=attribute_names,
  701. with_for_update=with_for_update,
  702. )
  703. async def rollback(self) -> None:
  704. r"""Rollback the current transaction in progress.
  705. .. container:: class_bases
  706. Proxied for the :class:`_asyncio.AsyncSession` class on
  707. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  708. .. seealso::
  709. :meth:`_orm.Session.rollback` - main documentation for
  710. "rollback"
  711. """ # noqa: E501
  712. return await self._proxied.rollback()
  713. @overload
  714. async def scalar(
  715. self,
  716. statement: TypedReturnsRows[Tuple[_T]],
  717. params: Optional[_CoreAnyExecuteParams] = None,
  718. *,
  719. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  720. bind_arguments: Optional[_BindArguments] = None,
  721. **kw: Any,
  722. ) -> Optional[_T]:
  723. ...
  724. @overload
  725. async def scalar(
  726. self,
  727. statement: Executable,
  728. params: Optional[_CoreAnyExecuteParams] = None,
  729. *,
  730. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  731. bind_arguments: Optional[_BindArguments] = None,
  732. **kw: Any,
  733. ) -> Any:
  734. ...
  735. async def scalar(
  736. self,
  737. statement: Executable,
  738. params: Optional[_CoreAnyExecuteParams] = None,
  739. *,
  740. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  741. bind_arguments: Optional[_BindArguments] = None,
  742. **kw: Any,
  743. ) -> Any:
  744. r"""Execute a statement and return a scalar result.
  745. .. container:: class_bases
  746. Proxied for the :class:`_asyncio.AsyncSession` class on
  747. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  748. .. seealso::
  749. :meth:`_orm.Session.scalar` - main documentation for scalar
  750. """ # noqa: E501
  751. return await self._proxied.scalar(
  752. statement,
  753. params=params,
  754. execution_options=execution_options,
  755. bind_arguments=bind_arguments,
  756. **kw,
  757. )
  758. @overload
  759. async def scalars(
  760. self,
  761. statement: TypedReturnsRows[Tuple[_T]],
  762. params: Optional[_CoreAnyExecuteParams] = None,
  763. *,
  764. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  765. bind_arguments: Optional[_BindArguments] = None,
  766. **kw: Any,
  767. ) -> ScalarResult[_T]:
  768. ...
  769. @overload
  770. async def scalars(
  771. self,
  772. statement: Executable,
  773. params: Optional[_CoreAnyExecuteParams] = None,
  774. *,
  775. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  776. bind_arguments: Optional[_BindArguments] = None,
  777. **kw: Any,
  778. ) -> ScalarResult[Any]:
  779. ...
  780. async def scalars(
  781. self,
  782. statement: Executable,
  783. params: Optional[_CoreAnyExecuteParams] = None,
  784. *,
  785. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  786. bind_arguments: Optional[_BindArguments] = None,
  787. **kw: Any,
  788. ) -> ScalarResult[Any]:
  789. r"""Execute a statement and return scalar results.
  790. .. container:: class_bases
  791. Proxied for the :class:`_asyncio.AsyncSession` class on
  792. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  793. :return: a :class:`_result.ScalarResult` object
  794. .. versionadded:: 1.4.24 Added :meth:`_asyncio.AsyncSession.scalars`
  795. .. versionadded:: 1.4.26 Added
  796. :meth:`_asyncio.async_scoped_session.scalars`
  797. .. seealso::
  798. :meth:`_orm.Session.scalars` - main documentation for scalars
  799. :meth:`_asyncio.AsyncSession.stream_scalars` - streaming version
  800. """ # noqa: E501
  801. return await self._proxied.scalars(
  802. statement,
  803. params=params,
  804. execution_options=execution_options,
  805. bind_arguments=bind_arguments,
  806. **kw,
  807. )
  808. async def get(
  809. self,
  810. entity: _EntityBindKey[_O],
  811. ident: _PKIdentityArgument,
  812. *,
  813. options: Optional[Sequence[ORMOption]] = None,
  814. populate_existing: bool = False,
  815. with_for_update: ForUpdateParameter = None,
  816. identity_token: Optional[Any] = None,
  817. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  818. ) -> Union[_O, None]:
  819. r"""Return an instance based on the given primary key identifier,
  820. or ``None`` if not found.
  821. .. container:: class_bases
  822. Proxied for the :class:`_asyncio.AsyncSession` class on
  823. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  824. .. seealso::
  825. :meth:`_orm.Session.get` - main documentation for get
  826. """ # noqa: E501
  827. result = await self._proxied.get(
  828. entity,
  829. ident,
  830. options=options,
  831. populate_existing=populate_existing,
  832. with_for_update=with_for_update,
  833. identity_token=identity_token,
  834. execution_options=execution_options,
  835. )
  836. return result
  837. async def get_one(
  838. self,
  839. entity: _EntityBindKey[_O],
  840. ident: _PKIdentityArgument,
  841. *,
  842. options: Optional[Sequence[ORMOption]] = None,
  843. populate_existing: bool = False,
  844. with_for_update: ForUpdateParameter = None,
  845. identity_token: Optional[Any] = None,
  846. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  847. ) -> _O:
  848. r"""Return an instance based on the given primary key identifier,
  849. or raise an exception if not found.
  850. .. container:: class_bases
  851. Proxied for the :class:`_asyncio.AsyncSession` class on
  852. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  853. Raises ``sqlalchemy.orm.exc.NoResultFound`` if the query selects
  854. no rows.
  855. ..versionadded: 2.0.22
  856. .. seealso::
  857. :meth:`_orm.Session.get_one` - main documentation for get_one
  858. """ # noqa: E501
  859. return await self._proxied.get_one(
  860. entity,
  861. ident,
  862. options=options,
  863. populate_existing=populate_existing,
  864. with_for_update=with_for_update,
  865. identity_token=identity_token,
  866. execution_options=execution_options,
  867. )
  868. @overload
  869. async def stream(
  870. self,
  871. statement: TypedReturnsRows[_T],
  872. params: Optional[_CoreAnyExecuteParams] = None,
  873. *,
  874. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  875. bind_arguments: Optional[_BindArguments] = None,
  876. **kw: Any,
  877. ) -> AsyncResult[_T]:
  878. ...
  879. @overload
  880. async def stream(
  881. self,
  882. statement: Executable,
  883. params: Optional[_CoreAnyExecuteParams] = None,
  884. *,
  885. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  886. bind_arguments: Optional[_BindArguments] = None,
  887. **kw: Any,
  888. ) -> AsyncResult[Any]:
  889. ...
  890. async def stream(
  891. self,
  892. statement: Executable,
  893. params: Optional[_CoreAnyExecuteParams] = None,
  894. *,
  895. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  896. bind_arguments: Optional[_BindArguments] = None,
  897. **kw: Any,
  898. ) -> AsyncResult[Any]:
  899. r"""Execute a statement and return a streaming
  900. :class:`_asyncio.AsyncResult` object.
  901. .. container:: class_bases
  902. Proxied for the :class:`_asyncio.AsyncSession` class on
  903. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  904. """ # noqa: E501
  905. return await self._proxied.stream(
  906. statement,
  907. params=params,
  908. execution_options=execution_options,
  909. bind_arguments=bind_arguments,
  910. **kw,
  911. )
  912. @overload
  913. async def stream_scalars(
  914. self,
  915. statement: TypedReturnsRows[Tuple[_T]],
  916. params: Optional[_CoreAnyExecuteParams] = None,
  917. *,
  918. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  919. bind_arguments: Optional[_BindArguments] = None,
  920. **kw: Any,
  921. ) -> AsyncScalarResult[_T]:
  922. ...
  923. @overload
  924. async def stream_scalars(
  925. self,
  926. statement: Executable,
  927. params: Optional[_CoreAnyExecuteParams] = None,
  928. *,
  929. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  930. bind_arguments: Optional[_BindArguments] = None,
  931. **kw: Any,
  932. ) -> AsyncScalarResult[Any]:
  933. ...
  934. async def stream_scalars(
  935. self,
  936. statement: Executable,
  937. params: Optional[_CoreAnyExecuteParams] = None,
  938. *,
  939. execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
  940. bind_arguments: Optional[_BindArguments] = None,
  941. **kw: Any,
  942. ) -> AsyncScalarResult[Any]:
  943. r"""Execute a statement and return a stream of scalar results.
  944. .. container:: class_bases
  945. Proxied for the :class:`_asyncio.AsyncSession` class on
  946. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  947. :return: an :class:`_asyncio.AsyncScalarResult` object
  948. .. versionadded:: 1.4.24
  949. .. seealso::
  950. :meth:`_orm.Session.scalars` - main documentation for scalars
  951. :meth:`_asyncio.AsyncSession.scalars` - non streaming version
  952. """ # noqa: E501
  953. return await self._proxied.stream_scalars(
  954. statement,
  955. params=params,
  956. execution_options=execution_options,
  957. bind_arguments=bind_arguments,
  958. **kw,
  959. )
  960. @property
  961. def bind(self) -> Any:
  962. r"""Proxy for the :attr:`_asyncio.AsyncSession.bind` attribute
  963. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  964. """ # noqa: E501
  965. return self._proxied.bind
  966. @bind.setter
  967. def bind(self, attr: Any) -> None:
  968. self._proxied.bind = attr
  969. @property
  970. def dirty(self) -> Any:
  971. r"""The set of all persistent instances considered dirty.
  972. .. container:: class_bases
  973. Proxied for the :class:`_asyncio.AsyncSession` class
  974. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  975. .. container:: class_bases
  976. Proxied for the :class:`_orm.Session` class
  977. on behalf of the :class:`_asyncio.AsyncSession` class.
  978. E.g.::
  979. some_mapped_object in session.dirty
  980. Instances are considered dirty when they were modified but not
  981. deleted.
  982. Note that this 'dirty' calculation is 'optimistic'; most
  983. attribute-setting or collection modification operations will
  984. mark an instance as 'dirty' and place it in this set, even if
  985. there is no net change to the attribute's value. At flush
  986. time, the value of each attribute is compared to its
  987. previously saved value, and if there's no net change, no SQL
  988. operation will occur (this is a more expensive operation so
  989. it's only done at flush time).
  990. To check if an instance has actionable net changes to its
  991. attributes, use the :meth:`.Session.is_modified` method.
  992. """ # noqa: E501
  993. return self._proxied.dirty
  994. @property
  995. def deleted(self) -> Any:
  996. r"""The set of all instances marked as 'deleted' within this ``Session``
  997. .. container:: class_bases
  998. Proxied for the :class:`_asyncio.AsyncSession` class
  999. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1000. .. container:: class_bases
  1001. Proxied for the :class:`_orm.Session` class
  1002. on behalf of the :class:`_asyncio.AsyncSession` class.
  1003. """ # noqa: E501
  1004. return self._proxied.deleted
  1005. @property
  1006. def new(self) -> Any:
  1007. r"""The set of all instances marked as 'new' within this ``Session``.
  1008. .. container:: class_bases
  1009. Proxied for the :class:`_asyncio.AsyncSession` class
  1010. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1011. .. container:: class_bases
  1012. Proxied for the :class:`_orm.Session` class
  1013. on behalf of the :class:`_asyncio.AsyncSession` class.
  1014. """ # noqa: E501
  1015. return self._proxied.new
  1016. @property
  1017. def identity_map(self) -> Any:
  1018. r"""Proxy for the :attr:`_orm.Session.identity_map` attribute
  1019. on behalf of the :class:`_asyncio.AsyncSession` class.
  1020. .. container:: class_bases
  1021. Proxied for the :class:`_asyncio.AsyncSession` class
  1022. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1023. """ # noqa: E501
  1024. return self._proxied.identity_map
  1025. @identity_map.setter
  1026. def identity_map(self, attr: Any) -> None:
  1027. self._proxied.identity_map = attr
  1028. @property
  1029. def is_active(self) -> Any:
  1030. r"""True if this :class:`.Session` not in "partial rollback" state.
  1031. .. container:: class_bases
  1032. Proxied for the :class:`_asyncio.AsyncSession` class
  1033. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1034. .. container:: class_bases
  1035. Proxied for the :class:`_orm.Session` class
  1036. on behalf of the :class:`_asyncio.AsyncSession` class.
  1037. .. versionchanged:: 1.4 The :class:`_orm.Session` no longer begins
  1038. a new transaction immediately, so this attribute will be False
  1039. when the :class:`_orm.Session` is first instantiated.
  1040. "partial rollback" state typically indicates that the flush process
  1041. of the :class:`_orm.Session` has failed, and that the
  1042. :meth:`_orm.Session.rollback` method must be emitted in order to
  1043. fully roll back the transaction.
  1044. If this :class:`_orm.Session` is not in a transaction at all, the
  1045. :class:`_orm.Session` will autobegin when it is first used, so in this
  1046. case :attr:`_orm.Session.is_active` will return True.
  1047. Otherwise, if this :class:`_orm.Session` is within a transaction,
  1048. and that transaction has not been rolled back internally, the
  1049. :attr:`_orm.Session.is_active` will also return True.
  1050. .. seealso::
  1051. :ref:`faq_session_rollback`
  1052. :meth:`_orm.Session.in_transaction`
  1053. """ # noqa: E501
  1054. return self._proxied.is_active
  1055. @property
  1056. def autoflush(self) -> Any:
  1057. r"""Proxy for the :attr:`_orm.Session.autoflush` attribute
  1058. on behalf of the :class:`_asyncio.AsyncSession` class.
  1059. .. container:: class_bases
  1060. Proxied for the :class:`_asyncio.AsyncSession` class
  1061. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1062. """ # noqa: E501
  1063. return self._proxied.autoflush
  1064. @autoflush.setter
  1065. def autoflush(self, attr: Any) -> None:
  1066. self._proxied.autoflush = attr
  1067. @property
  1068. def no_autoflush(self) -> Any:
  1069. r"""Return a context manager that disables autoflush.
  1070. .. container:: class_bases
  1071. Proxied for the :class:`_asyncio.AsyncSession` class
  1072. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1073. .. container:: class_bases
  1074. Proxied for the :class:`_orm.Session` class
  1075. on behalf of the :class:`_asyncio.AsyncSession` class.
  1076. e.g.::
  1077. with session.no_autoflush:
  1078. some_object = SomeClass()
  1079. session.add(some_object)
  1080. # won't autoflush
  1081. some_object.related_thing = session.query(SomeRelated).first()
  1082. Operations that proceed within the ``with:`` block
  1083. will not be subject to flushes occurring upon query
  1084. access. This is useful when initializing a series
  1085. of objects which involve existing database queries,
  1086. where the uncompleted object should not yet be flushed.
  1087. """ # noqa: E501
  1088. return self._proxied.no_autoflush
  1089. @property
  1090. def info(self) -> Any:
  1091. r"""A user-modifiable dictionary.
  1092. .. container:: class_bases
  1093. Proxied for the :class:`_asyncio.AsyncSession` class
  1094. on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1095. .. container:: class_bases
  1096. Proxied for the :class:`_orm.Session` class
  1097. on behalf of the :class:`_asyncio.AsyncSession` class.
  1098. The initial value of this dictionary can be populated using the
  1099. ``info`` argument to the :class:`.Session` constructor or
  1100. :class:`.sessionmaker` constructor or factory methods. The dictionary
  1101. here is always local to this :class:`.Session` and can be modified
  1102. independently of all other :class:`.Session` objects.
  1103. """ # noqa: E501
  1104. return self._proxied.info
  1105. @classmethod
  1106. async def close_all(cls) -> None:
  1107. r"""Close all :class:`_asyncio.AsyncSession` sessions.
  1108. .. container:: class_bases
  1109. Proxied for the :class:`_asyncio.AsyncSession` class on
  1110. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1111. .. 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`.
  1112. """ # noqa: E501
  1113. return await AsyncSession.close_all()
  1114. @classmethod
  1115. def object_session(cls, instance: object) -> Optional[Session]:
  1116. r"""Return the :class:`.Session` to which an object belongs.
  1117. .. container:: class_bases
  1118. Proxied for the :class:`_asyncio.AsyncSession` class on
  1119. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1120. .. container:: class_bases
  1121. Proxied for the :class:`_orm.Session` class on
  1122. behalf of the :class:`_asyncio.AsyncSession` class.
  1123. This is an alias of :func:`.object_session`.
  1124. """ # noqa: E501
  1125. return AsyncSession.object_session(instance)
  1126. @classmethod
  1127. def identity_key(
  1128. cls,
  1129. class_: Optional[Type[Any]] = None,
  1130. ident: Union[Any, Tuple[Any, ...]] = None,
  1131. *,
  1132. instance: Optional[Any] = None,
  1133. row: Optional[Union[Row[Any], RowMapping]] = None,
  1134. identity_token: Optional[Any] = None,
  1135. ) -> _IdentityKeyType[Any]:
  1136. r"""Return an identity key.
  1137. .. container:: class_bases
  1138. Proxied for the :class:`_asyncio.AsyncSession` class on
  1139. behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
  1140. .. container:: class_bases
  1141. Proxied for the :class:`_orm.Session` class on
  1142. behalf of the :class:`_asyncio.AsyncSession` class.
  1143. This is an alias of :func:`.util.identity_key`.
  1144. """ # noqa: E501
  1145. return AsyncSession.identity_key(
  1146. class_=class_,
  1147. ident=ident,
  1148. instance=instance,
  1149. row=row,
  1150. identity_token=identity_token,
  1151. )
  1152. # END PROXY METHODS async_scoped_session