mirror of
https://github.com/ytdl-org/youtube-dl.git
synced 2025-04-17 08:04:27 +00:00
[compat] Improve Py2 compatibility for URL Quoting
This commit is contained in:
parent
cedeeed56f
commit
7e136639db
@ -2498,8 +2498,7 @@ try:
|
|||||||
from urllib.parse import urlencode as compat_urllib_parse_urlencode
|
from urllib.parse import urlencode as compat_urllib_parse_urlencode
|
||||||
from urllib.parse import parse_qs as compat_parse_qs
|
from urllib.parse import parse_qs as compat_parse_qs
|
||||||
except ImportError: # Python 2
|
except ImportError: # Python 2
|
||||||
_asciire = (compat_urllib_parse._asciire if hasattr(compat_urllib_parse, '_asciire')
|
_asciire = getattr(compat_urllib_parse, '_asciire', None) or re.compile(r'([\x00-\x7f]+)')
|
||||||
else re.compile(r'([\x00-\x7f]+)'))
|
|
||||||
|
|
||||||
# HACK: The following are the correct unquote_to_bytes, unquote and unquote_plus
|
# HACK: The following are the correct unquote_to_bytes, unquote and unquote_plus
|
||||||
# implementations from cpython 3.4.3's stdlib. Python 2's version
|
# implementations from cpython 3.4.3's stdlib. Python 2's version
|
||||||
@ -2567,24 +2566,21 @@ except ImportError: # Python 2
|
|||||||
# Possible solutions are to either port it from python 3 with all
|
# Possible solutions are to either port it from python 3 with all
|
||||||
# the friends or manually ensure input query contains only byte strings.
|
# the friends or manually ensure input query contains only byte strings.
|
||||||
# We will stick with latter thus recursively encoding the whole query.
|
# We will stick with latter thus recursively encoding the whole query.
|
||||||
def compat_urllib_parse_urlencode(query, doseq=0, encoding='utf-8'):
|
def compat_urllib_parse_urlencode(query, doseq=0, safe='', encoding='utf-8', errors='strict'):
|
||||||
|
|
||||||
def encode_elem(e):
|
def encode_elem(e):
|
||||||
if isinstance(e, dict):
|
if isinstance(e, dict):
|
||||||
e = encode_dict(e)
|
e = encode_dict(e)
|
||||||
elif isinstance(e, (list, tuple,)):
|
elif isinstance(e, (list, tuple,)):
|
||||||
list_e = encode_list(e)
|
e = type(e)(encode_elem(el) for el in e)
|
||||||
e = tuple(list_e) if isinstance(e, tuple) else list_e
|
|
||||||
elif isinstance(e, compat_str):
|
elif isinstance(e, compat_str):
|
||||||
e = e.encode(encoding)
|
e = e.encode(encoding, errors)
|
||||||
return e
|
return e
|
||||||
|
|
||||||
def encode_dict(d):
|
def encode_dict(d):
|
||||||
return dict((encode_elem(k), encode_elem(v)) for k, v in d.items())
|
return tuple((encode_elem(k), encode_elem(v)) for k, v in d.items())
|
||||||
|
|
||||||
def encode_list(l):
|
return compat_urllib_parse._urlencode(encode_elem(query), doseq=doseq).decode('ascii')
|
||||||
return [encode_elem(e) for e in l]
|
|
||||||
|
|
||||||
return compat_urllib_parse._urlencode(encode_elem(query), doseq=doseq)
|
|
||||||
|
|
||||||
# HACK: The following is the correct parse_qs implementation from cpython 3's stdlib.
|
# HACK: The following is the correct parse_qs implementation from cpython 3's stdlib.
|
||||||
# Python 2's version is apparently totally broken
|
# Python 2's version is apparently totally broken
|
||||||
@ -2639,6 +2635,57 @@ except ImportError: # Python 2
|
|||||||
('parse_qs', compat_parse_qs)):
|
('parse_qs', compat_parse_qs)):
|
||||||
setattr(compat_urllib_parse, name, fix)
|
setattr(compat_urllib_parse, name, fix)
|
||||||
|
|
||||||
|
try:
|
||||||
|
all(chr(i) in b'' for i in range(256))
|
||||||
|
except TypeError:
|
||||||
|
# not all chr(i) are str: patch Python2 quote
|
||||||
|
|
||||||
|
_safemaps = getattr(compat_urllib_parse, '_safemaps', {})
|
||||||
|
_always_safe = frozenset(compat_urllib_parse.always_safe)
|
||||||
|
|
||||||
|
def _quote(s, safe='/'):
|
||||||
|
"""quote('abc def') -> 'abc%20def'"""
|
||||||
|
|
||||||
|
if not s and s is not None: # fast path
|
||||||
|
return s
|
||||||
|
safe = frozenset(safe)
|
||||||
|
cachekey = (safe, _always_safe)
|
||||||
|
try:
|
||||||
|
safe_map = _safemaps[cachekey]
|
||||||
|
except KeyError:
|
||||||
|
safe = _always_safe | safe
|
||||||
|
safe_map = {}
|
||||||
|
for i in range(256):
|
||||||
|
c = chr(i)
|
||||||
|
safe_map[c] = (
|
||||||
|
c if (i < 128 and c in safe)
|
||||||
|
else b'%{0:02X}'.format(i))
|
||||||
|
_safemaps[cachekey] = safe_map
|
||||||
|
|
||||||
|
if safe.issuperset(s):
|
||||||
|
return s
|
||||||
|
return ''.join(safe_map[c] for c in s)
|
||||||
|
|
||||||
|
# linked code
|
||||||
|
def _quote_plus(s, safe=''):
|
||||||
|
return (
|
||||||
|
_quote(s, safe + b' ').replace(b' ', b'+') if b' ' in s
|
||||||
|
else _quote(s, safe))
|
||||||
|
|
||||||
|
# linked code
|
||||||
|
def _urlcleanup():
|
||||||
|
if compat_urllib_parse._urlopener:
|
||||||
|
compat_urllib_parse._urlopener.cleanup()
|
||||||
|
_safemaps.clear()
|
||||||
|
compat_urllib_parse.ftpcache.clear()
|
||||||
|
|
||||||
|
for name, fix in (
|
||||||
|
('quote', _quote),
|
||||||
|
('quote_plus', _quote_plus),
|
||||||
|
('urlcleanup', _urlcleanup)):
|
||||||
|
setattr(compat_urllib_parse, '_' + name, getattr(compat_urllib_parse, name))
|
||||||
|
setattr(compat_urllib_parse, name, fix)
|
||||||
|
|
||||||
compat_urllib_parse_parse_qs = compat_parse_qs
|
compat_urllib_parse_parse_qs = compat_parse_qs
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user