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