Kaydet (Commit) af87f9f0 authored tarafından Florent Xicluna's avatar Florent Xicluna

Issue #1285086: Speed up urllib.quote and urllib.unquote for simple cases.

üst 4fc2a008
...@@ -92,7 +92,7 @@ def urlretrieve(url, filename=None, reporthook=None, data=None): ...@@ -92,7 +92,7 @@ def urlretrieve(url, filename=None, reporthook=None, data=None):
def urlcleanup(): def urlcleanup():
if _urlopener: if _urlopener:
_urlopener.cleanup() _urlopener.cleanup()
_safemaps.clear() _safe_quoters.clear()
ftpcache.clear() ftpcache.clear()
# check for SSL # check for SSL
...@@ -1163,15 +1163,18 @@ _hextochr = dict((a + b, chr(int(a + b, 16))) ...@@ -1163,15 +1163,18 @@ _hextochr = dict((a + b, chr(int(a + b, 16)))
def unquote(s): def unquote(s):
"""unquote('abc%20def') -> 'abc def'.""" """unquote('abc%20def') -> 'abc def'."""
res = s.split('%') res = s.split('%')
for i in xrange(1, len(res)): # fastpath
item = res[i] if len(res) == 1:
return s
s = res[0]
for item in res[1:]:
try: try:
res[i] = _hextochr[item[:2]] + item[2:] s += _hextochr[item[:2]] + item[2:]
except KeyError: except KeyError:
res[i] = '%' + item s += '%' + item
except UnicodeDecodeError: except UnicodeDecodeError:
res[i] = unichr(int(item[:2], 16)) + item[2:] s += unichr(int(item[:2], 16)) + item[2:]
return "".join(res) return s
def unquote_plus(s): def unquote_plus(s):
"""unquote('%7e/abc+def') -> '~/abc def'""" """unquote('%7e/abc+def') -> '~/abc def'"""
...@@ -1181,7 +1184,10 @@ def unquote_plus(s): ...@@ -1181,7 +1184,10 @@ def unquote_plus(s):
always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'
'abcdefghijklmnopqrstuvwxyz' 'abcdefghijklmnopqrstuvwxyz'
'0123456789' '_.-') '0123456789' '_.-')
_safemaps = {} _safe_map = {}
for i, c in zip(xrange(256), str(bytearray(xrange(256)))):
_safe_map[c] = c if (i < 128 and c in always_safe) else '%{:02X}'.format(i)
_safe_quoters = {}
def quote(s, safe='/'): def quote(s, safe='/'):
"""quote('abc def') -> 'abc%20def' """quote('abc def') -> 'abc%20def'
...@@ -1204,18 +1210,21 @@ def quote(s, safe='/'): ...@@ -1204,18 +1210,21 @@ def quote(s, safe='/'):
called on a path where the existing slash characters are used as called on a path where the existing slash characters are used as
reserved characters. reserved characters.
""" """
# fastpath
if not s:
return s
cachekey = (safe, always_safe) cachekey = (safe, always_safe)
try: try:
safe_map = _safemaps[cachekey] (quoter, safe) = _safe_quoters[cachekey]
except KeyError: except KeyError:
safe += always_safe safe_map = _safe_map.copy()
safe_map = {} safe_map.update([(c, c) for c in safe])
for i in range(256): quoter = safe_map.__getitem__
c = chr(i) safe = always_safe + safe
safe_map[c] = (c in safe) and c or ('%%%02X' % i) _safe_quoters[cachekey] = (quoter, safe)
_safemaps[cachekey] = safe_map if not s.rstrip(safe):
res = map(safe_map.__getitem__, s) return s
return ''.join(res) return ''.join(map(quoter, s))
def quote_plus(s, safe=''): def quote_plus(s, safe=''):
"""Quote the query fragment of a URL; replacing ' ' with '+'""" """Quote the query fragment of a URL; replacing ' ' with '+'"""
......
...@@ -15,6 +15,8 @@ Core and Builtins ...@@ -15,6 +15,8 @@ Core and Builtins
Library Library
------- -------
- Issue #1285086: Speed up urllib.quote and urllib.unquote for simple cases.
- Issue #8688: Distutils now recalculates MANIFEST everytime. - Issue #8688: Distutils now recalculates MANIFEST everytime.
- Issue #5099: subprocess.Popen's __del__ method (and the methods it calls) - Issue #5099: subprocess.Popen's __del__ method (and the methods it calls)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment