|  | @@ -2498,8 +2498,7 @@ try:
 | 
	
		
			
				|  |  |      from urllib.parse import urlencode as compat_urllib_parse_urlencode
 | 
	
		
			
				|  |  |      from urllib.parse import parse_qs as compat_parse_qs
 | 
	
		
			
				|  |  |  except ImportError:  # Python 2
 | 
	
		
			
				|  |  | -    _asciire = (compat_urllib_parse._asciire if hasattr(compat_urllib_parse, '_asciire')
 | 
	
		
			
				|  |  | -                else re.compile(r'([\x00-\x7f]+)'))
 | 
	
		
			
				|  |  | +    _asciire = getattr(compat_urllib_parse, '_asciire', None) or re.compile(r'([\x00-\x7f]+)')
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      # 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
 | 
	
	
		
			
				|  | @@ -2567,24 +2566,21 @@ except ImportError:  # Python 2
 | 
	
		
			
				|  |  |      # Possible solutions are to either port it from python 3 with all
 | 
	
		
			
				|  |  |      # the friends or manually ensure input query contains only byte strings.
 | 
	
		
			
				|  |  |      # 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):
 | 
	
		
			
				|  |  |              if isinstance(e, dict):
 | 
	
		
			
				|  |  |                  e = encode_dict(e)
 | 
	
		
			
				|  |  |              elif isinstance(e, (list, tuple,)):
 | 
	
		
			
				|  |  | -                list_e = encode_list(e)
 | 
	
		
			
				|  |  | -                e = tuple(list_e) if isinstance(e, tuple) else list_e
 | 
	
		
			
				|  |  | +                e = type(e)(encode_elem(el) for el in e)
 | 
	
		
			
				|  |  |              elif isinstance(e, compat_str):
 | 
	
		
			
				|  |  | -                e = e.encode(encoding)
 | 
	
		
			
				|  |  | +                e = e.encode(encoding, errors)
 | 
	
		
			
				|  |  |              return e
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          def encode_dict(d):
 | 
	
		
			
				|  |  | -            return dict((encode_elem(k), encode_elem(v)) for k, v in d.items())
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        def encode_list(l):
 | 
	
		
			
				|  |  | -            return [encode_elem(e) for e in l]
 | 
	
		
			
				|  |  | +            return tuple((encode_elem(k), encode_elem(v)) for k, v in d.items())
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        return compat_urllib_parse._urlencode(encode_elem(query), doseq=doseq)
 | 
	
		
			
				|  |  | +        return compat_urllib_parse._urlencode(encode_elem(query), doseq=doseq).decode('ascii')
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      # HACK: The following is the correct parse_qs implementation from cpython 3's stdlib.
 | 
	
		
			
				|  |  |      # Python 2's version is apparently totally broken
 | 
	
	
		
			
				|  | @@ -2639,6 +2635,57 @@ except ImportError:  # Python 2
 | 
	
		
			
				|  |  |              ('parse_qs', compat_parse_qs)):
 | 
	
		
			
				|  |  |          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
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 |