25 import xml
.etree
.ElementTree
as etree
26 from subprocess
import DEVNULL
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):
36 def compat_ctypes_WINFUNCTYPE(*args
, **kwargs
):
37 return ctypes
.WINFUNCTYPE(*args
, **kwargs
)
40 class _TreeBuilder(etree
.TreeBuilder
):
41 def doctype(self
, name
, pubid
, system
):
45 def compat_etree_fromstring(text
):
46 return etree
.XML(text
, parser
=etree
.XMLParser(target
=_TreeBuilder()))
49 compat_os_name
= os
._name
if os
.name
== 'java' else os
.name
52 if compat_os_name
== 'nt':
53 def compat_shlex_quote(s
):
54 return s
if re
.match(r
'^[-_\w./]+$', s
) else '"%s"' % s
.replace('"', '\\"')
56 from shlex
import quote
as compat_shlex_quote
66 def compat_setenv(key
, value
, env
=os
.environ
):
70 if compat_os_name
== 'nt' and sys
.version_info
< (3, 8):
71 # os.path.realpath on Windows does not follow symbolic links
72 # prior to Python 3.8 (see https://bugs.python.org/issue9949)
73 def compat_realpath(path
):
74 while os
.path
.islink(path
):
75 path
= os
.path
.abspath(os
.readlink(path
))
78 compat_realpath
= os
.path
.realpath
82 assert isinstance(s
, compat_str
)
86 # Fix https://github.com/ytdl-org/youtube-dl/issues/4223
87 # See http://bugs.python.org/issue9161 for what is broken
88 def workaround_optparse_bug9161():
89 op
= optparse
.OptionParser()
90 og
= optparse
.OptionGroup(op
, 'foo')
94 real_add_option
= optparse
.OptionGroup
.add_option
96 def _compat_add_option(self
, *args
, **kwargs
):
98 v
.encode('ascii', 'replace') if isinstance(v
, compat_str
)
100 bargs
= [enc(a
) for a
in args
]
102 (k
, enc(v
)) for k
, v
in kwargs
.items())
103 return real_add_option(self
, *bargs
, **bkwargs
)
104 optparse
.OptionGroup
.add_option
= _compat_add_option
108 compat_Pattern
= re
.Pattern
109 except AttributeError:
110 compat_Pattern
= type(re
.compile(''))
114 compat_Match
= re
.Match
115 except AttributeError:
116 compat_Match
= type(re
.compile('').match(''))
120 compat_asyncio_run
= asyncio
.run
# >= 3.7
121 except AttributeError:
122 def compat_asyncio_run(coro
):
124 loop
= asyncio
.get_event_loop()
126 loop
= asyncio
.new_event_loop()
127 asyncio
.set_event_loop(loop
)
128 loop
.run_until_complete(coro
)
130 asyncio
.run
= compat_asyncio_run
135 compat_basestring
= str
138 compat_integer_types
= (int, )
139 compat_kwargs
= lambda kwargs
: kwargs
140 compat_numeric_types
= (int, float, complex)
142 compat_xpath
= lambda xpath
: xpath
145 compat_HTMLParser
= html
.parser
.HTMLParser
146 compat_HTTPError
= urllib
.error
.HTTPError
147 compat_Struct
= struct
.Struct
148 compat_b64decode
= base64
.b64decode
149 compat_cookiejar
= http
.cookiejar
150 compat_cookiejar_Cookie
= compat_cookiejar
.Cookie
151 compat_cookies
= http
.cookies
152 compat_cookies_SimpleCookie
= compat_cookies
.SimpleCookie
153 compat_etree_Element
= etree
.Element
154 compat_etree_register_namespace
= etree
.register_namespace
155 compat_expanduser
= os
.path
.expanduser
156 compat_get_terminal_size
= shutil
.get_terminal_size
157 compat_getenv
= os
.getenv
158 compat_getpass
= getpass
.getpass
159 compat_html_entities
= html
.entities
160 compat_html_entities_html5
= compat_html_entities
.html5
161 compat_http_client
= http
.client
162 compat_http_server
= http
.server
163 compat_itertools_count
= itertools
.count
164 compat_parse_qs
= urllib
.parse
.parse_qs
165 compat_shlex_split
= shlex
.split
166 compat_socket_create_connection
= socket
.create_connection
167 compat_struct_pack
= struct
.pack
168 compat_struct_unpack
= struct
.unpack
169 compat_subprocess_get_DEVNULL
= lambda: DEVNULL
170 compat_tokenize_tokenize
= tokenize
.tokenize
171 compat_urllib_error
= urllib
.error
172 compat_urllib_parse
= urllib
.parse
173 compat_urllib_parse_quote
= urllib
.parse
.quote
174 compat_urllib_parse_quote_plus
= urllib
.parse
.quote_plus
175 compat_urllib_parse_unquote
= urllib
.parse
.unquote
176 compat_urllib_parse_unquote_plus
= urllib
.parse
.unquote_plus
177 compat_urllib_parse_unquote_to_bytes
= urllib
.parse
.unquote_to_bytes
178 compat_urllib_parse_urlencode
= urllib
.parse
.urlencode
179 compat_urllib_parse_urlparse
= urllib
.parse
.urlparse
180 compat_urllib_parse_urlunparse
= urllib
.parse
.urlunparse
181 compat_urllib_request
= urllib
.request
182 compat_urllib_request_DataHandler
= urllib
.request
.DataHandler
183 compat_urllib_response
= urllib
.response
184 compat_urlparse
= urllib
.parse
185 compat_urlretrieve
= urllib
.request
.urlretrieve
186 compat_xml_parse_error
= etree
.ParseError
192 'compat_HTMLParseError',
198 'compat_asyncio_run',
203 'compat_cookiejar_Cookie',
205 'compat_cookies_SimpleCookie',
206 'compat_ctypes_WINFUNCTYPE',
207 'compat_etree_Element',
208 'compat_etree_fromstring',
209 'compat_etree_register_namespace',
211 'compat_get_terminal_size',
214 'compat_html_entities',
215 'compat_html_entities_html5',
216 'compat_http_client',
217 'compat_http_server',
219 'compat_integer_types',
220 'compat_itertools_count',
222 'compat_numeric_types',
229 'compat_shlex_quote',
230 'compat_shlex_split',
231 'compat_socket_create_connection',
233 'compat_struct_pack',
234 'compat_struct_unpack',
235 'compat_subprocess_get_DEVNULL',
236 'compat_tokenize_tokenize',
237 'compat_urllib_error',
238 'compat_urllib_parse',
239 'compat_urllib_parse_quote',
240 'compat_urllib_parse_quote_plus',
241 'compat_urllib_parse_unquote',
242 'compat_urllib_parse_unquote_plus',
243 'compat_urllib_parse_unquote_to_bytes',
244 'compat_urllib_parse_urlencode',
245 'compat_urllib_parse_urlparse',
246 'compat_urllib_parse_urlunparse',
247 'compat_urllib_request',
248 'compat_urllib_request_DataHandler',
249 'compat_urllib_response',
251 'compat_urlretrieve',
252 'compat_xml_parse_error',
255 'workaround_optparse_bug9161',