From: Mike Bayer Date: Tue, 17 Oct 2023 22:54:23 +0000 (-0400) Subject: revise argument to mysqlclient/pymysql ping X-Git-Tag: rel_1_4_50~2^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e15323ccf6de6b3820c02c8c947b876ab399aa14;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 (cherry picked from commit 0790c612b3d13761b04b55a5fdd7f6affd852320) --- 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 7eef518549..ad44286238 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqldb.py +++ b/lib/sqlalchemy/dialects/mysql/mysqldb.py @@ -165,9 +165,12 @@ class MySQLDialect_mysqldb(MySQLDialect): return on_connect + def _ping_impl(self, dbapi_connection): + return dbapi_connection.ping() + def do_ping(self, dbapi_connection): try: - dbapi_connection.ping(False) + self._ping_impl(dbapi_connection) except self.dbapi.Error as err: if self.is_disconnect(err, dbapi_connection, None): return False diff --git a/lib/sqlalchemy/dialects/mysql/pymysql.py b/lib/sqlalchemy/dialects/mysql/pymysql.py index 3a776f8775..26a03fa4c9 100644 --- a/lib/sqlalchemy/dialects/mysql/pymysql.py +++ b/lib/sqlalchemy/dialects/mysql/pymysql.py @@ -79,6 +79,40 @@ class MySQLDialect_pymysql(MySQLDialect_mysqldb): def 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 _ping_impl(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")