1 from __future__ 
import unicode_literals
 
  11     import urllib
.request 
as compat_urllib_request
 
  12 except ImportError: # Python 2 
  13     import urllib2 
as compat_urllib_request
 
  16     import urllib
.error 
as compat_urllib_error
 
  17 except ImportError: # Python 2 
  18     import urllib2 
as compat_urllib_error
 
  21     import urllib
.parse 
as compat_urllib_parse
 
  22 except ImportError: # Python 2 
  23     import urllib 
as compat_urllib_parse
 
  26     from urllib
.parse 
import urlparse 
as compat_urllib_parse_urlparse
 
  27 except ImportError: # Python 2 
  28     from urlparse 
import urlparse 
as compat_urllib_parse_urlparse
 
  31     import urllib
.parse 
as compat_urlparse
 
  32 except ImportError: # Python 2 
  33     import urlparse 
as compat_urlparse
 
  36     import http
.cookiejar 
as compat_cookiejar
 
  37 except ImportError: # Python 2 
  38     import cookielib 
as compat_cookiejar
 
  41     import html
.entities 
as compat_html_entities
 
  42 except ImportError: # Python 2 
  43     import htmlentitydefs 
as compat_html_entities
 
  46     import html
.parser 
as compat_html_parser
 
  47 except ImportError: # Python 2 
  48     import HTMLParser 
as compat_html_parser
 
  51     import http
.client 
as compat_http_client
 
  52 except ImportError: # Python 2 
  53     import httplib 
as compat_http_client
 
  56     from urllib
.error 
import HTTPError 
as compat_HTTPError
 
  57 except ImportError:  # Python 2 
  58     from urllib2 
import HTTPError 
as compat_HTTPError
 
  61     from urllib
.request 
import urlretrieve 
as compat_urlretrieve
 
  62 except ImportError:  # Python 2 
  63     from urllib 
import urlretrieve 
as compat_urlretrieve
 
  67     from subprocess 
import DEVNULL
 
  68     compat_subprocess_get_DEVNULL 
= lambda: DEVNULL
 
  70     compat_subprocess_get_DEVNULL 
= lambda: open(os
.path
.devnull
, 'w') 
  73     from urllib
.parse 
import unquote 
as compat_urllib_parse_unquote
 
  75     def compat_urllib_parse_unquote(string
, encoding
='utf-8', errors
='replace'): 
  78         res 
= string
.split('%') 
  85         # pct_sequence: contiguous sequence of percent-encoded bytes, decoded 
  92                 pct_sequence 
+= item
[:2].decode('hex') 
  95                     # This segment was just a single percent-encoded character. 
  96                     # May be part of a sequence of code units, so delay decoding. 
  97                     # (Stored in pct_sequence). 
 101             # Encountered non-percent-encoded characters. Flush the current 
 103             string 
+= pct_sequence
.decode(encoding
, errors
) + rest
 
 106             # Flush the final pct_sequence 
 107             string 
+= pct_sequence
.decode(encoding
, errors
) 
 112     from urllib
.parse 
import parse_qs 
as compat_parse_qs
 
 113 except ImportError: # Python 2 
 114     # HACK: The following is the correct parse_qs implementation from cpython 3's stdlib. 
 115     # Python 2's version is apparently totally broken 
 117     def _parse_qsl(qs
, keep_blank_values
=False, strict_parsing
=False, 
 118                 encoding
='utf-8', errors
='replace'): 
 119         qs
, _coerce_result 
= qs
, unicode 
 120         pairs 
= [s2 
for s1 
in qs
.split('&') for s2 
in s1
.split(';')] 
 122         for name_value 
in pairs
: 
 123             if not name_value 
and not strict_parsing
: 
 125             nv 
= name_value
.split('=', 1) 
 128                     raise ValueError("bad query field: %r" % (name_value
,)) 
 129                 # Handle case of a control-name with no equal sign 
 130                 if keep_blank_values
: 
 134             if len(nv
[1]) or keep_blank_values
: 
 135                 name 
= nv
[0].replace('+', ' ') 
 136                 name 
= compat_urllib_parse_unquote( 
 137                     name
, encoding
=encoding
, errors
=errors
) 
 138                 name 
= _coerce_result(name
) 
 139                 value 
= nv
[1].replace('+', ' ') 
 140                 value 
= compat_urllib_parse_unquote( 
 141                     value
, encoding
=encoding
, errors
=errors
) 
 142                 value 
= _coerce_result(value
) 
 143                 r
.append((name
, value
)) 
 146     def compat_parse_qs(qs
, keep_blank_values
=False, strict_parsing
=False, 
 147                 encoding
='utf-8', errors
='replace'): 
 149         pairs 
= _parse_qsl(qs
, keep_blank_values
, strict_parsing
, 
 150                         encoding
=encoding
, errors
=errors
) 
 151         for name
, value 
in pairs
: 
 152             if name 
in parsed_result
: 
 153                 parsed_result
[name
].append(value
) 
 155                 parsed_result
[name
] = [value
] 
 159     compat_str 
= unicode # Python 2 
 164     compat_chr 
= unichr # Python 2 
 169     from xml
.etree
.ElementTree 
import ParseError 
as compat_xml_parse_error
 
 170 except ImportError:  # Python 2.6 
 171     from xml
.parsers
.expat 
import ExpatError 
as compat_xml_parse_error
 
 174     from shlex 
import quote 
as shlex_quote
 
 175 except ImportError:  # Python < 3.3 
 177         return "'" + s
.replace("'", "'\"'\"'") + "'" 
 181     if type(c
) is int: return c
 
 185 if sys
