diff --git a/CHANGES.rst b/CHANGES.rst index c1927447..8563e935 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,7 @@ everything less than 3.7. - Add the "Requires Python" metadata to prevent installation on Python < 3.7. +- The minimum supported version of MySQL is 5.3.3. 3.5.0 (2022-09-16) diff --git a/appveyor.yml b/appveyor.yml index 18969dd5..e4303644 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,12 +41,11 @@ environment: # Fully supported 64-bit versions, with testing. This should be # all the current (non EOL) versions. - # Need gevent for testing. - # - PYTHON: "C:\\Python312-x64" - # PYTHON_VERSION: "3.12.0b3" - # PYTHON_ARCH: "64" - # PYTHON_EXE: python - # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - PYTHON: "C:\\Python312-x64" + PYTHON_VERSION: "3.12.0b3" + PYTHON_ARCH: "64" + PYTHON_EXE: python + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 - PYTHON: "C:\\Python311-x64" PYTHON_VERSION: "3.11.0" diff --git a/scripts/releases/make-manylinux b/scripts/releases/make-manylinux index 3eda9b07..76b9a137 100755 --- a/scripts/releases/make-manylinux +++ b/scripts/releases/make-manylinux @@ -93,7 +93,7 @@ if [ -d /RelStorage -a -d /opt/python ]; then rm -rf wheelhouse mkdir wheelhouse - for variant in `ls -d /opt/python/cp{37,38,39,310,311}*`; do + for variant in `ls -d /opt/python/cp{37,38,39,310,311,312}*`; do echo "Building $variant" mkdir /tmp/build cd /tmp/build diff --git a/setup.py b/setup.py index be08f92e..4be335c7 100644 --- a/setup.py +++ b/setup.py @@ -71,7 +71,8 @@ def read_file(*path): 'zc.zlibstorage', 'zope.testrunner', 'nti.testing', - 'gevent >= 1.5a1', + # At this writing, gevent isn't supported on 3.12 yet. + 'gevent >= 1.5a1; python_version < "3.12"', 'pyperf', # Versions of PyPy2 prior to 7.4 (maybe?) are incompatible with # psutil >= 5.6.4. @@ -210,7 +211,7 @@ def read_file(*path): # pylint:disable=line-too-long 'mysql:platform_python_implementation=="CPython" and (sys_platform != "win32")': [ - 'mysqlclient >= 1.4, != 2.0.0', + 'mysqlclient >= 2.0.0', ], 'mysql:platform_python_implementation=="PyPy" or (sys_platform == "win32")': [ 'PyMySQL>=0.6.6', @@ -261,28 +262,22 @@ def read_file(*path): # up too heavy for better parallelism. # First, mysql - # pymysql on 3.6 on all platforms. We get coverage data from Travis, - # and we get 2.7 from PyPy and Windows. - 'PyMySQL >= 0.6.6; python_version == "3.7" or platform_python_implementation == "PyPy" or sys_platform == "win32"', - # mysqlclient (binary) on all CPythons. It's the default, - # except on old Windows. We get coverage from Travis. - 'mysqlclient >= 1.4,!=2.0.0;platform_python_implementation=="CPython" and (sys_platform != "win32")', - # mysql-connector-python on Python 3.7 for coverage on Travis and ensuring it works - # on Windows, and PyPy for testing there, since it's one of two pure-python versions. - #'mysql-connector-python >= 8.0.16; python_version == "3.7"', - # 8.0.24 (!) quietly dropped support for Python 2, but they didn't set the - # PyPI metadata right at least up through 8.0.26, so we get an incompatible version - # without this pin. - #'mysql-connector-python >= 8.0.16, < 8.0.24; platform_python_implementation == "PyPy"', + # pymysql on 3.6 on all platforms. + 'PyMySQL >= 0.6.6', + # mysqlclient (binary) on all CPythons. It's the default. + 'mysqlclient >= 2.0.0', + # mysql-connector-python; one of two pure-python versions + # XXX: >= 8.0.32 has issues with binary values! + 'mysql-connector-python == 8.0.31; python_version == "3.11"', + # postgresql # pure-python - # pg8000 on Python 2.7 or PyPy. We get coverage from Travis, and we also - # get Windows. - 'pg8000 >= 1.11.0 ; python_version == "2.7" or platform_python_implementation == "PyPy"', + # pg8000 + 'pg8000 >= 1.11.0', # CFFI, runs on all implementations. # We get coverage from 3.x on Travis and verification it works on Windows from Travis. # We get 2.7 testing from PyPy on Travis. - 'psycopg2cffi >= 2.7.4; python_version == "3.6" or platform_python_implementation == "PyPy"', + 'psycopg2cffi >= 2.7.4; python_version == "3.11" or platform_python_implementation == "PyPy"', # Psycopg2 on all CPython, it's the default 'psycopg2 >= 2.8.3; platform_python_implementation == "CPython"', ], diff --git a/src/relstorage/adapters/batch.py b/src/relstorage/adapters/batch.py index ea992eff..c66231fc 100644 --- a/src/relstorage/adapters/batch.py +++ b/src/relstorage/adapters/batch.py @@ -360,6 +360,6 @@ def _do_inserts(self): # INSERT INTO table(c1, c2) # VALUES (%s, %s), (%s, %s), (%s, %s) # - __traceback_info__ = stmt + __traceback_info__ = stmt, params self.cursor.execute(stmt, params) return count diff --git a/src/relstorage/adapters/mysql/schema.py b/src/relstorage/adapters/mysql/schema.py index cd6d5a49..dd4703db 100644 --- a/src/relstorage/adapters/mysql/schema.py +++ b/src/relstorage/adapters/mysql/schema.py @@ -91,7 +91,7 @@ class MySQLSchemaInstaller(AbstractSchemaInstaller): def __init__(self, driver=None, version_detector=None, **kwargs): self.driver = driver self.version_detector = version_detector or MySQLVersionDetector() - super(MySQLSchemaInstaller, self).__init__(**kwargs) + super().__init__(**kwargs) def get_database_name(self, cursor): cursor.execute("SELECT DATABASE()") @@ -141,7 +141,7 @@ def list_views(self, cursor): return [self._metadata_to_native_str(r[0]) for r in cursor] def check_compatibility(self, cursor, tables): - super(MySQLSchemaInstaller, self).check_compatibility(cursor, tables) + super().check_compatibility(cursor, tables) tables_that_are_not_innodb = self.__list_tables_not_innodb(cursor) if tables_that_are_not_innodb: raise StorageError( @@ -198,11 +198,11 @@ def __convert_all_tables_to_innodb(self, cursor): def _prepare_with_connection(self, conn, cursor): from .oidallocator import MySQLOIDAllocator self.__convert_all_tables_to_innodb(cursor) - super(MySQLSchemaInstaller, self)._prepare_with_connection(conn, cursor) + super()._prepare_with_connection(conn, cursor) MySQLOIDAllocator(self.driver).garbage_collect_oids(cursor) def _read_proc_files(self): - name_to_source = super(MySQLSchemaInstaller, self)._read_proc_files() + name_to_source = super()._read_proc_files() for proc_name, source in name_to_source.items(): # No leading or trailing lines allowed, only the procedure @@ -212,7 +212,7 @@ def _read_proc_files(self): assert proc_name in source return name_to_source - def create_procedures(self, cursor): + def create_procedures(self, cursor): # pylint:disable=too-many-locals # Apparently procedures remember the ``character_set_client`` and ``collation_connection`` # that was in use at the time they were defined, and use that # to perform implicit conversions on arguments and even internally. If we have @@ -240,8 +240,22 @@ def create_procedures(self, cursor): set_lock_timeout = 'SET innodb_lock_wait_timeout = 1;' for_share = 'LOCK IN SHARE MODE' - cursor.execute('SET SESSION character_set_client = utf8, ' - 'collation_connection = utf8_general_ci') + # MySQL added the utf8mb4 charset in version 5.5.3. utf8mb4 + # fully implements the current standard. Now utf8 is an alias + # for utf8mb3 and will be switched to utf8mb4. + # collation names: charset-algo-case + # algo: bin (binary); general (simplified, speedy); unicode (full) + # case: ci (insensitive); cs (sensitive) + # + # XXX: MySqlConnectorPython is complaining about encoding in >= 8.0.32: + # mysql.connector.errors.Warning: ( + # 1300, + # bytearray(b"Invalid utf8mb4 character string: \'800363\'")) + # + # On ``INSERT INTO object_state...`` where the values are all parameterized + # and are all bytstrings + cursor.execute('SET SESSION character_set_client = utf8mb4, ' + 'collation_connection = utf8mb4_general_ci') for name, create_stmt in self.procedures.items(): __traceback_info__ = name @@ -289,7 +303,7 @@ def _after_zap_all_tables(self, cursor, slow=False): self.create_tables(cursor) logger.debug("Done creating tables after drop") else: - super(MySQLSchemaInstaller, self)._after_zap_all_tables(cursor, slow) + super()._after_zap_all_tables(cursor, slow) class MySQLVersionDetector(DatabaseHelpersMixin): diff --git a/version.txt b/version.txt index a0247846..62e24b9a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.5.1.dev0 +4.0.0.dev0