from sqlalchemy import create_engine
def main():
uri = "mysql+mysqlconnector://uname:password@mysqlserver/realdb2?connect_timeout=5" # correct credentials to test
e = create_engine(uri)
##
## will produce a
## (mysql.connector.errors.OperationalError) an integer is required (got type str)
## from the
## site-packages/mysql/connector/network.py:471 mysql-connector 2.1.3
##
## while attempting to execute self.sock.settimeout(self._connection_timeout)
## where self._connection_timeout is set to '5' (the str '5' not the integer 5)
## tracing back usages and parsing of the supplied uri
##
## MySQLDialect_mysqlconnector::create_connect_args in site-packages/sqlalchemy/dialects/mysql/mysqlconnector.py:115
##
## and the lines:
## util.coerce_kw_type(opts, 'buffered', bool)
## util.coerce_kw_type(opts, 'raise_on_warnings', bool)
##
## Where it is parsing SOME of the options for mysql but not all of them and leaving
## connect_timeout as a string
##
e.execute("select sleep(10);") # error will occur here
print("done")
if __name__ == '__main__':
main()
Of course the workaround is to simply use:
create_engine(uri, connect_args={ 'connect_timeout': 5))
But if you're going to parse some of the documented options for the connector why not them all?
Also this was uncovered in a system where changing the configuration of the system and supplying options via the url was trivial but modifying the code base was exceedingly painful.
Adding the line
util.coerce_kw_type(opts, 'connect_timeout', int)
to site-packages/sqlalchemy/dialects/mysql/mysqlconnector.py
appears to correct the issue for the 'connect_timeout' args
I would note that we do parse "all" options, as of the last time this part of the dialect was worked on many years ago. Unfortunately, there is no mechanism for us to be alerted of new changes at https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html except for user reporting.