SQLAlchemy 2.0.47__cp313-cp313t-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.
- sqlalchemy/__init__.py +283 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +184 -0
- sqlalchemy/connectors/asyncio.py +429 -0
- sqlalchemy/connectors/pyodbc.py +250 -0
- sqlalchemy/cyextension/__init__.py +6 -0
- sqlalchemy/cyextension/collections.cp313t-win32.pyd +0 -0
- sqlalchemy/cyextension/collections.pyx +409 -0
- sqlalchemy/cyextension/immutabledict.cp313t-win32.pyd +0 -0
- sqlalchemy/cyextension/immutabledict.pxd +8 -0
- sqlalchemy/cyextension/immutabledict.pyx +133 -0
- sqlalchemy/cyextension/processors.cp313t-win32.pyd +0 -0
- sqlalchemy/cyextension/processors.pyx +68 -0
- sqlalchemy/cyextension/resultproxy.cp313t-win32.pyd +0 -0
- sqlalchemy/cyextension/resultproxy.pyx +102 -0
- sqlalchemy/cyextension/util.cp313t-win32.pyd +0 -0
- sqlalchemy/cyextension/util.pyx +90 -0
- sqlalchemy/dialects/__init__.py +62 -0
- sqlalchemy/dialects/_typing.py +30 -0
- sqlalchemy/dialects/mssql/__init__.py +88 -0
- sqlalchemy/dialects/mssql/aioodbc.py +63 -0
- sqlalchemy/dialects/mssql/base.py +4093 -0
- sqlalchemy/dialects/mssql/information_schema.py +285 -0
- sqlalchemy/dialects/mssql/json.py +129 -0
- sqlalchemy/dialects/mssql/provision.py +185 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +760 -0
- sqlalchemy/dialects/mysql/__init__.py +104 -0
- sqlalchemy/dialects/mysql/aiomysql.py +250 -0
- sqlalchemy/dialects/mysql/asyncmy.py +231 -0
- sqlalchemy/dialects/mysql/base.py +3949 -0
- sqlalchemy/dialects/mysql/cymysql.py +106 -0
- sqlalchemy/dialects/mysql/dml.py +225 -0
- sqlalchemy/dialects/mysql/enumerated.py +282 -0
- sqlalchemy/dialects/mysql/expression.py +146 -0
- sqlalchemy/dialects/mysql/json.py +91 -0
- sqlalchemy/dialects/mysql/mariadb.py +72 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +322 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +302 -0
- sqlalchemy/dialects/mysql/mysqldb.py +314 -0
- sqlalchemy/dialects/mysql/provision.py +153 -0
- sqlalchemy/dialects/mysql/pymysql.py +158 -0
- sqlalchemy/dialects/mysql/pyodbc.py +157 -0
- sqlalchemy/dialects/mysql/reflection.py +727 -0
- sqlalchemy/dialects/mysql/reserved_words.py +570 -0
- sqlalchemy/dialects/mysql/types.py +835 -0
- sqlalchemy/dialects/oracle/__init__.py +81 -0
- sqlalchemy/dialects/oracle/base.py +3802 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1555 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/oracledb.py +941 -0
- sqlalchemy/dialects/oracle/provision.py +297 -0
- sqlalchemy/dialects/oracle/types.py +316 -0
- sqlalchemy/dialects/oracle/vector.py +365 -0
- sqlalchemy/dialects/postgresql/__init__.py +167 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +189 -0
- sqlalchemy/dialects/postgresql/array.py +519 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1284 -0
- sqlalchemy/dialects/postgresql/base.py +5378 -0
- sqlalchemy/dialects/postgresql/dml.py +339 -0
- sqlalchemy/dialects/postgresql/ext.py +540 -0
- sqlalchemy/dialects/postgresql/hstore.py +406 -0
- sqlalchemy/dialects/postgresql/json.py +404 -0
- sqlalchemy/dialects/postgresql/named_types.py +524 -0
- sqlalchemy/dialects/postgresql/operators.py +129 -0
- sqlalchemy/dialects/postgresql/pg8000.py +669 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +326 -0
- sqlalchemy/dialects/postgresql/provision.py +183 -0
- sqlalchemy/dialects/postgresql/psycopg.py +862 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +892 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1031 -0
- sqlalchemy/dialects/postgresql/types.py +313 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +482 -0
- sqlalchemy/dialects/sqlite/base.py +3056 -0
- sqlalchemy/dialects/sqlite/dml.py +263 -0
- sqlalchemy/dialects/sqlite/json.py +92 -0
- sqlalchemy/dialects/sqlite/provision.py +229 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +157 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_py_processors.py +136 -0
- sqlalchemy/engine/_py_row.py +128 -0
- sqlalchemy/engine/_py_util.py +74 -0
- sqlalchemy/engine/base.py +3390 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +893 -0
- sqlalchemy/engine/cursor.py +2298 -0
- sqlalchemy/engine/default.py +2394 -0
- sqlalchemy/engine/events.py +965 -0
- sqlalchemy/engine/interfaces.py +3471 -0
- sqlalchemy/engine/mock.py +134 -0
- sqlalchemy/engine/processors.py +61 -0
- sqlalchemy/engine/reflection.py +2102 -0
- sqlalchemy/engine/result.py +2399 -0
- sqlalchemy/engine/row.py +400 -0
- sqlalchemy/engine/strategies.py +16 -0
- sqlalchemy/engine/url.py +924 -0
- sqlalchemy/engine/util.py +167 -0
- sqlalchemy/event/__init__.py +26 -0
- sqlalchemy/event/api.py +220 -0
- sqlalchemy/event/attr.py +676 -0
- sqlalchemy/event/base.py +472 -0
- sqlalchemy/event/legacy.py +258 -0
- sqlalchemy/event/registry.py +390 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +832 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2027 -0
- sqlalchemy/ext/asyncio/__init__.py +25 -0
- sqlalchemy/ext/asyncio/base.py +281 -0
- sqlalchemy/ext/asyncio/engine.py +1471 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +965 -0
- sqlalchemy/ext/asyncio/scoping.py +1599 -0
- sqlalchemy/ext/asyncio/session.py +1947 -0
- sqlalchemy/ext/automap.py +1701 -0
- sqlalchemy/ext/baked.py +570 -0
- sqlalchemy/ext/compiler.py +600 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +564 -0
- sqlalchemy/ext/horizontal_shard.py +478 -0
- sqlalchemy/ext/hybrid.py +1535 -0
- sqlalchemy/ext/indexable.py +364 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1085 -0
- sqlalchemy/ext/mypy/__init__.py +6 -0
- sqlalchemy/ext/mypy/apply.py +324 -0
- sqlalchemy/ext/mypy/decl_class.py +515 -0
- sqlalchemy/ext/mypy/infer.py +590 -0
- sqlalchemy/ext/mypy/names.py +335 -0
- sqlalchemy/ext/mypy/plugin.py +303 -0
- sqlalchemy/ext/mypy/util.py +357 -0
- sqlalchemy/ext/orderinglist.py +439 -0
- sqlalchemy/ext/serializer.py +185 -0
- sqlalchemy/future/__init__.py +16 -0
- sqlalchemy/future/engine.py +15 -0
- sqlalchemy/inspection.py +174 -0
- sqlalchemy/log.py +288 -0
- sqlalchemy/orm/__init__.py +171 -0
- sqlalchemy/orm/_orm_constructors.py +2661 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2845 -0
- sqlalchemy/orm/base.py +971 -0
- sqlalchemy/orm/bulk_persistence.py +2135 -0
- sqlalchemy/orm/clsregistry.py +571 -0
- sqlalchemy/orm/collections.py +1627 -0
- sqlalchemy/orm/context.py +3334 -0
- sqlalchemy/orm/decl_api.py +2004 -0
- sqlalchemy/orm/decl_base.py +2192 -0
- sqlalchemy/orm/dependency.py +1302 -0
- sqlalchemy/orm/descriptor_props.py +1092 -0
- sqlalchemy/orm/dynamic.py +300 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3252 -0
- sqlalchemy/orm/exc.py +237 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +754 -0
- sqlalchemy/orm/interfaces.py +1496 -0
- sqlalchemy/orm/loading.py +1686 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4444 -0
- sqlalchemy/orm/path_registry.py +809 -0
- sqlalchemy/orm/persistence.py +1788 -0
- sqlalchemy/orm/properties.py +935 -0
- sqlalchemy/orm/query.py +3459 -0
- sqlalchemy/orm/relationships.py +3508 -0
- sqlalchemy/orm/scoping.py +2148 -0
- sqlalchemy/orm/session.py +5280 -0
- sqlalchemy/orm/state.py +1168 -0
- sqlalchemy/orm/state_changes.py +196 -0
- sqlalchemy/orm/strategies.py +3470 -0
- sqlalchemy/orm/strategy_options.py +2568 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +796 -0
- sqlalchemy/orm/util.py +2403 -0
- sqlalchemy/orm/writeonly.py +674 -0
- sqlalchemy/pool/__init__.py +44 -0
- sqlalchemy/pool/base.py +1524 -0
- sqlalchemy/pool/events.py +375 -0
- sqlalchemy/pool/impl.py +588 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +69 -0
- sqlalchemy/sql/__init__.py +145 -0
- sqlalchemy/sql/_dml_constructors.py +132 -0
- sqlalchemy/sql/_elements_constructors.py +1872 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_py_util.py +75 -0
- sqlalchemy/sql/_selectable_constructors.py +763 -0
- sqlalchemy/sql/_typing.py +482 -0
- sqlalchemy/sql/annotation.py +587 -0
- sqlalchemy/sql/base.py +2293 -0
- sqlalchemy/sql/cache_key.py +1057 -0
- sqlalchemy/sql/coercions.py +1404 -0
- sqlalchemy/sql/compiler.py +8081 -0
- sqlalchemy/sql/crud.py +1752 -0
- sqlalchemy/sql/ddl.py +1444 -0
- sqlalchemy/sql/default_comparator.py +551 -0
- sqlalchemy/sql/dml.py +1850 -0
- sqlalchemy/sql/elements.py +5589 -0
- sqlalchemy/sql/events.py +458 -0
- sqlalchemy/sql/expression.py +159 -0
- sqlalchemy/sql/functions.py +2158 -0
- sqlalchemy/sql/lambdas.py +1442 -0
- sqlalchemy/sql/naming.py +209 -0
- sqlalchemy/sql/operators.py +2623 -0
- sqlalchemy/sql/roles.py +323 -0
- sqlalchemy/sql/schema.py +6222 -0
- sqlalchemy/sql/selectable.py +7265 -0
- sqlalchemy/sql/sqltypes.py +3930 -0
- sqlalchemy/sql/traversals.py +1024 -0
- sqlalchemy/sql/type_api.py +2368 -0
- sqlalchemy/sql/util.py +1485 -0
- sqlalchemy/sql/visitors.py +1164 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +994 -0
- sqlalchemy/testing/assertsql.py +520 -0
- sqlalchemy/testing/asyncio.py +135 -0
- sqlalchemy/testing/config.py +434 -0
- sqlalchemy/testing/engines.py +483 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +476 -0
- sqlalchemy/testing/fixtures/__init__.py +28 -0
- sqlalchemy/testing/fixtures/base.py +384 -0
- sqlalchemy/testing/fixtures/mypy.py +332 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +482 -0
- sqlalchemy/testing/pickleable.py +155 -0
- sqlalchemy/testing/plugin/__init__.py +6 -0
- sqlalchemy/testing/plugin/bootstrap.py +51 -0
- sqlalchemy/testing/plugin/plugin_base.py +828 -0
- sqlalchemy/testing/plugin/pytestplugin.py +892 -0
- sqlalchemy/testing/profiling.py +329 -0
- sqlalchemy/testing/provision.py +603 -0
- sqlalchemy/testing/requirements.py +1945 -0
- sqlalchemy/testing/schema.py +198 -0
- sqlalchemy/testing/suite/__init__.py +19 -0
- sqlalchemy/testing/suite/test_cte.py +237 -0
- sqlalchemy/testing/suite/test_ddl.py +389 -0
- sqlalchemy/testing/suite/test_deprecations.py +153 -0
- sqlalchemy/testing/suite/test_dialect.py +776 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3557 -0
- sqlalchemy/testing/suite/test_results.py +504 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +2010 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_types.py +2147 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +535 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +74 -0
- sqlalchemy/util/__init__.py +162 -0
- sqlalchemy/util/_collections.py +712 -0
- sqlalchemy/util/_concurrency_py3k.py +288 -0
- sqlalchemy/util/_has_cy.py +40 -0
- sqlalchemy/util/_py_collections.py +541 -0
- sqlalchemy/util/compat.py +421 -0
- sqlalchemy/util/concurrency.py +110 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2203 -0
- sqlalchemy/util/preloaded.py +150 -0
- sqlalchemy/util/queue.py +322 -0
- sqlalchemy/util/tool_support.py +201 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +734 -0
- sqlalchemy-2.0.47.dist-info/METADATA +243 -0
- sqlalchemy-2.0.47.dist-info/RECORD +274 -0
- sqlalchemy-2.0.47.dist-info/WHEEL +5 -0
- sqlalchemy-2.0.47.dist-info/licenses/LICENSE +19 -0
- sqlalchemy-2.0.47.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# dialects/mysql/__init__.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
|
+
# mypy: ignore-errors
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from . import aiomysql # noqa
|
|
11
|
+
from . import asyncmy # noqa
|
|
12
|
+
from . import base # noqa
|
|
13
|
+
from . import cymysql # noqa
|
|
14
|
+
from . import mariadbconnector # noqa
|
|
15
|
+
from . import mysqlconnector # noqa
|
|
16
|
+
from . import mysqldb # noqa
|
|
17
|
+
from . import pymysql # noqa
|
|
18
|
+
from . import pyodbc # noqa
|
|
19
|
+
from .base import BIGINT
|
|
20
|
+
from .base import BINARY
|
|
21
|
+
from .base import BIT
|
|
22
|
+
from .base import BLOB
|
|
23
|
+
from .base import BOOLEAN
|
|
24
|
+
from .base import CHAR
|
|
25
|
+
from .base import DATE
|
|
26
|
+
from .base import DATETIME
|
|
27
|
+
from .base import DECIMAL
|
|
28
|
+
from .base import DOUBLE
|
|
29
|
+
from .base import ENUM
|
|
30
|
+
from .base import FLOAT
|
|
31
|
+
from .base import INTEGER
|
|
32
|
+
from .base import JSON
|
|
33
|
+
from .base import LONGBLOB
|
|
34
|
+
from .base import LONGTEXT
|
|
35
|
+
from .base import MEDIUMBLOB
|
|
36
|
+
from .base import MEDIUMINT
|
|
37
|
+
from .base import MEDIUMTEXT
|
|
38
|
+
from .base import NCHAR
|
|
39
|
+
from .base import NUMERIC
|
|
40
|
+
from .base import NVARCHAR
|
|
41
|
+
from .base import REAL
|
|
42
|
+
from .base import SET
|
|
43
|
+
from .base import SMALLINT
|
|
44
|
+
from .base import TEXT
|
|
45
|
+
from .base import TIME
|
|
46
|
+
from .base import TIMESTAMP
|
|
47
|
+
from .base import TINYBLOB
|
|
48
|
+
from .base import TINYINT
|
|
49
|
+
from .base import TINYTEXT
|
|
50
|
+
from .base import VARBINARY
|
|
51
|
+
from .base import VARCHAR
|
|
52
|
+
from .base import YEAR
|
|
53
|
+
from .dml import Insert
|
|
54
|
+
from .dml import insert
|
|
55
|
+
from .expression import match
|
|
56
|
+
from .mariadb import INET4
|
|
57
|
+
from .mariadb import INET6
|
|
58
|
+
|
|
59
|
+
# default dialect
|
|
60
|
+
base.dialect = dialect = mysqldb.dialect
|
|
61
|
+
|
|
62
|
+
__all__ = (
|
|
63
|
+
"BIGINT",
|
|
64
|
+
"BINARY",
|
|
65
|
+
"BIT",
|
|
66
|
+
"BLOB",
|
|
67
|
+
"BOOLEAN",
|
|
68
|
+
"CHAR",
|
|
69
|
+
"DATE",
|
|
70
|
+
"DATETIME",
|
|
71
|
+
"DECIMAL",
|
|
72
|
+
"DOUBLE",
|
|
73
|
+
"ENUM",
|
|
74
|
+
"FLOAT",
|
|
75
|
+
"INET4",
|
|
76
|
+
"INET6",
|
|
77
|
+
"INTEGER",
|
|
78
|
+
"INTEGER",
|
|
79
|
+
"JSON",
|
|
80
|
+
"LONGBLOB",
|
|
81
|
+
"LONGTEXT",
|
|
82
|
+
"MEDIUMBLOB",
|
|
83
|
+
"MEDIUMINT",
|
|
84
|
+
"MEDIUMTEXT",
|
|
85
|
+
"NCHAR",
|
|
86
|
+
"NVARCHAR",
|
|
87
|
+
"NUMERIC",
|
|
88
|
+
"SET",
|
|
89
|
+
"SMALLINT",
|
|
90
|
+
"REAL",
|
|
91
|
+
"TEXT",
|
|
92
|
+
"TIME",
|
|
93
|
+
"TIMESTAMP",
|
|
94
|
+
"TINYBLOB",
|
|
95
|
+
"TINYINT",
|
|
96
|
+
"TINYTEXT",
|
|
97
|
+
"VARBINARY",
|
|
98
|
+
"VARCHAR",
|
|
99
|
+
"YEAR",
|
|
100
|
+
"dialect",
|
|
101
|
+
"insert",
|
|
102
|
+
"Insert",
|
|
103
|
+
"match",
|
|
104
|
+
)
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# dialects/mysql/aiomysql.py
|
|
2
|
+
# Copyright (C) 2005-2026 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
|
+
|
|
8
|
+
r"""
|
|
9
|
+
.. dialect:: mysql+aiomysql
|
|
10
|
+
:name: aiomysql
|
|
11
|
+
:dbapi: aiomysql
|
|
12
|
+
:connectstring: mysql+aiomysql://user:password@host:port/dbname[?key=value&key=value...]
|
|
13
|
+
:url: https://github.com/aio-libs/aiomysql
|
|
14
|
+
|
|
15
|
+
The aiomysql dialect is SQLAlchemy's second Python asyncio dialect.
|
|
16
|
+
|
|
17
|
+
Using a special asyncio mediation layer, the aiomysql dialect is usable
|
|
18
|
+
as the backend for the :ref:`SQLAlchemy asyncio <asyncio_toplevel>`
|
|
19
|
+
extension package.
|
|
20
|
+
|
|
21
|
+
This dialect should normally be used only with the
|
|
22
|
+
:func:`_asyncio.create_async_engine` engine creation function::
|
|
23
|
+
|
|
24
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
25
|
+
|
|
26
|
+
engine = create_async_engine(
|
|
27
|
+
"mysql+aiomysql://user:pass@hostname/dbname?charset=utf8mb4"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
""" # noqa
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
from types import ModuleType
|
|
34
|
+
from typing import Any
|
|
35
|
+
from typing import Dict
|
|
36
|
+
from typing import Optional
|
|
37
|
+
from typing import Tuple
|
|
38
|
+
from typing import TYPE_CHECKING
|
|
39
|
+
from typing import Union
|
|
40
|
+
|
|
41
|
+
from .pymysql import MySQLDialect_pymysql
|
|
42
|
+
from ... import pool
|
|
43
|
+
from ... import util
|
|
44
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_connection
|
|
45
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_cursor
|
|
46
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_module
|
|
47
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_ss_cursor
|
|
48
|
+
from ...connectors.asyncio import AsyncAdapt_terminate
|
|
49
|
+
from ...util.concurrency import await_fallback
|
|
50
|
+
from ...util.concurrency import await_only
|
|
51
|
+
|
|
52
|
+
if TYPE_CHECKING:
|
|
53
|
+
|
|
54
|
+
from ...connectors.asyncio import AsyncIODBAPIConnection
|
|
55
|
+
from ...connectors.asyncio import AsyncIODBAPICursor
|
|
56
|
+
from ...engine.interfaces import ConnectArgsType
|
|
57
|
+
from ...engine.interfaces import DBAPIConnection
|
|
58
|
+
from ...engine.interfaces import DBAPICursor
|
|
59
|
+
from ...engine.interfaces import DBAPIModule
|
|
60
|
+
from ...engine.interfaces import PoolProxiedConnection
|
|
61
|
+
from ...engine.url import URL
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class AsyncAdapt_aiomysql_cursor(AsyncAdapt_dbapi_cursor):
|
|
65
|
+
__slots__ = ()
|
|
66
|
+
|
|
67
|
+
def _make_new_cursor(
|
|
68
|
+
self, connection: AsyncIODBAPIConnection
|
|
69
|
+
) -> AsyncIODBAPICursor:
|
|
70
|
+
return connection.cursor(self._adapt_connection.dbapi.Cursor)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class AsyncAdapt_aiomysql_ss_cursor(
|
|
74
|
+
AsyncAdapt_dbapi_ss_cursor, AsyncAdapt_aiomysql_cursor
|
|
75
|
+
):
|
|
76
|
+
__slots__ = ()
|
|
77
|
+
|
|
78
|
+
def _make_new_cursor(
|
|
79
|
+
self, connection: AsyncIODBAPIConnection
|
|
80
|
+
) -> AsyncIODBAPICursor:
|
|
81
|
+
return connection.cursor(
|
|
82
|
+
self._adapt_connection.dbapi.aiomysql.cursors.SSCursor
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class AsyncAdapt_aiomysql_connection(
|
|
87
|
+
AsyncAdapt_terminate, AsyncAdapt_dbapi_connection
|
|
88
|
+
):
|
|
89
|
+
__slots__ = ()
|
|
90
|
+
|
|
91
|
+
_cursor_cls = AsyncAdapt_aiomysql_cursor
|
|
92
|
+
_ss_cursor_cls = AsyncAdapt_aiomysql_ss_cursor
|
|
93
|
+
|
|
94
|
+
def ping(self, reconnect: bool) -> None:
|
|
95
|
+
assert not reconnect
|
|
96
|
+
self.await_(self._connection.ping(reconnect))
|
|
97
|
+
|
|
98
|
+
def character_set_name(self) -> Optional[str]:
|
|
99
|
+
return self._connection.character_set_name() # type: ignore[no-any-return] # noqa: E501
|
|
100
|
+
|
|
101
|
+
def autocommit(self, value: Any) -> None:
|
|
102
|
+
self.await_(self._connection.autocommit(value))
|
|
103
|
+
|
|
104
|
+
def get_autocommit(self) -> bool:
|
|
105
|
+
return self._connection.get_autocommit() # type: ignore
|
|
106
|
+
|
|
107
|
+
def close(self) -> None:
|
|
108
|
+
self.await_(self._connection.ensure_closed())
|
|
109
|
+
|
|
110
|
+
async def _terminate_graceful_close(self) -> None:
|
|
111
|
+
await self._connection.ensure_closed()
|
|
112
|
+
|
|
113
|
+
def _terminate_force_close(self) -> None:
|
|
114
|
+
# it's not awaitable.
|
|
115
|
+
self._connection.close()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class AsyncAdaptFallback_aiomysql_connection(AsyncAdapt_aiomysql_connection):
|
|
119
|
+
__slots__ = ()
|
|
120
|
+
|
|
121
|
+
await_ = staticmethod(await_fallback)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class AsyncAdapt_aiomysql_dbapi(AsyncAdapt_dbapi_module):
|
|
125
|
+
def __init__(self, aiomysql: ModuleType, pymysql: ModuleType):
|
|
126
|
+
self.aiomysql = aiomysql
|
|
127
|
+
self.pymysql = pymysql
|
|
128
|
+
self.paramstyle = "format"
|
|
129
|
+
self._init_dbapi_attributes()
|
|
130
|
+
self.Cursor, self.SSCursor = self._init_cursors_subclasses()
|
|
131
|
+
|
|
132
|
+
def _init_dbapi_attributes(self) -> None:
|
|
133
|
+
for name in (
|
|
134
|
+
"Warning",
|
|
135
|
+
"Error",
|
|
136
|
+
"InterfaceError",
|
|
137
|
+
"DataError",
|
|
138
|
+
"DatabaseError",
|
|
139
|
+
"OperationalError",
|
|
140
|
+
"InterfaceError",
|
|
141
|
+
"IntegrityError",
|
|
142
|
+
"ProgrammingError",
|
|
143
|
+
"InternalError",
|
|
144
|
+
"NotSupportedError",
|
|
145
|
+
):
|
|
146
|
+
setattr(self, name, getattr(self.aiomysql, name))
|
|
147
|
+
|
|
148
|
+
for name in (
|
|
149
|
+
"NUMBER",
|
|
150
|
+
"STRING",
|
|
151
|
+
"DATETIME",
|
|
152
|
+
"BINARY",
|
|
153
|
+
"TIMESTAMP",
|
|
154
|
+
"Binary",
|
|
155
|
+
):
|
|
156
|
+
setattr(self, name, getattr(self.pymysql, name))
|
|
157
|
+
|
|
158
|
+
def connect(self, *arg: Any, **kw: Any) -> AsyncAdapt_aiomysql_connection:
|
|
159
|
+
async_fallback = kw.pop("async_fallback", False)
|
|
160
|
+
creator_fn = kw.pop("async_creator_fn", self.aiomysql.connect)
|
|
161
|
+
|
|
162
|
+
if util.asbool(async_fallback):
|
|
163
|
+
return AsyncAdaptFallback_aiomysql_connection(
|
|
164
|
+
self,
|
|
165
|
+
await_fallback(creator_fn(*arg, **kw)),
|
|
166
|
+
)
|
|
167
|
+
else:
|
|
168
|
+
return AsyncAdapt_aiomysql_connection(
|
|
169
|
+
self,
|
|
170
|
+
await_only(creator_fn(*arg, **kw)),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
def _init_cursors_subclasses(
|
|
174
|
+
self,
|
|
175
|
+
) -> Tuple[AsyncIODBAPICursor, AsyncIODBAPICursor]:
|
|
176
|
+
# suppress unconditional warning emitted by aiomysql
|
|
177
|
+
class Cursor(self.aiomysql.Cursor): # type: ignore[misc, name-defined]
|
|
178
|
+
async def _show_warnings(
|
|
179
|
+
self, conn: AsyncIODBAPIConnection
|
|
180
|
+
) -> None:
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
class SSCursor(self.aiomysql.SSCursor): # type: ignore[misc, name-defined] # noqa: E501
|
|
184
|
+
async def _show_warnings(
|
|
185
|
+
self, conn: AsyncIODBAPIConnection
|
|
186
|
+
) -> None:
|
|
187
|
+
pass
|
|
188
|
+
|
|
189
|
+
return Cursor, SSCursor # type: ignore[return-value]
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class MySQLDialect_aiomysql(MySQLDialect_pymysql):
|
|
193
|
+
driver = "aiomysql"
|
|
194
|
+
supports_statement_cache = True
|
|
195
|
+
|
|
196
|
+
supports_server_side_cursors = True
|
|
197
|
+
_sscursor = AsyncAdapt_aiomysql_ss_cursor
|
|
198
|
+
|
|
199
|
+
is_async = True
|
|
200
|
+
has_terminate = True
|
|
201
|
+
|
|
202
|
+
@classmethod
|
|
203
|
+
def import_dbapi(cls) -> AsyncAdapt_aiomysql_dbapi:
|
|
204
|
+
return AsyncAdapt_aiomysql_dbapi(
|
|
205
|
+
__import__("aiomysql"), __import__("pymysql")
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
@classmethod
|
|
209
|
+
def get_pool_class(cls, url: URL) -> type:
|
|
210
|
+
async_fallback = url.query.get("async_fallback", False)
|
|
211
|
+
|
|
212
|
+
if util.asbool(async_fallback):
|
|
213
|
+
return pool.FallbackAsyncAdaptedQueuePool
|
|
214
|
+
else:
|
|
215
|
+
return pool.AsyncAdaptedQueuePool
|
|
216
|
+
|
|
217
|
+
def do_terminate(self, dbapi_connection: DBAPIConnection) -> None:
|
|
218
|
+
dbapi_connection.terminate()
|
|
219
|
+
|
|
220
|
+
def create_connect_args(
|
|
221
|
+
self, url: URL, _translate_args: Optional[Dict[str, Any]] = None
|
|
222
|
+
) -> ConnectArgsType:
|
|
223
|
+
return super().create_connect_args(
|
|
224
|
+
url, _translate_args=dict(username="user", database="db")
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
def is_disconnect(
|
|
228
|
+
self,
|
|
229
|
+
e: DBAPIModule.Error,
|
|
230
|
+
connection: Optional[Union[PoolProxiedConnection, DBAPIConnection]],
|
|
231
|
+
cursor: Optional[DBAPICursor],
|
|
232
|
+
) -> bool:
|
|
233
|
+
if super().is_disconnect(e, connection, cursor):
|
|
234
|
+
return True
|
|
235
|
+
else:
|
|
236
|
+
str_e = str(e).lower()
|
|
237
|
+
return "not connected" in str_e
|
|
238
|
+
|
|
239
|
+
def _found_rows_client_flag(self) -> int:
|
|
240
|
+
from pymysql.constants import CLIENT # type: ignore
|
|
241
|
+
|
|
242
|
+
return CLIENT.FOUND_ROWS # type: ignore[no-any-return]
|
|
243
|
+
|
|
244
|
+
def get_driver_connection(
|
|
245
|
+
self, connection: DBAPIConnection
|
|
246
|
+
) -> AsyncIODBAPIConnection:
|
|
247
|
+
return connection._connection # type: ignore[no-any-return]
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
dialect = MySQLDialect_aiomysql
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# dialects/mysql/asyncmy.py
|
|
2
|
+
# Copyright (C) 2005-2026 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
|
+
|
|
8
|
+
r"""
|
|
9
|
+
.. dialect:: mysql+asyncmy
|
|
10
|
+
:name: asyncmy
|
|
11
|
+
:dbapi: asyncmy
|
|
12
|
+
:connectstring: mysql+asyncmy://user:password@host:port/dbname[?key=value&key=value...]
|
|
13
|
+
:url: https://github.com/long2ice/asyncmy
|
|
14
|
+
|
|
15
|
+
Using a special asyncio mediation layer, the asyncmy dialect is usable
|
|
16
|
+
as the backend for the :ref:`SQLAlchemy asyncio <asyncio_toplevel>`
|
|
17
|
+
extension package.
|
|
18
|
+
|
|
19
|
+
This dialect should normally be used only with the
|
|
20
|
+
:func:`_asyncio.create_async_engine` engine creation function::
|
|
21
|
+
|
|
22
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
23
|
+
|
|
24
|
+
engine = create_async_engine(
|
|
25
|
+
"mysql+asyncmy://user:pass@hostname/dbname?charset=utf8mb4"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
""" # noqa
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
from types import ModuleType
|
|
32
|
+
from typing import Any
|
|
33
|
+
from typing import NoReturn
|
|
34
|
+
from typing import Optional
|
|
35
|
+
from typing import TYPE_CHECKING
|
|
36
|
+
from typing import Union
|
|
37
|
+
|
|
38
|
+
from .pymysql import MySQLDialect_pymysql
|
|
39
|
+
from ... import pool
|
|
40
|
+
from ... import util
|
|
41
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_connection
|
|
42
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_cursor
|
|
43
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_module
|
|
44
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_ss_cursor
|
|
45
|
+
from ...connectors.asyncio import AsyncAdapt_terminate
|
|
46
|
+
from ...util.concurrency import await_fallback
|
|
47
|
+
from ...util.concurrency import await_only
|
|
48
|
+
|
|
49
|
+
if TYPE_CHECKING:
|
|
50
|
+
from ...connectors.asyncio import AsyncIODBAPIConnection
|
|
51
|
+
from ...connectors.asyncio import AsyncIODBAPICursor
|
|
52
|
+
from ...engine.interfaces import ConnectArgsType
|
|
53
|
+
from ...engine.interfaces import DBAPIConnection
|
|
54
|
+
from ...engine.interfaces import DBAPICursor
|
|
55
|
+
from ...engine.interfaces import DBAPIModule
|
|
56
|
+
from ...engine.interfaces import PoolProxiedConnection
|
|
57
|
+
from ...engine.url import URL
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AsyncAdapt_asyncmy_cursor(AsyncAdapt_dbapi_cursor):
|
|
61
|
+
__slots__ = ()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class AsyncAdapt_asyncmy_ss_cursor(
|
|
65
|
+
AsyncAdapt_dbapi_ss_cursor, AsyncAdapt_asyncmy_cursor
|
|
66
|
+
):
|
|
67
|
+
__slots__ = ()
|
|
68
|
+
|
|
69
|
+
def _make_new_cursor(
|
|
70
|
+
self, connection: AsyncIODBAPIConnection
|
|
71
|
+
) -> AsyncIODBAPICursor:
|
|
72
|
+
return connection.cursor(
|
|
73
|
+
self._adapt_connection.dbapi.asyncmy.cursors.SSCursor
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class AsyncAdapt_asyncmy_connection(
|
|
78
|
+
AsyncAdapt_terminate, AsyncAdapt_dbapi_connection
|
|
79
|
+
):
|
|
80
|
+
__slots__ = ()
|
|
81
|
+
|
|
82
|
+
_cursor_cls = AsyncAdapt_asyncmy_cursor
|
|
83
|
+
_ss_cursor_cls = AsyncAdapt_asyncmy_ss_cursor
|
|
84
|
+
|
|
85
|
+
def _handle_exception(self, error: Exception) -> NoReturn:
|
|
86
|
+
if isinstance(error, AttributeError):
|
|
87
|
+
raise self.dbapi.InternalError(
|
|
88
|
+
"network operation failed due to asyncmy attribute error"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
raise error
|
|
92
|
+
|
|
93
|
+
def ping(self, reconnect: bool) -> None:
|
|
94
|
+
assert not reconnect
|
|
95
|
+
return self.await_(self._do_ping())
|
|
96
|
+
|
|
97
|
+
async def _do_ping(self) -> None:
|
|
98
|
+
try:
|
|
99
|
+
async with self._execute_mutex:
|
|
100
|
+
await self._connection.ping(False)
|
|
101
|
+
except Exception as error:
|
|
102
|
+
self._handle_exception(error)
|
|
103
|
+
|
|
104
|
+
def character_set_name(self) -> Optional[str]:
|
|
105
|
+
return self._connection.character_set_name() # type: ignore[no-any-return] # noqa: E501
|
|
106
|
+
|
|
107
|
+
def autocommit(self, value: Any) -> None:
|
|
108
|
+
self.await_(self._connection.autocommit(value))
|
|
109
|
+
|
|
110
|
+
def get_autocommit(self) -> bool:
|
|
111
|
+
return self._connection.get_autocommit() # type: ignore
|
|
112
|
+
|
|
113
|
+
def close(self) -> None:
|
|
114
|
+
self.await_(self._connection.ensure_closed())
|
|
115
|
+
|
|
116
|
+
async def _terminate_graceful_close(self) -> None:
|
|
117
|
+
await self._connection.ensure_closed()
|
|
118
|
+
|
|
119
|
+
def _terminate_force_close(self) -> None:
|
|
120
|
+
# it's not awaitable.
|
|
121
|
+
self._connection.close()
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class AsyncAdaptFallback_asyncmy_connection(AsyncAdapt_asyncmy_connection):
|
|
125
|
+
__slots__ = ()
|
|
126
|
+
|
|
127
|
+
await_ = staticmethod(await_fallback)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class AsyncAdapt_asyncmy_dbapi(AsyncAdapt_dbapi_module):
|
|
131
|
+
def __init__(self, asyncmy: ModuleType):
|
|
132
|
+
self.asyncmy = asyncmy
|
|
133
|
+
self.paramstyle = "format"
|
|
134
|
+
self._init_dbapi_attributes()
|
|
135
|
+
|
|
136
|
+
def _init_dbapi_attributes(self) -> None:
|
|
137
|
+
for name in (
|
|
138
|
+
"Warning",
|
|
139
|
+
"Error",
|
|
140
|
+
"InterfaceError",
|
|
141
|
+
"DataError",
|
|
142
|
+
"DatabaseError",
|
|
143
|
+
"OperationalError",
|
|
144
|
+
"InterfaceError",
|
|
145
|
+
"IntegrityError",
|
|
146
|
+
"ProgrammingError",
|
|
147
|
+
"InternalError",
|
|
148
|
+
"NotSupportedError",
|
|
149
|
+
):
|
|
150
|
+
setattr(self, name, getattr(self.asyncmy.errors, name))
|
|
151
|
+
|
|
152
|
+
STRING = util.symbol("STRING")
|
|
153
|
+
NUMBER = util.symbol("NUMBER")
|
|
154
|
+
BINARY = util.symbol("BINARY")
|
|
155
|
+
DATETIME = util.symbol("DATETIME")
|
|
156
|
+
TIMESTAMP = util.symbol("TIMESTAMP")
|
|
157
|
+
Binary = staticmethod(bytes)
|
|
158
|
+
|
|
159
|
+
def connect(self, *arg: Any, **kw: Any) -> AsyncAdapt_asyncmy_connection:
|
|
160
|
+
async_fallback = kw.pop("async_fallback", False)
|
|
161
|
+
creator_fn = kw.pop("async_creator_fn", self.asyncmy.connect)
|
|
162
|
+
|
|
163
|
+
if util.asbool(async_fallback):
|
|
164
|
+
return AsyncAdaptFallback_asyncmy_connection(
|
|
165
|
+
self,
|
|
166
|
+
await_fallback(creator_fn(*arg, **kw)),
|
|
167
|
+
)
|
|
168
|
+
else:
|
|
169
|
+
return AsyncAdapt_asyncmy_connection(
|
|
170
|
+
self,
|
|
171
|
+
await_only(creator_fn(*arg, **kw)),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class MySQLDialect_asyncmy(MySQLDialect_pymysql):
|
|
176
|
+
driver = "asyncmy"
|
|
177
|
+
supports_statement_cache = True
|
|
178
|
+
|
|
179
|
+
supports_server_side_cursors = True
|
|
180
|
+
_sscursor = AsyncAdapt_asyncmy_ss_cursor
|
|
181
|
+
|
|
182
|
+
is_async = True
|
|
183
|
+
has_terminate = True
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def import_dbapi(cls) -> DBAPIModule:
|
|
187
|
+
return AsyncAdapt_asyncmy_dbapi(__import__("asyncmy"))
|
|
188
|
+
|
|
189
|
+
@classmethod
|
|
190
|
+
def get_pool_class(cls, url: URL) -> type:
|
|
191
|
+
async_fallback = url.query.get("async_fallback", False)
|
|
192
|
+
|
|
193
|
+
if util.asbool(async_fallback):
|
|
194
|
+
return pool.FallbackAsyncAdaptedQueuePool
|
|
195
|
+
else:
|
|
196
|
+
return pool.AsyncAdaptedQueuePool
|
|
197
|
+
|
|
198
|
+
def do_terminate(self, dbapi_connection: DBAPIConnection) -> None:
|
|
199
|
+
dbapi_connection.terminate()
|
|
200
|
+
|
|
201
|
+
def create_connect_args(self, url: URL) -> ConnectArgsType: # type: ignore[override] # noqa: E501
|
|
202
|
+
return super().create_connect_args(
|
|
203
|
+
url, _translate_args=dict(username="user", database="db")
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def is_disconnect(
|
|
207
|
+
self,
|
|
208
|
+
e: DBAPIModule.Error,
|
|
209
|
+
connection: Optional[Union[PoolProxiedConnection, DBAPIConnection]],
|
|
210
|
+
cursor: Optional[DBAPICursor],
|
|
211
|
+
) -> bool:
|
|
212
|
+
if super().is_disconnect(e, connection, cursor):
|
|
213
|
+
return True
|
|
214
|
+
else:
|
|
215
|
+
str_e = str(e).lower()
|
|
216
|
+
return (
|
|
217
|
+
"not connected" in str_e or "network operation failed" in str_e
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
def _found_rows_client_flag(self) -> int:
|
|
221
|
+
from asyncmy.constants import CLIENT # type: ignore
|
|
222
|
+
|
|
223
|
+
return CLIENT.FOUND_ROWS # type: ignore[no-any-return]
|
|
224
|
+
|
|
225
|
+
def get_driver_connection(
|
|
226
|
+
self, connection: DBAPIConnection
|
|
227
|
+
) -> AsyncIODBAPIConnection:
|
|
228
|
+
return connection._connection # type: ignore[no-any-return]
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
dialect = MySQLDialect_asyncmy
|