SQLAlchemy 2.0.36__cp313-cp313-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. SQLAlchemy-2.0.36.dist-info/LICENSE +19 -0
  2. SQLAlchemy-2.0.36.dist-info/METADATA +243 -0
  3. SQLAlchemy-2.0.36.dist-info/RECORD +273 -0
  4. SQLAlchemy-2.0.36.dist-info/WHEEL +5 -0
  5. SQLAlchemy-2.0.36.dist-info/top_level.txt +1 -0
  6. sqlalchemy/__init__.py +294 -0
  7. sqlalchemy/connectors/__init__.py +18 -0
  8. sqlalchemy/connectors/aioodbc.py +174 -0
  9. sqlalchemy/connectors/asyncio.py +213 -0
  10. sqlalchemy/connectors/pyodbc.py +249 -0
  11. sqlalchemy/cyextension/__init__.py +6 -0
  12. sqlalchemy/cyextension/collections.cp313-win32.pyd +0 -0
  13. sqlalchemy/cyextension/collections.pyx +409 -0
  14. sqlalchemy/cyextension/immutabledict.cp313-win32.pyd +0 -0
  15. sqlalchemy/cyextension/immutabledict.pxd +8 -0
  16. sqlalchemy/cyextension/immutabledict.pyx +133 -0
  17. sqlalchemy/cyextension/processors.cp313-win32.pyd +0 -0
  18. sqlalchemy/cyextension/processors.pyx +68 -0
  19. sqlalchemy/cyextension/resultproxy.cp313-win32.pyd +0 -0
  20. sqlalchemy/cyextension/resultproxy.pyx +102 -0
  21. sqlalchemy/cyextension/util.cp313-win32.pyd +0 -0
  22. sqlalchemy/cyextension/util.pyx +91 -0
  23. sqlalchemy/dialects/__init__.py +61 -0
  24. sqlalchemy/dialects/_typing.py +25 -0
  25. sqlalchemy/dialects/mssql/__init__.py +88 -0
  26. sqlalchemy/dialects/mssql/aioodbc.py +64 -0
  27. sqlalchemy/dialects/mssql/base.py +4010 -0
  28. sqlalchemy/dialects/mssql/information_schema.py +254 -0
  29. sqlalchemy/dialects/mssql/json.py +133 -0
  30. sqlalchemy/dialects/mssql/provision.py +162 -0
  31. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  32. sqlalchemy/dialects/mssql/pyodbc.py +745 -0
  33. sqlalchemy/dialects/mysql/__init__.py +101 -0
  34. sqlalchemy/dialects/mysql/aiomysql.py +333 -0
  35. sqlalchemy/dialects/mysql/asyncmy.py +337 -0
  36. sqlalchemy/dialects/mysql/base.py +3494 -0
  37. sqlalchemy/dialects/mysql/cymysql.py +84 -0
  38. sqlalchemy/dialects/mysql/dml.py +219 -0
  39. sqlalchemy/dialects/mysql/enumerated.py +244 -0
  40. sqlalchemy/dialects/mysql/expression.py +141 -0
  41. sqlalchemy/dialects/mysql/json.py +81 -0
  42. sqlalchemy/dialects/mysql/mariadb.py +32 -0
  43. sqlalchemy/dialects/mysql/mariadbconnector.py +277 -0
  44. sqlalchemy/dialects/mysql/mysqlconnector.py +180 -0
  45. sqlalchemy/dialects/mysql/mysqldb.py +303 -0
  46. sqlalchemy/dialects/mysql/provision.py +110 -0
  47. sqlalchemy/dialects/mysql/pymysql.py +137 -0
  48. sqlalchemy/dialects/mysql/pyodbc.py +138 -0
  49. sqlalchemy/dialects/mysql/reflection.py +677 -0
  50. sqlalchemy/dialects/mysql/reserved_words.py +571 -0
  51. sqlalchemy/dialects/mysql/types.py +774 -0
  52. sqlalchemy/dialects/oracle/__init__.py +67 -0
  53. sqlalchemy/dialects/oracle/base.py +3271 -0
  54. sqlalchemy/dialects/oracle/cx_oracle.py +1483 -0
  55. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  56. sqlalchemy/dialects/oracle/oracledb.py +431 -0
  57. sqlalchemy/dialects/oracle/provision.py +220 -0
  58. sqlalchemy/dialects/oracle/types.py +287 -0
  59. sqlalchemy/dialects/postgresql/__init__.py +167 -0
  60. sqlalchemy/dialects/postgresql/_psycopg_common.py +187 -0
  61. sqlalchemy/dialects/postgresql/array.py +425 -0
  62. sqlalchemy/dialects/postgresql/asyncpg.py +1274 -0
  63. sqlalchemy/dialects/postgresql/base.py +5008 -0
  64. sqlalchemy/dialects/postgresql/dml.py +310 -0
  65. sqlalchemy/dialects/postgresql/ext.py +496 -0
  66. sqlalchemy/dialects/postgresql/hstore.py +397 -0
  67. sqlalchemy/dialects/postgresql/json.py +333 -0
  68. sqlalchemy/dialects/postgresql/named_types.py +509 -0
  69. sqlalchemy/dialects/postgresql/operators.py +129 -0
  70. sqlalchemy/dialects/postgresql/pg8000.py +662 -0
  71. sqlalchemy/dialects/postgresql/pg_catalog.py +300 -0
  72. sqlalchemy/dialects/postgresql/provision.py +175 -0
  73. sqlalchemy/dialects/postgresql/psycopg.py +772 -0
  74. sqlalchemy/dialects/postgresql/psycopg2.py +886 -0
  75. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  76. sqlalchemy/dialects/postgresql/ranges.py +1029 -0
  77. sqlalchemy/dialects/postgresql/types.py +303 -0
  78. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  79. sqlalchemy/dialects/sqlite/aiosqlite.py +396 -0
  80. sqlalchemy/dialects/sqlite/base.py +2805 -0
  81. sqlalchemy/dialects/sqlite/dml.py +240 -0
  82. sqlalchemy/dialects/sqlite/json.py +92 -0
  83. sqlalchemy/dialects/sqlite/provision.py +198 -0
  84. sqlalchemy/dialects/sqlite/pysqlcipher.py +155 -0
  85. sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
  86. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  87. sqlalchemy/engine/__init__.py +62 -0
  88. sqlalchemy/engine/_py_processors.py +136 -0
  89. sqlalchemy/engine/_py_row.py +128 -0
  90. sqlalchemy/engine/_py_util.py +74 -0
  91. sqlalchemy/engine/base.py +3375 -0
  92. sqlalchemy/engine/characteristics.py +155 -0
  93. sqlalchemy/engine/create.py +875 -0
  94. sqlalchemy/engine/cursor.py +2181 -0
  95. sqlalchemy/engine/default.py +2365 -0
  96. sqlalchemy/engine/events.py +951 -0
  97. sqlalchemy/engine/interfaces.py +3403 -0
  98. sqlalchemy/engine/mock.py +131 -0
  99. sqlalchemy/engine/processors.py +61 -0
  100. sqlalchemy/engine/reflection.py +2098 -0
  101. sqlalchemy/engine/result.py +2382 -0
  102. sqlalchemy/engine/row.py +401 -0
  103. sqlalchemy/engine/strategies.py +19 -0
  104. sqlalchemy/engine/url.py +910 -0
  105. sqlalchemy/engine/util.py +167 -0
  106. sqlalchemy/event/__init__.py +25 -0
  107. sqlalchemy/event/api.py +225 -0
  108. sqlalchemy/event/attr.py +655 -0
  109. sqlalchemy/event/base.py +470 -0
  110. sqlalchemy/event/legacy.py +246 -0
  111. sqlalchemy/event/registry.py +386 -0
  112. sqlalchemy/events.py +17 -0
  113. sqlalchemy/exc.py +830 -0
  114. sqlalchemy/ext/__init__.py +11 -0
  115. sqlalchemy/ext/associationproxy.py +2013 -0
  116. sqlalchemy/ext/asyncio/__init__.py +25 -0
  117. sqlalchemy/ext/asyncio/base.py +279 -0
  118. sqlalchemy/ext/asyncio/engine.py +1466 -0
  119. sqlalchemy/ext/asyncio/exc.py +21 -0
  120. sqlalchemy/ext/asyncio/result.py +961 -0
  121. sqlalchemy/ext/asyncio/scoping.py +1614 -0
  122. sqlalchemy/ext/asyncio/session.py +1936 -0
  123. sqlalchemy/ext/automap.py +1691 -0
  124. sqlalchemy/ext/baked.py +574 -0
  125. sqlalchemy/ext/compiler.py +570 -0
  126. sqlalchemy/ext/declarative/__init__.py +65 -0
  127. sqlalchemy/ext/declarative/extensions.py +548 -0
  128. sqlalchemy/ext/horizontal_shard.py +481 -0
  129. sqlalchemy/ext/hybrid.py +1514 -0
  130. sqlalchemy/ext/indexable.py +341 -0
  131. sqlalchemy/ext/instrumentation.py +450 -0
  132. sqlalchemy/ext/mutable.py +1073 -0
  133. sqlalchemy/ext/mypy/__init__.py +6 -0
  134. sqlalchemy/ext/mypy/apply.py +320 -0
  135. sqlalchemy/ext/mypy/decl_class.py +515 -0
  136. sqlalchemy/ext/mypy/infer.py +590 -0
  137. sqlalchemy/ext/mypy/names.py +335 -0
  138. sqlalchemy/ext/mypy/plugin.py +303 -0
  139. sqlalchemy/ext/mypy/util.py +357 -0
  140. sqlalchemy/ext/orderinglist.py +416 -0
  141. sqlalchemy/ext/serializer.py +181 -0
  142. sqlalchemy/future/__init__.py +16 -0
  143. sqlalchemy/future/engine.py +15 -0
  144. sqlalchemy/inspection.py +174 -0
  145. sqlalchemy/log.py +288 -0
  146. sqlalchemy/orm/__init__.py +170 -0
  147. sqlalchemy/orm/_orm_constructors.py +2571 -0
  148. sqlalchemy/orm/_typing.py +179 -0
  149. sqlalchemy/orm/attributes.py +2835 -0
  150. sqlalchemy/orm/base.py +973 -0
  151. sqlalchemy/orm/bulk_persistence.py +2123 -0
  152. sqlalchemy/orm/clsregistry.py +571 -0
  153. sqlalchemy/orm/collections.py +1620 -0
  154. sqlalchemy/orm/context.py +3268 -0
  155. sqlalchemy/orm/decl_api.py +1883 -0
  156. sqlalchemy/orm/decl_base.py +2190 -0
  157. sqlalchemy/orm/dependency.py +1304 -0
  158. sqlalchemy/orm/descriptor_props.py +1076 -0
  159. sqlalchemy/orm/dynamic.py +300 -0
  160. sqlalchemy/orm/evaluator.py +379 -0
  161. sqlalchemy/orm/events.py +3261 -0
  162. sqlalchemy/orm/exc.py +228 -0
  163. sqlalchemy/orm/identity.py +302 -0
  164. sqlalchemy/orm/instrumentation.py +754 -0
  165. sqlalchemy/orm/interfaces.py +1474 -0
  166. sqlalchemy/orm/loading.py +1682 -0
  167. sqlalchemy/orm/mapped_collection.py +557 -0
  168. sqlalchemy/orm/mapper.py +4432 -0
  169. sqlalchemy/orm/path_registry.py +811 -0
  170. sqlalchemy/orm/persistence.py +1782 -0
  171. sqlalchemy/orm/properties.py +886 -0
  172. sqlalchemy/orm/query.py +3396 -0
  173. sqlalchemy/orm/relationships.py +3500 -0
  174. sqlalchemy/orm/scoping.py +2165 -0
  175. sqlalchemy/orm/session.py +5301 -0
  176. sqlalchemy/orm/state.py +1143 -0
  177. sqlalchemy/orm/state_changes.py +198 -0
  178. sqlalchemy/orm/strategies.py +3473 -0
  179. sqlalchemy/orm/strategy_options.py +2569 -0
  180. sqlalchemy/orm/sync.py +164 -0
  181. sqlalchemy/orm/unitofwork.py +796 -0
  182. sqlalchemy/orm/util.py +2424 -0
  183. sqlalchemy/orm/writeonly.py +678 -0
  184. sqlalchemy/pool/__init__.py +44 -0
  185. sqlalchemy/pool/base.py +1515 -0
  186. sqlalchemy/pool/events.py +370 -0
  187. sqlalchemy/pool/impl.py +581 -0
  188. sqlalchemy/py.typed +0 -0
  189. sqlalchemy/schema.py +70 -0
  190. sqlalchemy/sql/__init__.py +145 -0
  191. sqlalchemy/sql/_dml_constructors.py +140 -0
  192. sqlalchemy/sql/_elements_constructors.py +1850 -0
  193. sqlalchemy/sql/_orm_types.py +20 -0
  194. sqlalchemy/sql/_py_util.py +75 -0
  195. sqlalchemy/sql/_selectable_constructors.py +635 -0
  196. sqlalchemy/sql/_typing.py +460 -0
  197. sqlalchemy/sql/annotation.py +585 -0
  198. sqlalchemy/sql/base.py +2185 -0
  199. sqlalchemy/sql/cache_key.py +1057 -0
  200. sqlalchemy/sql/coercions.py +1405 -0
  201. sqlalchemy/sql/compiler.py +7818 -0
  202. sqlalchemy/sql/crud.py +1669 -0
  203. sqlalchemy/sql/ddl.py +1378 -0
  204. sqlalchemy/sql/default_comparator.py +552 -0
  205. sqlalchemy/sql/dml.py +1817 -0
  206. sqlalchemy/sql/elements.py +5499 -0
  207. sqlalchemy/sql/events.py +455 -0
  208. sqlalchemy/sql/expression.py +162 -0
  209. sqlalchemy/sql/functions.py +2055 -0
  210. sqlalchemy/sql/lambdas.py +1449 -0
  211. sqlalchemy/sql/naming.py +212 -0
  212. sqlalchemy/sql/operators.py +2579 -0
  213. sqlalchemy/sql/roles.py +323 -0
  214. sqlalchemy/sql/schema.py +6158 -0
  215. sqlalchemy/sql/selectable.py +7004 -0
  216. sqlalchemy/sql/sqltypes.py +3827 -0
  217. sqlalchemy/sql/traversals.py +1024 -0
  218. sqlalchemy/sql/type_api.py +2339 -0
  219. sqlalchemy/sql/util.py +1486 -0
  220. sqlalchemy/sql/visitors.py +1165 -0
  221. sqlalchemy/testing/__init__.py +96 -0
  222. sqlalchemy/testing/assertions.py +989 -0
  223. sqlalchemy/testing/assertsql.py +516 -0
  224. sqlalchemy/testing/asyncio.py +135 -0
  225. sqlalchemy/testing/config.py +427 -0
  226. sqlalchemy/testing/engines.py +472 -0
  227. sqlalchemy/testing/entities.py +117 -0
  228. sqlalchemy/testing/exclusions.py +435 -0
  229. sqlalchemy/testing/fixtures/__init__.py +28 -0
  230. sqlalchemy/testing/fixtures/base.py +366 -0
  231. sqlalchemy/testing/fixtures/mypy.py +312 -0
  232. sqlalchemy/testing/fixtures/orm.py +227 -0
  233. sqlalchemy/testing/fixtures/sql.py +503 -0
  234. sqlalchemy/testing/pickleable.py +155 -0
  235. sqlalchemy/testing/plugin/__init__.py +6 -0
  236. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  237. sqlalchemy/testing/plugin/plugin_base.py +779 -0
  238. sqlalchemy/testing/plugin/pytestplugin.py +868 -0
  239. sqlalchemy/testing/profiling.py +324 -0
  240. sqlalchemy/testing/provision.py +496 -0
  241. sqlalchemy/testing/requirements.py +1818 -0
  242. sqlalchemy/testing/schema.py +224 -0
  243. sqlalchemy/testing/suite/__init__.py +19 -0
  244. sqlalchemy/testing/suite/test_cte.py +211 -0
  245. sqlalchemy/testing/suite/test_ddl.py +389 -0
  246. sqlalchemy/testing/suite/test_deprecations.py +153 -0
  247. sqlalchemy/testing/suite/test_dialect.py +740 -0
  248. sqlalchemy/testing/suite/test_insert.py +630 -0
  249. sqlalchemy/testing/suite/test_reflection.py +3225 -0
  250. sqlalchemy/testing/suite/test_results.py +502 -0
  251. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  252. sqlalchemy/testing/suite/test_select.py +1999 -0
  253. sqlalchemy/testing/suite/test_sequence.py +317 -0
  254. sqlalchemy/testing/suite/test_types.py +2141 -0
  255. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  256. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  257. sqlalchemy/testing/util.py +537 -0
  258. sqlalchemy/testing/warnings.py +52 -0
  259. sqlalchemy/types.py +76 -0
  260. sqlalchemy/util/__init__.py +160 -0
  261. sqlalchemy/util/_collections.py +715 -0
  262. sqlalchemy/util/_concurrency_py3k.py +288 -0
  263. sqlalchemy/util/_has_cy.py +40 -0
  264. sqlalchemy/util/_py_collections.py +541 -0
  265. sqlalchemy/util/compat.py +301 -0
  266. sqlalchemy/util/concurrency.py +108 -0
  267. sqlalchemy/util/deprecations.py +401 -0
  268. sqlalchemy/util/langhelpers.py +2218 -0
  269. sqlalchemy/util/preloaded.py +150 -0
  270. sqlalchemy/util/queue.py +322 -0
  271. sqlalchemy/util/tool_support.py +201 -0
  272. sqlalchemy/util/topological.py +120 -0
  273. sqlalchemy/util/typing.py +629 -0