.version_info 
>= (3, 0): 
 186     compat_getenv 
= os
.getenv
 
 187     compat_expanduser 
= os
.path
.expanduser
 
 189     # Environment variables should be decoded with filesystem encoding. 
 190     # Otherwise it will fail if any non-ASCII characters present (see #3854 #3217 #2918) 
 192     def compat_getenv(key
, default
=None): 
 193         from .utils 
import get_filesystem_encoding
 
 194         env 
= os
.getenv(key
, default
) 
 196             env 
= env
.decode(get_filesystem_encoding()) 
 199     # HACK: The default implementations of os.path.expanduser from cpython do not decode 
 200     # environment variables with filesystem encoding. We will work around this by 
 201     # providing adjusted implementations. 
 202     # The following are os.path.expanduser implementations from cpython 2.7.8 stdlib 
 203     # for different platforms with correct environment variables decoding. 
 205     if os
.name 
== 'posix': 
 206         def compat_expanduser(path
): 
 207             """Expand ~ and ~user constructions.  If user or $HOME is unknown, 
 209             if not path
.startswith('~'): 
 211             i 
= path
.find('/', 1) 
 215                 if 'HOME' not in os
.environ
: 
 217                     userhome 
= pwd
.getpwuid(os
.getuid()).pw_dir
 
 219                     userhome 
= compat_getenv('HOME') 
 223                     pwent 
= pwd
.getpwnam(path
[1:i
]) 
 226                 userhome 
= pwent
.pw_dir
 
 227             userhome 
= userhome
.rstrip('/') 
 228             return (userhome 
+ path
[i
:]) or '/' 
 229     elif os
.name 
== 'nt' or os
.name 
== 'ce': 
 230         def compat_expanduser(path
): 
 231             """Expand ~ and ~user constructs. 
 233             If user or $HOME is unknown, do nothing.""" 
 237             while i 
< n 
and path
[i
] not in '/\\': 
 240             if 'HOME' in os
.environ
: 
 241                 userhome 
= compat_getenv('HOME') 
 242             elif 'USERPROFILE' in os
.environ
: 
 243                 userhome 
= compat_getenv('USERPROFILE') 
 244             elif not 'HOMEPATH' in os
.environ
: 
 248                     drive 
= compat_getenv('HOMEDRIVE') 
 251                 userhome 
= os
.path
.join(drive
, compat_getenv('HOMEPATH')) 
 254                 userhome 
= os
.path
.join(os
.path
.dirname(userhome
), path
[1:i
]) 
 256             return userhome 
+ path
[i
:] 
 258         compat_expanduser 
= os
.path
.expanduser
 
 261 if sys
.version_info 
< (3, 0): 
 263         from .utils 
import preferredencoding
 
 264         print(s
.encode(preferredencoding(), 'xmlcharrefreplace')) 
 267         assert type(s
) == type(u
'') 
 272     subprocess_check_output 
= subprocess
.check_output
 
 273 except AttributeError: 
 274     def subprocess_check_output(*args
, **kwargs
): 
 275         assert 'input' not in kwargs
 
 276         p 
= subprocess
.Popen(*args
, stdout
=subprocess
.PIPE
, **kwargs
) 
 277         output
, _ 
= p
.communicate() 
 280             raise subprocess
.CalledProcessError(ret
, p
.args
, output
=output
) 
 283 if sys
.version_info 
< (3, 0) and sys
.platform 
== 'win32': 
 284     def compat_getpass(prompt
, *args
, **kwargs
): 
 285         if isinstance(prompt
, compat_str
): 
 286             from .utils 
import preferredencoding
 
 287             prompt 
= prompt
.encode(preferredencoding()) 
 288         return getpass
.getpass(prompt
, *args
, **kwargs
) 
 290     compat_getpass 
= getpass
.getpass
 
 292 # Old 2.6 and 2.7 releases require kwargs to be bytes 
 294     (lambda x
: x
)(**{'x': 0}) 
 296     def compat_kwargs(kwargs
): 
 297         return dict((bytes(k
), v
) for k
, v 
in kwargs
.items()) 
 299     compat_kwargs 
= lambda kwargs
: kwargs
 
 302 # Fix https://github.com/rg3/youtube-dl/issues/4223 
 303 # See http://bugs.python.org/issue9161 for what is broken 
 304 def workaround_optparse_bug9161(): 
 305     op 
= optparse
.OptionParser() 
 306     og 
= optparse
.OptionGroup(op
, 'foo') 
 310         real_add_option 
= optparse
.OptionGroup
.add_option
 
 312         def _compat_add_option(self
, *args
, **kwargs
): 
 314                 v
.encode('ascii', 'replace') if isinstance(v
, compat_str
) 
 316             bargs 
= [enc(a
) for a 
in args
] 
 318                 (k
, enc(v
)) for k
, v 
in kwargs
.items()) 
 319             return real_add_option(self
, *bargs
, **bkwargs
) 
 320         optparse
.OptionGroup
.add_option 
= _compat_add_option
 
 330     'compat_html_entities', 
 331     'compat_html_parser', 
 332     'compat_http_client', 
 338     'compat_subprocess_get_DEVNULL', 
 339     'compat_urllib_error', 
 340     'compat_urllib_parse', 
 341     'compat_urllib_parse_unquote', 
 342     'compat_urllib_parse_urlparse', 
 343     'compat_urllib_request', 
 345     'compat_urlretrieve', 
 346     'compat_xml_parse_error', 
 348     'subprocess_check_output', 
 349     'workaround_optparse_bug9161',