X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=youtube_dl%2Fcompat.py;h=db0da5828dd317eb5eef0b0945dec9300c7c1f75;hb=3cc8b4c327585ff4dbb045d17d6f5c160df6fdb8;hp=de9ba2c14e418ff2617d0af16f89b5c3476ed4d0;hpb=a0f28f90fa277d9c00f0305624dea36a20b8066e;p=youtube-dl.git diff --git a/youtube_dl/compat.py b/youtube_dl/compat.py index de9ba2c14..db0da5828 100644 --- a/youtube_dl/compat.py +++ b/youtube_dl/compat.py @@ -75,8 +75,16 @@ except ImportError: import BaseHTTPServer as compat_http_server try: + from urllib.parse import unquote_to_bytes as compat_urllib_parse_unquote_to_bytes from urllib.parse import unquote as compat_urllib_parse_unquote -except ImportError: + from urllib.parse import unquote_plus as compat_urllib_parse_unquote_plus +except ImportError: # Python 2 + _asciire = re.compile('([\x00-\x7f]+)') if sys.version_info < (2, 7) else compat_urllib_parse._asciire + + # 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 + # is apparently broken (see https://github.com/rg3/youtube-dl/pull/6244) + def compat_urllib_parse_unquote_to_bytes(string): """unquote_to_bytes('abc%20def') -> b'abc def'.""" # Note: strings are encoded as UTF-8. This is only an issue if it contains @@ -85,29 +93,22 @@ except ImportError: # Is it a string-like object? string.split return b'' - if isinstance(string, str): + if isinstance(string, unicode): string = string.encode('utf-8') - # string = encode('utf-8') - - # python3 -> 2: must implicitly convert to bits - bits = bytes(string).split(b'%') - + bits = string.split(b'%') if len(bits) == 1: return string res = [bits[0]] append = res.append - for item in bits[1:]: try: - append(item[:2].decode('hex')) + append(compat_urllib_parse._hextochr[item[:2]]) append(item[2:]) - except: + except KeyError: append(b'%') append(item) return b''.join(res) - compat_urllib_parse_asciire = re.compile('([\x00-\x7f]+)') - def compat_urllib_parse_unquote(string, encoding='utf-8', errors='replace'): """Replace %xx escapes by their single-character equivalent. The optional encoding and errors parameters specify how to decode percent-encoded @@ -118,7 +119,6 @@ except ImportError: unquote('abc%20def') -> 'abc def'. """ - if '%' not in string: string.split return string @@ -126,22 +126,23 @@ except ImportError: encoding = 'utf-8' if errors is None: errors = 'replace' - - bits = compat_urllib_parse_asciire.split(string) + bits = _asciire.split(string) res = [bits[0]] append = res.append for i in range(1, len(bits), 2): - foo = compat_urllib_parse_unquote_to_bytes(bits[i]) - foo = foo.decode(encoding, errors) - append(foo) - - if bits[i + 1]: - bar = bits[i + 1] - if not isinstance(bar, unicode): - bar = bar.decode('utf-8') - append(bar) + append(compat_urllib_parse_unquote_to_bytes(bits[i]).decode(encoding, errors)) + append(bits[i + 1]) return ''.join(res) + def compat_urllib_parse_unquote_plus(string, encoding='utf-8', errors='replace'): + """Like unquote(), but also replace plus signs by spaces, as required for + unquoting HTML form values. + + unquote_plus('%7e/abc+def') -> '~/abc def' + """ + string = string.replace('+', ' ') + return compat_urllib_parse_unquote(string, encoding, errors) + try: compat_str = unicode # Python 2 except NameError: @@ -452,6 +453,8 @@ __all__ = [ 'compat_urllib_error', 'compat_urllib_parse', 'compat_urllib_parse_unquote', + 'compat_urllib_parse_unquote_plus', + 'compat_urllib_parse_unquote_to_bytes', 'compat_urllib_parse_urlparse', 'compat_urllib_request', 'compat_urlparse',