escaping bytes is faster on Python 3
This commit is contained in:
@@ -4,17 +4,12 @@ import sys
|
|||||||
import binascii
|
import binascii
|
||||||
import datetime
|
import datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
import re
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from .constants import FIELD_TYPE, FLAG
|
from .constants import FIELD_TYPE, FLAG
|
||||||
from .charset import charset_by_id, charset_to_encoding
|
from .charset import charset_by_id, charset_to_encoding
|
||||||
|
|
||||||
|
|
||||||
ESCAPE_REGEX = re.compile(r"[\0\n\r\032\'\"\\]")
|
|
||||||
ESCAPE_MAP = {'\0': '\\0', '\n': '\\n', '\r': '\\r', '\032': '\\Z',
|
|
||||||
'\'': '\\\'', '"': '\\"', '\\': '\\\\'}
|
|
||||||
|
|
||||||
def escape_item(val, charset, mapping=None):
|
def escape_item(val, charset, mapping=None):
|
||||||
if mapping is None:
|
if mapping is None:
|
||||||
mapping = encoders
|
mapping = encoders
|
||||||
@@ -48,8 +43,7 @@ def escape_sequence(val, charset, mapping=None):
|
|||||||
return "(" + ",".join(n) + ")"
|
return "(" + ",".join(n) + ")"
|
||||||
|
|
||||||
def escape_set(val, charset, mapping=None):
|
def escape_set(val, charset, mapping=None):
|
||||||
val = map(lambda x: escape_item(x, charset, mapping), val)
|
return ','.join([escape_item(x, charset, mapping) for x in val])
|
||||||
return ','.join(val)
|
|
||||||
|
|
||||||
def escape_bool(value, mapping=None):
|
def escape_bool(value, mapping=None):
|
||||||
return str(int(value))
|
return str(int(value))
|
||||||
@@ -63,9 +57,46 @@ def escape_int(value, mapping=None):
|
|||||||
def escape_float(value, mapping=None):
|
def escape_float(value, mapping=None):
|
||||||
return ('%.15g' % value)
|
return ('%.15g' % value)
|
||||||
|
|
||||||
def escape_string(value, mapping=None):
|
if PY2:
|
||||||
return ("%s" % (ESCAPE_REGEX.sub(
|
def escape_string(value, mapping=None):
|
||||||
lambda match: ESCAPE_MAP.get(match.group(0)), value),))
|
"""escape_string escapes *value* but not surround it with quotes.
|
||||||
|
|
||||||
|
Value should be bytes or unicode.
|
||||||
|
"""
|
||||||
|
value = value.replace('\\', '\\\\')
|
||||||
|
value = value.replace('\0', '\\0')
|
||||||
|
value = value.replace('\n', '\\n')
|
||||||
|
value = value.replace('\r', '\\r')
|
||||||
|
value = value.replace('\032', '\\Z')
|
||||||
|
value = value.replace("'", "\\'")
|
||||||
|
value = value.replace('"', '\\"')
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
_escape_table = [chr(x) for x in range(128)]
|
||||||
|
_escape_table[0] = '\\0'
|
||||||
|
_escape_table[ord('\\')] = '\\\\'
|
||||||
|
_escape_table[ord('\n')] = '\\n'
|
||||||
|
_escape_table[ord('\r')] = '\\r'
|
||||||
|
_escape_table[ord('\032')] = '\\Z'
|
||||||
|
_escape_table[ord('"')] = '\\"'
|
||||||
|
_escape_table[ord("'")] = "\\'"
|
||||||
|
|
||||||
|
def escape_string(value, mapping=None):
|
||||||
|
"""escape_string escapes *value* but not surround it with quotes.
|
||||||
|
|
||||||
|
Value should be str (unicode).
|
||||||
|
"""
|
||||||
|
return value.translate(_escape_table)
|
||||||
|
|
||||||
|
# On Python ~3.5, str.decode('ascii', 'surrogateescape') is slow.
|
||||||
|
# (fixed in Python 3.6, http://bugs.python.org/issue24870)
|
||||||
|
# Workaround is str.decode('latin1') then translate 0x80-0xff into 0udc80-0udcff.
|
||||||
|
# We can escape special chars and surrogateescape at once.
|
||||||
|
_escape_bytes_table = _escape_table + [chr(i) for i in range(0xdc80, 0xdd00)]
|
||||||
|
|
||||||
|
def escape_bytes(value, mapping=None):
|
||||||
|
return "'%s'" % value.decode('latin1').translate(_escape_bytes_table)
|
||||||
|
|
||||||
|
|
||||||
def escape_str(value, mapping=None):
|
def escape_str(value, mapping=None):
|
||||||
return "'%s'" % escape_string(value, mapping)
|
return "'%s'" % escape_string(value, mapping)
|
||||||
@@ -73,10 +104,6 @@ def escape_str(value, mapping=None):
|
|||||||
def escape_unicode(value, mapping=None):
|
def escape_unicode(value, mapping=None):
|
||||||
return escape_str(value, mapping)
|
return escape_str(value, mapping)
|
||||||
|
|
||||||
def escape_bytes(value, mapping=None):
|
|
||||||
# escape_bytes is calld only on Python 3.
|
|
||||||
return escape_str(value.decode('ascii', 'surrogateescape'), mapping)
|
|
||||||
|
|
||||||
def escape_None(value, mapping=None):
|
def escape_None(value, mapping=None):
|
||||||
return 'NULL'
|
return 'NULL'
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class Cursor(object):
|
|||||||
# If it's not a dictionary let's try escaping it anyways.
|
# If it's not a dictionary let's try escaping it anyways.
|
||||||
# Worst case it will throw a Value error
|
# Worst case it will throw a Value error
|
||||||
if PY2:
|
if PY2:
|
||||||
ensure_bytes(args)
|
args = ensure_bytes(args)
|
||||||
return conn.escape(args)
|
return conn.escape(args)
|
||||||
|
|
||||||
def mogrify(self, query, args=None):
|
def mogrify(self, query, args=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user