@@ -0,0 +1,337 @@
1
+ # dialects/mysql/asyncmy.py
2
+ # Copyright (C) 2005-2024 the SQLAlchemy authors and contributors <see AUTHORS
3
+ # 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
+ # mypy: ignore-errors
8
+
9
+ r"""
10
+ .. dialect:: mysql+asyncmy
11
+ :name: asyncmy
12
+ :dbapi: asyncmy
13
+ :connectstring: mysql+asyncmy://user:password@host:port/dbname[?key=value&key=value...]
14
+ :url: https://github.com/long2ice/asyncmy
15
+
16
+ Using a special asyncio mediation layer, the asyncmy dialect is usable
17
+ as the backend for the :ref:`SQLAlchemy asyncio <asyncio_toplevel>`
18
+ extension package.
19
+
20
+ This dialect should normally be used only with the
21
+ :func:`_asyncio.create_async_engine` engine creation function::
22
+
23
+ from sqlalchemy.ext.asyncio import create_async_engine
24
+ engine = create_async_engine("mysql+asyncmy://user:pass@hostname/dbname?charset=utf8mb4")
25
+
26
+
27
+ """ # noqa
28
+ from collections import deque
29
+ from contextlib import asynccontextmanager
30
+
31
+ from .pymysql import MySQLDialect_pymysql
32
+ from ... import pool
33
+ from ... import util
34
+ from ...engine import AdaptedConnection
35
+ from ...util.concurrency import asyncio
36
+ from ...util.concurrency import await_fallback
37
+ from ...util.concurrency import await_only
38
+
39
+
40
+ class AsyncAdapt_asyncmy_cursor:
41
+ # TODO: base on connectors/asyncio.py
42
+ # see #10415
43
+ server_side = False
44
+ __slots__ = (
45
+ "_adapt_connection",
46
+ "_connection",
47
+ "await_",
48
+ "_cursor",
49
+ "_rows",
50
+ )
51
+
52
+ def __init__(self, adapt_connection):
53
+ self._adapt_connection = adapt_connection
54
+ self._connection = adapt_connection._connection
55
+ self.await_ = adapt_connection.await_
56
+
57
+ cursor = self._connection.cursor()
58
+
59
+ self._cursor = self.await_(cursor.__aenter__())
60
+ self._rows = deque()
61
+
62
+ @property
63
+ def description(self):
64
+ return self._cursor.description
65
+
66
+ @property
67
+ def rowcount(self):
68
+ return self._cursor.rowcount
69
+
70
+ @property
71
+ def arraysize(self):
72
+ return self._cursor.arraysize
73
+
74
+ @arraysize.setter
75
+ def arraysize(self, value):
76
+ self._cursor.arraysize = value
77
+
78
+ @property
79
+ def lastrowid(self):
80
+ return self._cursor.lastrowid
81
+
82
+ def close(self):
83
+ # note we aren't actually closing the cursor here,
84
+ # we are just letting GC do it. to allow this to be async
85
+ # we would need the Result to change how it does "Safe close cursor".
86
+ # MySQL "cursors" don't actually have state to be "closed" besides
87
+ # exhausting rows, which we already have done for sync cursor.
88
+ # another option would be to emulate aiosqlite dialect and assign
89
+ # cursor only if we are doing server side cursor operation.
90
+ self._rows.clear()
91
+
92
+ def execute(self, operation, parameters=None):
93
+ return self.await_(self._execute_async(operation, parameters))
94
+
95
+ def executemany(self, operation, seq_of_parameters):
96
+ return self.await_(
97
+ self._executemany_async(operation, seq_of_parameters)
98
+ )
99
+
100
+ async def _execute_async(self, operation, parameters):
101
+ async with self._adapt_connection._mutex_and_adapt_errors():
102
+ if parameters is None:
103
+ result = await self._cursor.execute(operation)
104
+ else:
105
+ result = await self._cursor.execute(operation, parameters)
106
+
107
+ if not self.server_side:
108
+ # asyncmy has a "fake" async result, so we have to pull it out
109
+ # of that here since our default result is not async.
110
+ # we could just as easily grab "_rows" here and be done with it
111
+ # but this is safer.
112
+ self._rows = deque(await self._cursor.fetchall())
113
+ return result
114
+
115
+ async def _executemany_async(self, operation, seq_of_parameters):
116
+ async with self._adapt_connection._mutex_and_adapt_errors():
117
+ return await self._cursor.executemany(operation, seq_of_parameters)
118
+
119
+ def setinputsizes(self, *inputsizes):
120
+ pass
121
+
122
+ def __iter__(self):
123
+ while self._rows:
124
+ yield self._rows.popleft()
125
+
126
+ def fetchone(self):
127
+ if self._rows:
128
+ return self._rows.popleft()
129
+ else:
130
+ return None
131
+
132
+ def fetchmany(self, size=None):
133
+ if size is None:
134
+ size = self.arraysize
135
+
136
+ rr = self._rows
137
+ return [rr.popleft() for _ in range(min(size, len(rr)))]
138
+
139
+ def fetchall(self):
140
+ retval = list(self._rows)
141
+ self._rows.clear()
142
+ return retval
143
+
144
+
145
+ class AsyncAdapt_asyncmy_ss_cursor(AsyncAdapt_asyncmy_cursor):
146
+ # TODO: base on connectors/asyncio.py
147
+ # see #10415
148
+ __slots__ = ()
149
+ server_side = True
150
+
151
+ def __init__(self, adapt_connection):
152
+ self._adapt_connection = adapt_connection
153
+ self._connection = adapt_connection._connection
154
+ self.await_ = adapt_connection.await_
155
+
156
+ cursor = self._connection.cursor(
157
+ adapt_connection.dbapi.asyncmy.cursors.SSCursor
158
+ )
159
+
160
+ self._cursor = self.await_(cursor.__aenter__())
161
+
162
+ def close(self):
163
+ if self._cursor is not None:
164
+ self.await_(self._cursor.close())
165
+ self._cursor = None
166
+
167
+ def fetchone(self):
168
+ return self.await_(self._cursor.fetchone())
169
+
170
+ def fetchmany(self, size=None):
171
+ return self.await_(self._cursor.fetchmany(size=size))
172
+
173
+ def fetchall(self):
174
+ return self.await_(self._cursor.fetchall())
175
+
176
+
177
+ class AsyncAdapt_asyncmy_connection(AdaptedConnection):
178
+ # TODO: base on connectors/asyncio.py
179
+ # see #10415
180
+ await_ = staticmethod(await_only)
181
+ __slots__ = ("dbapi", "_execute_mutex")
182
+
183
+ def __init__(self, dbapi, connection):
184
+ self.dbapi = dbapi
185
+ self._connection = connection
186
+ self._execute_mutex = asyncio.Lock()
187
+
188
+ @asynccontextmanager
189
+ async def _mutex_and_adapt_errors(self):
190
+ async with self._execute_mutex:
191
+ try:
192
+ yield
193
+ except AttributeError:
194
+ raise self.dbapi.InternalError(
195
+ "network operation failed due to asyncmy attribute error"
196
+ )
197
+
198
+ def ping(self, reconnect):
199
+ assert not reconnect
200
+ return self.await_(self._do_ping())
201
+
202
+ async def _do_ping(self):
203
+ async with self._mutex_and_adapt_errors():
204
+ return await self._connection.ping(False)
205
+
206
+ def character_set_name(self):
207
+ return self._connection.character_set_name()
208
+
209
+ def autocommit(self, value):
210
+ self.await_(self._connection.autocommit(value))
211
+
212
+ def cursor(self, server_side=False):
213
+ if server_side:
214
+ return AsyncAdapt_asyncmy_ss_cursor(self)
215
+ else:
216
+ return AsyncAdapt_asyncmy_cursor(self)
217
+
218
+ def rollback(self):
219
+ self.await_(self._connection.rollback())
220
+
221
+ def commit(self):
222
+ self.await_(self._connection.commit())
223
+
224
+ def terminate(self):
225
+ # it's not awaitable.
226
+ self._connection.close()
227
+
228
+ def close(self) -> None:
229
+ self.await_(self._connection.ensure_closed())
230
+
231
+
232
+ class AsyncAdaptFallback_asyncmy_connection(AsyncAdapt_asyncmy_connection):
233
+ __slots__ = ()
234
+
235
+ await_ = staticmethod(await_fallback)
236
+
237
+
238
+ def _Binary(x):
239
+ """Return x as a binary type."""
240
+ return bytes(x)
241
+
242
+
243
+ class AsyncAdapt_asyncmy_dbapi:
244
+ def __init__(self, asyncmy):
245
+ self.asyncmy = asyncmy
246
+ self.paramstyle = "format"
247
+ self._init_dbapi_attributes()
248
+
249
+ def _init_dbapi_attributes(self):
250
+ for name in (
251
+ "Warning",
252
+ "Error",
253
+ "InterfaceError",
254
+ "DataError",
255
+ "DatabaseError",
256
+ "OperationalError",
257
+ "InterfaceError",
258
+ "IntegrityError",
259
+ "ProgrammingError",
260
+ "InternalError",
261
+ "NotSupportedError",
262
+ ):
263
+ setattr(self, name, getattr(self.asyncmy.errors, name))
264
+
265
+ STRING = util.symbol("STRING")
266
+ NUMBER = util.symbol("NUMBER")
267
+ BINARY = util.symbol("BINARY")
268
+ DATETIME = util.symbol("DATETIME")
269
+ TIMESTAMP = util.symbol("TIMESTAMP")
270
+ Binary = staticmethod(_Binary)
271
+
272
+ def connect(self, *arg, **kw):
273
+ async_fallback = kw.pop("async_fallback", False)
274
+ creator_fn = kw.pop("async_creator_fn", self.asyncmy.connect)
275
+
276
+ if util.asbool(async_fallback):
277
+ return AsyncAdaptFallback_asyncmy_connection(
278
+ self,
279
+ await_fallback(creator_fn(*arg, **kw)),
280
+ )
281
+ else:
282
+ return AsyncAdapt_asyncmy_connection(
283
+ self,
284
+ await_only(creator_fn(*arg, **kw)),
285
+ )
286
+
287
+
288
+ class MySQLDialect_asyncmy(MySQLDialect_pymysql):
289
+ driver = "asyncmy"
290
+ supports_statement_cache = True
291
+
292
+ supports_server_side_cursors = True
293
+ _sscursor = AsyncAdapt_asyncmy_ss_cursor
294
+
295
+ is_async = True
296
+ has_terminate = True
297
+
298
+ @classmethod
299
+ def import_dbapi(cls):
300
+ return AsyncAdapt_asyncmy_dbapi(__import__("asyncmy"))
301
+
302
+ @classmethod
303
+ def get_pool_class(cls, url):
304
+ async_fallback = url.query.get("async_fallback", False)
305
+
306
+ if util.asbool(async_fallback):
307
+ return pool.FallbackAsyncAdaptedQueuePool
308
+ else:
309
+ return pool.AsyncAdaptedQueuePool
310
+
311
+ def do_terminate(self, dbapi_connection) -> None:
312
+ dbapi_connection.terminate()
313
+
314
+ def create_connect_args(self, url):
315
+ return super().create_connect_args(
316
+ url, _translate_args=dict(username="user", database="db")
317
+ )
318
+
319
+ def is_disconnect(self, e, connection, cursor):
320
+ if super().is_disconnect(e, connection, cursor):
321
+ return True
322
+ else:
323
+ str_e = str(e).lower()
324
+ return (
325
+ "not connected" in str_e or "network operation failed" in str_e
326
+ )
327
+
328
+ def _found_rows_client_flag(self):
329
+ from asyncmy.constants import CLIENT
330
+
331
+ return CLIENT.FOUND_ROWS
332
+
333
+ def get_driver_connection(self, connection):
334
+ return connection._connection
335
+
336
+
337
+ dialect = MySQLDialect_asyncmy