mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-23 11:31:29 +01:00
[cleanup] Remove unused code paths (#2173)
Notes: * `_windows_write_string`: Fixed in 3.6 * https://bugs.python.org/issue1602 * PEP: https://www.python.org/dev/peps/pep-0528 * Windows UTF-8 fix: Fixed in 3.3 * https://bugs.python.org/issue13216 * `__loader__`: is always present in 3.3+ * https://bugs.python.org/issue14646 * `workaround_optparse_bug9161`: Fixed in 2.7 * https://bugs.python.org/issue9161 Authored by: fstirlitz
This commit is contained in:
parent
ab96d1ad1b
commit
cfb0511d82
|
@ -64,7 +64,7 @@ def report_warning(message):
|
||||||
else:
|
else:
|
||||||
_msg_header = 'WARNING:'
|
_msg_header = 'WARNING:'
|
||||||
output = '%s %s\n' % (_msg_header, message)
|
output = '%s %s\n' % (_msg_header, message)
|
||||||
if 'b' in getattr(sys.stderr, 'mode', '') or sys.version_info[0] < 3:
|
if 'b' in getattr(sys.stderr, 'mode', ''):
|
||||||
output = output.encode(preferredencoding())
|
output = output.encode(preferredencoding())
|
||||||
sys.stderr.write(output)
|
sys.stderr.write(output)
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,7 @@ def test_import(self):
|
||||||
subprocess.check_call([sys.executable, '-c', 'import yt_dlp'], cwd=rootDir)
|
subprocess.check_call([sys.executable, '-c', 'import yt_dlp'], cwd=rootDir)
|
||||||
|
|
||||||
def test_module_exec(self):
|
def test_module_exec(self):
|
||||||
if sys.version_info >= (2, 7): # Python 2.6 doesn't support package execution
|
subprocess.check_call([sys.executable, '-m', 'yt_dlp', '--version'], cwd=rootDir, stdout=_DEV_NULL)
|
||||||
subprocess.check_call([sys.executable, '-m', 'yt_dlp', '--version'], cwd=rootDir, stdout=_DEV_NULL)
|
|
||||||
|
|
||||||
def test_main_exec(self):
|
def test_main_exec(self):
|
||||||
subprocess.check_call([sys.executable, 'yt_dlp/__main__.py', '--version'], cwd=rootDir, stdout=_DEV_NULL)
|
subprocess.check_call([sys.executable, 'yt_dlp/__main__.py', '--version'], cwd=rootDir, stdout=_DEV_NULL)
|
||||||
|
|
|
@ -32,17 +32,6 @@ def do_GET(self):
|
||||||
self.send_header('Content-Type', 'video/mp4')
|
self.send_header('Content-Type', 'video/mp4')
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(b'\x00\x00\x00\x00\x20\x66\x74[video]')
|
self.wfile.write(b'\x00\x00\x00\x00\x20\x66\x74[video]')
|
||||||
elif self.path == '/302':
|
|
||||||
if sys.version_info[0] == 3:
|
|
||||||
# XXX: Python 3 http server does not allow non-ASCII header values
|
|
||||||
self.send_response(404)
|
|
||||||
self.end_headers()
|
|
||||||
return
|
|
||||||
|
|
||||||
new_url = 'http://127.0.0.1:%d/中文.html' % http_server_port(self.server)
|
|
||||||
self.send_response(302)
|
|
||||||
self.send_header(b'Location', new_url.encode('utf-8'))
|
|
||||||
self.end_headers()
|
|
||||||
elif self.path == '/%E4%B8%AD%E6%96%87.html':
|
elif self.path == '/%E4%B8%AD%E6%96%87.html':
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header('Content-Type', 'text/html; charset=utf-8')
|
self.send_header('Content-Type', 'text/html; charset=utf-8')
|
||||||
|
@ -72,15 +61,6 @@ def setUp(self):
|
||||||
self.server_thread.daemon = True
|
self.server_thread.daemon = True
|
||||||
self.server_thread.start()
|
self.server_thread.start()
|
||||||
|
|
||||||
def test_unicode_path_redirection(self):
|
|
||||||
# XXX: Python 3 http server does not allow non-ASCII header values
|
|
||||||
if sys.version_info[0] == 3:
|
|
||||||
return
|
|
||||||
|
|
||||||
ydl = YoutubeDL({'logger': FakeLogger()})
|
|
||||||
r = ydl.extract_info('http://127.0.0.1:%d/302' % self.port)
|
|
||||||
self.assertEqual(r['entries'][0]['url'], 'http://127.0.0.1:%d/vid.mp4' % self.port)
|
|
||||||
|
|
||||||
|
|
||||||
class TestHTTPS(unittest.TestCase):
|
class TestHTTPS(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -95,11 +75,10 @@ def setUp(self):
|
||||||
self.server_thread.start()
|
self.server_thread.start()
|
||||||
|
|
||||||
def test_nocheckcertificate(self):
|
def test_nocheckcertificate(self):
|
||||||
if sys.version_info >= (2, 7, 9): # No certificate checking anyways
|
ydl = YoutubeDL({'logger': FakeLogger()})
|
||||||
ydl = YoutubeDL({'logger': FakeLogger()})
|
self.assertRaises(
|
||||||
self.assertRaises(
|
Exception,
|
||||||
Exception,
|
ydl.extract_info, 'https://127.0.0.1:%d/video.html' % self.port)
|
||||||
ydl.extract_info, 'https://127.0.0.1:%d/video.html' % self.port)
|
|
||||||
|
|
||||||
ydl = YoutubeDL({'logger': FakeLogger(), 'nocheckcertificate': True})
|
ydl = YoutubeDL({'logger': FakeLogger(), 'nocheckcertificate': True})
|
||||||
r = ydl.extract_info('https://127.0.0.1:%d/video.html' % self.port)
|
r = ydl.extract_info('https://127.0.0.1:%d/video.html' % self.port)
|
||||||
|
|
|
@ -538,9 +538,6 @@ def test_str_to_int(self):
|
||||||
self.assertEqual(str_to_int('123,456'), 123456)
|
self.assertEqual(str_to_int('123,456'), 123456)
|
||||||
self.assertEqual(str_to_int('123.456'), 123456)
|
self.assertEqual(str_to_int('123.456'), 123456)
|
||||||
self.assertEqual(str_to_int(523), 523)
|
self.assertEqual(str_to_int(523), 523)
|
||||||
# Python 3 has no long
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
eval('self.assertEqual(str_to_int(123456L), 123456)')
|
|
||||||
self.assertEqual(str_to_int('noninteger'), None)
|
self.assertEqual(str_to_int('noninteger'), None)
|
||||||
self.assertEqual(str_to_int([]), None)
|
self.assertEqual(str_to_int([]), None)
|
||||||
|
|
||||||
|
|
|
@ -1008,12 +1008,6 @@ def get_output_path(self, dir_type='', filename=None):
|
||||||
expand_path(paths.get('home', '').strip()),
|
expand_path(paths.get('home', '').strip()),
|
||||||
expand_path(paths.get(dir_type, '').strip()) if dir_type else '',
|
expand_path(paths.get(dir_type, '').strip()) if dir_type else '',
|
||||||
filename or '')
|
filename or '')
|
||||||
|
|
||||||
# Temporary fix for #4787
|
|
||||||
# 'Treat' all problem characters by passing filename through preferredencoding
|
|
||||||
# to workaround encoding issues with subprocess on python2 @ Windows
|
|
||||||
if sys.version_info < (3, 0) and sys.platform == 'win32':
|
|
||||||
path = encodeFilename(path, True).decode(preferredencoding())
|
|
||||||
return sanitize_path(path, force=self.params.get('windowsfilenames'))
|
return sanitize_path(path, force=self.params.get('windowsfilenames'))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
__license__ = 'Public Domain'
|
__license__ = 'Public Domain'
|
||||||
|
|
||||||
import codecs
|
|
||||||
import io
|
import io
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
|
@ -18,7 +17,6 @@
|
||||||
compat_getpass,
|
compat_getpass,
|
||||||
compat_os_name,
|
compat_os_name,
|
||||||
compat_shlex_quote,
|
compat_shlex_quote,
|
||||||
workaround_optparse_bug9161,
|
|
||||||
)
|
)
|
||||||
from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
|
from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
|
||||||
from .utils import (
|
from .utils import (
|
||||||
|
@ -807,13 +805,6 @@ def parse_options(argv=None):
|
||||||
|
|
||||||
|
|
||||||
def _real_main(argv=None):
|
def _real_main(argv=None):
|
||||||
# Compatibility fixes for Windows
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
# https://github.com/ytdl-org/youtube-dl/issues/820
|
|
||||||
codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
|
|
||||||
|
|
||||||
workaround_optparse_bug9161()
|
|
||||||
|
|
||||||
setproctitle('yt-dlp')
|
setproctitle('yt-dlp')
|
||||||
|
|
||||||
parser, opts, all_urls, ydl_opts = parse_options(argv)
|
parser, opts, all_urls, ydl_opts = parse_options(argv)
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
# Execute with
|
# Execute with
|
||||||
# $ python yt_dlp/__main__.py (2.6+)
|
# $ python -m yt_dlp
|
||||||
# $ python -m yt_dlp (2.7+)
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
import http.cookies
|
import http.cookies
|
||||||
import http.server
|
import http.server
|
||||||
import itertools
|
import itertools
|
||||||
import optparse
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
@ -86,28 +85,6 @@ def compat_print(s):
|
||||||
assert isinstance(s, compat_str)
|
assert isinstance(s, compat_str)
|
||||||
print(s)
|
print(s)
|
||||||
|
|
||||||
|
|
||||||
# Fix https://github.com/ytdl-org/youtube-dl/issues/4223
|
|
||||||
# See http://bugs.python.org/issue9161 for what is broken
|
|
||||||
def workaround_optparse_bug9161():
|
|
||||||
op = optparse.OptionParser()
|
|
||||||
og = optparse.OptionGroup(op, 'foo')
|
|
||||||
try:
|
|
||||||
og.add_option('-t')
|
|
||||||
except TypeError:
|
|
||||||
real_add_option = optparse.OptionGroup.add_option
|
|
||||||
|
|
||||||
def _compat_add_option(self, *args, **kwargs):
|
|
||||||
enc = lambda v: (
|
|
||||||
v.encode('ascii', 'replace') if isinstance(v, compat_str)
|
|
||||||
else v)
|
|
||||||
bargs = [enc(a) for a in args]
|
|
||||||
bkwargs = dict(
|
|
||||||
(k, enc(v)) for k, v in kwargs.items())
|
|
||||||
return real_add_option(self, *bargs, **bkwargs)
|
|
||||||
optparse.OptionGroup.add_option = _compat_add_option
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
compat_Pattern = re.Pattern
|
compat_Pattern = re.Pattern
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
@ -207,6 +184,7 @@ def windows_enable_vt_mode(): # TODO: Do this the proper way https://bugs.pytho
|
||||||
compat_str = str
|
compat_str = str
|
||||||
compat_xpath = lambda xpath: xpath
|
compat_xpath = lambda xpath: xpath
|
||||||
compat_zip = zip
|
compat_zip = zip
|
||||||
|
workaround_optparse_bug9161 = lambda: None
|
||||||
|
|
||||||
compat_collections_abc = collections.abc
|
compat_collections_abc = collections.abc
|
||||||
compat_HTMLParser = html.parser.HTMLParser
|
compat_HTMLParser = html.parser.HTMLParser
|
||||||
|
|
|
@ -16,7 +16,6 @@ class BpbIE(InfoExtractor):
|
||||||
|
|
||||||
_TEST = {
|
_TEST = {
|
||||||
'url': 'http://www.bpb.de/mediathek/297/joachim-gauck-zu-1989-und-die-erinnerung-an-die-ddr',
|
'url': 'http://www.bpb.de/mediathek/297/joachim-gauck-zu-1989-und-die-erinnerung-an-die-ddr',
|
||||||
# md5 fails in Python 2.6 due to buggy server response and wrong handling of urllib2
|
|
||||||
'md5': 'c4f84c8a8044ca9ff68bb8441d300b3f',
|
'md5': 'c4f84c8a8044ca9ff68bb8441d300b3f',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '297',
|
'id': '297',
|
||||||
|
|
|
@ -3606,9 +3606,7 @@ def _apply_first_set_cookie_header(self, url_handle, cookie):
|
||||||
for header, cookies in url_handle.headers.items():
|
for header, cookies in url_handle.headers.items():
|
||||||
if header.lower() != 'set-cookie':
|
if header.lower() != 'set-cookie':
|
||||||
continue
|
continue
|
||||||
if sys.version_info[0] >= 3:
|
cookies = cookies.encode('iso-8859-1').decode('utf-8')
|
||||||
cookies = cookies.encode('iso-8859-1')
|
|
||||||
cookies = cookies.decode('utf-8')
|
|
||||||
cookie_value = re.search(
|
cookie_value = re.search(
|
||||||
r'%s=(.+?);.*?\b[Dd]omain=(.+?)(?:[,;]|$)' % cookie, cookies)
|
r'%s=(.+?);.*?\b[Dd]omain=(.+?)(?:[,;]|$)' % cookie, cookies)
|
||||||
if cookie_value:
|
if cookie_value:
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..utils import ExtractorError
|
from ..utils import ExtractorError
|
||||||
|
|
||||||
|
@ -35,9 +33,7 @@ class UnicodeBOMIE(InfoExtractor):
|
||||||
IE_DESC = False
|
IE_DESC = False
|
||||||
_VALID_URL = r'(?P<bom>\ufeff)(?P<id>.*)$'
|
_VALID_URL = r'(?P<bom>\ufeff)(?P<id>.*)$'
|
||||||
|
|
||||||
# Disable test for python 3.2 since BOM is broken in re in this version
|
_TESTS = [{
|
||||||
# (see https://github.com/ytdl-org/youtube-dl/issues/9751)
|
|
||||||
_TESTS = [] if (3, 0) < sys.version_info <= (3, 3) else [{
|
|
||||||
'url': '\ufeffhttp://www.youtube.com/watch?v=BaW_jenozKc',
|
'url': '\ufeffhttp://www.youtube.com/watch?v=BaW_jenozKc',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from .youtube import YoutubeIE
|
from .youtube import YoutubeIE
|
||||||
|
@ -4011,9 +4010,6 @@ def filter_video(urls):
|
||||||
# Look also in Refresh HTTP header
|
# Look also in Refresh HTTP header
|
||||||
refresh_header = head_response.headers.get('Refresh')
|
refresh_header = head_response.headers.get('Refresh')
|
||||||
if refresh_header:
|
if refresh_header:
|
||||||
# In python 2 response HTTP headers are bytestrings
|
|
||||||
if sys.version_info < (3, 0) and isinstance(refresh_header, str):
|
|
||||||
refresh_header = refresh_header.decode('iso-8859-1')
|
|
||||||
found = re.search(REDIRECT_REGEX, refresh_header)
|
found = re.search(REDIRECT_REGEX, refresh_header)
|
||||||
if found:
|
if found:
|
||||||
new_url = compat_urlparse.urljoin(url, unescapeHTML(found.group(1)))
|
new_url = compat_urlparse.urljoin(url, unescapeHTML(found.group(1)))
|
||||||
|
|
|
@ -15,22 +15,6 @@
|
||||||
from .version import __version__
|
from .version import __version__
|
||||||
|
|
||||||
|
|
||||||
''' # Not signed
|
|
||||||
def rsa_verify(message, signature, key):
|
|
||||||
from hashlib import sha256
|
|
||||||
assert isinstance(message, bytes)
|
|
||||||
byte_size = (len(bin(key[0])) - 2 + 8 - 1) // 8
|
|
||||||
signature = ('%x' % pow(int(signature, 16), key[1], key[0])).encode()
|
|
||||||
signature = (byte_size * 2 - len(signature)) * b'0' + signature
|
|
||||||
asn1 = b'3031300d060960864801650304020105000420'
|
|
||||||
asn1 += sha256(message).hexdigest().encode()
|
|
||||||
if byte_size < len(asn1) // 2 + 11:
|
|
||||||
return False
|
|
||||||
expected = b'0001' + (byte_size - len(asn1) // 2 - 3) * b'ff' + b'00' + asn1
|
|
||||||
return expected == signature
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def detect_variant():
|
def detect_variant():
|
||||||
if hasattr(sys, 'frozen'):
|
if hasattr(sys, 'frozen'):
|
||||||
prefix = 'mac' if sys.platform == 'darwin' else 'win'
|
prefix = 'mac' if sys.platform == 'darwin' else 'win'
|
||||||
|
@ -39,7 +23,7 @@ def detect_variant():
|
||||||
return f'{prefix}_dir'
|
return f'{prefix}_dir'
|
||||||
return f'{prefix}_exe'
|
return f'{prefix}_exe'
|
||||||
return 'py2exe'
|
return 'py2exe'
|
||||||
elif isinstance(globals().get('__loader__'), zipimporter):
|
elif isinstance(__loader__, zipimporter):
|
||||||
return 'zip'
|
return 'zip'
|
||||||
elif os.path.basename(sys.argv[0]) == '__main__.py':
|
elif os.path.basename(sys.argv[0]) == '__main__.py':
|
||||||
return 'source'
|
return 'source'
|
||||||
|
@ -232,24 +216,6 @@ def get_sha256sum(bin_or_exe, version):
|
||||||
assert False, f'Unhandled variant: {variant}'
|
assert False, f'Unhandled variant: {variant}'
|
||||||
|
|
||||||
|
|
||||||
''' # UNUSED
|
|
||||||
def get_notes(versions, fromVersion):
|
|
||||||
notes = []
|
|
||||||
for v, vdata in sorted(versions.items()):
|
|
||||||
if v > fromVersion:
|
|
||||||
notes.extend(vdata.get('notes', []))
|
|
||||||
return notes
|
|
||||||
|
|
||||||
|
|
||||||
def print_notes(to_screen, versions, fromVersion=__version__):
|
|
||||||
notes = get_notes(versions, fromVersion)
|
|
||||||
if notes:
|
|
||||||
to_screen('PLEASE NOTE:')
|
|
||||||
for note in notes:
|
|
||||||
to_screen(note)
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
def update_self(to_screen, verbose, opener):
|
def update_self(to_screen, verbose, opener):
|
||||||
|
|
||||||
|
|
247
yt_dlp/utils.py
247
yt_dlp/utils.py
|
@ -50,7 +50,6 @@
|
||||||
compat_brotli,
|
compat_brotli,
|
||||||
compat_chr,
|
compat_chr,
|
||||||
compat_cookiejar,
|
compat_cookiejar,
|
||||||
compat_ctypes_WINFUNCTYPE,
|
|
||||||
compat_etree_fromstring,
|
compat_etree_fromstring,
|
||||||
compat_expanduser,
|
compat_expanduser,
|
||||||
compat_html_entities,
|
compat_html_entities,
|
||||||
|
@ -288,37 +287,9 @@ def preferredencoding():
|
||||||
def write_json_file(obj, fn):
|
def write_json_file(obj, fn):
|
||||||
""" Encode obj as JSON and write it to fn, atomically if possible """
|
""" Encode obj as JSON and write it to fn, atomically if possible """
|
||||||
|
|
||||||
fn = encodeFilename(fn)
|
tf = tempfile.NamedTemporaryFile(
|
||||||
if sys.version_info < (3, 0) and sys.platform != 'win32':
|
prefix=f'{os.path.basename(fn)}.', dir=os.path.dirname(fn),
|
||||||
encoding = get_filesystem_encoding()
|
suffix='.tmp', delete=False, mode='w', encoding='utf-8')
|
||||||
# os.path.basename returns a bytes object, but NamedTemporaryFile
|
|
||||||
# will fail if the filename contains non ascii characters unless we
|
|
||||||
# use a unicode object
|
|
||||||
path_basename = lambda f: os.path.basename(fn).decode(encoding)
|
|
||||||
# the same for os.path.dirname
|
|
||||||
path_dirname = lambda f: os.path.dirname(fn).decode(encoding)
|
|
||||||
else:
|
|
||||||
path_basename = os.path.basename
|
|
||||||
path_dirname = os.path.dirname
|
|
||||||
|
|
||||||
args = {
|
|
||||||
'suffix': '.tmp',
|
|
||||||
'prefix': path_basename(fn) + '.',
|
|
||||||
'dir': path_dirname(fn),
|
|
||||||
'delete': False,
|
|
||||||
}
|
|
||||||
|
|
||||||
# In Python 2.x, json.dump expects a bytestream.
|
|
||||||
# In Python 3.x, it writes to a character stream
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
args['mode'] = 'wb'
|
|
||||||
else:
|
|
||||||
args.update({
|
|
||||||
'mode': 'w',
|
|
||||||
'encoding': 'utf-8',
|
|
||||||
})
|
|
||||||
|
|
||||||
tf = tempfile.NamedTemporaryFile(**compat_kwargs(args))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with tf:
|
with tf:
|
||||||
|
@ -345,20 +316,11 @@ def write_json_file(obj, fn):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info >= (2, 7):
|
def find_xpath_attr(node, xpath, key, val=None):
|
||||||
def find_xpath_attr(node, xpath, key, val=None):
|
""" Find the xpath xpath[@key=val] """
|
||||||
""" Find the xpath xpath[@key=val] """
|
assert re.match(r'^[a-zA-Z_-]+$', key)
|
||||||
assert re.match(r'^[a-zA-Z_-]+$', key)
|
expr = xpath + ('[@%s]' % key if val is None else "[@%s='%s']" % (key, val))
|
||||||
expr = xpath + ('[@%s]' % key if val is None else "[@%s='%s']" % (key, val))
|
return node.find(expr)
|
||||||
return node.find(expr)
|
|
||||||
else:
|
|
||||||
def find_xpath_attr(node, xpath, key, val=None):
|
|
||||||
for f in node.findall(compat_xpath(xpath)):
|
|
||||||
if key not in f.attrib:
|
|
||||||
continue
|
|
||||||
if val is None or f.attrib.get(key) == val:
|
|
||||||
return f
|
|
||||||
return None
|
|
||||||
|
|
||||||
# On python2.6 the xml.etree.ElementTree.Element methods don't support
|
# On python2.6 the xml.etree.ElementTree.Element methods don't support
|
||||||
# the namespace parameter
|
# the namespace parameter
|
||||||
|
@ -626,8 +588,6 @@ def extract_attributes(html_element):
|
||||||
'empty': '', 'noval': None, 'entity': '&',
|
'empty': '', 'noval': None, 'entity': '&',
|
||||||
'sq': '"', 'dq': '\''
|
'sq': '"', 'dq': '\''
|
||||||
}.
|
}.
|
||||||
NB HTMLParser is stricter in Python 2.6 & 3.2 than in later versions,
|
|
||||||
but the cases in the unit test will work for all of 2.6, 2.7, 3.2-3.5.
|
|
||||||
"""
|
"""
|
||||||
parser = HTMLAttributeParser()
|
parser = HTMLAttributeParser()
|
||||||
try:
|
try:
|
||||||
|
@ -763,8 +723,6 @@ def sanitize_path(s, force=False):
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
force = False
|
force = False
|
||||||
drive_or_unc, _ = os.path.splitdrive(s)
|
drive_or_unc, _ = os.path.splitdrive(s)
|
||||||
if sys.version_info < (2, 7) and not drive_or_unc:
|
|
||||||
drive_or_unc, _ = os.path.splitunc(s)
|
|
||||||
elif force:
|
elif force:
|
||||||
drive_or_unc = ''
|
drive_or_unc = ''
|
||||||
else:
|
else:
|
||||||
|
@ -922,51 +880,23 @@ def get_subprocess_encoding():
|
||||||
|
|
||||||
|
|
||||||
def encodeFilename(s, for_subprocess=False):
|
def encodeFilename(s, for_subprocess=False):
|
||||||
"""
|
assert type(s) == str
|
||||||
@param s The name of the file
|
return s
|
||||||
"""
|
|
||||||
|
|
||||||
assert type(s) == compat_str
|
|
||||||
|
|
||||||
# Python 3 has a Unicode API
|
|
||||||
if sys.version_info >= (3, 0):
|
|
||||||
return s
|
|
||||||
|
|
||||||
# Pass '' directly to use Unicode APIs on Windows 2000 and up
|
|
||||||
# (Detecting Windows NT 4 is tricky because 'major >= 4' would
|
|
||||||
# match Windows 9x series as well. Besides, NT 4 is obsolete.)
|
|
||||||
if not for_subprocess and sys.platform == 'win32' and sys.getwindowsversion()[0] >= 5:
|
|
||||||
return s
|
|
||||||
|
|
||||||
# Jython assumes filenames are Unicode strings though reported as Python 2.x compatible
|
|
||||||
if sys.platform.startswith('java'):
|
|
||||||
return s
|
|
||||||
|
|
||||||
return s.encode(get_subprocess_encoding(), 'ignore')
|
|
||||||
|
|
||||||
|
|
||||||
def decodeFilename(b, for_subprocess=False):
|
def decodeFilename(b, for_subprocess=False):
|
||||||
|
return b
|
||||||
if sys.version_info >= (3, 0):
|
|
||||||
return b
|
|
||||||
|
|
||||||
if not isinstance(b, bytes):
|
|
||||||
return b
|
|
||||||
|
|
||||||
return b.decode(get_subprocess_encoding(), 'ignore')
|
|
||||||
|
|
||||||
|
|
||||||
def encodeArgument(s):
|
def encodeArgument(s):
|
||||||
if not isinstance(s, compat_str):
|
# Legacy code that uses byte strings
|
||||||
# Legacy code that uses byte strings
|
# Uncomment the following line after fixing all post processors
|
||||||
# Uncomment the following line after fixing all post processors
|
# assert isinstance(s, str), 'Internal error: %r should be of type %r, is %r' % (s, compat_str, type(s))
|
||||||
# assert False, 'Internal error: %r should be of type %r, is %r' % (s, compat_str, type(s))
|
return s if isinstance(s, str) else s.decode('ascii')
|
||||||
s = s.decode('ascii')
|
|
||||||
return encodeFilename(s, True)
|
|
||||||
|
|
||||||
|
|
||||||
def decodeArgument(b):
|
def decodeArgument(b):
|
||||||
return decodeFilename(b, True)
|
return b
|
||||||
|
|
||||||
|
|
||||||
def decodeOption(optval):
|
def decodeOption(optval):
|
||||||
|
@ -1263,11 +1193,6 @@ class XAttrUnavailableError(YoutubeDLError):
|
||||||
|
|
||||||
|
|
||||||
def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
|
def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
|
||||||
# Working around python 2 bug (see http://bugs.python.org/issue17849) by limiting
|
|
||||||
# expected HTTP responses to meet HTTP/1.0 or later (see also
|
|
||||||
# https://github.com/ytdl-org/youtube-dl/issues/6727)
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
kwargs['strict'] = True
|
|
||||||
hc = http_class(*args, **compat_kwargs(kwargs))
|
hc = http_class(*args, **compat_kwargs(kwargs))
|
||||||
source_address = ydl_handler._params.get('source_address')
|
source_address = ydl_handler._params.get('source_address')
|
||||||
|
|
||||||
|
@ -1309,20 +1234,7 @@ def _create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_a
|
||||||
raise socket.error('getaddrinfo returns an empty list')
|
raise socket.error('getaddrinfo returns an empty list')
|
||||||
if hasattr(hc, '_create_connection'):
|
if hasattr(hc, '_create_connection'):
|
||||||
hc._create_connection = _create_connection
|
hc._create_connection = _create_connection
|
||||||
sa = (source_address, 0)
|
hc.source_address = (source_address, 0)
|
||||||
if hasattr(hc, 'source_address'): # Python 2.7+
|
|
||||||
hc.source_address = sa
|
|
||||||
else: # Python 2.6
|
|
||||||
def _hc_connect(self, *args, **kwargs):
|
|
||||||
sock = _create_connection(
|
|
||||||
(self.host, self.port), self.timeout, sa)
|
|
||||||
if is_https:
|
|
||||||
self.sock = ssl.wrap_socket(
|
|
||||||
sock, self.key_file, self.cert_file,
|
|
||||||
ssl_version=ssl.PROTOCOL_TLSv1)
|
|
||||||
else:
|
|
||||||
self.sock = sock
|
|
||||||
hc.connect = functools.partial(_hc_connect, hc)
|
|
||||||
|
|
||||||
return hc
|
return hc
|
||||||
|
|
||||||
|
@ -1413,11 +1325,6 @@ def http_request(self, req):
|
||||||
|
|
||||||
req.headers = handle_youtubedl_headers(req.headers)
|
req.headers = handle_youtubedl_headers(req.headers)
|
||||||
|
|
||||||
if sys.version_info < (2, 7) and '#' in req.get_full_url():
|
|
||||||
# Python 2.6 is brain-dead when it comes to fragments
|
|
||||||
req._Request__original = req._Request__original.partition('#')[0]
|
|
||||||
req._Request__r_type = req._Request__r_type.partition('#')[0]
|
|
||||||
|
|
||||||
return req
|
return req
|
||||||
|
|
||||||
def http_response(self, req, resp):
|
def http_response(self, req, resp):
|
||||||
|
@ -1461,15 +1368,10 @@ def http_response(self, req, resp):
|
||||||
location = resp.headers.get('Location')
|
location = resp.headers.get('Location')
|
||||||
if location:
|
if location:
|
||||||
# As of RFC 2616 default charset is iso-8859-1 that is respected by python 3
|
# As of RFC 2616 default charset is iso-8859-1 that is respected by python 3
|
||||||
if sys.version_info >= (3, 0):
|
location = location.encode('iso-8859-1').decode('utf-8')
|
||||||
location = location.encode('iso-8859-1').decode('utf-8')
|
|
||||||
else:
|
|
||||||
location = location.decode('utf-8')
|
|
||||||
location_escaped = escape_url(location)
|
location_escaped = escape_url(location)
|
||||||
if location != location_escaped:
|
if location != location_escaped:
|
||||||
del resp.headers['Location']
|
del resp.headers['Location']
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
location_escaped = location_escaped.encode('utf-8')
|
|
||||||
resp.headers['Location'] = location_escaped
|
resp.headers['Location'] = location_escaped
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
@ -1668,19 +1570,6 @@ def __init__(self, cookiejar=None):
|
||||||
compat_urllib_request.HTTPCookieProcessor.__init__(self, cookiejar)
|
compat_urllib_request.HTTPCookieProcessor.__init__(self, cookiejar)
|
||||||
|
|
||||||
def http_response(self, request, response):
|
def http_response(self, request, response):
|
||||||
# Python 2 will choke on next HTTP request in row if there are non-ASCII
|
|
||||||
# characters in Set-Cookie HTTP header of last response (see
|
|
||||||
# https://github.com/ytdl-org/youtube-dl/issues/6769).
|
|
||||||
# In order to at least prevent crashing we will percent encode Set-Cookie
|
|
||||||
# header before HTTPCookieProcessor starts processing it.
|
|
||||||
# if sys.version_info < (3, 0) and response.headers:
|
|
||||||
# for set_cookie_header in ('Set-Cookie', 'Set-Cookie2'):
|
|
||||||
# set_cookie = response.headers.get(set_cookie_header)
|
|
||||||
# if set_cookie:
|
|
||||||
# set_cookie_escaped = compat_urllib_parse.quote(set_cookie, b"%/;:@&=+$,!~*'()?#[] ")
|
|
||||||
# if set_cookie != set_cookie_escaped:
|
|
||||||
# del response.headers[set_cookie_header]
|
|
||||||
# response.headers[set_cookie_header] = set_cookie_escaped
|
|
||||||
return compat_urllib_request.HTTPCookieProcessor.http_response(self, request, response)
|
return compat_urllib_request.HTTPCookieProcessor.http_response(self, request, response)
|
||||||
|
|
||||||
https_request = compat_urllib_request.HTTPCookieProcessor.http_request
|
https_request = compat_urllib_request.HTTPCookieProcessor.http_request
|
||||||
|
@ -1724,12 +1613,6 @@ def redirect_request(self, req, fp, code, msg, headers, newurl):
|
||||||
# essentially all clients do redirect in this case, so we do
|
# essentially all clients do redirect in this case, so we do
|
||||||
# the same.
|
# the same.
|
||||||
|
|
||||||
# On python 2 urlh.geturl() may sometimes return redirect URL
|
|
||||||
# as byte string instead of unicode. This workaround allows
|
|
||||||
# to force it always return unicode.
|
|
||||||
if sys.version_info[0] < 3:
|
|
||||||
newurl = compat_str(newurl)
|
|
||||||
|
|
||||||
# Be conciliant with URIs containing a space. This is mainly
|
# Be conciliant with URIs containing a space. This is mainly
|
||||||
# redundant with the more complete encoding done in http_error_302(),
|
# redundant with the more complete encoding done in http_error_302(),
|
||||||
# but it is kept for compatibility with other callers.
|
# but it is kept for compatibility with other callers.
|
||||||
|
@ -2013,91 +1896,12 @@ def get_windows_version():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _windows_write_string(s, out):
|
|
||||||
""" Returns True if the string was written using special methods,
|
|
||||||
False if it has yet to be written out."""
|
|
||||||
# Adapted from http://stackoverflow.com/a/3259271/35070
|
|
||||||
|
|
||||||
import ctypes.wintypes
|
|
||||||
|
|
||||||
WIN_OUTPUT_IDS = {
|
|
||||||
1: -11,
|
|
||||||
2: -12,
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
fileno = out.fileno()
|
|
||||||
except AttributeError:
|
|
||||||
# If the output stream doesn't have a fileno, it's virtual
|
|
||||||
return False
|
|
||||||
except io.UnsupportedOperation:
|
|
||||||
# Some strange Windows pseudo files?
|
|
||||||
return False
|
|
||||||
if fileno not in WIN_OUTPUT_IDS:
|
|
||||||
return False
|
|
||||||
|
|
||||||
GetStdHandle = compat_ctypes_WINFUNCTYPE(
|
|
||||||
ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD)(
|
|
||||||
('GetStdHandle', ctypes.windll.kernel32))
|
|
||||||
h = GetStdHandle(WIN_OUTPUT_IDS[fileno])
|
|
||||||
|
|
||||||
WriteConsoleW = compat_ctypes_WINFUNCTYPE(
|
|
||||||
ctypes.wintypes.BOOL, ctypes.wintypes.HANDLE, ctypes.wintypes.LPWSTR,
|
|
||||||
ctypes.wintypes.DWORD, ctypes.POINTER(ctypes.wintypes.DWORD),
|
|
||||||
ctypes.wintypes.LPVOID)(('WriteConsoleW', ctypes.windll.kernel32))
|
|
||||||
written = ctypes.wintypes.DWORD(0)
|
|
||||||
|
|
||||||
GetFileType = compat_ctypes_WINFUNCTYPE(ctypes.wintypes.DWORD, ctypes.wintypes.DWORD)(('GetFileType', ctypes.windll.kernel32))
|
|
||||||
FILE_TYPE_CHAR = 0x0002
|
|
||||||
FILE_TYPE_REMOTE = 0x8000
|
|
||||||
GetConsoleMode = compat_ctypes_WINFUNCTYPE(
|
|
||||||
ctypes.wintypes.BOOL, ctypes.wintypes.HANDLE,
|
|
||||||
ctypes.POINTER(ctypes.wintypes.DWORD))(
|
|
||||||
('GetConsoleMode', ctypes.windll.kernel32))
|
|
||||||
INVALID_HANDLE_VALUE = ctypes.wintypes.DWORD(-1).value
|
|
||||||
|
|
||||||
def not_a_console(handle):
|
|
||||||
if handle == INVALID_HANDLE_VALUE or handle is None:
|
|
||||||
return True
|
|
||||||
return ((GetFileType(handle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR
|
|
||||||
or GetConsoleMode(handle, ctypes.byref(ctypes.wintypes.DWORD())) == 0)
|
|
||||||
|
|
||||||
if not_a_console(h):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def next_nonbmp_pos(s):
|
|
||||||
try:
|
|
||||||
return next(i for i, c in enumerate(s) if ord(c) > 0xffff)
|
|
||||||
except StopIteration:
|
|
||||||
return len(s)
|
|
||||||
|
|
||||||
while s:
|
|
||||||
count = min(next_nonbmp_pos(s), 1024)
|
|
||||||
|
|
||||||
ret = WriteConsoleW(
|
|
||||||
h, s, count if count else 2, ctypes.byref(written), None)
|
|
||||||
if ret == 0:
|
|
||||||
raise OSError('Failed to write string')
|
|
||||||
if not count: # We just wrote a non-BMP character
|
|
||||||
assert written.value == 2
|
|
||||||
s = s[1:]
|
|
||||||
else:
|
|
||||||
assert written.value > 0
|
|
||||||
s = s[written.value:]
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def write_string(s, out=None, encoding=None):
|
def write_string(s, out=None, encoding=None):
|
||||||
if out is None:
|
if out is None:
|
||||||
out = sys.stderr
|
out = sys.stderr
|
||||||
assert type(s) == compat_str
|
assert type(s) == compat_str
|
||||||
|
|
||||||
if sys.platform == 'win32' and encoding is None and hasattr(out, 'fileno'):
|
if 'b' in getattr(out, 'mode', ''):
|
||||||
if _windows_write_string(s, out):
|
|
||||||
return
|
|
||||||
|
|
||||||
if ('b' in getattr(out, 'mode', '')
|
|
||||||
or sys.version_info[0] < 3): # Python 2 lies about mode of sys.stderr
|
|
||||||
byt = s.encode(encoding or preferredencoding(), 'ignore')
|
byt = s.encode(encoding or preferredencoding(), 'ignore')
|
||||||
out.write(byt)
|
out.write(byt)
|
||||||
elif hasattr(out, 'buffer'):
|
elif hasattr(out, 'buffer'):
|
||||||
|
@ -2985,8 +2789,6 @@ def lowercase_escape(s):
|
||||||
|
|
||||||
def escape_rfc3986(s):
|
def escape_rfc3986(s):
|
||||||
"""Escape non-ASCII characters as suggested by RFC 3986"""
|
"""Escape non-ASCII characters as suggested by RFC 3986"""
|
||||||
if sys.version_info < (3, 0) and isinstance(s, compat_str):
|
|
||||||
s = s.encode('utf-8')
|
|
||||||
return compat_urllib_parse.quote(s, b"%/;:@&=+$,!~*'()?#[]")
|
return compat_urllib_parse.quote(s, b"%/;:@&=+$,!~*'()?#[]")
|
||||||
|
|
||||||
|
|
||||||
|
@ -3335,12 +3137,7 @@ def args_to_str(args):
|
||||||
|
|
||||||
|
|
||||||
def error_to_compat_str(err):
|
def error_to_compat_str(err):
|
||||||
err_str = str(err)
|
return str(err)
|
||||||
# On python 2 error byte string must be decoded with proper
|
|
||||||
# encoding rather than ascii
|
|
||||||
if sys.version_info[0] < 3:
|
|
||||||
err_str = err_str.decode(preferredencoding())
|
|
||||||
return err_str
|
|
||||||
|
|
||||||
|
|
||||||
def error_to_str(err):
|
def error_to_str(err):
|
||||||
|
@ -5144,7 +4941,7 @@ def get_executable_path():
|
||||||
from zipimport import zipimporter
|
from zipimport import zipimporter
|
||||||
if hasattr(sys, 'frozen'): # Running from PyInstaller
|
if hasattr(sys, 'frozen'): # Running from PyInstaller
|
||||||
path = os.path.dirname(sys.executable)
|
path = os.path.dirname(sys.executable)
|
||||||
elif isinstance(globals().get('__loader__'), zipimporter): # Running from ZIP
|
elif isinstance(__loader__, zipimporter): # Running from ZIP
|
||||||
path = os.path.join(os.path.dirname(__file__), '../..')
|
path = os.path.join(os.path.dirname(__file__), '../..')
|
||||||
else:
|
else:
|
||||||
path = os.path.join(os.path.dirname(__file__), '..')
|
path = os.path.join(os.path.dirname(__file__), '..')
|
||||||
|
@ -5436,8 +5233,6 @@ def read_file(filename, default=[]):
|
||||||
try:
|
try:
|
||||||
# FIXME: https://github.com/ytdl-org/youtube-dl/commit/dfe5fa49aed02cf36ba9f743b11b0903554b5e56
|
# FIXME: https://github.com/ytdl-org/youtube-dl/commit/dfe5fa49aed02cf36ba9f743b11b0903554b5e56
|
||||||
contents = optionf.read()
|
contents = optionf.read()
|
||||||
if sys.version_info < (3,):
|
|
||||||
contents = contents.decode(preferredencoding())
|
|
||||||
res = compat_shlex_split(contents, comments=True)
|
res = compat_shlex_split(contents, comments=True)
|
||||||
finally:
|
finally:
|
||||||
optionf.close()
|
optionf.close()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user