mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2026-08-27 14:23:41 +03:00
[cleanup] Remove obsolete Python compatibility code (#17357)
Authored by: doe1080
This commit is contained in:
@@ -66,8 +66,7 @@ def convert_code_blocks(readme):
|
|||||||
|
|
||||||
def move_sections(readme):
|
def move_sections(readme):
|
||||||
MOVE_TAG_TEMPLATE = '<!-- MANPAGE: MOVE "%s" SECTION HERE -->'
|
MOVE_TAG_TEMPLATE = '<!-- MANPAGE: MOVE "%s" SECTION HERE -->'
|
||||||
sections = re.findall(r'(?m)^%s$' % (
|
sections = re.findall(r'(?m)^%s$' % (re.escape(MOVE_TAG_TEMPLATE) % '(.+)'), readme)
|
||||||
re.escape(MOVE_TAG_TEMPLATE).replace(r'\%', '%') % '(.+)'), readme)
|
|
||||||
|
|
||||||
for section_name in sections:
|
for section_name in sections:
|
||||||
move_tag = MOVE_TAG_TEMPLATE % section_name
|
move_tag = MOVE_TAG_TEMPLATE % section_name
|
||||||
|
|||||||
+1
-37
@@ -3,7 +3,6 @@ import hashlib
|
|||||||
import json
|
import json
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
import ssl
|
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
|
|
||||||
@@ -318,36 +317,6 @@ def expect_info_dict(self, got_dict, expected_dict):
|
|||||||
'Missing keys in test definition: {}'.format(', '.join(sorted(missing_keys))))
|
'Missing keys in test definition: {}'.format(', '.join(sorted(missing_keys))))
|
||||||
|
|
||||||
|
|
||||||
def assertRegexpMatches(self, text, regexp, msg=None):
|
|
||||||
if hasattr(self, 'assertRegexp'):
|
|
||||||
return self.assertRegexp(text, regexp, msg)
|
|
||||||
else:
|
|
||||||
m = re.match(regexp, text)
|
|
||||||
if not m:
|
|
||||||
note = f'Regexp didn\'t match: {regexp!r} not found'
|
|
||||||
if len(text) < 1000:
|
|
||||||
note += f' in {text!r}'
|
|
||||||
if msg is None:
|
|
||||||
msg = note
|
|
||||||
else:
|
|
||||||
msg = note + ', ' + msg
|
|
||||||
self.assertTrue(m, msg)
|
|
||||||
|
|
||||||
|
|
||||||
def assertGreaterEqual(self, got, expected, msg=None):
|
|
||||||
if not (got >= expected):
|
|
||||||
if msg is None:
|
|
||||||
msg = f'{got!r} not greater than or equal to {expected!r}'
|
|
||||||
self.assertTrue(got >= expected, msg)
|
|
||||||
|
|
||||||
|
|
||||||
def assertLessEqual(self, got, expected, msg=None):
|
|
||||||
if not (got <= expected):
|
|
||||||
if msg is None:
|
|
||||||
msg = f'{got!r} not less than or equal to {expected!r}'
|
|
||||||
self.assertTrue(got <= expected, msg)
|
|
||||||
|
|
||||||
|
|
||||||
def assertEqual(self, got, expected, msg=None):
|
def assertEqual(self, got, expected, msg=None):
|
||||||
if got != expected:
|
if got != expected:
|
||||||
if msg is None:
|
if msg is None:
|
||||||
@@ -366,12 +335,7 @@ def expect_warnings(ydl, warnings_re):
|
|||||||
|
|
||||||
|
|
||||||
def http_server_port(httpd):
|
def http_server_port(httpd):
|
||||||
if os.name == 'java' and isinstance(httpd.socket, ssl.SSLSocket):
|
return httpd.server_address[1]
|
||||||
# In Jython SSLSocket is not a subclass of socket.socket
|
|
||||||
sock = httpd.socket.sock
|
|
||||||
else:
|
|
||||||
sock = httpd.socket
|
|
||||||
return sock.getsockname()[1]
|
|
||||||
|
|
||||||
|
|
||||||
def verify_address_availability(address):
|
def verify_address_availability(address):
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import contextlib
|
|||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from test.helper import FakeYDL, assertRegexpMatches, try_rm
|
from test.helper import FakeYDL, try_rm
|
||||||
from yt_dlp import YoutubeDL
|
from yt_dlp import YoutubeDL
|
||||||
from yt_dlp.extractor.common import InfoExtractor
|
from yt_dlp.extractor.common import InfoExtractor
|
||||||
from yt_dlp.postprocessor.common import PostProcessor
|
from yt_dlp.postprocessor.common import PostProcessor
|
||||||
@@ -860,10 +860,10 @@ class TestYoutubeDL(unittest.TestCase):
|
|||||||
def test_format_note(self):
|
def test_format_note(self):
|
||||||
ydl = YoutubeDL()
|
ydl = YoutubeDL()
|
||||||
self.assertEqual(ydl._format_note({}), '')
|
self.assertEqual(ydl._format_note({}), '')
|
||||||
assertRegexpMatches(self, ydl._format_note({
|
self.assertRegex(ydl._format_note({
|
||||||
'vbr': 10,
|
'vbr': 10,
|
||||||
}), r'^\s*10k$')
|
}), r'^\s*10k$')
|
||||||
assertRegexpMatches(self, ydl._format_note({
|
self.assertRegex(ydl._format_note({
|
||||||
'fps': 30,
|
'fps': 30,
|
||||||
}), r'^30fps$')
|
}), r'^30fps$')
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ import hashlib
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from test.helper import (
|
from test.helper import (
|
||||||
assertGreaterEqual,
|
|
||||||
assertLessEqual,
|
|
||||||
expect_info_dict,
|
expect_info_dict,
|
||||||
expect_warnings,
|
expect_warnings,
|
||||||
get_params,
|
get_params,
|
||||||
@@ -201,8 +199,8 @@ def generator(test_case, tname):
|
|||||||
num_entries = len(res_dict.get('entries', []))
|
num_entries = len(res_dict.get('entries', []))
|
||||||
if 'playlist_mincount' in test_case:
|
if 'playlist_mincount' in test_case:
|
||||||
mincount = test_case['playlist_mincount']
|
mincount = test_case['playlist_mincount']
|
||||||
assertGreaterEqual(
|
self.assertGreaterEqual(
|
||||||
self, num_entries, mincount,
|
num_entries, mincount,
|
||||||
f'Expected at least {mincount} entries in playlist {test_url}, but got only {num_entries}')
|
f'Expected at least {mincount} entries in playlist {test_url}, but got only {num_entries}')
|
||||||
if 'playlist_count' in test_case:
|
if 'playlist_count' in test_case:
|
||||||
count = test_case['playlist_count']
|
count = test_case['playlist_count']
|
||||||
@@ -212,8 +210,8 @@ def generator(test_case, tname):
|
|||||||
f'Expected exactly {count} entries in playlist {test_url}, but got {got}')
|
f'Expected exactly {count} entries in playlist {test_url}, but got {got}')
|
||||||
if 'playlist_maxcount' in test_case:
|
if 'playlist_maxcount' in test_case:
|
||||||
maxcount = test_case['playlist_maxcount']
|
maxcount = test_case['playlist_maxcount']
|
||||||
assertLessEqual(
|
self.assertLessEqual(
|
||||||
self, num_entries, maxcount,
|
num_entries, maxcount,
|
||||||
f'Expected at most {maxcount} entries in playlist {test_url}, but got more')
|
f'Expected at most {maxcount} entries in playlist {test_url}, but got more')
|
||||||
if 'playlist_duration_sum' in test_case:
|
if 'playlist_duration_sum' in test_case:
|
||||||
got_duration = sum(e['duration'] for e in res_dict['entries'])
|
got_duration = sum(e['duration'] for e in res_dict['entries'])
|
||||||
@@ -241,8 +239,8 @@ def generator(test_case, tname):
|
|||||||
if params.get('test'):
|
if params.get('test'):
|
||||||
expected_minsize = max(expected_minsize, 10000)
|
expected_minsize = max(expected_minsize, 10000)
|
||||||
got_fsize = os.path.getsize(tc_filename)
|
got_fsize = os.path.getsize(tc_filename)
|
||||||
assertGreaterEqual(
|
self.assertGreaterEqual(
|
||||||
self, got_fsize, expected_minsize,
|
got_fsize, expected_minsize,
|
||||||
f'Expected {tc_filename} to be at least {format_bytes(expected_minsize)}, '
|
f'Expected {tc_filename} to be at least {format_bytes(expected_minsize)}, '
|
||||||
f'but it\'s only {format_bytes(got_fsize)} ')
|
f'but it\'s only {format_bytes(got_fsize)} ')
|
||||||
if 'md5' in tc:
|
if 'md5' in tc:
|
||||||
|
|||||||
+5
-18
@@ -984,28 +984,15 @@ class TestUrllibRequestHandler(TestRequestHandlerBase):
|
|||||||
):
|
):
|
||||||
validate_and_send(rh, Request(f'https://127.0.0.1:{self.https_port}/headers'))
|
validate_and_send(rh, Request(f'https://127.0.0.1:{self.https_port}/headers'))
|
||||||
|
|
||||||
@pytest.mark.parametrize('req,match,version_check', [
|
@pytest.mark.parametrize('req,match', [
|
||||||
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1256
|
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1256
|
||||||
# bpo-39603: Check implemented in 3.7.9+, 3.8.5+
|
(Request('http://127.0.0.1', method='GET\n'), 'method can\'t contain control characters'),
|
||||||
(
|
|
||||||
Request('http://127.0.0.1', method='GET\n'),
|
|
||||||
'method can\'t contain control characters',
|
|
||||||
lambda v: v < (3, 7, 9) or (3, 8, 0) <= v < (3, 8, 5),
|
|
||||||
),
|
|
||||||
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1265
|
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1265
|
||||||
# bpo-38576: Check implemented in 3.7.8+, 3.8.3+
|
(Request('http://127.0.0. 1', method='GET'), 'URL can\'t contain control characters'),
|
||||||
(
|
|
||||||
Request('http://127.0.0. 1', method='GET'),
|
|
||||||
'URL can\'t contain control characters',
|
|
||||||
lambda v: v < (3, 7, 8) or (3, 8, 0) <= v < (3, 8, 3),
|
|
||||||
),
|
|
||||||
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1288C31-L1288C50
|
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1288C31-L1288C50
|
||||||
(Request('http://127.0.0.1', headers={'foo\n': 'bar'}), 'Invalid header name', None),
|
(Request('http://127.0.0.1', headers={'foo\n': 'bar'}), 'Invalid header name'),
|
||||||
])
|
])
|
||||||
def test_httplib_validation_errors(self, handler, req, match, version_check):
|
def test_httplib_validation_errors(self, handler, req, match):
|
||||||
if version_check and version_check(sys.version_info):
|
|
||||||
pytest.skip(f'Python {sys.version} version does not have the required validation for this test.')
|
|
||||||
|
|
||||||
with handler() as rh:
|
with handler() as rh:
|
||||||
with pytest.raises(RequestError, match=match) as exc_info:
|
with pytest.raises(RequestError, match=match) as exc_info:
|
||||||
validate_and_send(rh, req)
|
validate_and_send(rh, req)
|
||||||
|
|||||||
+2
-9
@@ -1347,15 +1347,8 @@ class TestUtil(unittest.TestCase):
|
|||||||
self.assertEqual(extract_attributes('<e _:funny-name1=1>'), {'_:funny-name1': '1'})
|
self.assertEqual(extract_attributes('<e _:funny-name1=1>'), {'_:funny-name1': '1'})
|
||||||
self.assertEqual(extract_attributes('<e x="Fáilte 世界 \U0001f600">'), {'x': 'Fáilte 世界 \U0001f600'})
|
self.assertEqual(extract_attributes('<e x="Fáilte 世界 \U0001f600">'), {'x': 'Fáilte 世界 \U0001f600'})
|
||||||
self.assertEqual(extract_attributes('<e x="décomposé">'), {'x': 'décompose\u0301'})
|
self.assertEqual(extract_attributes('<e x="décomposé">'), {'x': 'décompose\u0301'})
|
||||||
# "Narrow" Python builds don't support unicode code points outside BMP.
|
self.assertEqual(extract_attributes('<e x="Smile 😀!">'), {'x': 'Smile \U0001f600!'})
|
||||||
try:
|
# Malformed HTML should not break attribute extraction
|
||||||
chr(0x10000)
|
|
||||||
supports_outside_bmp = True
|
|
||||||
except ValueError:
|
|
||||||
supports_outside_bmp = False
|
|
||||||
if supports_outside_bmp:
|
|
||||||
self.assertEqual(extract_attributes('<e x="Smile 😀!">'), {'x': 'Smile \U0001f600!'})
|
|
||||||
# Malformed HTML should not break attributes extraction on older Python
|
|
||||||
self.assertEqual(extract_attributes('<mal"formed/>'), {})
|
self.assertEqual(extract_attributes('<mal"formed/>'), {})
|
||||||
|
|
||||||
def test_clean_html(self):
|
def test_clean_html(self):
|
||||||
|
|||||||
+1
-2
@@ -2398,8 +2398,7 @@ class YoutubeDL:
|
|||||||
selectors = []
|
selectors = []
|
||||||
current_selector = None
|
current_selector = None
|
||||||
for type_, string_, start, _, _ in tokens:
|
for type_, string_, start, _, _ in tokens:
|
||||||
# ENCODING is only defined in Python 3.x
|
if type_ == tokenize.ENCODING:
|
||||||
if type_ == getattr(tokenize, 'ENCODING', None):
|
|
||||||
continue
|
continue
|
||||||
elif type_ in [tokenize.NAME, tokenize.NUMBER]:
|
elif type_ in [tokenize.NAME, tokenize.NUMBER]:
|
||||||
current_selector = FormatSelector(SINGLE, string_, [])
|
current_selector = FormatSelector(SINGLE, string_, [])
|
||||||
|
|||||||
+1
-1
@@ -293,7 +293,7 @@ def aes_decrypt_text(data, password, key_size_bytes):
|
|||||||
- Mode of operation is 'counter'
|
- Mode of operation is 'counter'
|
||||||
|
|
||||||
@param {str} data Base64 encoded string
|
@param {str} data Base64 encoded string
|
||||||
@param {str,unicode} password Password (will be encoded with utf-8)
|
@param {str} password Password (will be encoded with UTF-8)
|
||||||
@param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
|
@param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
|
||||||
@returns {str} Decrypted data
|
@returns {str} Decrypted data
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -8,9 +8,8 @@ passthrough_module(__name__, '._deprecated')
|
|||||||
del passthrough_module
|
del passthrough_module
|
||||||
|
|
||||||
|
|
||||||
# HTMLParseError has been deprecated in Python 3.3 and removed in
|
# HTMLParseError was deprecated in Python 3.3 and removed in Python 3.5.
|
||||||
# Python 3.5. Introducing dummy exception for Python >3.5 for compatible
|
# Keep a replacement for API compatibility and uniform exception handling.
|
||||||
# and uniform cross-version exception handling
|
|
||||||
class compat_HTMLParseError(ValueError):
|
class compat_HTMLParseError(ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ def write_piff_header(stream, params):
|
|||||||
sample_entry_payload += u16.pack(0x18) # depth
|
sample_entry_payload += u16.pack(0x18) # depth
|
||||||
sample_entry_payload += s16.pack(-1) # pre defined
|
sample_entry_payload += s16.pack(-1) # pre defined
|
||||||
|
|
||||||
codec_private_data = binascii.unhexlify(params['codec_private_data'].encode())
|
codec_private_data = binascii.unhexlify(params['codec_private_data'])
|
||||||
if fourcc in ('H264', 'AVC1'):
|
if fourcc in ('H264', 'AVC1'):
|
||||||
sps, pps = codec_private_data.split(u32.pack(1))[1:]
|
sps, pps = codec_private_data.split(u32.pack(1))[1:]
|
||||||
avcc_payload = u8.pack(1) # configuration version
|
avcc_payload = u8.pack(1) # configuration version
|
||||||
|
|||||||
@@ -432,29 +432,28 @@ class InfoExtractor:
|
|||||||
|
|
||||||
chapter: Name or title of the chapter the video belongs to.
|
chapter: Name or title of the chapter the video belongs to.
|
||||||
chapter_number: Number of the chapter the video belongs to, as an integer.
|
chapter_number: Number of the chapter the video belongs to, as an integer.
|
||||||
chapter_id: Id of the chapter the video belongs to, as a unicode string.
|
chapter_id: Id of the chapter the video belongs to.
|
||||||
|
|
||||||
The following fields should only be used when the video is an episode of some
|
The following fields should only be used when the video is an episode of some
|
||||||
series, programme or podcast:
|
series, programme or podcast:
|
||||||
|
|
||||||
series: Title of the series or programme the video episode belongs to.
|
series: Title of the series or programme the video episode belongs to.
|
||||||
series_id: Id of the series or programme the video episode belongs to, as a unicode string.
|
series_id: Id of the series or programme the video episode belongs to.
|
||||||
season: Title of the season the video episode belongs to.
|
season: Title of the season the video episode belongs to.
|
||||||
season_number: Number of the season the video episode belongs to, as an integer.
|
season_number: Number of the season the video episode belongs to, as an integer.
|
||||||
season_id: Id of the season the video episode belongs to, as a unicode string.
|
season_id: Id of the season the video episode belongs to.
|
||||||
episode: Title of the video episode. Unlike mandatory video title field,
|
episode: Title of the video episode. Unlike mandatory video title field,
|
||||||
this field should denote the exact title of the video episode
|
this field should denote the exact title of the video episode
|
||||||
without any kind of decoration.
|
without any kind of decoration.
|
||||||
episode_number: Number of the video episode within a season, as an integer.
|
episode_number: Number of the video episode within a season, as an integer.
|
||||||
episode_id: Id of the video episode, as a unicode string.
|
episode_id: Id of the video episode.
|
||||||
|
|
||||||
The following fields should only be used when the media is a track or a part of
|
The following fields should only be used when the media is a track or a part of
|
||||||
a music album:
|
a music album:
|
||||||
|
|
||||||
track: Title of the track.
|
track: Title of the track.
|
||||||
track_number: Number of the track within an album or a disc, as an integer.
|
track_number: Number of the track within an album or a disc, as an integer.
|
||||||
track_id: Id of the track (useful in case of custom indexing, e.g. 6.iii),
|
track_id: Id of the track (useful for custom indexing, e.g. 6.iii).
|
||||||
as a unicode string.
|
|
||||||
artists: List of artists of the track.
|
artists: List of artists of the track.
|
||||||
composers: List of composers of the piece.
|
composers: List of composers of the piece.
|
||||||
genres: List of genres of the track.
|
genres: List of genres of the track.
|
||||||
@@ -487,7 +486,7 @@ class InfoExtractor:
|
|||||||
creator: Use "creators" instead.
|
creator: Use "creators" instead.
|
||||||
The creator of the video.
|
The creator of the video.
|
||||||
|
|
||||||
Unless mentioned otherwise, the fields should be Unicode strings.
|
Unless mentioned otherwise, the fields should be strings.
|
||||||
|
|
||||||
Unless mentioned otherwise, None is equivalent to absence of information.
|
Unless mentioned otherwise, None is equivalent to absence of information.
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class ITVIE(InfoExtractor):
|
|||||||
# See: https://github.com/yt-dlp/yt-dlp/issues/986
|
# See: https://github.com/yt-dlp/yt-dlp/issues/986
|
||||||
platform_tag_subs, featureset_subs = next(
|
platform_tag_subs, featureset_subs = next(
|
||||||
((platform_tag, featureset)
|
((platform_tag, featureset)
|
||||||
for platform_tag, featuresets in reversed(list(variants.items())) for featureset in featuresets
|
for platform_tag, featuresets in reversed(variants.items()) for featureset in featuresets
|
||||||
if try_get(featureset, lambda x: x[2]) == 'outband-webvtt'),
|
if try_get(featureset, lambda x: x[2]) == 'outband-webvtt'),
|
||||||
(None, None))
|
(None, None))
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ class ITVIE(InfoExtractor):
|
|||||||
# See: https://github.com/yt-dlp/yt-dlp/issues/986
|
# See: https://github.com/yt-dlp/yt-dlp/issues/986
|
||||||
platform_tag_video, featureset_video = next(
|
platform_tag_video, featureset_video = next(
|
||||||
((platform_tag, featureset)
|
((platform_tag, featureset)
|
||||||
for platform_tag, featuresets in reversed(list(variants.items())) for featureset in featuresets
|
for platform_tag, featuresets in reversed(variants.items()) for featureset in featuresets
|
||||||
if set(try_get(featureset, lambda x: x[:2]) or []) == {'aes', 'hls'}),
|
if set(try_get(featureset, lambda x: x[:2]) or []) == {'aes', 'hls'}),
|
||||||
(None, None))
|
(None, None))
|
||||||
if not platform_tag_video or not featureset_video:
|
if not platform_tag_video or not featureset_video:
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class YoutubeIEContentProviderLogger(IEContentProviderLogger):
|
|||||||
if self.log_level <= self.LogLevel.ERROR:
|
if self.log_level <= self.LogLevel.ERROR:
|
||||||
self.__ie._downloader.report_error(
|
self.__ie._downloader.report_error(
|
||||||
self._format_msg(message), is_error=False,
|
self._format_msg(message), is_error=False,
|
||||||
tb=''.join(traceback.format_exception(None, cause, cause.__traceback__)) if cause else None)
|
tb=''.join(traceback.format_exception(cause)) if cause else None)
|
||||||
|
|
||||||
|
|
||||||
class PoTokenCache:
|
class PoTokenCache:
|
||||||
|
|||||||
@@ -108,9 +108,7 @@ def make_ssl_context(
|
|||||||
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||||
context.check_hostname = verify
|
context.check_hostname = verify
|
||||||
context.verify_mode = ssl.CERT_REQUIRED if verify else ssl.CERT_NONE
|
context.verify_mode = ssl.CERT_REQUIRED if verify else ssl.CERT_NONE
|
||||||
# OpenSSL 1.1.1+ Python 3.8+ keylog file
|
context.keylog_filename = os.environ.get('SSLKEYLOGFILE') or None
|
||||||
if hasattr(context, 'keylog_filename'):
|
|
||||||
context.keylog_filename = os.environ.get('SSLKEYLOGFILE') or None
|
|
||||||
|
|
||||||
# Some servers may reject requests if ALPN extension is not sent. See:
|
# Some servers may reject requests if ALPN extension is not sent. See:
|
||||||
# https://github.com/python/cpython/issues/85140
|
# https://github.com/python/cpython/issues/85140
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class RequestsResponseAdapter(Response):
|
|||||||
# Work around issue with `.read(amt)` then `.read()`
|
# Work around issue with `.read(amt)` then `.read()`
|
||||||
# See: https://github.com/urllib3/urllib3/issues/3636
|
# See: https://github.com/urllib3/urllib3/issues/3636
|
||||||
if amt is None:
|
if amt is None:
|
||||||
# compat: py3.9: Python 3.9 preallocates the whole read buffer, read in chunks
|
# Read in chunks to avoid preallocating a large buffer
|
||||||
read_chunk = functools.partial(self.fp.read, 1 << 20, decode_content=True)
|
read_chunk = functools.partial(self.fp.read, 1 << 20, decode_content=True)
|
||||||
return b''.join(iter(read_chunk, b''))
|
return b''.join(iter(read_chunk, b''))
|
||||||
# Interact with urllib3 response directly.
|
# Interact with urllib3 response directly.
|
||||||
|
|||||||
@@ -296,13 +296,9 @@ class UrllibResponseAdapter(Response):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, res: http.client.HTTPResponse | urllib.response.addinfourl):
|
def __init__(self, res: http.client.HTTPResponse | urllib.response.addinfourl):
|
||||||
# addinfourl: In Python 3.9+, .status was introduced and .getcode() was deprecated [1]
|
|
||||||
# HTTPResponse: .getcode() was deprecated, .status always existed [2]
|
|
||||||
# 1. https://docs.python.org/3/library/urllib.request.html#urllib.response.addinfourl.getcode
|
|
||||||
# 2. https://docs.python.org/3.10/library/http.client.html#http.client.HTTPResponse.status
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
fp=res, headers=res.headers, url=res.url,
|
fp=res, headers=res.headers, url=res.url,
|
||||||
status=getattr(res, 'status', None) or res.getcode(), reason=getattr(res, 'reason', None))
|
status=res.status, reason=getattr(res, 'reason', None))
|
||||||
|
|
||||||
def read(self, amt=None):
|
def read(self, amt=None):
|
||||||
if self.closed:
|
if self.closed:
|
||||||
|
|||||||
+8
-15
@@ -238,11 +238,9 @@ def find_xpath_attr(node, xpath, key, val=None):
|
|||||||
expr = xpath + (f'[@{key}]' if val is None else f"[@{key}='{val}']")
|
expr = xpath + (f'[@{key}]' if val is None else f"[@{key}='{val}']")
|
||||||
return node.find(expr)
|
return node.find(expr)
|
||||||
|
|
||||||
# On python2.6 the xml.etree.ElementTree.Element methods don't support
|
|
||||||
# the namespace parameter
|
|
||||||
|
|
||||||
|
|
||||||
def xpath_with_ns(path, ns_map):
|
def xpath_with_ns(path, ns_map):
|
||||||
|
"""Expand namespace-prefixed names to Clark notation."""
|
||||||
components = [c.split(':') for c in path.split('/')]
|
components = [c.split(':') for c in path.split('/')]
|
||||||
replaced = []
|
replaced = []
|
||||||
for c in components:
|
for c in components:
|
||||||
@@ -876,7 +874,7 @@ class Popen(subprocess.Popen):
|
|||||||
|
|
||||||
self.__text_mode = kwargs.get('encoding') or kwargs.get('errors') or text or kwargs.get('universal_newlines')
|
self.__text_mode = kwargs.get('encoding') or kwargs.get('errors') or text or kwargs.get('universal_newlines')
|
||||||
if text is True:
|
if text is True:
|
||||||
kwargs['universal_newlines'] = True # For 3.6 compatibility
|
kwargs['text'] = True
|
||||||
kwargs.setdefault('encoding', 'utf-8')
|
kwargs.setdefault('encoding', 'utf-8')
|
||||||
kwargs.setdefault('errors', 'replace')
|
kwargs.setdefault('errors', 'replace')
|
||||||
|
|
||||||
@@ -1012,7 +1010,7 @@ class ExtractorError(YoutubeDLError):
|
|||||||
def format_traceback(self):
|
def format_traceback(self):
|
||||||
return join_nonempty(
|
return join_nonempty(
|
||||||
self.traceback and ''.join(traceback.format_tb(self.traceback)),
|
self.traceback and ''.join(traceback.format_tb(self.traceback)),
|
||||||
self.cause and ''.join(traceback.format_exception(None, self.cause, self.cause.__traceback__)[1:]),
|
self.cause and ''.join(traceback.format_exception(self.cause)[1:]),
|
||||||
delim='\n') or None
|
delim='\n') or None
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
@@ -1960,11 +1958,7 @@ def setproctitle(title):
|
|||||||
libc = ctypes.cdll.LoadLibrary('libc.so.6')
|
libc = ctypes.cdll.LoadLibrary('libc.so.6')
|
||||||
except OSError:
|
except OSError:
|
||||||
return
|
return
|
||||||
except TypeError:
|
|
||||||
# LoadLibrary in Windows Python 2.7.13 only expects
|
|
||||||
# a bytestring, but since unicode_literals turns
|
|
||||||
# every string into a unicode string, it fails.
|
|
||||||
return
|
|
||||||
title_bytes = title.encode()
|
title_bytes = title.encode()
|
||||||
buf = ctypes.create_string_buffer(len(title_bytes))
|
buf = ctypes.create_string_buffer(len(title_bytes))
|
||||||
buf.value = title_bytes
|
buf.value = title_bytes
|
||||||
@@ -2655,11 +2649,10 @@ def multipart_encode(data, boundary=None):
|
|||||||
Encode a dict to RFC 7578-compliant form-data
|
Encode a dict to RFC 7578-compliant form-data
|
||||||
|
|
||||||
data:
|
data:
|
||||||
A dict where keys and values can be either Unicode or bytes-like
|
A dict where keys and values can be either str or bytes-like objects.
|
||||||
objects.
|
|
||||||
boundary:
|
boundary:
|
||||||
If specified a Unicode object, it's used as the boundary. Otherwise
|
An ASCII string to use as the boundary. If omitted, a random boundary
|
||||||
a random boundary is generated.
|
is generated.
|
||||||
|
|
||||||
Reference: https://tools.ietf.org/html/rfc7578
|
Reference: https://tools.ietf.org/html/rfc7578
|
||||||
"""
|
"""
|
||||||
@@ -3422,7 +3415,7 @@ def ass_subtitles_timecode(seconds):
|
|||||||
def dfxp2srt(dfxp_data):
|
def dfxp2srt(dfxp_data):
|
||||||
"""
|
"""
|
||||||
@param dfxp_data A bytes-like object containing DFXP data
|
@param dfxp_data A bytes-like object containing DFXP data
|
||||||
@returns A unicode object containing converted SRT data
|
@returns A string containing the converted SRT data
|
||||||
"""
|
"""
|
||||||
LEGACY_NAMESPACES = (
|
LEGACY_NAMESPACES = (
|
||||||
(b'http://www.w3.org/ns/ttml', [
|
(b'http://www.w3.org/ns/ttml', [
|
||||||
|
|||||||
Reference in New Issue
Block a user