Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/dialects/mysql/pymysql.py: 40%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

55 statements  

1# dialects/mysql/pymysql.py 

2# Copyright (C) 2005-2024 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 

8r""" 

9 

10.. dialect:: mysql+pymysql 

11 :name: PyMySQL 

12 :dbapi: pymysql 

13 :connectstring: mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] 

14 :url: https://pymysql.readthedocs.io/ 

15 

16Unicode 

17------- 

18 

19Please see :ref:`mysql_unicode` for current recommendations on unicode 

20handling. 

21 

22.. _pymysql_ssl: 

23 

24SSL Connections 

25------------------ 

26 

27The PyMySQL DBAPI accepts the same SSL arguments as that of MySQLdb, 

28described at :ref:`mysqldb_ssl`. See that section for additional examples. 

29 

30If the server uses an automatically-generated certificate that is self-signed 

31or does not match the host name (as seen from the client), it may also be 

32necessary to indicate ``ssl_check_hostname=false`` in PyMySQL:: 

33 

34 connection_uri = ( 

35 "mysql+pymysql://scott:tiger@192.168.0.134/test" 

36 "?ssl_ca=/home/gord/client-ssl/ca.pem" 

37 "&ssl_cert=/home/gord/client-ssl/client-cert.pem" 

38 "&ssl_key=/home/gord/client-ssl/client-key.pem" 

39 "&ssl_check_hostname=false" 

40 ) 

41 

42 

43MySQL-Python Compatibility 

44-------------------------- 

45 

46The pymysql DBAPI is a pure Python port of the MySQL-python (MySQLdb) driver, 

47and targets 100% compatibility. Most behavioral notes for MySQL-python apply 

48to the pymysql driver as well. 

49 

50""" # noqa 

51 

52from .mysqldb import MySQLDialect_mysqldb 

53from ...util import langhelpers 

54from ...util import py3k 

55 

56 

57class MySQLDialect_pymysql(MySQLDialect_mysqldb): 

58 driver = "pymysql" 

59 supports_statement_cache = True 

60 

61 description_encoding = None 

62 

63 # generally, these two values should be both True 

64 # or both False. PyMySQL unicode tests pass all the way back 

65 # to 0.4 either way. See [ticket:3337] 

66 supports_unicode_statements = True 

67 supports_unicode_binds = True 

68 

69 @langhelpers.memoized_property 

70 def supports_server_side_cursors(self): 

71 try: 

72 cursors = __import__("pymysql.cursors").cursors 

73 self._sscursor = cursors.SSCursor 

74 return True 

75 except (ImportError, AttributeError): 

76 return False 

77 

78 @classmethod 

79 def dbapi(cls): 

80 return __import__("pymysql") 

81 

82 @langhelpers.memoized_property 

83 def _send_false_to_ping(self): 

84 """determine if pymysql has deprecated, changed the default of, 

85 or removed the 'reconnect' argument of connection.ping(). 

86 

87 See #10492 and 

88 https://github.com/PyMySQL/mysqlclient/discussions/651#discussioncomment-7308971 

89 for background. 

90 

91 """ # noqa: E501 

92 

93 try: 

94 Connection = __import__( 

95 "pymysql.connections" 

96 ).connections.Connection 

97 except (ImportError, AttributeError): 

98 return True 

99 else: 

100 insp = langhelpers.get_callable_argspec(Connection.ping) 

101 try: 

102 reconnect_arg = insp.args[1] 

103 except IndexError: 

104 return False 

105 else: 

106 return reconnect_arg == "reconnect" and ( 

107 not insp.defaults or insp.defaults[0] is not False 

108 ) 

109 

110 def _ping_impl(self, dbapi_connection): 

111 if self._send_false_to_ping: 

112 dbapi_connection.ping(False) 

113 else: 

114 dbapi_connection.ping() 

115 

116 return True 

117 

118 def create_connect_args(self, url, _translate_args=None): 

119 if _translate_args is None: 

120 _translate_args = dict(username="user") 

121 return super(MySQLDialect_pymysql, self).create_connect_args( 

122 url, _translate_args=_translate_args 

123 ) 

124 

125 def is_disconnect(self, e, connection, cursor): 

126 if super(MySQLDialect_pymysql, self).is_disconnect( 

127 e, connection, cursor 

128 ): 

129 return True 

130 elif isinstance(e, self.dbapi.Error): 

131 str_e = str(e).lower() 

132 return ( 

133 "already closed" in str_e or "connection was killed" in str_e 

134 ) 

135 else: 

136 return False 

137 

138 if py3k: 

139 

140 def _extract_error_code(self, exception): 

141 if isinstance(exception.args[0], Exception): 

142 exception = exception.args[0] 

143 return exception.args[0] 

144 

145 

146dialect = MySQLDialect_pymysql