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