Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 520573d

Browse filesBrowse files
committed
escaping bytes is faster on Python 3
1 parent dbb16ee commit 520573d
Copy full SHA for 520573d

File tree

Expand file treeCollapse file tree

2 files changed

+45
-13
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+45
-13
lines changed

‎pymysql/converters.py

Copy file name to clipboardExpand all lines: pymysql/converters.py
+44-12Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,12 @@
44
import binascii
55
import datetime
66
from decimal import Decimal
7-
import re
87
import time
98

109
from .constants import FIELD_TYPE, FLAG
1110
from .charset import charset_by_id, charset_to_encoding
1211

1312

14-
ESCAPE_REGEX = re.compile(r"[\0\n\r\032\'\"\\]")
15-
ESCAPE_MAP = {'\0': '\\0', '\n': '\\n', '\r': '\\r', '\032': '\\Z',
16-
'\'': '\\\'', '"': '\\"', '\\': '\\\\'}
17-
1813
def escape_item(val, charset, mapping=None):
1914
if mapping is None:
2015
mapping = encoders
@@ -48,8 +43,7 @@ def escape_sequence(val, charset, mapping=None):
4843
return "(" + ",".join(n) + ")"
4944

5045
def escape_set(val, charset, mapping=None):
51-
val = map(lambda x: escape_item(x, charset, mapping), val)
52-
return ','.join(val)
46+
return ','.join([escape_item(x, charset, mapping) for x in val])
5347

5448
def escape_bool(value, mapping=None):
5549
return str(int(value))
@@ -63,19 +57,57 @@ def escape_int(value, mapping=None):
6357
def escape_float(value, mapping=None):
6458
return ('%.15g' % value)
6559

66-
def escape_string(value, mapping=None):
67-
return ("%s" % (ESCAPE_REGEX.sub(
68-
lambda match: ESCAPE_MAP.get(match.group(0)), value),))
60+
61+
def escape_string_2(value, mapping=None):
62+
"""escape_string escapes *value* but not surround it with quotes.
63+
64+
Value should be bytes or unicode.
65+
"""
66+
value = value.replace('\\', '\\\\')
67+
value = value.replace('\0', '\\0')
68+
value = value.replace('\n', '\\n')
69+
value = value.replace('\r', '\\r')
70+
value = value.replace('\032', '\\Z')
71+
value = value.replace("'", "\\'")
72+
value = value.replace('"', '\\"')
73+
return value
74+
75+
76+
_escape_table = [chr(x) for x in range(128)]
77+
_escape_table[0] = '\\0'
78+
_escape_table[ord('\\')] = '\\\\'
79+
_escape_table[ord('\n')] = '\\n'
80+
_escape_table[ord('\r')] = '\\r'
81+
_escape_table[ord('\032')] = '\\Z'
82+
_escape_table[ord('"')] = '\\"'
83+
_escape_table[ord("'")] = "\\'"
84+
85+
def escape_string_3(value, mapping=None):
86+
"""escape_string escapes *value* but not surround it with quotes.
87+
88+
Value should be str (unicode).
89+
"""
90+
return value.translate(_escape_table)
91+
92+
escape_string = escape_string_2 if PY2 else escape_string_3
93+
6994

7095
def escape_str(value, mapping=None):
7196
return "'%s'" % escape_string(value, mapping)
7297

7398
def escape_unicode(value, mapping=None):
7499
return escape_str(value, mapping)
75100

101+
102+
# On Python ~3.5, str.decode('ascii', 'surrogateescape') is slow.
103+
# (fixed in Python 3.6, http://bugs.python.org/issue24870)
104+
# Workaround is str.decode('latin1') then translate 0x80-0xff into 0udc80-0udcff.
105+
# We can escape special chars and surrogateescape at once.
106+
_escape_bytes_table = _escape_table + [chr(i) for i in range(0xdc80, 0xdd00)]
107+
76108
def escape_bytes(value, mapping=None):
77-
# escape_bytes is calld only on Python 3.
78-
return escape_str(value.decode('ascii', 'surrogateescape'), mapping)
109+
return "'%s'" % value.decode('latin1').translate(_escape_bytes_table)
110+
79111

80112
def escape_None(value, mapping=None):
81113
return 'NULL'

‎pymysql/cursors.py

Copy file name to clipboardExpand all lines: pymysql/cursors.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def _escape_args(self, args, conn):
117117
# If it's not a dictionary let's try escaping it anyways.
118118
# Worst case it will throw a Value error
119119
if PY2:
120-
ensure_bytes(args)
120+
args = ensure_bytes(args)
121121
return conn.escape(args)
122122

123123
def mogrify(self, query, args=None):

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.