SQLAlchemy 2.1.0__cp315-cp315t-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. sqlalchemy/__init__.py +299 -0
  2. sqlalchemy/connectors/__init__.py +18 -0
  3. sqlalchemy/connectors/aioodbc.py +171 -0
  4. sqlalchemy/connectors/asyncio.py +476 -0
  5. sqlalchemy/connectors/pyodbc.py +248 -0
  6. sqlalchemy/dialects/__init__.py +62 -0
  7. sqlalchemy/dialects/_typing.py +29 -0
  8. sqlalchemy/dialects/mssql/__init__.py +88 -0
  9. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  10. sqlalchemy/dialects/mssql/base.py +4833 -0
  11. sqlalchemy/dialects/mssql/information_schema.py +345 -0
  12. sqlalchemy/dialects/mssql/json.py +140 -0
  13. sqlalchemy/dialects/mssql/mssqlpython.py +251 -0
  14. sqlalchemy/dialects/mssql/provision.py +196 -0
  15. sqlalchemy/dialects/mssql/pymssql.py +130 -0
  16. sqlalchemy/dialects/mssql/pyodbc.py +697 -0
  17. sqlalchemy/dialects/mysql/__init__.py +106 -0
  18. sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
  19. sqlalchemy/dialects/mysql/aiomysql.py +260 -0
  20. sqlalchemy/dialects/mysql/asyncmy.py +241 -0
  21. sqlalchemy/dialects/mysql/base.py +3896 -0
  22. sqlalchemy/dialects/mysql/cymysql.py +107 -0
  23. sqlalchemy/dialects/mysql/dml.py +279 -0
  24. sqlalchemy/dialects/mysql/enumerated.py +277 -0
  25. sqlalchemy/dialects/mysql/expression.py +146 -0
  26. sqlalchemy/dialects/mysql/json.py +92 -0
  27. sqlalchemy/dialects/mysql/mariadb.py +67 -0
  28. sqlalchemy/dialects/mysql/mariadbconnector.py +314 -0
  29. sqlalchemy/dialects/mysql/mysqlconnector.py +291 -0
  30. sqlalchemy/dialects/mysql/mysqldb.py +318 -0
  31. sqlalchemy/dialects/mysql/provision.py +153 -0
  32. sqlalchemy/dialects/mysql/pymysql.py +188 -0
  33. sqlalchemy/dialects/mysql/pyodbc.py +157 -0
  34. sqlalchemy/dialects/mysql/reflection.py +724 -0
  35. sqlalchemy/dialects/mysql/reserved_words.py +570 -0
  36. sqlalchemy/dialects/mysql/types.py +845 -0
  37. sqlalchemy/dialects/oracle/__init__.py +85 -0
  38. sqlalchemy/dialects/oracle/base.py +3847 -0
  39. sqlalchemy/dialects/oracle/cx_oracle.py +1736 -0
  40. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  41. sqlalchemy/dialects/oracle/json.py +157 -0
  42. sqlalchemy/dialects/oracle/oracledb.py +921 -0
  43. sqlalchemy/dialects/oracle/provision.py +288 -0
  44. sqlalchemy/dialects/oracle/types.py +367 -0
  45. sqlalchemy/dialects/oracle/vector.py +366 -0
  46. sqlalchemy/dialects/postgresql/__init__.py +170 -0
  47. sqlalchemy/dialects/postgresql/_psycopg_common.py +232 -0
  48. sqlalchemy/dialects/postgresql/array.py +534 -0
  49. sqlalchemy/dialects/postgresql/asyncpg.py +1318 -0
  50. sqlalchemy/dialects/postgresql/base.py +5977 -0
  51. sqlalchemy/dialects/postgresql/bitstring.py +327 -0
  52. sqlalchemy/dialects/postgresql/dml.py +360 -0
  53. sqlalchemy/dialects/postgresql/ext.py +599 -0
  54. sqlalchemy/dialects/postgresql/hstore.py +422 -0
  55. sqlalchemy/dialects/postgresql/json.py +411 -0
  56. sqlalchemy/dialects/postgresql/named_types.py +535 -0
  57. sqlalchemy/dialects/postgresql/operators.py +129 -0
  58. sqlalchemy/dialects/postgresql/pg8000.py +655 -0
  59. sqlalchemy/dialects/postgresql/pg_catalog.py +345 -0
  60. sqlalchemy/dialects/postgresql/provision.py +202 -0
  61. sqlalchemy/dialects/postgresql/psycopg.py +800 -0
  62. sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
  63. sqlalchemy/dialects/postgresql/psycopg2cffi.py +62 -0
  64. sqlalchemy/dialects/postgresql/ranges.py +1002 -0
  65. sqlalchemy/dialects/postgresql/types.py +388 -0
  66. sqlalchemy/dialects/sqlite/__init__.py +59 -0
  67. sqlalchemy/dialects/sqlite/aiosqlite.py +375 -0
  68. sqlalchemy/dialects/sqlite/base.py +3156 -0
  69. sqlalchemy/dialects/sqlite/dml.py +314 -0
  70. sqlalchemy/dialects/sqlite/json.py +134 -0
  71. sqlalchemy/dialects/sqlite/provision.py +237 -0
  72. sqlalchemy/dialects/sqlite/pysqlcipher.py +166 -0
  73. sqlalchemy/dialects/sqlite/pysqlite.py +959 -0
  74. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  75. sqlalchemy/engine/__init__.py +62 -0
  76. sqlalchemy/engine/_processors_cy.cp315t-win32.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp315t-win32.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +711 -0
  80. sqlalchemy/engine/_row_cy.cp315t-win32.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp315t-win32.pyd +0 -0
  83. sqlalchemy/engine/_util_cy.py +136 -0
  84. sqlalchemy/engine/base.py +3357 -0
  85. sqlalchemy/engine/characteristics.py +155 -0
  86. sqlalchemy/engine/create.py +877 -0
  87. sqlalchemy/engine/cursor.py +2425 -0
  88. sqlalchemy/engine/default.py +2627 -0
  89. sqlalchemy/engine/events.py +965 -0
  90. sqlalchemy/engine/interfaces.py +3647 -0
  91. sqlalchemy/engine/mock.py +133 -0
  92. sqlalchemy/engine/processors.py +83 -0
  93. sqlalchemy/engine/reflection.py +2141 -0
  94. sqlalchemy/engine/result.py +2012 -0
  95. sqlalchemy/engine/row.py +397 -0
  96. sqlalchemy/engine/strategies.py +16 -0
  97. sqlalchemy/engine/url.py +922 -0
  98. sqlalchemy/engine/util.py +164 -0
  99. sqlalchemy/event/__init__.py +26 -0
  100. sqlalchemy/event/api.py +220 -0
  101. sqlalchemy/event/attr.py +675 -0
  102. sqlalchemy/event/base.py +473 -0
  103. sqlalchemy/event/legacy.py +259 -0
  104. sqlalchemy/event/registry.py +391 -0
  105. sqlalchemy/events.py +17 -0
  106. sqlalchemy/exc.py +939 -0
  107. sqlalchemy/ext/__init__.py +10 -0
  108. sqlalchemy/ext/associationproxy.py +2073 -0
  109. sqlalchemy/ext/asyncio/__init__.py +29 -0
  110. sqlalchemy/ext/asyncio/base.py +281 -0
  111. sqlalchemy/ext/asyncio/engine.py +1489 -0
  112. sqlalchemy/ext/asyncio/exc.py +30 -0
  113. sqlalchemy/ext/asyncio/result.py +994 -0
  114. sqlalchemy/ext/asyncio/scoping.py +1787 -0
  115. sqlalchemy/ext/asyncio/session.py +2268 -0
  116. sqlalchemy/ext/automap.py +1702 -0
  117. sqlalchemy/ext/baked.py +558 -0
  118. sqlalchemy/ext/compiler.py +601 -0
  119. sqlalchemy/ext/declarative/__init__.py +65 -0
  120. sqlalchemy/ext/declarative/extensions.py +561 -0
  121. sqlalchemy/ext/horizontal_shard.py +481 -0
  122. sqlalchemy/ext/hybrid.py +1877 -0
  123. sqlalchemy/ext/indexable.py +364 -0
  124. sqlalchemy/ext/instrumentation.py +450 -0
  125. sqlalchemy/ext/mutable.py +1081 -0
  126. sqlalchemy/ext/orderinglist.py +440 -0
  127. sqlalchemy/ext/serializer.py +184 -0
  128. sqlalchemy/future/__init__.py +17 -0
  129. sqlalchemy/future/engine.py +15 -0
  130. sqlalchemy/inspection.py +188 -0
  131. sqlalchemy/log.py +279 -0
  132. sqlalchemy/orm/__init__.py +176 -0
  133. sqlalchemy/orm/_orm_constructors.py +2711 -0
  134. sqlalchemy/orm/_typing.py +180 -0
  135. sqlalchemy/orm/attributes.py +2868 -0
  136. sqlalchemy/orm/base.py +991 -0
  137. sqlalchemy/orm/bulk_persistence.py +2168 -0
  138. sqlalchemy/orm/clsregistry.py +630 -0
  139. sqlalchemy/orm/collections.py +1569 -0
  140. sqlalchemy/orm/context.py +3475 -0
  141. sqlalchemy/orm/decl_api.py +2335 -0
  142. sqlalchemy/orm/decl_base.py +2300 -0
  143. sqlalchemy/orm/dependency.py +1306 -0
  144. sqlalchemy/orm/descriptor_props.py +1205 -0
  145. sqlalchemy/orm/dynamic.py +306 -0
  146. sqlalchemy/orm/evaluator.py +378 -0
  147. sqlalchemy/orm/events.py +3387 -0
  148. sqlalchemy/orm/exc.py +237 -0
  149. sqlalchemy/orm/identity.py +302 -0
  150. sqlalchemy/orm/instrumentation.py +749 -0
  151. sqlalchemy/orm/interfaces.py +1595 -0
  152. sqlalchemy/orm/loading.py +1712 -0
  153. sqlalchemy/orm/mapped_collection.py +557 -0
  154. sqlalchemy/orm/mapper.py +4465 -0
  155. sqlalchemy/orm/path_registry.py +907 -0
  156. sqlalchemy/orm/persistence.py +1790 -0
  157. sqlalchemy/orm/properties.py +972 -0
  158. sqlalchemy/orm/query.py +3528 -0
  159. sqlalchemy/orm/relationships.py +3615 -0
  160. sqlalchemy/orm/scoping.py +2251 -0
  161. sqlalchemy/orm/session.py +5493 -0
  162. sqlalchemy/orm/state.py +1175 -0
  163. sqlalchemy/orm/state_changes.py +196 -0
  164. sqlalchemy/orm/strategies.py +3559 -0
  165. sqlalchemy/orm/strategy_options.py +2648 -0
  166. sqlalchemy/orm/sync.py +164 -0
  167. sqlalchemy/orm/unitofwork.py +797 -0
  168. sqlalchemy/orm/util.py +2550 -0
  169. sqlalchemy/orm/writeonly.py +701 -0
  170. sqlalchemy/pool/__init__.py +41 -0
  171. sqlalchemy/pool/base.py +1544 -0
  172. sqlalchemy/pool/events.py +375 -0
  173. sqlalchemy/pool/impl.py +583 -0
  174. sqlalchemy/py.typed +0 -0
  175. sqlalchemy/schema.py +75 -0
  176. sqlalchemy/sql/__init__.py +156 -0
  177. sqlalchemy/sql/_annotated_cols.py +402 -0
  178. sqlalchemy/sql/_cache_key_cy.cp315t-win32.pyd +0 -0
  179. sqlalchemy/sql/_cache_key_cy.py +363 -0
  180. sqlalchemy/sql/_dml_constructors.py +132 -0
  181. sqlalchemy/sql/_elements_constructors.py +2190 -0
  182. sqlalchemy/sql/_orm_types.py +19 -0
  183. sqlalchemy/sql/_selectable_constructors.py +840 -0
  184. sqlalchemy/sql/_typing.py +500 -0
  185. sqlalchemy/sql/_util_cy.cp315t-win32.pyd +0 -0
  186. sqlalchemy/sql/_util_cy.pxd +11 -0
  187. sqlalchemy/sql/_util_cy.py +127 -0
  188. sqlalchemy/sql/annotation.py +590 -0
  189. sqlalchemy/sql/base.py +2852 -0
  190. sqlalchemy/sql/cache_key.py +915 -0
  191. sqlalchemy/sql/coercions.py +1373 -0
  192. sqlalchemy/sql/compiler.py +8469 -0
  193. sqlalchemy/sql/crud.py +1816 -0
  194. sqlalchemy/sql/ddl.py +1962 -0
  195. sqlalchemy/sql/default_comparator.py +660 -0
  196. sqlalchemy/sql/dml.py +2018 -0
  197. sqlalchemy/sql/elements.py +6062 -0
  198. sqlalchemy/sql/events.py +458 -0
  199. sqlalchemy/sql/expression.py +171 -0
  200. sqlalchemy/sql/functions.py +2380 -0
  201. sqlalchemy/sql/lambdas.py +1442 -0
  202. sqlalchemy/sql/naming.py +204 -0
  203. sqlalchemy/sql/operators.py +2909 -0
  204. sqlalchemy/sql/roles.py +332 -0
  205. sqlalchemy/sql/schema.py +7080 -0
  206. sqlalchemy/sql/selectable.py +7644 -0
  207. sqlalchemy/sql/sqltypes.py +4130 -0
  208. sqlalchemy/sql/traversals.py +1041 -0
  209. sqlalchemy/sql/type_api.py +2450 -0
  210. sqlalchemy/sql/util.py +1496 -0
  211. sqlalchemy/sql/visitors.py +1153 -0
  212. sqlalchemy/testing/__init__.py +97 -0
  213. sqlalchemy/testing/assertions.py +1007 -0
  214. sqlalchemy/testing/assertsql.py +519 -0
  215. sqlalchemy/testing/asyncio.py +128 -0
  216. sqlalchemy/testing/cancellation.py +237 -0
  217. sqlalchemy/testing/config.py +440 -0
  218. sqlalchemy/testing/engines.py +496 -0
  219. sqlalchemy/testing/entities.py +117 -0
  220. sqlalchemy/testing/exclusions.py +501 -0
  221. sqlalchemy/testing/fixtures/__init__.py +30 -0
  222. sqlalchemy/testing/fixtures/base.py +426 -0
  223. sqlalchemy/testing/fixtures/mypy.py +247 -0
  224. sqlalchemy/testing/fixtures/orm.py +227 -0
  225. sqlalchemy/testing/fixtures/sql.py +538 -0
  226. sqlalchemy/testing/pickleable.py +155 -0
  227. sqlalchemy/testing/plugin/__init__.py +6 -0
  228. sqlalchemy/testing/plugin/bootstrap.py +50 -0
  229. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  230. sqlalchemy/testing/plugin/pytestplugin.py +896 -0
  231. sqlalchemy/testing/profiles_file.py +350 -0
  232. sqlalchemy/testing/profiling.py +294 -0
  233. sqlalchemy/testing/provision.py +633 -0
  234. sqlalchemy/testing/requirements.py +1990 -0
  235. sqlalchemy/testing/schema.py +198 -0
  236. sqlalchemy/testing/suite/__init__.py +19 -0
  237. sqlalchemy/testing/suite/test_cte.py +237 -0
  238. sqlalchemy/testing/suite/test_ddl.py +420 -0
  239. sqlalchemy/testing/suite/test_dialect.py +777 -0
  240. sqlalchemy/testing/suite/test_insert.py +630 -0
  241. sqlalchemy/testing/suite/test_reflection.py +3815 -0
  242. sqlalchemy/testing/suite/test_results.py +660 -0
  243. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  244. sqlalchemy/testing/suite/test_select.py +2112 -0
  245. sqlalchemy/testing/suite/test_sequence.py +317 -0
  246. sqlalchemy/testing/suite/test_table_via_select.py +686 -0
  247. sqlalchemy/testing/suite/test_types.py +2271 -0
  248. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  249. sqlalchemy/testing/suite/test_update_delete.py +176 -0
  250. sqlalchemy/testing/util.py +575 -0
  251. sqlalchemy/testing/warnings.py +52 -0
  252. sqlalchemy/types.py +75 -0
  253. sqlalchemy/util/__init__.py +165 -0
  254. sqlalchemy/util/_collections.py +688 -0
  255. sqlalchemy/util/_collections_cy.cp315t-win32.pyd +0 -0
  256. sqlalchemy/util/_collections_cy.pxd +8 -0
  257. sqlalchemy/util/_collections_cy.py +516 -0
  258. sqlalchemy/util/_has_cython.py +48 -0
  259. sqlalchemy/util/_immutabledict_cy.cp315t-win32.pyd +0 -0
  260. sqlalchemy/util/_immutabledict_cy.py +240 -0
  261. sqlalchemy/util/compat.py +298 -0
  262. sqlalchemy/util/concurrency.py +272 -0
  263. sqlalchemy/util/cython.py +95 -0
  264. sqlalchemy/util/deprecations.py +401 -0
  265. sqlalchemy/util/langhelpers.py +2803 -0
  266. sqlalchemy/util/preloaded.py +153 -0
  267. sqlalchemy/util/queue.py +304 -0
  268. sqlalchemy/util/tool_support.py +202 -0
  269. sqlalchemy/util/topological.py +120 -0
  270. sqlalchemy/util/typing.py +709 -0
  271. sqlalchemy-2.1.0.dist-info/METADATA +270 -0
  272. sqlalchemy-2.1.0.dist-info/RECORD +276 -0
  273. sqlalchemy-2.1.0.dist-info/WHEEL +5 -0
  274. sqlalchemy-2.1.0.dist-info/licenses/AUTHORS +30 -0
  275. sqlalchemy-2.1.0.dist-info/licenses/LICENSE +19 -0
  276. sqlalchemy-2.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1787 @@
