pymysql.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. # mysql/pymysql.py
  2. # Copyright (C) 2005-2022 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: https://www.opensource.org/licenses/mit-license.php
  7. r"""
  8. .. dialect:: mysql+pymysql
  9. :name: PyMySQL
  10. :dbapi: pymysql
  11. :connectstring: mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
  12. :url: https://pymysql.readthedocs.io/
  13. Unicode
  14. -------
  15. Please see :ref:`mysql_unicode` for current recommendations on unicode
  16. handling.
  17. .. _pymysql_ssl:
  18. SSL Connections
  19. ------------------
  20. The PyMySQL DBAPI accepts the same SSL arguments as that of MySQLdb,
  21. described at :ref:`mysqldb_ssl`. See that section for examples.
  22. MySQL-Python Compatibility
  23. --------------------------
  24. The pymysql DBAPI is a pure Python port of the MySQL-python (MySQLdb) driver,
  25. and targets 100% compatibility. Most behavioral notes for MySQL-python apply
  26. to the pymysql driver as well.
  27. """ # noqa
  28. from .mysqldb import MySQLDialect_mysqldb
  29. from ...util import langhelpers
  30. from ...util import py3k
  31. class MySQLDialect_pymysql(MySQLDialect_mysqldb):
  32. driver = "pymysql"
  33. supports_statement_cache = True
  34. description_encoding = None
  35. # generally, these two values should be both True
  36. # or both False. PyMySQL unicode tests pass all the way back
  37. # to 0.4 either way. See [ticket:3337]
  38. supports_unicode_statements = True
  39. supports_unicode_binds = True
  40. @langhelpers.memoized_property
  41. def supports_server_side_cursors(self):
  42. try:
  43. cursors = __import__("pymysql.cursors").cursors
  44. self._sscursor = cursors.SSCursor
  45. return True
  46. except (ImportError, AttributeError):
  47. return False
  48. @classmethod
  49. def dbapi(cls):
  50. return __import__("pymysql")
  51. def create_connect_args(self, url, _translate_args=None):
  52. if _translate_args is None:
  53. _translate_args = dict(username="user")
  54. return super(MySQLDialect_pymysql, self).create_connect_args(
  55. url, _translate_args=_translate_args
  56. )
  57. def is_disconnect(self, e, connection, cursor):
  58. if super(MySQLDialect_pymysql, self).is_disconnect(
  59. e, connection, cursor
  60. ):
  61. return True
  62. elif isinstance(e, self.dbapi.Error):
  63. str_e = str(e).lower()
  64. return (
  65. "already closed" in str_e or "connection was killed" in str_e
  66. )
  67. else:
  68. return False
  69. if py3k:
  70. def _extract_error_code(self, exception):
  71. if isinstance(exception.args[0], Exception):
  72. exception = exception.args[0]
  73. return exception.args[0]
  74. dialect = MySQLDialect_pymysql