From: Mike Bayer Date: Thu, 20 Jan 2022 20:21:17 +0000 (-0500) Subject: re-enable tests for asyncmy; fix Binary X-Git-Tag: rel_2_0_0b1~525^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=469f7fd2f3d51796904cde63dfcc2aafe5663087;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git re-enable tests for asyncmy; fix Binary Fixed regression in asyncmy dialect caused by :ticket:`7567` where removal of the PyMySQL dependency broke binary columns, due to the asyncmy dialect not being properly included within CI tests. Also repairs mariadbconnector isolation level for 2.0. basically tox config was failing to include additional drivers. Fixes: #7593 Change-Id: Iefc1061c24c75fcb9ca1a02d0b5e5f43970ade17 --- diff --git a/doc/build/changelog/unreleased_14/7593.rst b/doc/build/changelog/unreleased_14/7593.rst new file mode 100644 index 0000000000..ebb3406ed7 --- /dev/null +++ b/doc/build/changelog/unreleased_14/7593.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: bug, mysql, regression + :tickets: 7593 + + Fixed regression in asyncmy dialect caused by :ticket:`7567` where removal + of the PyMySQL dependency broke binary columns, due to the asyncmy dialect + not being properly included within CI tests. diff --git a/lib/sqlalchemy/dialects/mysql/asyncmy.py b/lib/sqlalchemy/dialects/mysql/asyncmy.py index 3eb19411e3..915b666bbe 100644 --- a/lib/sqlalchemy/dialects/mysql/asyncmy.py +++ b/lib/sqlalchemy/dialects/mysql/asyncmy.py @@ -229,6 +229,11 @@ class AsyncAdaptFallback_asyncmy_connection(AsyncAdapt_asyncmy_connection): await_ = staticmethod(await_fallback) +def _Binary(x): + """Return x as a binary type.""" + return bytes(x) + + class AsyncAdapt_asyncmy_dbapi: def __init__(self, asyncmy): self.asyncmy = asyncmy @@ -251,6 +256,13 @@ class AsyncAdapt_asyncmy_dbapi: ): setattr(self, name, getattr(self.asyncmy.errors, name)) + STRING = util.symbol("STRING") + NUMBER = util.symbol("NUMBER") + BINARY = util.symbol("BINARY") + DATETIME = util.symbol("DATETIME") + TIMESTAMP = util.symbol("TIMESTAMP") + Binary = staticmethod(_Binary) + def connect(self, *arg, **kw): async_fallback = kw.pop("async_fallback", False) diff --git a/lib/sqlalchemy/dialects/mysql/mariadbconnector.py b/lib/sqlalchemy/dialects/mysql/mariadbconnector.py index f313048878..ea6060c01b 100644 --- a/lib/sqlalchemy/dialects/mysql/mariadbconnector.py +++ b/lib/sqlalchemy/dialects/mysql/mariadbconnector.py @@ -163,22 +163,21 @@ class MySQLDialect_mariadbconnector(MySQLDialect): def _detect_charset(self, connection): return "utf8mb4" - _isolation_lookup = set( - [ + def get_isolation_level_values(self, dbapi_connection): + return ( "SERIALIZABLE", "READ UNCOMMITTED", "READ COMMITTED", "REPEATABLE READ", "AUTOCOMMIT", - ] - ) + ) - def _set_isolation_level(self, connection, level): + def set_isolation_level(self, connection, level): if level == "AUTOCOMMIT": connection.autocommit = True else: connection.autocommit = False - super(MySQLDialect_mariadbconnector, self)._set_isolation_level( + super(MySQLDialect_mariadbconnector, self).set_isolation_level( connection, level ) diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index 796de5d939..efab043ee9 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -42,6 +42,8 @@ from ... import Unicode from ... import UnicodeText from ...orm import declarative_base from ...orm import Session +from ...sql.sqltypes import LargeBinary +from ...sql.sqltypes import PickleType class _LiteralRoundTripFixture: @@ -193,6 +195,42 @@ class UnicodeTextTest(_UnicodeFixture, fixtures.TablesTest): self._test_null_strings(connection) +class BinaryTest(_LiteralRoundTripFixture, fixtures.TablesTest): + __requires__ = ("binary_literals",) + __backend__ = True + + @classmethod + def define_tables(cls, metadata): + Table( + "binary_table", + metadata, + Column( + "id", Integer, primary_key=True, test_needs_autoincrement=True + ), + Column("binary_data", LargeBinary), + Column("pickle_data", PickleType), + ) + + def test_binary_roundtrip(self, connection): + binary_table = self.tables.binary_table + + connection.execute( + binary_table.insert(), {"id": 1, "binary_data": b"this is binary"} + ) + row = connection.execute(select(binary_table.c.binary_data)).first() + eq_(row, (b"this is binary",)) + + def test_pickle_roundtrip(self, connection): + binary_table = self.tables.binary_table + + connection.execute( + binary_table.insert(), + {"id": 1, "pickle_data": {"foo": [1, 2, 3], "bar": "bat"}}, + ) + row = connection.execute(select(binary_table.c.pickle_data)).first() + eq_(row, ({"foo": [1, 2, 3], "bar": "bat"},)) + + class TextTest(_LiteralRoundTripFixture, fixtures.TablesTest): __requires__ = ("text_type",) __backend__ = True @@ -1535,6 +1573,7 @@ class JSONLegacyStringCastIndexTest( __all__ = ( + "BinaryTest", "UnicodeVarcharTest", "UnicodeTextTest", "JSONTest", diff --git a/test/requirements.py b/test/requirements.py index b42bab7d35..cfd11f3ba4 100644 --- a/test/requirements.py +++ b/test/requirements.py @@ -1054,7 +1054,19 @@ class DefaultRequirements(SuiteRequirements): a plain string. """ - return exclusions.fails_on(["mysql", "mariadb"]) + + # mariadbconnector works. pyodbc we dont know, not supported in + # testing. + return exclusions.fails_on( + [ + "+mysqldb", + "+pymysql", + "+asyncmy", + "+mysqlconnector", + "+cymysql", + "+aiomysql", + ] + ) @property def datetime_timezone(self): diff --git a/tox.ini b/tox.ini index def2108260..fad0c50758 100644 --- a/tox.ini +++ b/tox.ini @@ -102,7 +102,7 @@ setenv= py2{,7}-mysql: MYSQL={env:TOX_MYSQL_PY2K:{env:TOX_MYSQL:--db mysql}} mysql: EXTRA_MYSQL_DRIVERS={env:EXTRA_MYSQL_DRIVERS:--dbdriver mysqldb --dbdriver pymysql} - py3-mysql: EXTRA_MYSQL_DRIVERS={env:EXTRA_MYSQL_DRIVERS:--dbdriver mysqldb --dbdriver pymysql --dbdriver mariadbconnector --dbdriver asyncmy} + py3{,7,8,9,10,11}-mysql: EXTRA_MYSQL_DRIVERS={env:EXTRA_MYSQL_DRIVERS:--dbdriver mysqldb --dbdriver pymysql --dbdriver mariadbconnector --dbdriver asyncmy} mssql: MSSQL={env:TOX_MSSQL:--db mssql}