1
+ # ext/asyncio/scoping.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any
11
+ from typing import Callable
12
+ from typing import Generic
13
+ from typing import Iterable
14
+ from typing import Iterator
15
+ from typing import Mapping
16
+ from typing import Optional
17
+ from typing import overload
18
+ from typing import Sequence
19
+ from typing import Tuple
20
+ from typing import Type
21
+ from typing import TYPE_CHECKING
22
+ from typing import TypeVar
23
+ from typing import Union
24
+
25
+ from .session import _AS
26
+ from .session import async_sessionmaker
27
+ from .session import AsyncSession
28
+ from ... import exc as sa_exc
29
+ from ... import util
30
+ from ...orm.session import Session
31
+ from ...util import create_proxy_methods
32
+ from ...util import ScopedRegistry
33
+ from ...util import warn
34
+ from ...util import warn_deprecated
35
+ from ...util.typing import Never
36
+ from ...util.typing import TupleAny
37
+ from ...util.typing import TypeVarTuple
38
+ from ...util.typing import Unpack
39
+
40
+ if TYPE_CHECKING:
41
+ from .engine import AsyncConnection
42
+ from .result import AsyncResult
43
+ from .result import AsyncScalarResult
44
+ from .session import _AsyncSessionBind
45
+ from .session import AsyncSessionTransaction
46
+ from ...engine import Connection
47
+ from ...engine import Engine
48
+ from ...engine import Result
49
+ from ...engine import Row
50
+ from ...engine import RowMapping
51
+ from ...engine import ScalarResult
52
+ from ...engine.interfaces import _CoreAnyExecuteParams
53
+ from ...engine.interfaces import _ExecuteOptions
54
+ from ...engine.interfaces import CoreExecuteOptionsParameter
55
+ from ...orm._typing import _IdentityKeyType
56
+ from ...orm._typing import _O
57
+ from ...orm._typing import OrmExecuteOptionsParameter
58
+ from ...orm.identity import IdentityMap
59
+ from ...orm.interfaces import ORMOption
60
+ from ...orm.session import _BindArguments
61
+ from ...orm.session import _EntityBindKey
62
+ from ...orm.session import _PKIdentityArgument
63
+ from ...orm.session import _SessionBind
64
+ from ...orm.session import _SessionBindKey
65
+ from ...sql._typing import _InfoType
66
+ from ...sql.base import Executable
67
+ from ...sql.elements import ClauseElement
68
+ from ...sql.selectable import ForUpdateParameter
69
+ from ...sql.selectable import TypedReturnsRows
70
+ from ...util import IdentitySet
71
+
72
+ _T = TypeVar("_T", bound=Any)
73
+ _Ts = TypeVarTuple("_Ts")
74
+
75
+
76
+ @create_proxy_methods(
77
+ AsyncSession,
78
+ ":class:`_asyncio.AsyncSession`",
79
+ ":class:`_asyncio.scoping.async_scoped_session`",
80
+ classmethods=["close_all", "object_session", "identity_key"],
81
+ methods=[
82
+ "__contains__",
83
+ "__iter__",
84
+ "aclose",
85
+ "add",
86
+ "add_all",
87
+ "begin",
88
+ "begin_nested",
89
+ "close",
90
+ "reset",
91
+ "commit",
92
+ "connection",
93
+ "delete",
94
+ "delete_all",
95
+ "execute",
96
+ "expire",
97
+ "expire_all",
98
+ "expunge",
99
+ "expunge_all",
100
+ "flush",
101
+ "get_bind",
102
+ "get_async_bind",
103
+ "is_modified",
104
+ "invalidate",
105
+ "merge",
106
+ "merge_all",
107
+ "refresh",
108
+ "rollback",
109
+ "scalar",
110
+ "scalars",
111
+ "get",
112
+ "get_one",
113
+ "stream",
114
+ "stream_scalars",
115
+ ],
116
+ attributes=[
117
+ "bind",
118
+ "binds",
119
+ "dirty",
120
+ "deleted",
121
+ "new",
122
+ "identity_map",
123
+ "is_active",
124
+ "autoflush",
125
+ "no_autoflush",
126
+ "info",
127
+ "execution_options",
128
+ ],
129
+ use_intermediate_variable=["get"],
130
+ )
131
+ class async_scoped_session(Generic[_AS]):
132
+ """Provides scoped management of :class:`.AsyncSession` objects.
133
+
134
+ See the section :ref:`asyncio_scoped_session` for usage details.
135
+
136
+ .. versionadded:: 1.4.19
137
+
138
+
139
+ """
140
+
141
+ _support_async = True
142
+
143
+ session_factory: async_sessionmaker[_AS]
144
+ """The `session_factory` provided to `__init__` is stored in this
145
+ attribute and may be accessed at a later time. This can be useful when
146
+ a new non-scoped :class:`.AsyncSession` is needed."""
147
+
148
+ registry: ScopedRegistry[_AS]
149
+
150
+ def __init__(
151
+ self,
152
+ session_factory: async_sessionmaker[_AS],
153
+ scopefunc: Callable[[], Any],
154
+ ):
155
+ """Construct a new :class:`_asyncio.async_scoped_session`.
156
+
157
+ :param session_factory: a factory to create new :class:`_asyncio.AsyncSession`
158
+ instances. This is usually, but not necessarily, an instance
159
+ of :class:`_asyncio.async_sessionmaker`.
160
+
161
+ :param scopefunc: function which defines
162
+ the current scope. A function such as ``asyncio.current_task``
163
+ may be useful here.
164
+
165
+ """ # noqa: E501
166
+
167
+ self.session_factory = session_factory
168
+ self.registry = ScopedRegistry(session_factory, scopefunc)
169
+
170
+ @property
171
+ def _proxied(self) -> _AS:
172
+ return self.registry()
173
+
174
+ def __call__(self, **kw: Any) -> _AS:
175
+ r"""Return the current :class:`.AsyncSession`, creating it
176
+ using the :attr:`.scoped_session.session_factory` if not present.
177
+
178
+ :param \**kw: Keyword arguments will be passed to the
179
+ :attr:`.scoped_session.session_factory` callable, if an existing
180
+ :class:`.AsyncSession` is not present. If the
181
+ :class:`.AsyncSession` is present
182
+ and keyword arguments have been passed,
183
+ :exc:`~sqlalchemy.exc.InvalidRequestError` is raised.
184
+
185
+ """
186
+ if kw:
187
+ if self.registry.has():
188
+ raise sa_exc.InvalidRequestError(
189
+ "Scoped session is already present; "
190
+ "no new arguments may be specified."
191
+ )
192
+ else:
193
+ sess = self.session_factory(**kw)
194
+ self.registry.set(sess)
195
+ else:
196
+ sess = self.registry()
197
+ if not self._support_async and sess._is_asyncio:
198
+ warn_deprecated(
199
+ "Using `scoped_session` with asyncio is deprecated and "
200
+ "will raise an error in a future version. "
201
+ "Please use `async_scoped_session` instead.",
202
+ "1.4.23",
203
+ )
204
+ return sess
205
+
206
+ def configure(self, **kwargs: Any) -> None:
207
+ """reconfigure the :class:`.sessionmaker` used by this
208
+ :class:`.scoped_session`.
209
+
210
+ See :meth:`.sessionmaker.configure`.
211
+
212
+ """
213
+
214
+ if self.registry.has():
215
+ warn(
216
+ "At least one scoped session is already present. "
217
+ " configure() can not affect sessions that have "
218
+ "already been created."
219
+ )
220
+
221
+ self.session_factory.configure(**kwargs)
222
+
223
+ async def remove(self) -> None:
224
+ """Dispose of the current :class:`.AsyncSession`, if present.
225
+
226
+ Different from scoped_session's remove method, this method would use
227
+ await to wait for the close method of AsyncSession.
228
+
229
+ """
230
+
231
+ if self.registry.has():
232
+ await self.registry().close()
233
+ self.registry.clear()
234
+
235
+ # START PROXY METHODS async_scoped_session
236
+
237
+ # code within this block is **programmatically,
238
+ # statically generated** by tools/generate_proxy_methods.py
239
+
240
+ def __contains__(self, instance: object) -> bool:
241
+ r"""Return True if the instance is associated with this session.
242
+
243
+ .. container:: class_bases
244
+
245
+ Proxied for the :class:`_asyncio.AsyncSession` class on
246
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
247
+
248
+ .. container:: class_bases
249
+
250
+ Proxied for the :class:`_orm.Session` class on
251
+ behalf of the :class:`_asyncio.AsyncSession` class.
252
+
253
+ The instance may be pending or persistent within the Session for a
254
+ result of True.
255
+
256
+
257
+
258
+ """ # noqa: E501
259
+
260
+ return self._proxied.__contains__(instance)
261
+
262
+ def __iter__(self) -> Iterator[object]:
263
+ r"""Iterate over all pending or persistent instances within this
264
+ Session.
265
+
266
+ .. container:: class_bases
267
+
268
+ Proxied for the :class:`_asyncio.AsyncSession` class on
269
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
270
+
271
+ .. container:: class_bases
272
+
273
+ Proxied for the :class:`_orm.Session` class on
274
+ behalf of the :class:`_asyncio.AsyncSession` class.
275
+
276
+
277
+
278
+ """ # noqa: E501
279
+
280
+ return self._proxied.__iter__()
281
+
282
+ async def aclose(self) -> None:
283
+ r"""A synonym for :meth:`_asyncio.AsyncSession.close`.
284
+
285
+ .. container:: class_bases
286
+
287
+ Proxied for the :class:`_asyncio.AsyncSession` class on
288
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
289
+
290
+ The :meth:`_asyncio.AsyncSession.aclose` name is specifically
291
+ to support the Python standard library ``@contextlib.aclosing``
292
+ context manager function.
293
+
294
+ .. versionadded:: 2.0.20
295
+
296
+
297
+ """ # noqa: E501
298
+
299
+ return await self._proxied.aclose()
300
+
301
+ def add(self, instance: object, *, _warn: bool = True) -> None:
302
+ r"""Place an object into this :class:`_orm.Session`.
303
+
304
+ .. container:: class_bases
305
+
306
+ Proxied for the :class:`_asyncio.AsyncSession` class on
307
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
308
+
309
+ .. container:: class_bases
310
+
311
+ Proxied for the :class:`_orm.Session` class on
312
+ behalf of the :class:`_asyncio.AsyncSession` class.
313
+
314
+ Objects that are in the :term:`transient` state when passed to the
315
+ :meth:`_orm.Session.add` method will move to the
316
+ :term:`pending` state, until the next flush, at which point they
317
+ will move to the :term:`persistent` state.
318
+
319
+ Objects that are in the :term:`detached` state when passed to the
320
+ :meth:`_orm.Session.add` method will move to the :term:`persistent`
321
+ state directly.
322
+
323
+ If the transaction used by the :class:`_orm.Session` is rolled back,
324
+ objects which were transient when they were passed to
325
+ :meth:`_orm.Session.add` will be moved back to the
326
+ :term:`transient` state, and will no longer be present within this
327
+ :class:`_orm.Session`.
328
+
329
+ .. seealso::
330
+
331
+ :meth:`_orm.Session.add_all`
332
+
333
+ :ref:`session_adding` - at :ref:`session_basics`
334
+
335
+
336
+
337
+ """ # noqa: E501
338
+
339
+ return self._proxied.add(instance, _warn=_warn)
340
+
341
+ def add_all(self, instances: Iterable[object]) -> None:
342
+ r"""Add the given collection of instances to this :class:`_orm.Session`.
343
+
344
+ .. container:: class_bases
345
+
346
+ Proxied for the :class:`_asyncio.AsyncSession` class on
347
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
348
+
349
+ .. container:: class_bases
350
+
351
+ Proxied for the :class:`_orm.Session` class on
352
+ behalf of the :class:`_asyncio.AsyncSession` class.
353
+
354
+ See the documentation for :meth:`_orm.Session.add` for a general
355
+ behavioral description.
356
+
357
+ .. seealso::
358
+
359
+ :meth:`_orm.Session.add`
360
+
361
+ :ref:`session_adding` - at :ref:`session_basics`
362
+
363
+
364
+
365
+ """ # noqa: E501
366
+
367
+ return self._proxied.add_all(instances)
368
+
369
+ def begin(self) -> AsyncSessionTransaction:
370
+ r"""Return an :class:`_asyncio.AsyncSessionTransaction` object.
371
+
372
+ .. container:: class_bases
373
+
374
+ Proxied for the :class:`_asyncio.AsyncSession` class on
375
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
376
+
377
+ The underlying :class:`_orm.Session` will perform the
378
+ "begin" action when the :class:`_asyncio.AsyncSessionTransaction`
379
+ object is entered::
380
+
381
+ async with async_session.begin():
382
+ ... # ORM transaction is begun
383
+
384
+ Note that database IO will not normally occur when the session-level
385
+ transaction is begun, as database transactions begin on an
386
+ on-demand basis. However, the begin block is async to accommodate
387
+ for a :meth:`_orm.SessionEvents.after_transaction_create`
388
+ event hook that may perform IO.
389
+
390
+ For a general description of ORM begin, see
391
+ :meth:`_orm.Session.begin`.
392
+
393
+
394
+ """ # noqa: E501
395
+
396
+ return self._proxied.begin()
397
+
398
+ def begin_nested(self) -> AsyncSessionTransaction:
399
+ r"""Return an :class:`_asyncio.AsyncSessionTransaction` object
400
+ which will begin a "nested" transaction, e.g. SAVEPOINT.
401
+
402
+ .. container:: class_bases
403
+
404
+ Proxied for the :class:`_asyncio.AsyncSession` class on
405
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
406
+
407
+ Behavior is the same as that of :meth:`_asyncio.AsyncSession.begin`.
408
+
409
+ For a general description of ORM begin nested, see
410
+ :meth:`_orm.Session.begin_nested`.
411
+
412
+ .. seealso::
413
+
414
+ :ref:`aiosqlite_serializable` - special workarounds required
415
+ with the SQLite asyncio driver in order for SAVEPOINT to work
416
+ correctly.
417
+
418
+
419
+ """ # noqa: E501
420
+
421
+ return self._proxied.begin_nested()
422
+
423
+ async def close(self) -> None:
424
+ r"""Close out the transactional resources and ORM objects used by this
425
+ :class:`_asyncio.AsyncSession`.
426
+
427
+ .. container:: class_bases
428
+
429
+ Proxied for the :class:`_asyncio.AsyncSession` class on
430
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
431
+
432
+ .. seealso::
433
+
434
+ :meth:`_orm.Session.close` - main documentation for
435
+ "close"
436
+
437
+ :ref:`session_closing` - detail on the semantics of
438
+ :meth:`_asyncio.AsyncSession.close` and
439
+ :meth:`_asyncio.AsyncSession.reset`.
440
+
441
+
442
+ """ # noqa: E501
443
+
444
+ return await self._proxied.close()
445
+
446
+ async def reset(self) -> None:
447
+ r"""Close out the transactional resources and ORM objects used by this
448
+ :class:`_orm.Session`, resetting the session to its initial state.
449
+
450
+ .. container:: class_bases
451
+
452
+ Proxied for the :class:`_asyncio.AsyncSession` class on
453
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
454
+
455
+ .. versionadded:: 2.0.22
456
+
457
+ .. seealso::
458
+
459
+ :meth:`_orm.Session.reset` - main documentation for
460
+ "reset"
461
+
462
+ :ref:`session_closing` - detail on the semantics of
463
+ :meth:`_asyncio.AsyncSession.close` and
464
+ :meth:`_asyncio.AsyncSession.reset`.
465
+
466
+
467
+ """ # noqa: E501
468
+
469
+ return await self._proxied.reset()
470
+
471
+ async def commit(self) -> None:
472
+ r"""Commit the current transaction in progress.
473
+
474
+ .. container:: class_bases
475
+
476
+ Proxied for the :class:`_asyncio.AsyncSession` class on
477
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
478
+
479
+ .. seealso::
480
+
481
+ :meth:`_orm.Session.commit` - main documentation for
482
+ "commit"
483
+
484
+ """ # noqa: E501
485
+
486
+ return await self._proxied.commit()
487
+
488
+ async def connection(
489
+ self,
490
+ bind_arguments: Optional[_BindArguments] = None,
491
+ execution_options: Optional[CoreExecuteOptionsParameter] = None,
492
+ **kw: Any,
493
+ ) -> AsyncConnection:
494
+ r"""Return a :class:`_asyncio.AsyncConnection` object corresponding to
495
+ this :class:`.Session` object's transactional state.
496
+
497
+ .. container:: class_bases
498
+
499
+ Proxied for the :class:`_asyncio.AsyncSession` class on
500
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
501
+
502
+ This method may also be used to establish execution options for the
503
+ database connection used by the current transaction.
504
+
505
+ .. versionadded:: 1.4.24 Added \**kw arguments which are passed
506
+ through to the underlying :meth:`_orm.Session.connection` method.
507
+
508
+ .. seealso::
509
+
510
+ :meth:`_orm.Session.connection` - main documentation for
511
+ "connection"
512
+
513
+
514
+ """ # noqa: E501
515
+
516
+ return await self._proxied.connection(
517
+ bind_arguments=bind_arguments,
518
+ execution_options=execution_options,
519
+ **kw,
520
+ )
521
+
522
+ async def delete(self, instance: object) -> None:
523
+ r"""Mark an instance as deleted.
524
+
525
+ .. container:: class_bases
526
+
527
+ Proxied for the :class:`_asyncio.AsyncSession` class on
528
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
529
+
530
+ The database delete operation occurs upon ``flush()``.
531
+
532
+ As this operation may need to cascade along unloaded relationships,
533
+ it is awaitable to allow for those queries to take place.
534
+
535
+ .. seealso::
536
+
537
+ :meth:`_orm.Session.delete` - main documentation for delete
538
+
539
+
540
+ """ # noqa: E501
541
+
542
+ return await self._proxied.delete(instance)
543
+
544
+ async def delete_all(self, instances: Iterable[object]) -> None:
545
+ r"""Calls :meth:`.AsyncSession.delete` on multiple instances.
546
+
547
+ .. container:: class_bases
548
+
549
+ Proxied for the :class:`_asyncio.AsyncSession` class on
550
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
551
+
552
+ .. seealso::
553
+
554
+ :meth:`_orm.Session.delete_all` - main documentation for delete_all
555
+
556
+
557
+ """ # noqa: E501
558
+
559
+ return await self._proxied.delete_all(instances)
560
+
561
+ @overload
562
+ async def execute(
563
+ self,
564
+ statement: TypedReturnsRows[Unpack[_Ts]],
565
+ params: Optional[_CoreAnyExecuteParams] = None,
566
+ *,
567
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
568
+ bind_arguments: Optional[_BindArguments] = None,
569
+ _parent_execute_state: Optional[Any] = None,
570
+ _add_event: Optional[Any] = None,
571
+ ) -> Result[Unpack[_Ts]]: ...
572
+
573
+ @overload
574
+ async def execute(
575
+ self,
576
+ statement: Executable,
577
+ params: Optional[_CoreAnyExecuteParams] = None,
578
+ *,
579
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
580
+ bind_arguments: Optional[_BindArguments] = None,
581
+ _parent_execute_state: Optional[Any] = None,
582
+ _add_event: Optional[Any] = None,
583
+ ) -> Result[Unpack[TupleAny]]: ...
584
+
585
+ async def execute(
586
+ self,
587
+ statement: Executable,
588
+ params: Optional[_CoreAnyExecuteParams] = None,
589
+ *,
590
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
591
+ bind_arguments: Optional[_BindArguments] = None,
592
+ **kw: Any,
593
+ ) -> Result[Unpack[TupleAny]]:
594
+ r"""Execute a statement and return a buffered
595
+ :class:`_engine.Result` object.
596
+
597
+ .. container:: class_bases
598
+
599
+ Proxied for the :class:`_asyncio.AsyncSession` class on
600
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
601
+
602
+ .. seealso::
603
+
604
+ :meth:`_orm.Session.execute` - main documentation for execute
605
+
606
+
607
+ """ # noqa: E501
608
+
609
+ return await self._proxied.execute(
610
+ statement,
611
+ params=params,
612
+ execution_options=execution_options,
613
+ bind_arguments=bind_arguments,
614
+ **kw,
615
+ )
616
+
617
+ def expire(
618
+ self, instance: object, attribute_names: Optional[Iterable[str]] = None
619
+ ) -> None:
620
+ r"""Expire the attributes on an instance.
621
+
622
+ .. container:: class_bases
623
+
624
+ Proxied for the :class:`_asyncio.AsyncSession` class on
625
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
626
+
627
+ .. container:: class_bases
628
+
629
+ Proxied for the :class:`_orm.Session` class on
630
+ behalf of the :class:`_asyncio.AsyncSession` class.
631
+
632
+ Marks the attributes of an instance as out of date. When an expired
633
+ attribute is next accessed, a query will be issued to the
634
+ :class:`.Session` object's current transactional context in order to
635
+ load all expired attributes for the given instance. Note that
636
+ a highly isolated transaction will return the same values as were
637
+ previously read in that same transaction, regardless of changes
638
+ in database state outside of that transaction.
639
+
640
+ To expire all objects in the :class:`.Session` simultaneously,
641
+ use :meth:`Session.expire_all`.
642
+
643
+ The :class:`.Session` object's default behavior is to
644
+ expire all state whenever the :meth:`Session.rollback`
645
+ or :meth:`Session.commit` methods are called, so that new
646
+ state can be loaded for the new transaction. For this reason,
647
+ calling :meth:`Session.expire` only makes sense for the specific
648
+ case that a non-ORM SQL statement was emitted in the current
649
+ transaction.
650
+
651
+ :param instance: The instance to be refreshed.
652
+ :param attribute_names: optional list of string attribute names
653
+ indicating a subset of attributes to be expired.
654
+
655
+ .. seealso::
656
+
657
+ :ref:`session_expire` - introductory material
658
+
659
+ :meth:`.Session.expire`
660
+
661
+ :meth:`.Session.refresh`
662
+
663
+ :meth:`_orm.Query.populate_existing`
664
+
665
+
666
+
667
+ """ # noqa: E501
668
+
669
+ return self._proxied.expire(instance, attribute_names=attribute_names)
670
+
671
+ def expire_all(self) -> None:
672
+ r"""Expires all persistent instances within this Session.
673
+
674
+ .. container:: class_bases
675
+
676
+ Proxied for the :class:`_asyncio.AsyncSession` class on
677
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
678
+
679
+ .. container:: class_bases
680
+
681
+ Proxied for the :class:`_orm.Session` class on
682
+ behalf of the :class:`_asyncio.AsyncSession` class.
683
+
684
+ When any attributes on a persistent instance is next accessed,
685
+ a query will be issued using the
686
+ :class:`.Session` object's current transactional context in order to
687
+ load all expired attributes for the given instance. Note that
688
+ a highly isolated transaction will return the same values as were
689
+ previously read in that same transaction, regardless of changes
690
+ in database state outside of that transaction.
691
+
692
+ To expire individual objects and individual attributes
693
+ on those objects, use :meth:`Session.expire`.
694
+
695
+ The :class:`.Session` object's default behavior is to
696
+ expire all state whenever the :meth:`Session.rollback`
697
+ or :meth:`Session.commit` methods are called, so that new
698
+ state can be loaded for the new transaction. For this reason,
699
+ calling :meth:`Session.expire_all` is not usually needed,
700
+ assuming the transaction is isolated.
701
+
702
+ .. seealso::
703
+
704
+ :ref:`session_expire` - introductory material
705
+
706
+ :meth:`.Session.expire`
707
+
708
+ :meth:`.Session.refresh`
709
+
710
+ :meth:`_orm.Query.populate_existing`
711
+
712
+
713
+
714
+ """ # noqa: E501
715
+
716
+ return self._proxied.expire_all()
717
+
718
+ def expunge(self, instance: object) -> None:
719
+ r"""Remove the `instance` from this ``Session``.
720
+
721
+ .. container:: class_bases
722
+
723
+ Proxied for the :class:`_asyncio.AsyncSession` class on
724
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
725
+
726
+ .. container:: class_bases
727
+
728
+ Proxied for the :class:`_orm.Session` class on
729
+ behalf of the :class:`_asyncio.AsyncSession` class.
730
+
731
+ This will free all internal references to the instance. Cascading
732
+ will be applied according to the *expunge* cascade rule.
733
+
734
+
735
+
736
+ """ # noqa: E501
737
+
738
+ return self._proxied.expunge(instance)
739
+
740
+ def expunge_all(self) -> None:
741
+ r"""Remove all object instances from this ``Session``.
742
+
743
+ .. container:: class_bases
744
+
745
+ Proxied for the :class:`_asyncio.AsyncSession` class on
746
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
747
+
748
+ .. container:: class_bases
749
+
750
+ Proxied for the :class:`_orm.Session` class on
751
+ behalf of the :class:`_asyncio.AsyncSession` class.
752
+
753
+ This is equivalent to calling ``expunge(obj)`` on all objects in this
754
+ ``Session``.
755
+
756
+
757
+
758
+ """ # noqa: E501
759
+
760
+ return self._proxied.expunge_all()
761
+
762
+ async def flush(self, objects: Optional[Sequence[Any]] = None) -> None:
763
+ r"""Flush all the object changes to the database.
764
+
765
+ .. container:: class_bases
766
+
767
+ Proxied for the :class:`_asyncio.AsyncSession` class on
768
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
769
+
770
+ .. seealso::
771
+
772
+ :meth:`_orm.Session.flush` - main documentation for flush
773
+
774
+
775
+ """ # noqa: E501
776
+
777
+ return await self._proxied.flush(objects=objects)
778
+
779
+ def get_bind(
780
+ self,
781
+ mapper: Optional[_EntityBindKey[_O]] = None,
782
+ clause: Optional[ClauseElement] = None,
783
+ bind: Optional[_SessionBind] = None,
784
+ **kw: Any,
785
+ ) -> Union[Engine, Connection]:
786
+ r"""Return a "bind" to which the synchronous proxied :class:`_orm.Session`
787
+ is bound.
788
+
789
+ .. container:: class_bases
790
+
791
+ Proxied for the :class:`_asyncio.AsyncSession` class on
792
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
793
+
794
+ Unlike the :meth:`_orm.Session.get_bind` method, this method is
795
+ currently **not** used by this :class:`.AsyncSession` in any way
796
+ in order to resolve engines for requests.
797
+
798
+ .. note::
799
+
800
+ This method proxies directly to the :meth:`_orm.Session.get_bind`
801
+ method, however is currently **not** useful as an override target,
802
+ in contrast to that of the :meth:`_orm.Session.get_bind` method.
803
+ The example below illustrates how to implement custom
804
+ :meth:`_orm.Session.get_bind` schemes that work with
805
+ :class:`.AsyncSession` and :class:`.AsyncEngine`.
806
+
807
+ The pattern introduced at :ref:`session_custom_partitioning`
808
+ illustrates how to apply a custom bind-lookup scheme to a
809
+ :class:`_orm.Session` given a set of :class:`_engine.Engine` objects.
810
+ To apply a corresponding :meth:`_orm.Session.get_bind` implementation
811
+ for use with a :class:`.AsyncSession` and :class:`.AsyncEngine`
812
+ objects, continue to subclass :class:`_orm.Session` and apply it to
813
+ :class:`.AsyncSession` using
814
+ :paramref:`.AsyncSession.sync_session_class`. The inner method must
815
+ continue to return :class:`_engine.Engine` instances, which can be
816
+ acquired from a :class:`_asyncio.AsyncEngine` using the
817
+ :attr:`_asyncio.AsyncEngine.sync_engine` attribute::
818
+
819
+ # using example from "Custom Vertical Partitioning"
820
+
821
+
822
+ import random
823
+
824
+ from sqlalchemy.ext.asyncio import AsyncSession
825
+ from sqlalchemy.ext.asyncio import create_async_engine
826
+ from sqlalchemy.ext.asyncio import async_sessionmaker
827
+ from sqlalchemy.orm import Session
828
+
829
+ # construct async engines w/ async drivers
830
+ engines = {
831
+ "leader": create_async_engine("sqlite+aiosqlite:///leader.db"),
832
+ "other": create_async_engine("sqlite+aiosqlite:///other.db"),
833
+ "follower1": create_async_engine("sqlite+aiosqlite:///follower1.db"),
834
+ "follower2": create_async_engine("sqlite+aiosqlite:///follower2.db"),
835
+ }
836
+
837
+
838
+ class RoutingSession(Session):
839
+ def get_bind(self, mapper=None, clause=None, **kw):
840
+ # within get_bind(), return sync engines
841
+ if mapper and issubclass(mapper.class_, MyOtherClass):
842
+ return engines["other"].sync_engine
843
+ elif self._flushing or isinstance(clause, (Update, Delete)):
844
+ return engines["leader"].sync_engine
845
+ else:
846
+ return engines[
847
+ random.choice(["follower1", "follower2"])
848
+ ].sync_engine
849
+
850
+
851
+ # apply to AsyncSession using sync_session_class
852
+ AsyncSessionMaker = async_sessionmaker(sync_session_class=RoutingSession)
853
+
854
+ The :meth:`_orm.Session.get_bind` method is called in a non-asyncio,
855
+ implicitly non-blocking context in the same manner as ORM event hooks
856
+ and functions that are invoked via :meth:`.AsyncSession.run_sync`, so
857
+ routines that wish to run SQL commands inside of
858
+ :meth:`_orm.Session.get_bind` can continue to do so using
859
+ blocking-style code, which will be translated to implicitly async calls
860
+ at the point of invoking IO on the database drivers.
861
+
862
+ .. seealso::
863
+
864
+ :meth:`.AsyncSession.get_async_bind`
865
+
866
+
867
+ """ # noqa: E501
868
+
869
+ return self._proxied.get_bind(
870
+ mapper=mapper, clause=clause, bind=bind, **kw
871
+ )
872
+
873
+ def get_async_bind(
874
+ self,
875
+ mapper: Optional[_EntityBindKey[_O]] = None,
876
+ clause: Optional[ClauseElement] = None,
877
+ bind: Optional[_AsyncSessionBind] = None,
878
+ **kw: Any,
879
+ ) -> _AsyncSessionBind:
880
+ r"""Return a "bind" to which this :class:`.AsyncSession` is bound.
881
+
882
+ .. container:: class_bases
883
+
884
+ Proxied for the :class:`_asyncio.AsyncSession` class on
885
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
886
+
887
+ This is the asyncio-facing counterpart to
888
+ :meth:`.AsyncSession.get_bind`; the bind resolved against the
889
+ underlying :attr:`.AsyncSession.sync_session` is translated back into
890
+ the :class:`.AsyncEngine` or :class:`.AsyncConnection` that it was
891
+ derived from. :paramref:`.AsyncSession.get_async_bind.bind` is
892
+ likewise given as an asyncio object, and is translated on the way in.
893
+
894
+ Raises :class:`_asyncio.exc.AsyncBindNotFound` if the bind that's
895
+ resolved has no asyncio counterpart known to this
896
+ :class:`.AsyncSession`.
897
+
898
+ Like :meth:`.AsyncSession.get_bind`, this method is currently
899
+ **not** used by this :class:`.AsyncSession` in any way in order to
900
+ resolve engines for requests.
901
+
902
+ .. note::
903
+
904
+ This method delegates to :meth:`.AsyncSession.get_bind`, and is
905
+ likewise currently **not** useful as an override target, in
906
+ contrast to that of the :meth:`_orm.Session.get_bind` method.
907
+ To apply a custom bind-lookup scheme to an
908
+ :class:`.AsyncSession`, subclass :class:`_orm.Session` and apply
909
+ it using :paramref:`.AsyncSession.sync_session_class`, as
910
+ illustrated at :meth:`.AsyncSession.get_bind`.
911
+
912
+ .. versionadded:: 2.1
913
+
914
+ .. seealso::
915
+
916
+ :meth:`.AsyncSession.get_bind`
917
+
918
+
919
+ """ # noqa: E501
920
+
921
+ return self._proxied.get_async_bind(
922
+ mapper=mapper, clause=clause, bind=bind, **kw
923
+ )
924
+
925
+ def is_modified(
926
+ self, instance: object, include_collections: bool = True
927
+ ) -> bool:
928
+ r"""Return ``True`` if the given instance has locally
929
+ modified attributes.
930
+
931
+ .. container:: class_bases
932
+
933
+ Proxied for the :class:`_asyncio.AsyncSession` class on
934
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
935
+
936
+ .. container:: class_bases
937
+
938
+ Proxied for the :class:`_orm.Session` class on
939
+ behalf of the :class:`_asyncio.AsyncSession` class.
940
+
941
+ This method retrieves the history for each instrumented
942
+ attribute on the instance and performs a comparison of the current
943
+ value to its previously flushed or committed value, if any.
944
+
945
+ It is in effect a more expensive and accurate
946
+ version of checking for the given instance in the
947
+ :attr:`.Session.dirty` collection; a full test for
948
+ each attribute's net "dirty" status is performed.
949
+
950
+ E.g.::
951
+
952
+ return session.is_modified(someobject)
953
+
954
+ A few caveats to this method apply:
955
+
956
+ * Instances present in the :attr:`.Session.dirty` collection may
957
+ report ``False`` when tested with this method. This is because
958
+ the object may have received change events via attribute mutation,
959
+ thus placing it in :attr:`.Session.dirty`, but ultimately the state
960
+ is the same as that loaded from the database, resulting in no net
961
+ change here.
962
+ * Scalar attributes may not have recorded the previously set
963
+ value when a new value was applied, if the attribute was not loaded,
964
+ or was expired, at the time the new value was received - in these
965
+ cases, the attribute is assumed to have a change, even if there is
966
+ ultimately no net change against its database value. SQLAlchemy in
967
+ most cases does not need the "old" value when a set event occurs, so
968
+ it skips the expense of a SQL call if the old value isn't present,
969
+ based on the assumption that an UPDATE of the scalar value is
970
+ usually needed, and in those few cases where it isn't, is less
971
+ expensive on average than issuing a defensive SELECT.
972
+
973
+ The "old" value is fetched unconditionally upon set only if the
974
+ attribute container has the ``active_history`` flag set to ``True``.
975
+ This flag is set typically for primary key attributes and scalar
976
+ object references that are not a simple many-to-one. To set this
977
+ flag for any arbitrary mapped column, use the ``active_history``
978
+ argument with :func:`.column_property`.
979
+
980
+ :param instance: mapped instance to be tested for pending changes.
981
+ :param include_collections: Indicates if multivalued collections
982
+ should be included in the operation. Setting this to ``False`` is a
983
+ way to detect only local-column based properties (i.e. scalar columns
984
+ or many-to-one foreign keys) that would result in an UPDATE for this
985
+ instance upon flush.
986
+
987
+
988
+
989
+ """ # noqa: E501
990
+
991
+ return self._proxied.is_modified(
992
+ instance, include_collections=include_collections
993
+ )
994
+
995
+ async def invalidate(self) -> None:
996
+ r"""Close this Session, using connection invalidation.
997
+
998
+ .. container:: class_bases
999
+
1000
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1001
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1002
+
1003
+ For a complete description, see :meth:`_orm.Session.invalidate`.
1004
+
1005
+ """ # noqa: E501
1006
+
1007
+ return await self._proxied.invalidate()
1008
+
1009
+ async def merge(
1010
+ self,
1011
+ instance: _O,
1012
+ *,
1013
+ load: bool = True,
1014
+ options: Optional[Sequence[ORMOption]] = None,
1015
+ ) -> _O:
1016
+ r"""Copy the state of a given instance into a corresponding instance
1017
+ within this :class:`_asyncio.AsyncSession`.
1018
+
1019
+ .. container:: class_bases
1020
+
1021
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1022
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1023
+
1024
+ .. seealso::
1025
+
1026
+ :meth:`_orm.Session.merge` - main documentation for merge
1027
+
1028
+
1029
+ """ # noqa: E501
1030
+
1031
+ return await self._proxied.merge(instance, load=load, options=options)
1032
+
1033
+ async def merge_all(
1034
+ self,
1035
+ instances: Iterable[_O],
1036
+ *,
1037
+ load: bool = True,
1038
+ options: Optional[Sequence[ORMOption]] = None,
1039
+ ) -> Sequence[_O]:
1040
+ r"""Calls :meth:`.AsyncSession.merge` on multiple instances.
1041
+
1042
+ .. container:: class_bases
1043
+
1044
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1045
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1046
+
1047
+ .. seealso::
1048
+
1049
+ :meth:`_orm.Session.merge_all` - main documentation for merge_all
1050
+
1051
+
1052
+ """ # noqa: E501
1053
+
1054
+ return await self._proxied.merge_all(
1055
+ instances, load=load, options=options
1056
+ )
1057
+
1058
+ async def refresh(
1059
+ self,
1060
+ instance: object,
1061
+ attribute_names: Optional[Iterable[str]] = None,
1062
+ with_for_update: ForUpdateParameter = None,
1063
+ ) -> None:
1064
+ r"""Expire and refresh the attributes on the given instance.
1065
+
1066
+ .. container:: class_bases
1067
+
1068
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1069
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1070
+
1071
+ A query will be issued to the database and all attributes will be
1072
+ refreshed with their current database value.
1073
+
1074
+ This is the async version of the :meth:`_orm.Session.refresh` method.
1075
+ See that method for a complete description of all options.
1076
+
1077
+ .. seealso::
1078
+
1079
+ :meth:`_orm.Session.refresh` - main documentation for refresh
1080
+
1081
+
1082
+ """ # noqa: E501
1083
+
1084
+ return await self._proxied.refresh(
1085
+ instance,
1086
+ attribute_names=attribute_names,
1087
+ with_for_update=with_for_update,
1088
+ )
1089
+
1090
+ async def rollback(self) -> None:
1091
+ r"""Rollback the current transaction in progress.
1092
+
1093
+ .. container:: class_bases
1094
+
1095
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1096
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1097
+
1098
+ .. seealso::
1099
+
1100
+ :meth:`_orm.Session.rollback` - main documentation for
1101
+ "rollback"
1102
+
1103
+ """ # noqa: E501
1104
+
1105
+ return await self._proxied.rollback()
1106
+
1107
+ @overload
1108
+ async def scalar(
1109
+ self,
1110
+ statement: TypedReturnsRows[Never],
1111
+ params: Optional[_CoreAnyExecuteParams] = None,
1112
+ *,
1113
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1114
+ bind_arguments: Optional[_BindArguments] = None,
1115
+ **kw: Any,
1116
+ ) -> Optional[Any]: ...
1117
+
1118
+ @overload
1119
+ async def scalar(
1120
+ self,
1121
+ statement: TypedReturnsRows[_T],
1122
+ params: Optional[_CoreAnyExecuteParams] = None,
1123
+ *,
1124
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1125
+ bind_arguments: Optional[_BindArguments] = None,
1126
+ **kw: Any,
1127
+ ) -> Optional[_T]: ...
1128
+
1129
+ @overload
1130
+ async def scalar(
1131
+ self,
1132
+ statement: Executable,
1133
+ params: Optional[_CoreAnyExecuteParams] = None,
1134
+ *,
1135
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1136
+ bind_arguments: Optional[_BindArguments] = None,
1137
+ **kw: Any,
1138
+ ) -> Any: ...
1139
+
1140
+ async def scalar(
1141
+ self,
1142
+ statement: Executable,
1143
+ params: Optional[_CoreAnyExecuteParams] = None,
1144
+ *,
1145
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1146
+ bind_arguments: Optional[_BindArguments] = None,
1147
+ **kw: Any,
1148
+ ) -> Any:
1149
+ r"""Execute a statement and return a scalar result.
1150
+
1151
+ .. container:: class_bases
1152
+
1153
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1154
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1155
+
1156
+ .. seealso::
1157
+
1158
+ :meth:`_orm.Session.scalar` - main documentation for scalar
1159
+
1160
+
1161
+ """ # noqa: E501
1162
+
1163
+ return await self._proxied.scalar(
1164
+ statement,
1165
+ params=params,
1166
+ execution_options=execution_options,
1167
+ bind_arguments=bind_arguments,
1168
+ **kw,
1169
+ )
1170
+
1171
+ @overload
1172
+ async def scalars(
1173
+ self,
1174
+ statement: TypedReturnsRows[_T],
1175
+ params: Optional[_CoreAnyExecuteParams] = None,
1176
+ *,
1177
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1178
+ bind_arguments: Optional[_BindArguments] = None,
1179
+ **kw: Any,
1180
+ ) -> ScalarResult[_T]: ...
1181
+
1182
+ @overload
1183
+ async def scalars(
1184
+ self,
1185
+ statement: Executable,
1186
+ params: Optional[_CoreAnyExecuteParams] = None,
1187
+ *,
1188
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1189
+ bind_arguments: Optional[_BindArguments] = None,
1190
+ **kw: Any,
1191
+ ) -> ScalarResult[Any]: ...
1192
+
1193
+ async def scalars(
1194
+ self,
1195
+ statement: Executable,
1196
+ params: Optional[_CoreAnyExecuteParams] = None,
1197
+ *,
1198
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1199
+ bind_arguments: Optional[_BindArguments] = None,
1200
+ **kw: Any,
1201
+ ) -> ScalarResult[Any]:
1202
+ r"""Execute a statement and return scalar results.
1203
+
1204
+ .. container:: class_bases
1205
+
1206
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1207
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1208
+
1209
+ :return: a :class:`_result.ScalarResult` object
1210
+
1211
+ .. versionadded:: 1.4.24 Added :meth:`_asyncio.AsyncSession.scalars`
1212
+
1213
+ .. versionadded:: 1.4.26 Added
1214
+ :meth:`_asyncio.async_scoped_session.scalars`
1215
+
1216
+ .. seealso::
1217
+
1218
+ :meth:`_orm.Session.scalars` - main documentation for scalars
1219
+
1220
+ :meth:`_asyncio.AsyncSession.stream_scalars` - streaming version
1221
+
1222
+
1223
+ """ # noqa: E501
1224
+
1225
+ return await self._proxied.scalars(
1226
+ statement,
1227
+ params=params,
1228
+ execution_options=execution_options,
1229
+ bind_arguments=bind_arguments,
1230
+ **kw,
1231
+ )
1232
+
1233
+ async def get(
1234
+ self,
1235
+ entity: _EntityBindKey[_O],
1236
+ ident: _PKIdentityArgument,
1237
+ *,
1238
+ options: Optional[Sequence[ORMOption]] = None,
1239
+ populate_existing: bool | None = None,
1240
+ with_for_update: ForUpdateParameter = None,
1241
+ identity_token: Optional[Any] = None,
1242
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1243
+ ) -> Union[_O, None]:
1244
+ r"""Return an instance based on the given primary key identifier,
1245
+ or ``None`` if not found.
1246
+
1247
+ .. container:: class_bases
1248
+
1249
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1250
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1251
+
1252
+ .. seealso::
1253
+
1254
+ :meth:`_orm.Session.get` - main documentation for get
1255
+
1256
+
1257
+
1258
+ """ # noqa: E501
1259
+
1260
+ result = await self._proxied.get(
1261
+ entity,
1262
+ ident,
1263
+ options=options,
1264
+ populate_existing=populate_existing,
1265
+ with_for_update=with_for_update,
1266
+ identity_token=identity_token,
1267
+ execution_options=execution_options,
1268
+ )
1269
+ return result
1270
+
1271
+ async def get_one(
1272
+ self,
1273
+ entity: _EntityBindKey[_O],
1274
+ ident: _PKIdentityArgument,
1275
+ *,
1276
+ options: Optional[Sequence[ORMOption]] = None,
1277
+ populate_existing: bool | None = None,
1278
+ with_for_update: ForUpdateParameter = None,
1279
+ identity_token: Optional[Any] = None,
1280
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1281
+ ) -> _O:
1282
+ r"""Return an instance based on the given primary key identifier,
1283
+ or raise an exception if not found.
1284
+
1285
+ .. container:: class_bases
1286
+
1287
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1288
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1289
+
1290
+ Raises :class:`_exc.NoResultFound` if the query selects no rows.
1291
+
1292
+ ..versionadded: 2.0.22
1293
+
1294
+ .. seealso::
1295
+
1296
+ :meth:`_orm.Session.get_one` - main documentation for get_one
1297
+
1298
+
1299
+ """ # noqa: E501
1300
+
1301
+ return await self._proxied.get_one(
1302
+ entity,
1303
+ ident,
1304
+ options=options,
1305
+ populate_existing=populate_existing,
1306
+ with_for_update=with_for_update,
1307
+ identity_token=identity_token,
1308
+ execution_options=execution_options,
1309
+ )
1310
+
1311
+ @overload
1312
+ async def stream(
1313
+ self,
1314
+ statement: TypedReturnsRows[Unpack[_Ts]],
1315
+ params: Optional[_CoreAnyExecuteParams] = None,
1316
+ *,
1317
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1318
+ bind_arguments: Optional[_BindArguments] = None,
1319
+ **kw: Any,
1320
+ ) -> AsyncResult[Unpack[_Ts]]: ...
1321
+
1322
+ @overload
1323
+ async def stream(
1324
+ self,
1325
+ statement: Executable,
1326
+ params: Optional[_CoreAnyExecuteParams] = None,
1327
+ *,
1328
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1329
+ bind_arguments: Optional[_BindArguments] = None,
1330
+ **kw: Any,
1331
+ ) -> AsyncResult[Unpack[TupleAny]]: ...
1332
+
1333
+ async def stream(
1334
+ self,
1335
+ statement: Executable,
1336
+ params: Optional[_CoreAnyExecuteParams] = None,
1337
+ *,
1338
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1339
+ bind_arguments: Optional[_BindArguments] = None,
1340
+ **kw: Any,
1341
+ ) -> AsyncResult[Unpack[TupleAny]]:
1342
+ r"""Execute a statement and return a streaming
1343
+ :class:`_asyncio.AsyncResult` object.
1344
+
1345
+ .. container:: class_bases
1346
+
1347
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1348
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1349
+
1350
+
1351
+ """ # noqa: E501
1352
+
1353
+ return await self._proxied.stream(
1354
+ statement,
1355
+ params=params,
1356
+ execution_options=execution_options,
1357
+ bind_arguments=bind_arguments,
1358
+ **kw,
1359
+ )
1360
+
1361
+ @overload
1362
+ async def stream_scalars(
1363
+ self,
1364
+ statement: TypedReturnsRows[_T],
1365
+ params: Optional[_CoreAnyExecuteParams] = None,
1366
+ *,
1367
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1368
+ bind_arguments: Optional[_BindArguments] = None,
1369
+ **kw: Any,
1370
+ ) -> AsyncScalarResult[_T]: ...
1371
+
1372
+ @overload
1373
+ async def stream_scalars(
1374
+ self,
1375
+ statement: Executable,
1376
+ params: Optional[_CoreAnyExecuteParams] = None,
1377
+ *,
1378
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1379
+ bind_arguments: Optional[_BindArguments] = None,
1380
+ **kw: Any,
1381
+ ) -> AsyncScalarResult[Any]: ...
1382
+
1383
+ async def stream_scalars(
1384
+ self,
1385
+ statement: Executable,
1386
+ params: Optional[_CoreAnyExecuteParams] = None,
1387
+ *,
1388
+ execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
1389
+ bind_arguments: Optional[_BindArguments] = None,
1390
+ **kw: Any,
1391
+ ) -> AsyncScalarResult[Any]:
1392
+ r"""Execute a statement and return a stream of scalar results.
1393
+
1394
+ .. container:: class_bases
1395
+
1396
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1397
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1398
+
1399
+ :return: an :class:`_asyncio.AsyncScalarResult` object
1400
+
1401
+ .. versionadded:: 1.4.24
1402
+
1403
+ .. seealso::
1404
+
1405
+ :meth:`_orm.Session.scalars` - main documentation for scalars
1406
+
1407
+ :meth:`_asyncio.AsyncSession.scalars` - non streaming version
1408
+
1409
+
1410
+ """ # noqa: E501
1411
+
1412
+ return await self._proxied.stream_scalars(
1413
+ statement,
1414
+ params=params,
1415
+ execution_options=execution_options,
1416
+ bind_arguments=bind_arguments,
1417
+ **kw,
1418
+ )
1419
+
1420
+ @property
1421
+ def bind(self) -> Optional[_AsyncSessionBind]:
1422
+ r"""The :class:`_asyncio.AsyncEngine` or
1423
+ :class:`_asyncio.AsyncConnection` this :class:`_asyncio.AsyncSession`
1424
+ is bound to, if any.
1425
+
1426
+ .. container:: class_bases
1427
+
1428
+ Proxied for the :class:`_asyncio.AsyncSession` class
1429
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1430
+
1431
+ The value is derived from :attr:`_orm.Session.bind` on the underlying
1432
+ :attr:`_asyncio.AsyncSession.sync_session`, translated back into the
1433
+ asyncio object it was established from, so that a bind assigned after
1434
+ construction is reflected here as well. The attribute may be assigned
1435
+ to, which establishes the bind on the
1436
+ :attr:`_asyncio.AsyncSession.sync_session`.
1437
+
1438
+ .. versionadded:: 2.1
1439
+
1440
+
1441
+ """ # noqa: E501
1442
+
1443
+ return self._proxied.bind
1444
+
1445
+ @bind.setter
1446
+ def bind(self, attr: Optional[_AsyncSessionBind]) -> None:
1447
+ self._proxied.bind = attr
1448
+
1449
+ @property
1450
+ def binds(self) -> Mapping[_SessionBindKey, _AsyncSessionBind]:
1451
+ r"""An immutable mapping of the per-mapper / per-table binds established
1452
+ for this :class:`_asyncio.AsyncSession`.
1453
+
1454
+ .. container:: class_bases
1455
+
1456
+ Proxied for the :class:`_asyncio.AsyncSession` class
1457
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1458
+
1459
+ Like :attr:`_asyncio.AsyncSession.bind`, the collection is derived from
1460
+ :attr:`_orm.Session.binds` on the underlying
1461
+ :attr:`_asyncio.AsyncSession.sync_session` with each bind translated
1462
+ back into the asyncio object it was established from; the keys are
1463
+ therefore normalized in the same way as they are for
1464
+ :attr:`_orm.Session.binds`.
1465
+
1466
+ As the collection is derived it is read-only; binds are established by
1467
+ passing the :paramref:`_asyncio.AsyncSession.binds` parameter.
1468
+
1469
+ .. versionadded:: 2.1
1470
+
1471
+
1472
+ """ # noqa: E501
1473
+
1474
+ return self._proxied.binds
1475
+
1476
+ @property
1477
+ def dirty(self) -> IdentitySet:
1478
+ r"""The set of all persistent instances considered dirty.
1479
+
1480
+ .. container:: class_bases
1481
+
1482
+ Proxied for the :class:`_asyncio.AsyncSession` class
1483
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1484
+
1485
+ .. container:: class_bases
1486
+
1487
+ Proxied for the :class:`_orm.Session` class
1488
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1489
+
1490
+ E.g.::
1491
+
1492
+ some_mapped_object in session.dirty
1493
+
1494
+ Instances are considered dirty when they were modified but not
1495
+ deleted.
1496
+
1497
+ Note that this 'dirty' calculation is 'optimistic'; most
1498
+ attribute-setting or collection modification operations will
1499
+ mark an instance as 'dirty' and place it in this set, even if
1500
+ there is no net change to the attribute's value. At flush
1501
+ time, the value of each attribute is compared to its
1502
+ previously saved value, and if there's no net change, no SQL
1503
+ operation will occur (this is a more expensive operation so
1504
+ it's only done at flush time).
1505
+
1506
+ To check if an instance has actionable net changes to its
1507
+ attributes, use the :meth:`.Session.is_modified` method.
1508
+
1509
+
1510
+
1511
+ """ # noqa: E501
1512
+
1513
+ return self._proxied.dirty
1514
+
1515
+ @property
1516
+ def deleted(self) -> IdentitySet:
1517
+ r"""The set of all instances marked as 'deleted' within this ``Session``
1518
+
1519
+ .. container:: class_bases
1520
+
1521
+ Proxied for the :class:`_asyncio.AsyncSession` class
1522
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1523
+
1524
+ .. container:: class_bases
1525
+
1526
+ Proxied for the :class:`_orm.Session` class
1527
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1528
+
1529
+
1530
+ """ # noqa: E501
1531
+
1532
+ return self._proxied.deleted
1533
+
1534
+ @property
1535
+ def new(self) -> IdentitySet:
1536
+ r"""The set of all instances marked as 'new' within this ``Session``.
1537
+
1538
+ .. container:: class_bases
1539
+
1540
+ Proxied for the :class:`_asyncio.AsyncSession` class
1541
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1542
+
1543
+ .. container:: class_bases
1544
+
1545
+ Proxied for the :class:`_orm.Session` class
1546
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1547
+
1548
+
1549
+ """ # noqa: E501
1550
+
1551
+ return self._proxied.new
1552
+
1553
+ @property
1554
+ def identity_map(self) -> IdentityMap:
1555
+ r"""Proxy for the :attr:`_orm.Session.identity_map` attribute
1556
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1557
+
1558
+ .. container:: class_bases
1559
+
1560
+ Proxied for the :class:`_asyncio.AsyncSession` class
1561
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1562
+
1563
+
1564
+ """ # noqa: E501
1565
+
1566
+ return self._proxied.identity_map
1567
+
1568
+ @identity_map.setter
1569
+ def identity_map(self, attr: IdentityMap) -> None:
1570
+ self._proxied.identity_map = attr
1571
+
1572
+ @property
1573
+ def is_active(self) -> bool:
1574
+ r"""True if this :class:`.Session` not in "partial rollback" state.
1575
+
1576
+ .. container:: class_bases
1577
+
1578
+ Proxied for the :class:`_asyncio.AsyncSession` class
1579
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1580
+
1581
+ .. container:: class_bases
1582
+
1583
+ Proxied for the :class:`_orm.Session` class
1584
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1585
+
1586
+ .. versionchanged:: 1.4 The :class:`_orm.Session` no longer begins
1587
+ a new transaction immediately, so this attribute will be False
1588
+ when the :class:`_orm.Session` is first instantiated.
1589
+
1590
+ "partial rollback" state typically indicates that the flush process
1591
+ of the :class:`_orm.Session` has failed, and that the
1592
+ :meth:`_orm.Session.rollback` method must be emitted in order to
1593
+ fully roll back the transaction.
1594
+
1595
+ If this :class:`_orm.Session` is not in a transaction at all, the
1596
+ :class:`_orm.Session` will autobegin when it is first used, so in this
1597
+ case :attr:`_orm.Session.is_active` will return True.
1598
+
1599
+ Otherwise, if this :class:`_orm.Session` is within a transaction,
1600
+ and that transaction has not been rolled back internally, the
1601
+ :attr:`_orm.Session.is_active` will also return True.
1602
+
1603
+ .. seealso::
1604
+
1605
+ :ref:`faq_session_rollback`
1606
+
1607
+ :meth:`_orm.Session.in_transaction`
1608
+
1609
+
1610
+
1611
+ """ # noqa: E501
1612
+
1613
+ return self._proxied.is_active
1614
+
1615
+ @property
1616
+ def autoflush(self) -> bool:
1617
+ r"""Proxy for the :attr:`_orm.Session.autoflush` attribute
1618
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1619
+
1620
+ .. container:: class_bases
1621
+
1622
+ Proxied for the :class:`_asyncio.AsyncSession` class
1623
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1624
+
1625
+
1626
+ """ # noqa: E501
1627
+
1628
+ return self._proxied.autoflush
1629
+
1630
+ @autoflush.setter
1631
+ def autoflush(self, attr: bool) -> None:
1632
+ self._proxied.autoflush = attr
1633
+
1634
+ @property
1635
+ def no_autoflush(self) -> Any:
1636
+ r"""Return a context manager that disables autoflush.
1637
+
1638
+ .. container:: class_bases
1639
+
1640
+ Proxied for the :class:`_asyncio.AsyncSession` class
1641
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1642
+
1643
+ .. container:: class_bases
1644
+
1645
+ Proxied for the :class:`_orm.Session` class
1646
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1647
+
1648
+ e.g.::
1649
+
1650
+ with session.no_autoflush:
1651
+
1652
+ some_object = SomeClass()
1653
+ session.add(some_object)
1654
+ # won't autoflush
1655
+ some_object.related_thing = session.query(SomeRelated).first()
1656
+
1657
+ Operations that proceed within the ``with:`` block
1658
+ will not be subject to flushes occurring upon query
1659
+ access. This is useful when initializing a series
1660
+ of objects which involve existing database queries,
1661
+ where the uncompleted object should not yet be flushed.
1662
+
1663
+
1664
+
1665
+ """ # noqa: E501
1666
+
1667
+ return self._proxied.no_autoflush
1668
+
1669
+ @property
1670
+ def info(self) -> _InfoType:
1671
+ r"""A user-modifiable dictionary.
1672
+
1673
+ .. container:: class_bases
1674
+
1675
+ Proxied for the :class:`_asyncio.AsyncSession` class
1676
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1677
+
1678
+ .. container:: class_bases
1679
+
1680
+ Proxied for the :class:`_orm.Session` class
1681
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1682
+
1683
+ The initial value of this dictionary can be populated using the
1684
+ ``info`` argument to the :class:`.Session` constructor or
1685
+ :class:`.sessionmaker` constructor or factory methods. The dictionary
1686
+ here is always local to this :class:`.Session` and can be modified
1687
+ independently of all other :class:`.Session` objects.
1688
+
1689
+
1690
+
1691
+ """ # noqa: E501
1692
+
1693
+ return self._proxied.info
1694
+
1695
+ @property
1696
+ def execution_options(self) -> _ExecuteOptions:
1697
+ r"""Proxy for the :attr:`_orm.Session.execution_options` attribute
1698
+ on behalf of the :class:`_asyncio.AsyncSession` class.
1699
+
1700
+ .. container:: class_bases
1701
+
1702
+ Proxied for the :class:`_asyncio.AsyncSession` class
1703
+ on behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1704
+
1705
+
1706
+ """ # noqa: E501
1707
+
1708
+ return self._proxied.execution_options
1709
+
1710
+ @execution_options.setter
1711
+ def execution_options(self, attr: _ExecuteOptions) -> None:
1712
+ self._proxied.execution_options = attr
1713
+
1714
+ @classmethod
1715
+ async def close_all(cls) -> None:
1716
+ r"""Close all :class:`_asyncio.AsyncSession` sessions.
1717
+
1718
+ .. container:: class_bases
1719
+
1720
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1721
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1722
+
1723
+ .. 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`.
1724
+
1725
+ """ # noqa: E501
1726
+
1727
+ return await AsyncSession.close_all()
1728
+
1729
+ @classmethod
1730
+ def object_session(cls, instance: object) -> Optional[Session]:
1731
+ r"""Return the :class:`.Session` to which an object belongs.
1732
+
1733
+ .. container:: class_bases
1734
+
1735
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1736
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1737
+
1738
+ .. container:: class_bases
1739
+
1740
+ Proxied for the :class:`_orm.Session` class on
1741
+ behalf of the :class:`_asyncio.AsyncSession` class.
1742
+
1743
+ This is an alias of :func:`.object_session`.
1744
+
1745
+
1746
+
1747
+ """ # noqa: E501
1748
+
1749
+ return AsyncSession.object_session(instance)
1750
+
1751
+ @classmethod
1752
+ def identity_key(
1753
+ cls,
1754
+ class_: Optional[Type[Any]] = None,
1755
+ ident: Union[Any, Tuple[Any, ...]] = None,
1756
+ *,
1757
+ instance: Optional[Any] = None,
1758
+ row: Optional[Union[Row[Unpack[TupleAny]], RowMapping]] = None,
1759
+ identity_token: Optional[Any] = None,
1760
+ ) -> _IdentityKeyType[Any]:
1761
+ r"""Return an identity key.
1762
+
1763
+ .. container:: class_bases
1764
+
1765
+ Proxied for the :class:`_asyncio.AsyncSession` class on
1766
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
1767
+
1768
+ .. container:: class_bases
1769
+
1770
+ Proxied for the :class:`_orm.Session` class on
1771
+ behalf of the :class:`_asyncio.AsyncSession` class.
1772
+
1773
+ This is an alias of :func:`.util.identity_key`.
1774
+
1775
+
1776
+
1777
+ """ # noqa: E501
1778
+
1779
+ return AsyncSession.identity_key(
1780
+ class_=class_,
1781
+ ident=ident,
1782
+ instance=instance,
1783
+ row=row,
1784
+ identity_token=identity_token,
1785
+ )
1786
+
1787
+ # END PROXY METHODS async_scoped_session