SQLAlchemy 2.1.0b2__cp313-cp313t-win_arm64.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 (270) hide show
  1. sqlalchemy/__init__.py +298 -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 +250 -0
  6. sqlalchemy/dialects/__init__.py +62 -0
  7. sqlalchemy/dialects/_typing.py +30 -0
  8. sqlalchemy/dialects/mssql/__init__.py +89 -0
  9. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  10. sqlalchemy/dialects/mssql/base.py +4166 -0
  11. sqlalchemy/dialects/mssql/information_schema.py +285 -0
  12. sqlalchemy/dialects/mssql/json.py +140 -0
  13. sqlalchemy/dialects/mssql/mssqlpython.py +220 -0
  14. sqlalchemy/dialects/mssql/provision.py +196 -0
  15. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  16. sqlalchemy/dialects/mssql/pyodbc.py +698 -0
  17. sqlalchemy/dialects/mysql/__init__.py +106 -0
  18. sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
  19. sqlalchemy/dialects/mysql/aiomysql.py +226 -0
  20. sqlalchemy/dialects/mysql/asyncmy.py +214 -0
  21. sqlalchemy/dialects/mysql/base.py +3877 -0
  22. sqlalchemy/dialects/mysql/cymysql.py +106 -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 +330 -0
  29. sqlalchemy/dialects/mysql/mysqlconnector.py +296 -0
  30. sqlalchemy/dialects/mysql/mysqldb.py +312 -0
  31. sqlalchemy/dialects/mysql/provision.py +153 -0
  32. sqlalchemy/dialects/mysql/pymysql.py +157 -0
  33. sqlalchemy/dialects/mysql/pyodbc.py +156 -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 +3977 -0
  39. sqlalchemy/dialects/oracle/cx_oracle.py +1601 -0
  40. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  41. sqlalchemy/dialects/oracle/json.py +158 -0
  42. sqlalchemy/dialects/oracle/oracledb.py +909 -0
  43. sqlalchemy/dialects/oracle/provision.py +288 -0
  44. sqlalchemy/dialects/oracle/types.py +367 -0
  45. sqlalchemy/dialects/oracle/vector.py +368 -0
  46. sqlalchemy/dialects/postgresql/__init__.py +171 -0
  47. sqlalchemy/dialects/postgresql/_psycopg_common.py +229 -0
  48. sqlalchemy/dialects/postgresql/array.py +534 -0
  49. sqlalchemy/dialects/postgresql/asyncpg.py +1323 -0
  50. sqlalchemy/dialects/postgresql/base.py +5789 -0
  51. sqlalchemy/dialects/postgresql/bitstring.py +327 -0
  52. sqlalchemy/dialects/postgresql/dml.py +360 -0
  53. sqlalchemy/dialects/postgresql/ext.py +593 -0
  54. sqlalchemy/dialects/postgresql/hstore.py +423 -0
  55. sqlalchemy/dialects/postgresql/json.py +408 -0
  56. sqlalchemy/dialects/postgresql/named_types.py +521 -0
  57. sqlalchemy/dialects/postgresql/operators.py +130 -0
  58. sqlalchemy/dialects/postgresql/pg8000.py +670 -0
  59. sqlalchemy/dialects/postgresql/pg_catalog.py +344 -0
  60. sqlalchemy/dialects/postgresql/provision.py +184 -0
  61. sqlalchemy/dialects/postgresql/psycopg.py +799 -0
  62. sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
  63. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  64. sqlalchemy/dialects/postgresql/ranges.py +1002 -0
  65. sqlalchemy/dialects/postgresql/types.py +388 -0
  66. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  67. sqlalchemy/dialects/sqlite/aiosqlite.py +321 -0
  68. sqlalchemy/dialects/sqlite/base.py +3063 -0
  69. sqlalchemy/dialects/sqlite/dml.py +279 -0
  70. sqlalchemy/dialects/sqlite/json.py +100 -0
  71. sqlalchemy/dialects/sqlite/provision.py +229 -0
  72. sqlalchemy/dialects/sqlite/pysqlcipher.py +161 -0
  73. sqlalchemy/dialects/sqlite/pysqlite.py +754 -0
  74. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  75. sqlalchemy/engine/__init__.py +62 -0
  76. sqlalchemy/engine/_processors_cy.cp313t-win_arm64.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp313t-win_arm64.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +633 -0
  80. sqlalchemy/engine/_row_cy.cp313t-win_arm64.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp313t-win_arm64.pyd +0 -0
  83. sqlalchemy/engine/_util_cy.py +136 -0
  84. sqlalchemy/engine/base.py +3354 -0
  85. sqlalchemy/engine/characteristics.py +155 -0
  86. sqlalchemy/engine/create.py +877 -0
  87. sqlalchemy/engine/cursor.py +2421 -0
  88. sqlalchemy/engine/default.py +2402 -0
  89. sqlalchemy/engine/events.py +965 -0
  90. sqlalchemy/engine/interfaces.py +3495 -0
  91. sqlalchemy/engine/mock.py +134 -0
  92. sqlalchemy/engine/processors.py +82 -0
  93. sqlalchemy/engine/reflection.py +2100 -0
  94. sqlalchemy/engine/result.py +1966 -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 +156 -0
  99. sqlalchemy/event/__init__.py +26 -0
  100. sqlalchemy/event/api.py +220 -0
  101. sqlalchemy/event/attr.py +674 -0
  102. sqlalchemy/event/base.py +472 -0
  103. sqlalchemy/event/legacy.py +258 -0
  104. sqlalchemy/event/registry.py +390 -0
  105. sqlalchemy/events.py +17 -0
  106. sqlalchemy/exc.py +922 -0
  107. sqlalchemy/ext/__init__.py +11 -0
  108. sqlalchemy/ext/associationproxy.py +2072 -0
  109. sqlalchemy/ext/asyncio/__init__.py +29 -0
  110. sqlalchemy/ext/asyncio/base.py +281 -0
  111. sqlalchemy/ext/asyncio/engine.py +1487 -0
  112. sqlalchemy/ext/asyncio/exc.py +21 -0
  113. sqlalchemy/ext/asyncio/result.py +994 -0
  114. sqlalchemy/ext/asyncio/scoping.py +1679 -0
  115. sqlalchemy/ext/asyncio/session.py +2007 -0
  116. sqlalchemy/ext/automap.py +1701 -0
  117. sqlalchemy/ext/baked.py +559 -0
  118. sqlalchemy/ext/compiler.py +600 -0
  119. sqlalchemy/ext/declarative/__init__.py +65 -0
  120. sqlalchemy/ext/declarative/extensions.py +560 -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 +439 -0
  127. sqlalchemy/ext/serializer.py +185 -0
  128. sqlalchemy/future/__init__.py +16 -0
  129. sqlalchemy/future/engine.py +15 -0
  130. sqlalchemy/inspection.py +174 -0
  131. sqlalchemy/log.py +283 -0
  132. sqlalchemy/orm/__init__.py +176 -0
  133. sqlalchemy/orm/_orm_constructors.py +2694 -0
  134. sqlalchemy/orm/_typing.py +179 -0
  135. sqlalchemy/orm/attributes.py +2868 -0
  136. sqlalchemy/orm/base.py +976 -0
  137. sqlalchemy/orm/bulk_persistence.py +2152 -0
  138. sqlalchemy/orm/clsregistry.py +582 -0
  139. sqlalchemy/orm/collections.py +1568 -0
  140. sqlalchemy/orm/context.py +3471 -0
  141. sqlalchemy/orm/decl_api.py +2280 -0
  142. sqlalchemy/orm/decl_base.py +2309 -0
  143. sqlalchemy/orm/dependency.py +1306 -0
  144. sqlalchemy/orm/descriptor_props.py +1183 -0
  145. sqlalchemy/orm/dynamic.py +307 -0
  146. sqlalchemy/orm/evaluator.py +379 -0
  147. sqlalchemy/orm/events.py +3386 -0
  148. sqlalchemy/orm/exc.py +237 -0
  149. sqlalchemy/orm/identity.py +302 -0
  150. sqlalchemy/orm/instrumentation.py +746 -0
  151. sqlalchemy/orm/interfaces.py +1589 -0
  152. sqlalchemy/orm/loading.py +1684 -0
  153. sqlalchemy/orm/mapped_collection.py +557 -0
  154. sqlalchemy/orm/mapper.py +4411 -0
  155. sqlalchemy/orm/path_registry.py +829 -0
  156. sqlalchemy/orm/persistence.py +1789 -0
  157. sqlalchemy/orm/properties.py +973 -0
  158. sqlalchemy/orm/query.py +3528 -0
  159. sqlalchemy/orm/relationships.py +3570 -0
  160. sqlalchemy/orm/scoping.py +2232 -0
  161. sqlalchemy/orm/session.py +5403 -0
  162. sqlalchemy/orm/state.py +1175 -0
  163. sqlalchemy/orm/state_changes.py +196 -0
  164. sqlalchemy/orm/strategies.py +3492 -0
  165. sqlalchemy/orm/strategy_options.py +2562 -0
  166. sqlalchemy/orm/sync.py +164 -0
  167. sqlalchemy/orm/unitofwork.py +798 -0
  168. sqlalchemy/orm/util.py +2438 -0
  169. sqlalchemy/orm/writeonly.py +694 -0
  170. sqlalchemy/pool/__init__.py +41 -0
  171. sqlalchemy/pool/base.py +1522 -0
  172. sqlalchemy/pool/events.py +375 -0
  173. sqlalchemy/pool/impl.py +582 -0
  174. sqlalchemy/py.typed +0 -0
  175. sqlalchemy/schema.py +74 -0
  176. sqlalchemy/sql/__init__.py +156 -0
  177. sqlalchemy/sql/_annotated_cols.py +397 -0
  178. sqlalchemy/sql/_dml_constructors.py +132 -0
  179. sqlalchemy/sql/_elements_constructors.py +2164 -0
  180. sqlalchemy/sql/_orm_types.py +20 -0
  181. sqlalchemy/sql/_selectable_constructors.py +840 -0
  182. sqlalchemy/sql/_typing.py +487 -0
  183. sqlalchemy/sql/_util_cy.cp313t-win_arm64.pyd +0 -0
  184. sqlalchemy/sql/_util_cy.py +127 -0
  185. sqlalchemy/sql/annotation.py +590 -0
  186. sqlalchemy/sql/base.py +2699 -0
  187. sqlalchemy/sql/cache_key.py +1066 -0
  188. sqlalchemy/sql/coercions.py +1373 -0
  189. sqlalchemy/sql/compiler.py +8327 -0
  190. sqlalchemy/sql/crud.py +1815 -0
  191. sqlalchemy/sql/ddl.py +1928 -0
  192. sqlalchemy/sql/default_comparator.py +654 -0
  193. sqlalchemy/sql/dml.py +1977 -0
  194. sqlalchemy/sql/elements.py +6033 -0
  195. sqlalchemy/sql/events.py +458 -0
  196. sqlalchemy/sql/expression.py +172 -0
  197. sqlalchemy/sql/functions.py +2305 -0
  198. sqlalchemy/sql/lambdas.py +1443 -0
  199. sqlalchemy/sql/naming.py +209 -0
  200. sqlalchemy/sql/operators.py +2897 -0
  201. sqlalchemy/sql/roles.py +332 -0
  202. sqlalchemy/sql/schema.py +6703 -0
  203. sqlalchemy/sql/selectable.py +7553 -0
  204. sqlalchemy/sql/sqltypes.py +4093 -0
  205. sqlalchemy/sql/traversals.py +1042 -0
  206. sqlalchemy/sql/type_api.py +2446 -0
  207. sqlalchemy/sql/util.py +1495 -0
  208. sqlalchemy/sql/visitors.py +1157 -0
  209. sqlalchemy/testing/__init__.py +96 -0
  210. sqlalchemy/testing/assertions.py +1007 -0
  211. sqlalchemy/testing/assertsql.py +519 -0
  212. sqlalchemy/testing/asyncio.py +128 -0
  213. sqlalchemy/testing/config.py +440 -0
  214. sqlalchemy/testing/engines.py +483 -0
  215. sqlalchemy/testing/entities.py +117 -0
  216. sqlalchemy/testing/exclusions.py +476 -0
  217. sqlalchemy/testing/fixtures/__init__.py +30 -0
  218. sqlalchemy/testing/fixtures/base.py +384 -0
  219. sqlalchemy/testing/fixtures/mypy.py +247 -0
  220. sqlalchemy/testing/fixtures/orm.py +227 -0
  221. sqlalchemy/testing/fixtures/sql.py +538 -0
  222. sqlalchemy/testing/pickleable.py +155 -0
  223. sqlalchemy/testing/plugin/__init__.py +6 -0
  224. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  225. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  226. sqlalchemy/testing/plugin/pytestplugin.py +892 -0
  227. sqlalchemy/testing/profiling.py +329 -0
  228. sqlalchemy/testing/provision.py +613 -0
  229. sqlalchemy/testing/requirements.py +1978 -0
  230. sqlalchemy/testing/schema.py +198 -0
  231. sqlalchemy/testing/suite/__init__.py +19 -0
  232. sqlalchemy/testing/suite/test_cte.py +237 -0
  233. sqlalchemy/testing/suite/test_ddl.py +420 -0
  234. sqlalchemy/testing/suite/test_dialect.py +776 -0
  235. sqlalchemy/testing/suite/test_insert.py +630 -0
  236. sqlalchemy/testing/suite/test_reflection.py +3557 -0
  237. sqlalchemy/testing/suite/test_results.py +660 -0
  238. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  239. sqlalchemy/testing/suite/test_select.py +2112 -0
  240. sqlalchemy/testing/suite/test_sequence.py +317 -0
  241. sqlalchemy/testing/suite/test_table_via_select.py +686 -0
  242. sqlalchemy/testing/suite/test_types.py +2271 -0
  243. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  244. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  245. sqlalchemy/testing/util.py +535 -0
  246. sqlalchemy/testing/warnings.py +52 -0
  247. sqlalchemy/types.py +76 -0
  248. sqlalchemy/util/__init__.py +158 -0
  249. sqlalchemy/util/_collections.py +688 -0
  250. sqlalchemy/util/_collections_cy.cp313t-win_arm64.pyd +0 -0
  251. sqlalchemy/util/_collections_cy.pxd +8 -0
  252. sqlalchemy/util/_collections_cy.py +516 -0
  253. sqlalchemy/util/_has_cython.py +46 -0
  254. sqlalchemy/util/_immutabledict_cy.cp313t-win_arm64.pyd +0 -0
  255. sqlalchemy/util/_immutabledict_cy.py +240 -0
  256. sqlalchemy/util/compat.py +299 -0
  257. sqlalchemy/util/concurrency.py +322 -0
  258. sqlalchemy/util/cython.py +79 -0
  259. sqlalchemy/util/deprecations.py +401 -0
  260. sqlalchemy/util/langhelpers.py +2320 -0
  261. sqlalchemy/util/preloaded.py +152 -0
  262. sqlalchemy/util/queue.py +304 -0
  263. sqlalchemy/util/tool_support.py +201 -0
  264. sqlalchemy/util/topological.py +120 -0
  265. sqlalchemy/util/typing.py +711 -0
  266. sqlalchemy-2.1.0b2.dist-info/METADATA +269 -0
  267. sqlalchemy-2.1.0b2.dist-info/RECORD +270 -0
  268. sqlalchemy-2.1.0b2.dist-info/WHEEL +5 -0
  269. sqlalchemy-2.1.0b2.dist-info/licenses/LICENSE +19 -0
  270. sqlalchemy-2.1.0b2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,476 @@
