]>
Commit | Line | Data |
---|---|---|
dfe5fa49 | 1 | # coding: utf-8 |
451948b2 | 2 | |
c634ad2a | 3 | import asyncio |
f206126d | 4 | import base64 |
d7cd9a9e | 5 | import ctypes |
8c25f81b | 6 | import getpass |
c634ad2a | 7 | import html |
8 | import html.parser | |
9 | import http | |
10 | import http.client | |
11 | import http.cookiejar | |
12 | import http.cookies | |
13 | import http.server | |
2384f5a6 | 14 | import itertools |
e07e9313 | 15 | import optparse |
8c25f81b | 16 | import os |
7d4111ed | 17 | import re |
51f579b6 | 18 | import shlex |
003c69a8 | 19 | import shutil |
be4a824d | 20 | import socket |
dab0daee | 21 | import struct |
8c25f81b | 22 | import sys |
c634ad2a | 23 | import tokenize |
24 | import urllib | |
25 | import xml.etree.ElementTree as etree | |
26 | from subprocess import DEVNULL | |
72b40955 | 27 | |
72b40955 | 28 | |
c634ad2a | 29 | # HTMLParseError has been deprecated in Python 3.3 and removed in |
30 | # Python 3.5. Introducing dummy exception for Python >3.5 for compatible | |
31 | # and uniform cross-version exception handling | |
32 | class compat_HTMLParseError(Exception): | |
33 | pass | |
15707c7e | 34 | |
15707c7e | 35 | |
e6f21b3d | 36 | # compat_ctypes_WINFUNCTYPE = ctypes.WINFUNCTYPE |
37 | # will not work since ctypes.WINFUNCTYPE does not exist in UNIX machines | |
c634ad2a | 38 | def compat_ctypes_WINFUNCTYPE(*args, **kwargs): |
39 | return ctypes.WINFUNCTYPE(*args, **kwargs) | |
eb7941e3 YCH |
40 | |
41 | ||
42 | class _TreeBuilder(etree.TreeBuilder): | |
43 | def doctype(self, name, pubid, system): | |
44 | pass | |
45 | ||
582be358 | 46 | |
c634ad2a | 47 | def compat_etree_fromstring(text): |
48 | return etree.XML(text, parser=etree.XMLParser(target=_TreeBuilder())) | |
8c25f81b | 49 | |
b08e235f S |
50 | |
51 | compat_os_name = os._name if os.name == 'java' else os.name | |
52 | ||
53 | ||
54 | if compat_os_name == 'nt': | |
702ccf2d | 55 | def compat_shlex_quote(s): |
b08e235f S |
56 | return s if re.match(r'^[-_\w./]+$', s) else '"%s"' % s.replace('"', '\\"') |
57 | else: | |
c634ad2a | 58 | from shlex import quote as compat_shlex_quote |
51f579b6 S |
59 | |
60 | ||
8c25f81b | 61 | def compat_ord(c): |
5f6a1245 JW |
62 | if type(c) is int: |
63 | return c | |
64 | else: | |
65 | return ord(c) | |
8c25f81b PH |
66 | |
67 | ||
c634ad2a | 68 | def compat_setenv(key, value, env=os.environ): |
69 | env[key] = value | |
8c25f81b PH |
70 | |
71 | ||
82fea5b4 S |
72 | if compat_os_name == 'nt' and sys.version_info < (3, 8): |
73 | # os.path.realpath on Windows does not follow symbolic links | |
74 | # prior to Python 3.8 (see https://bugs.python.org/issue9949) | |
75 | def compat_realpath(path): | |
76 | while os.path.islink(path): | |
77 | path = os.path.abspath(os.readlink(path)) | |
78 | return path | |
79 | else: | |
80 | compat_realpath = os.path.realpath | |
81 | ||
82 | ||
c634ad2a | 83 | def compat_print(s): |
84 | assert isinstance(s, compat_str) | |
85 | print(s) | |
be4a824d PH |
86 | |
87 | ||
067aa17e | 88 | # Fix https://github.com/ytdl-org/youtube-dl/issues/4223 |
e07e9313 PH |
89 | # See http://bugs.python.org/issue9161 for what is broken |
90 | def workaround_optparse_bug9161(): | |
07e378fa PH |
91 | op = optparse.OptionParser() |
92 | og = optparse.OptionGroup(op, 'foo') | |
e07e9313 | 93 | try: |
07e378fa | 94 | og.add_option('-t') |
b244b5c3 | 95 | except TypeError: |
e07e9313 PH |
96 | real_add_option = optparse.OptionGroup.add_option |
97 | ||
98 | def _compat_add_option(self, *args, **kwargs): | |
99 | enc = lambda v: ( | |
100 | v.encode('ascii', 'replace') if isinstance(v, compat_str) | |
101 | else v) | |
102 | bargs = [enc(a) for a in args] | |
103 | bkwargs = dict( | |
104 | (k, enc(v)) for k, v in kwargs.items()) | |
105 | return real_add_option(self, *bargs, **bkwargs) | |
106 | optparse.OptionGroup.add_option = _compat_add_option | |
107 | ||
582be358 | 108 | |
4a2f19ab F |
109 | try: |
110 | compat_Pattern = re.Pattern | |
111 | except AttributeError: | |
112 | compat_Pattern = type(re.compile('')) | |
113 | ||
114 | ||
115 | try: | |
116 | compat_Match = re.Match | |
117 | except AttributeError: | |
118 | compat_Match = type(re.compile('').match('')) | |
119 | ||
120 | ||
e36d50c5 | 121 | try: |
c634ad2a | 122 | compat_asyncio_run = asyncio.run # >= 3.7 |
e36d50c5 | 123 | except AttributeError: |
124 | def compat_asyncio_run(coro): | |
125 | try: | |
126 | loop = asyncio.get_event_loop() | |
127 | except RuntimeError: | |
128 | loop = asyncio.new_event_loop() | |
129 | asyncio.set_event_loop(loop) | |
130 | loop.run_until_complete(coro) | |
131 | ||
132 | asyncio.run = compat_asyncio_run | |
133 | ||
134 | ||
c589c1d3 | 135 | # Python 3.8+ does not honor %HOME% on windows, but this breaks compatibility with youtube-dl |
136 | # See https://github.com/yt-dlp/yt-dlp/issues/792 | |
137 | # https://docs.python.org/3/library/os.path.html#os.path.expanduser | |
138 | if compat_os_name in ('nt', 'ce') and 'HOME' in os.environ: | |
139 | _userhome = os.environ['HOME'] | |
140 | ||
141 | def compat_expanduser(path): | |
142 | if not path.startswith('~'): | |
143 | return path | |
144 | i = path.replace('\\', '/', 1).find('/') # ~user | |
145 | if i < 0: | |
146 | i = len(path) | |
147 | userhome = os.path.join(os.path.dirname(_userhome), path[1:i]) if i > 1 else _userhome | |
148 | return userhome + path[i:] | |
149 | else: | |
150 | compat_expanduser = os.path.expanduser | |
151 | ||
152 | ||
edf65256 | 153 | try: |
154 | from Cryptodome.Cipher import AES as compat_pycrypto_AES | |
155 | except ImportError: | |
156 | try: | |
157 | from Crypto.Cipher import AES as compat_pycrypto_AES | |
158 | except ImportError: | |
159 | compat_pycrypto_AES = None | |
160 | ||
161 | ||
c634ad2a | 162 | # Deprecated |
163 | ||
164 | compat_basestring = str | |
165 | compat_chr = chr | |
166 | compat_input = input | |
167 | compat_integer_types = (int, ) | |
168 | compat_kwargs = lambda kwargs: kwargs | |
169 | compat_numeric_types = (int, float, complex) | |
170 | compat_str = str | |
171 | compat_xpath = lambda xpath: xpath | |
172 | compat_zip = zip | |
173 | ||
174 | compat_HTMLParser = html.parser.HTMLParser | |
175 | compat_HTTPError = urllib.error.HTTPError | |
176 | compat_Struct = struct.Struct | |
177 | compat_b64decode = base64.b64decode | |
178 | compat_cookiejar = http.cookiejar | |
179 | compat_cookiejar_Cookie = compat_cookiejar.Cookie | |
180 | compat_cookies = http.cookies | |
181 | compat_cookies_SimpleCookie = compat_cookies.SimpleCookie | |
182 | compat_etree_Element = etree.Element | |
183 | compat_etree_register_namespace = etree.register_namespace | |
c634ad2a | 184 | compat_get_terminal_size = shutil.get_terminal_size |
185 | compat_getenv = os.getenv | |
186 | compat_getpass = getpass.getpass | |
187 | compat_html_entities = html.entities | |
188 | compat_html_entities_html5 = compat_html_entities.html5 | |
189 | compat_http_client = http.client | |
190 | compat_http_server = http.server | |
191 | compat_itertools_count = itertools.count | |
192 | compat_parse_qs = urllib.parse.parse_qs | |
193 | compat_shlex_split = shlex.split | |
194 | compat_socket_create_connection = socket.create_connection | |
195 | compat_struct_pack = struct.pack | |
196 | compat_struct_unpack = struct.unpack | |
197 | compat_subprocess_get_DEVNULL = lambda: DEVNULL | |
198 | compat_tokenize_tokenize = tokenize.tokenize | |
199 | compat_urllib_error = urllib.error | |
200 | compat_urllib_parse = urllib.parse | |
201 | compat_urllib_parse_quote = urllib.parse.quote | |
202 | compat_urllib_parse_quote_plus = urllib.parse.quote_plus | |
203 | compat_urllib_parse_unquote = urllib.parse.unquote | |
204 | compat_urllib_parse_unquote_plus = urllib.parse.unquote_plus | |
205 | compat_urllib_parse_unquote_to_bytes = urllib.parse.unquote_to_bytes | |
206 | compat_urllib_parse_urlencode = urllib.parse.urlencode | |
207 | compat_urllib_parse_urlparse = urllib.parse.urlparse | |
208 | compat_urllib_parse_urlunparse = urllib.parse.urlunparse | |
209 | compat_urllib_request = urllib.request | |
210 | compat_urllib_request_DataHandler = urllib.request.DataHandler | |
211 | compat_urllib_response = urllib.response | |
212 | compat_urlparse = urllib.parse | |
213 | compat_urlretrieve = urllib.request.urlretrieve | |
214 | compat_xml_parse_error = etree.ParseError | |
215 | ||
216 | ||
217 | # Set public objects | |
218 | ||
8c25f81b | 219 | __all__ = [ |
b081f53b | 220 | 'compat_HTMLParseError', |
8bb56eee | 221 | 'compat_HTMLParser', |
8c25f81b | 222 | 'compat_HTTPError', |
4a2f19ab F |
223 | 'compat_Match', |
224 | 'compat_Pattern', | |
65220c3b | 225 | 'compat_Struct', |
e36d50c5 | 226 | 'compat_asyncio_run', |
f206126d | 227 | 'compat_b64decode', |
0196149c | 228 | 'compat_basestring', |
8c25f81b PH |
229 | 'compat_chr', |
230 | 'compat_cookiejar', | |
6d874fee | 231 | 'compat_cookiejar_Cookie', |
799207e8 | 232 | 'compat_cookies', |
f7ad7160 | 233 | 'compat_cookies_SimpleCookie', |
d7cd9a9e | 234 | 'compat_ctypes_WINFUNCTYPE', |
399f7687 | 235 | 'compat_etree_Element', |
36e6f62c | 236 | 'compat_etree_fromstring', |
da162c11 | 237 | 'compat_etree_register_namespace', |
8c25f81b | 238 | 'compat_expanduser', |
003c69a8 | 239 | 'compat_get_terminal_size', |
8c25f81b PH |
240 | 'compat_getenv', |
241 | 'compat_getpass', | |
242 | 'compat_html_entities', | |
9631a94f | 243 | 'compat_html_entities_html5', |
8c25f81b | 244 | 'compat_http_client', |
83fda3c0 | 245 | 'compat_http_server', |
e67f6880 | 246 | 'compat_input', |
075a13d3 | 247 | 'compat_integer_types', |
a0e060ac | 248 | 'compat_itertools_count', |
c7b0add8 | 249 | 'compat_kwargs', |
28572a1a | 250 | 'compat_numeric_types', |
8c25f81b | 251 | 'compat_ord', |
e9c0cdd3 | 252 | 'compat_os_name', |
8c25f81b PH |
253 | 'compat_parse_qs', |
254 | 'compat_print', | |
edf65256 | 255 | 'compat_pycrypto_AES', |
bfe2b8cf | 256 | 'compat_realpath', |
fe40f9ee | 257 | 'compat_setenv', |
702ccf2d | 258 | 'compat_shlex_quote', |
51f579b6 | 259 | 'compat_shlex_split', |
be4a824d | 260 | 'compat_socket_create_connection', |
987493ae | 261 | 'compat_str', |
edaa23f8 YCH |
262 | 'compat_struct_pack', |
263 | 'compat_struct_unpack', | |
8c25f81b | 264 | 'compat_subprocess_get_DEVNULL', |
67134eab | 265 | 'compat_tokenize_tokenize', |
8c25f81b PH |
266 | 'compat_urllib_error', |
267 | 'compat_urllib_parse', | |
732044af | 268 | 'compat_urllib_parse_quote', |
269 | 'compat_urllib_parse_quote_plus', | |
8c25f81b | 270 | 'compat_urllib_parse_unquote', |
aa99aa4e | 271 | 'compat_urllib_parse_unquote_plus', |
9fefc886 | 272 | 'compat_urllib_parse_unquote_to_bytes', |
15707c7e | 273 | 'compat_urllib_parse_urlencode', |
8c25f81b | 274 | 'compat_urllib_parse_urlparse', |
732044af | 275 | 'compat_urllib_parse_urlunparse', |
8c25f81b | 276 | 'compat_urllib_request', |
0a67a363 YCH |
277 | 'compat_urllib_request_DataHandler', |
278 | 'compat_urllib_response', | |
8c25f81b PH |
279 | 'compat_urlparse', |
280 | 'compat_urlretrieve', | |
281 | 'compat_xml_parse_error', | |
57f7e3c6 | 282 | 'compat_xpath', |
2384f5a6 | 283 | 'compat_zip', |
e07e9313 | 284 | 'workaround_optparse_bug9161', |
8c25f81b | 285 | ] |