From: Mike Bayer Date: Tue, 17 Oct 2023 22:54:23 +0000 (-0400) Subject: revise argument to mysqlclient/pymysql ping X-Git-Tag: rel_2_0_23~22^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0790c612b3d13761b04b55a5fdd7f6affd852320;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git revise argument to mysqlclient/pymysql ping Repaired a new incompatibility in the MySQL "pre-ping" routine where the ``False`` argument passed to ``connection.ping()``, which is intended to disable an unwanted "automatic reconnect" feature, is being deprecated in MySQL drivers and backends, and is producing warnings for some versions of MySQL's native client drivers. It's removed for mysqlclient, whereas for PyMySQL and drivers based on PyMySQL, the parameter will be deprecated and removed at some point, so API introspection is used to future proof against these various stages of removal. Fixes: #10492 Change-Id: I8a52428c6f93a03b66a605cb0b85cc5924803d6d references: #10489 --- diff --git a/doc/build/changelog/unreleased_14/10492.rst b/doc/build/changelog/unreleased_14/10492.rst new file mode 100644 index 0000000000..8ddf5738b6 --- /dev/null +++ b/doc/build/changelog/unreleased_14/10492.rst @@ -0,0 +1,13 @@ +.. change:: + :tags: bug, mysql + :tickets: 10492 + :versions: 2.0.23 + + Repaired a new incompatibility in the MySQL "pre-ping" routine where the + ``False`` argument passed to ``connection.ping()``, which is intended to + disable an unwanted "automatic reconnect" feature, is being deprecated in + MySQL drivers and backends, and is producing warnings for some versions of + MySQL's native client drivers. It's removed for mysqlclient, whereas for + PyMySQL and drivers based on PyMySQL, the parameter will be deprecated and + removed at some point, so API introspection is used to future proof against + these various stages of removal. diff --git a/lib/sqlalchemy/dialects/mysql/mysqldb.py b/lib/sqlalchemy/dialects/mysql/mysqldb.py index 0868401d43..d1cf835c54 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqldb.py +++ b/lib/sqlalchemy/dialects/mysql/mysqldb.py @@ -168,7 +168,7 @@ class MySQLDialect_mysqldb(MySQLDialect): return on_connect def do_ping(self, dbapi_connection): - dbapi_connection.ping(False) + dbapi_connection.ping() return True def do_executemany(self, cursor, statement, parameters, context=None): diff --git a/lib/sqlalchemy/dialects/mysql/pymysql.py b/lib/sqlalchemy/dialects/mysql/pymysql.py index 67ccb17fd8..6567202a45 100644 --- a/lib/sqlalchemy/dialects/mysql/pymysql.py +++ b/lib/sqlalchemy/dialects/mysql/pymysql.py @@ -74,6 +74,40 @@ class MySQLDialect_pymysql(MySQLDialect_mysqldb): def import_dbapi(cls): return __import__("pymysql") + @langhelpers.memoized_property + def _send_false_to_ping(self): + """determine if pymysql has deprecated, changed the default of, + or removed the 'reconnect' argument of connection.ping(). + + See #10492 and + https://github.com/PyMySQL/mysqlclient/discussions/651#discussioncomment-7308971 + for background. + + """ # noqa: E501 + + try: + Connection = __import__("pymysql.connections").Connection + except (ImportError, AttributeError): + return True + else: + insp = langhelpers.get_callable_argspec(Connection.ping) + try: + reconnect_arg = insp.args[1] + except IndexError: + return False + else: + return reconnect_arg == "reconnect" and ( + not insp.defaults or insp.defaults[0] is not False + ) + + def do_ping(self, dbapi_connection): + if self._send_false_to_ping: + dbapi_connection.ping(False) + else: + dbapi_connection.ping() + + return True + def create_connect_args(self, url, _translate_args=None): if _translate_args is None: _translate_args = dict(username="user")