1
+ # connectors/asyncio.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
+ """generic asyncio-adapted versions of DBAPI connection and cursor"""
9
+
10
+ from __future__ import annotations
11
+
12
+ import asyncio
13
+ import collections
14
+ import sys
15
+ import types
16
+ from typing import Any
17
+ from typing import AsyncIterator
18
+ from typing import Awaitable
19
+ from typing import Deque
20
+ from typing import Iterator
21
+ from typing import NoReturn
22
+ from typing import Optional
23
+ from typing import Protocol
24
+ from typing import Sequence
25
+ from typing import Tuple
26
+ from typing import Type
27
+ from typing import TYPE_CHECKING
28
+
29
+ from ..engine import AdaptedConnection
30
+ from ..exc import EmulatedDBAPIException
31
+ from ..util import EMPTY_DICT
32
+ from ..util.concurrency import await_
33
+ from ..util.concurrency import in_greenlet
34
+
35
+ if TYPE_CHECKING:
36
+ from ..engine.interfaces import _DBAPICursorDescription
37
+ from ..engine.interfaces import _DBAPIMultiExecuteParams
38
+ from ..engine.interfaces import _DBAPISingleExecuteParams
39
+ from ..engine.interfaces import DBAPIModule
40
+ from ..util.typing import Self
41
+
42
+
43
+ class AsyncIODBAPIConnection(Protocol):
44
+ """protocol representing an async adapted version of a
45
+ :pep:`249` database connection.
46
+
47
+
48
+ """
49
+
50
+ # note that async DBAPIs dont agree if close() should be awaitable,
51
+ # so it is omitted here and picked up by the __getattr__ hook below
52
+
53
+ async def commit(self) -> None: ...
54
+
55
+ def cursor(self, *args: Any, **kwargs: Any) -> AsyncIODBAPICursor: ...
56
+
57
+ async def rollback(self) -> None: ...
58
+
59
+ def __getattr__(self, key: str) -> Any: ...
60
+
61
+ def __setattr__(self, key: str, value: Any) -> None: ...
62
+
63
+
64
+ class AsyncIODBAPICursor(Protocol):
65
+ """protocol representing an async adapted version
66
+ of a :pep:`249` database cursor.
67
+
68
+
69
+ """
70
+
71
+ def __aenter__(self) -> Any: ...
72
+
73
+ @property
74
+ def description(
75
+ self,
76
+ ) -> _DBAPICursorDescription:
77
+ """The description attribute of the Cursor."""
78
+ ...
79
+
80
+ @property
81
+ def rowcount(self) -> int: ...
82
+
83
+ arraysize: int
84
+
85
+ lastrowid: int
86
+
87
+ async def close(self) -> None: ...
88
+
89
+ async def execute(
90
+ self,
91
+ operation: Any,
92
+ parameters: Optional[_DBAPISingleExecuteParams] = None,
93
+ ) -> Any: ...
94
+
95
+ async def executemany(
96
+ self,
97
+ operation: Any,
98
+ parameters: _DBAPIMultiExecuteParams,
99
+ ) -> Any: ...
100
+
101
+ async def fetchone(self) -> Optional[Any]: ...
102
+
103
+ async def fetchmany(self, size: Optional[int] = ...) -> Sequence[Any]: ...
104
+
105
+ async def fetchall(self) -> Sequence[Any]: ...
106
+
107
+ async def setinputsizes(self, sizes: Sequence[Any]) -> None: ...
108
+
109
+ def setoutputsize(self, size: Any, column: Any) -> None: ...
110
+
111
+ async def callproc(
112
+ self, procname: str, parameters: Sequence[Any] = ...
113
+ ) -> Any: ...
114
+
115
+ async def nextset(self) -> Optional[bool]: ...
116
+
117
+ def __aiter__(self) -> AsyncIterator[Any]: ...
118
+
119
+
120
+ class AsyncAdapt_dbapi_module:
121
+ if TYPE_CHECKING:
122
+ Error = DBAPIModule.Error
123
+ OperationalError = DBAPIModule.OperationalError
124
+ InterfaceError = DBAPIModule.InterfaceError
125
+ IntegrityError = DBAPIModule.IntegrityError
126
+
127
+ def __getattr__(self, key: str) -> Any: ...
128
+
129
+ def __init__(
130
+ self,
131
+ driver: types.ModuleType,
132
+ *,
133
+ dbapi_module: types.ModuleType | None = None,
134
+ ):
135
+ self.driver = driver
136
+ self.dbapi_module = dbapi_module
137
+
138
+ @property
139
+ def exceptions_module(self) -> types.ModuleType:
140
+ """Return the module which we think will have the exception hierarchy.
141
+
142
+ For an asyncio driver that wraps a plain DBAPI like aiomysql,
143
+ aioodbc, aiosqlite, etc. these exceptions will be from the
144
+ dbapi_module. For a "pure" driver like asyncpg these will come
145
+ from the driver module.
146
+
147
+ .. versionadded:: 2.1
148
+
149
+ """
150
+ if self.dbapi_module is not None:
151
+ return self.dbapi_module
152
+ else:
153
+ return self.driver
154
+
155
+
156
+ class AsyncAdapt_dbapi_cursor:
157
+ server_side = False
158
+ __slots__ = (
159
+ "_adapt_connection",
160
+ "_connection",
161
+ "_cursor",
162
+ "_rows",
163
+ "_soft_closed_memoized",
164
+ )
165
+
166
+ _awaitable_cursor_close: bool = True
167
+
168
+ _cursor: AsyncIODBAPICursor
169
+ _adapt_connection: AsyncAdapt_dbapi_connection
170
+ _connection: AsyncIODBAPIConnection
171
+ _rows: Deque[Any]
172
+
173
+ def __init__(self, adapt_connection: AsyncAdapt_dbapi_connection):
174
+ self._adapt_connection = adapt_connection
175
+ self._connection = adapt_connection._connection
176
+
177
+ cursor = self._make_new_cursor(self._connection)
178
+ self._cursor = self._aenter_cursor(cursor)
179
+ self._soft_closed_memoized = EMPTY_DICT
180
+ if not self.server_side:
181
+ self._rows = collections.deque()
182
+
183
+ def _aenter_cursor(self, cursor: AsyncIODBAPICursor) -> AsyncIODBAPICursor:
184
+ try:
185
+ return await_(cursor.__aenter__()) # type: ignore[no-any-return]
186
+ except Exception as error:
187
+ self._adapt_connection._handle_exception(error)
188
+
189
+ def _make_new_cursor(
190
+ self, connection: AsyncIODBAPIConnection
191
+ ) -> AsyncIODBAPICursor:
192
+ return connection.cursor()
193
+
194
+ @property
195
+ def description(self) -> Optional[_DBAPICursorDescription]:
196
+ if "description" in self._soft_closed_memoized:
197
+ return self._soft_closed_memoized["description"] # type: ignore[no-any-return] # noqa: E501
198
+ return self._cursor.description
199
+
200
+ @property
201
+ def rowcount(self) -> int:
202
+ return self._cursor.rowcount
203
+
204
+ @property
205
+ def arraysize(self) -> int:
206
+ return self._cursor.arraysize
207
+
208
+ @arraysize.setter
209
+ def arraysize(self, value: int) -> None:
210
+ self._cursor.arraysize = value
211
+
212
+ @property
213
+ def lastrowid(self) -> int:
214
+ return self._cursor.lastrowid
215
+
216
+ async def _async_soft_close(self) -> None:
217
+ """close the cursor but keep the results pending, and memoize the
218
+ description.
219
+
220
+ .. versionadded:: 2.0.44
221
+
222
+ """
223
+
224
+ if not self._awaitable_cursor_close or self.server_side:
225
+ return
226
+
227
+ self._soft_closed_memoized = self._soft_closed_memoized.union(
228
+ {
229
+ "description": self._cursor.description,
230
+ }
231
+ )
232
+ await self._cursor.close()
233
+
234
+ def close(self) -> None:
235
+ self._rows.clear()
236
+
237
+ # updated as of 2.0.44
238
+ # try to "close" the cursor based on what we know about the driver
239
+ # and if we are able to. otherwise, hope that the asyncio
240
+ # extension called _async_soft_close() if the cursor is going into
241
+ # a sync context
242
+ if self._cursor is None or bool(self._soft_closed_memoized):
243
+ return
244
+
245
+ if not self._awaitable_cursor_close:
246
+ self._cursor.close() # type: ignore[unused-coroutine]
247
+ elif in_greenlet():
248
+ await_(self._cursor.close())
249
+
250
+ def execute(
251
+ self,
252
+ operation: Any,
253
+ parameters: Optional[_DBAPISingleExecuteParams] = None,
254
+ ) -> Any:
255
+ try:
256
+ return await_(self._execute_async(operation, parameters))
257
+ except Exception as error:
258
+ self._adapt_connection._handle_exception(error)
259
+
260
+ def executemany(
261
+ self,
262
+ operation: Any,
263
+ seq_of_parameters: _DBAPIMultiExecuteParams,
264
+ ) -> Any:
265
+ try:
266
+ return await_(
267
+ self._executemany_async(operation, seq_of_parameters)
268
+ )
269
+ except Exception as error:
270
+ self._adapt_connection._handle_exception(error)
271
+
272
+ async def _execute_async(
273
+ self, operation: Any, parameters: Optional[_DBAPISingleExecuteParams]
274
+ ) -> Any:
275
+ async with self._adapt_connection._execute_mutex:
276
+ if parameters is None:
277
+ result = await self._cursor.execute(operation)
278
+ else:
279
+ result = await self._cursor.execute(operation, parameters)
280
+
281
+ if self._cursor.description and not self.server_side:
282
+ self._rows = collections.deque(await self._cursor.fetchall())
283
+ return result
284
+
285
+ async def _executemany_async(
286
+ self,
287
+ operation: Any,
288
+ seq_of_parameters: _DBAPIMultiExecuteParams,
289
+ ) -> Any:
290
+ async with self._adapt_connection._execute_mutex:
291
+ return await self._cursor.executemany(operation, seq_of_parameters)
292
+
293
+ def nextset(self) -> None:
294
+ await_(self._cursor.nextset())
295
+ if self._cursor.description and not self.server_side:
296
+ self._rows = collections.deque(await_(self._cursor.fetchall()))
297
+
298
+ def setinputsizes(self, *inputsizes: Any) -> None:
299
+ # NOTE: this is overridden in aioodbc due to
300
+ # see https://github.com/aio-libs/aioodbc/issues/451
301
+ # right now
302
+
303
+ return await_(self._cursor.setinputsizes(*inputsizes))
304
+
305
+ def __enter__(self) -> Self:
306
+ return self
307
+
308
+ def __exit__(self, type_: Any, value: Any, traceback: Any) -> None:
309
+ self.close()
310
+
311
+ def __iter__(self) -> Iterator[Any]:
312
+ while self._rows:
313
+ yield self._rows.popleft()
314
+
315
+ def fetchone(self) -> Optional[Any]:
316
+ if self._rows:
317
+ return self._rows.popleft()
318
+ else:
319
+ return None
320
+
321
+ def fetchmany(self, size: Optional[int] = None) -> Sequence[Any]:
322
+ if size is None:
323
+ size = self.arraysize
324
+ rr = self._rows
325
+ return [rr.popleft() for _ in range(min(size, len(rr)))]
326
+
327
+ def fetchall(self) -> Sequence[Any]:
328
+ retval = list(self._rows)
329
+ self._rows.clear()
330
+ return retval
331
+
332
+
333
+ class AsyncAdapt_dbapi_ss_cursor(AsyncAdapt_dbapi_cursor):
334
+ __slots__ = ()
335
+ server_side = True
336
+
337
+ def close(self) -> None:
338
+ if self._cursor is not None:
339
+ await_(self._cursor.close())
340
+ self._cursor = None # type: ignore
341
+
342
+ def fetchone(self) -> Optional[Any]:
343
+ return await_(self._cursor.fetchone())
344
+
345
+ def fetchmany(self, size: Optional[int] = None) -> Any:
346
+ return await_(self._cursor.fetchmany(size=size))
347
+
348
+ def fetchall(self) -> Sequence[Any]:
349
+ return await_(self._cursor.fetchall())
350
+
351
+ def __iter__(self) -> Iterator[Any]:
352
+ iterator = self._cursor.__aiter__()
353
+ while True:
354
+ try:
355
+ yield await_(iterator.__anext__())
356
+ except StopAsyncIteration:
357
+ break
358
+
359
+
360
+ class AsyncAdapt_dbapi_connection(AdaptedConnection):
361
+ _cursor_cls = AsyncAdapt_dbapi_cursor
362
+ _ss_cursor_cls = AsyncAdapt_dbapi_ss_cursor
363
+
364
+ __slots__ = ("dbapi", "_execute_mutex")
365
+
366
+ _connection: AsyncIODBAPIConnection
367
+
368
+ @classmethod
369
+ async def create(
370
+ cls,
371
+ dbapi: Any,
372
+ connection_awaitable: Awaitable[AsyncIODBAPIConnection],
373
+ **kw: Any,
374
+ ) -> Self:
375
+ try:
376
+ connection = await connection_awaitable
377
+ except Exception as error:
378
+ cls._handle_exception_no_connection(dbapi, error)
379
+ else:
380
+ return cls(dbapi, connection, **kw)
381
+
382
+ def __init__(self, dbapi: Any, connection: AsyncIODBAPIConnection):
383
+ self.dbapi = dbapi
384
+ self._connection = connection
385
+ self._execute_mutex = asyncio.Lock()
386
+
387
+ def cursor(self, server_side: bool = False) -> AsyncAdapt_dbapi_cursor:
388
+ if server_side:
389
+ return self._ss_cursor_cls(self)
390
+ else:
391
+ return self._cursor_cls(self)
392
+
393
+ def execute(
394
+ self,
395
+ operation: Any,
396
+ parameters: Optional[_DBAPISingleExecuteParams] = None,
397
+ ) -> Any:
398
+ """lots of DBAPIs seem to provide this, so include it"""
399
+ cursor = self.cursor()
400
+ cursor.execute(operation, parameters)
401
+ return cursor
402
+
403
+ @classmethod
404
+ def _handle_exception_no_connection(
405
+ cls, dbapi: Any, error: Exception
406
+ ) -> NoReturn:
407
+ exc_info = sys.exc_info()
408
+
409
+ raise error.with_traceback(exc_info[2])
410
+
411
+ def _handle_exception(self, error: Exception) -> NoReturn:
412
+ self._handle_exception_no_connection(self.dbapi, error)
413
+
414
+ def rollback(self) -> None:
415
+ try:
416
+ await_(self._connection.rollback())
417
+ except Exception as error:
418
+ self._handle_exception(error)
419
+
420
+ def commit(self) -> None:
421
+ try:
422
+ await_(self._connection.commit())
423
+ except Exception as error:
424
+ self._handle_exception(error)
425
+
426
+ def close(self) -> None:
427
+ await_(self._connection.close())
428
+
429
+
430
+ class AsyncAdapt_terminate:
431
+ """Mixin for a AsyncAdapt_dbapi_connection to add terminate support."""
432
+
433
+ __slots__ = ()
434
+
435
+ def terminate(self) -> None:
436
+ if in_greenlet():
437
+ # in a greenlet; this is the connection was invalidated case.
438
+ try:
439
+ # try to gracefully close; see #10717
440
+ await_(asyncio.shield(self._terminate_graceful_close()))
441
+ except self._terminate_handled_exceptions() as e:
442
+ # in the case where we are recycling an old connection
443
+ # that may have already been disconnected, close() will
444
+ # fail. In this case, terminate
445
+ # the connection without any further waiting.
446
+ # see issue #8419
447
+ self._terminate_force_close()
448
+ if isinstance(e, asyncio.CancelledError):
449
+ # re-raise CancelledError if we were cancelled
450
+ raise
451
+ else:
452
+ # not in a greenlet; this is the gc cleanup case
453
+ self._terminate_force_close()
454
+
455
+ def _terminate_handled_exceptions(self) -> Tuple[Type[BaseException], ...]:
456
+ """Returns the exceptions that should be handled when
457
+ calling _graceful_close.
458
+ """
459
+ return (asyncio.TimeoutError, asyncio.CancelledError, OSError)
460
+
461
+ async def _terminate_graceful_close(self) -> None:
462
+ """Try to close connection gracefully"""
463
+ raise NotImplementedError
464
+
465
+ def _terminate_force_close(self) -> None:
466
+ """Terminate the connection"""
467
+ raise NotImplementedError
468
+
469
+
470
+ class AsyncAdapt_Error(EmulatedDBAPIException):
471
+ """Provide for the base of DBAPI ``Error`` base class for dialects
472
+ that need to emulate the DBAPI exception hierarchy.
473
+
474
+ .. versionadded:: 2.1
475
+
476
+ """