[cleanup] Upgrade syntax

Using https://github.com/asottile/pyupgrade

1. `__future__` imports and `coding: utf-8` were removed
2. Files were rewritten with `pyupgrade --py36-plus --keep-percent-format`
3. f-strings were cherry-picked from `pyupgrade --py36-plus`

Extractors are left untouched (except removing header) to avoid unnecessary merge conflicts
pull/3404/head
pukkandan 2 years ago
parent f9934b9614
commit 86e5f3ed2e
No known key found for this signature in database
GPG Key ID: 7EEE9E1E817D0A39

@ -178,7 +178,6 @@ After you have ensured this site is distributing its content legally, you can fo
1. Start with this simple template and save it to `yt_dlp/extractor/yourextractor.py`: 1. Start with this simple template and save it to `yt_dlp/extractor/yourextractor.py`:
```python ```python
# coding: utf-8
from .common import InfoExtractor from .common import InfoExtractor

@ -1,11 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import os import os
from os.path import dirname as dirn from os.path import dirname as dirn
import sys import sys
sys.path.insert(0, dirn(dirn((os.path.abspath(__file__))))) sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
import yt_dlp import yt_dlp
BASH_COMPLETION_FILE = "completions/bash/yt-dlp" BASH_COMPLETION_FILE = "completions/bash/yt-dlp"

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
""" """
This script employs a VERY basic heuristic ('porn' in webpage.lower()) to check This script employs a VERY basic heuristic ('porn' in webpage.lower()) to check
if we are not 'age_limit' tagging some porn site if we are not 'age_limit' tagging some porn site
@ -29,7 +27,7 @@ for test in gettestcases():
try: try:
webpage = compat_urllib_request.urlopen(test['url'], timeout=10).read() webpage = compat_urllib_request.urlopen(test['url'], timeout=10).read()
except Exception: except Exception:
print('\nFail: {0}'.format(test['name'])) print('\nFail: {}'.format(test['name']))
continue continue
webpage = webpage.decode('utf8', 'replace') webpage = webpage.decode('utf8', 'replace')
@ -39,7 +37,7 @@ for test in gettestcases():
elif METHOD == 'LIST': elif METHOD == 'LIST':
domain = compat_urllib_parse_urlparse(test['url']).netloc domain = compat_urllib_parse_urlparse(test['url']).netloc
if not domain: if not domain:
print('\nFail: {0}'.format(test['name'])) print('\nFail: {}'.format(test['name']))
continue continue
domain = '.'.join(domain.split('.')[-2:]) domain = '.'.join(domain.split('.')[-2:])
@ -47,11 +45,11 @@ for test in gettestcases():
if RESULT and ('info_dict' not in test or 'age_limit' not in test['info_dict'] if RESULT and ('info_dict' not in test or 'age_limit' not in test['info_dict']
or test['info_dict']['age_limit'] != 18): or test['info_dict']['age_limit'] != 18):
print('\nPotential missing age_limit check: {0}'.format(test['name'])) print('\nPotential missing age_limit check: {}'.format(test['name']))
elif not RESULT and ('info_dict' in test and 'age_limit' in test['info_dict'] elif not RESULT and ('info_dict' in test and 'age_limit' in test['info_dict']
and test['info_dict']['age_limit'] == 18): and test['info_dict']['age_limit'] == 18):
print('\nPotential false negative: {0}'.format(test['name'])) print('\nPotential false negative: {}'.format(test['name']))
else: else:
sys.stdout.write('.') sys.stdout.write('.')

@ -1,12 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import optparse import optparse
import os import os
from os.path import dirname as dirn from os.path import dirname as dirn
import sys import sys
sys.path.insert(0, dirn(dirn((os.path.abspath(__file__))))) sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
import yt_dlp import yt_dlp
from yt_dlp.utils import shell_quote from yt_dlp.utils import shell_quote

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import codecs import codecs
import subprocess import subprocess

@ -1,4 +1,3 @@
# coding: utf-8
import re import re
from ..utils import bug_reports_message, write_string from ..utils import bug_reports_message, write_string

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import io
import optparse import optparse
import re import re
@ -16,7 +13,7 @@ def main():
infile, outfile = args infile, outfile = args
with io.open(infile, encoding='utf-8') as inf: with open(infile, encoding='utf-8') as inf:
readme = inf.read() readme = inf.read()
bug_text = re.search( bug_text = re.search(
@ -26,7 +23,7 @@ def main():
out = bug_text + dev_text out = bug_text + dev_text
with io.open(outfile, 'w', encoding='utf-8') as outf: with open(outfile, 'w', encoding='utf-8') as outf:
outf.write(out) outf.write(out)

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import io import io
import optparse import optparse
@ -13,7 +11,7 @@ def main():
infile, outfile = args infile, outfile = args
with io.open(infile, encoding='utf-8') as inf: with open(infile, encoding='utf-8') as inf:
issue_template_tmpl = inf.read() issue_template_tmpl = inf.read()
# Get the version from yt_dlp/version.py without importing the package # Get the version from yt_dlp/version.py without importing the package
@ -22,8 +20,9 @@ def main():
out = issue_template_tmpl % {'version': locals()['__version__']} out = issue_template_tmpl % {'version': locals()['__version__']}
with io.open(outfile, 'w', encoding='utf-8') as outf: with open(outfile, 'w', encoding='utf-8') as outf:
outf.write(out) outf.write(out)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

@ -1,13 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals, print_function
from inspect import getsource from inspect import getsource
import io
import os import os
from os.path import dirname as dirn from os.path import dirname as dirn
import sys import sys
sys.path.insert(0, dirn(dirn((os.path.abspath(__file__))))) sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
lazy_extractors_filename = sys.argv[1] if len(sys.argv) > 1 else 'yt_dlp/extractor/lazy_extractors.py' lazy_extractors_filename = sys.argv[1] if len(sys.argv) > 1 else 'yt_dlp/extractor/lazy_extractors.py'
if os.path.exists(lazy_extractors_filename): if os.path.exists(lazy_extractors_filename):
@ -25,7 +22,7 @@ from yt_dlp.extractor.common import InfoExtractor, SearchInfoExtractor
if os.path.exists(plugins_blocked_dirname): if os.path.exists(plugins_blocked_dirname):
os.rename(plugins_blocked_dirname, plugins_dirname) os.rename(plugins_blocked_dirname, plugins_dirname)
with open('devscripts/lazy_load_template.py', 'rt') as f: with open('devscripts/lazy_load_template.py') as f:
module_template = f.read() module_template = f.read()
CLASS_PROPERTIES = ['ie_key', 'working', '_match_valid_url', 'suitable', '_match_id', 'get_temp_id'] CLASS_PROPERTIES = ['ie_key', 'working', '_match_valid_url', 'suitable', '_match_id', 'get_temp_id']
@ -72,7 +69,7 @@ classes = _ALL_CLASSES[:-1]
ordered_cls = [] ordered_cls = []
while classes: while classes:
for c in classes[:]: for c in classes[:]:
bases = set(c.__bases__) - set((object, InfoExtractor, SearchInfoExtractor)) bases = set(c.__bases__) - {object, InfoExtractor, SearchInfoExtractor}
stop = False stop = False
for b in bases: for b in bases:
if b not in classes and b not in ordered_cls: if b not in classes and b not in ordered_cls:
@ -97,9 +94,9 @@ for ie in ordered_cls:
names.append(name) names.append(name)
module_contents.append( module_contents.append(
'\n_ALL_CLASSES = [{0}]'.format(', '.join(names))) '\n_ALL_CLASSES = [{}]'.format(', '.join(names)))
module_src = '\n'.join(module_contents) + '\n' module_src = '\n'.join(module_contents) + '\n'
with io.open(lazy_extractors_filename, 'wt', encoding='utf-8') as f: with open(lazy_extractors_filename, 'wt', encoding='utf-8') as f:
f.write(module_src) f.write(module_src)

@ -2,10 +2,6 @@
# yt-dlp --help | make_readme.py # yt-dlp --help | make_readme.py
# This must be run in a console of correct width # This must be run in a console of correct width
from __future__ import unicode_literals
import io
import sys import sys
import re import re
@ -15,7 +11,7 @@ helptext = sys.stdin.read()
if isinstance(helptext, bytes): if isinstance(helptext, bytes):
helptext = helptext.decode('utf-8') helptext = helptext.decode('utf-8')
with io.open(README_FILE, encoding='utf-8') as f: with open(README_FILE, encoding='utf-8') as f:
oldreadme = f.read() oldreadme = f.read()
header = oldreadme[:oldreadme.index('## General Options:')] header = oldreadme[:oldreadme.index('## General Options:')]
@ -25,7 +21,7 @@ options = helptext[helptext.index(' General Options:'):]
options = re.sub(r'(?m)^ (\w.+)$', r'## \1', options) options = re.sub(r'(?m)^ (\w.+)$', r'## \1', options)
options = options + '\n' options = options + '\n'
with io.open(README_FILE, 'w', encoding='utf-8') as f: with open(README_FILE, 'w', encoding='utf-8') as f:
f.write(header) f.write(header)
f.write(options) f.write(options)
f.write(footer) f.write(footer)

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import io
import optparse import optparse
import os import os
import sys import sys
@ -23,11 +20,11 @@ def main():
def gen_ies_md(ies): def gen_ies_md(ies):
for ie in ies: for ie in ies:
ie_md = '**{0}**'.format(ie.IE_NAME) ie_md = f'**{ie.IE_NAME}**'
if ie.IE_DESC is False: if ie.IE_DESC is False:
continue continue
if ie.IE_DESC is not None: if ie.IE_DESC is not None:
ie_md += ': {0}'.format(ie.IE_DESC) ie_md += f': {ie.IE_DESC}'
search_key = getattr(ie, 'SEARCH_KEY', None) search_key = getattr(ie, 'SEARCH_KEY', None)
if search_key is not None: if search_key is not None:
ie_md += f'; "{ie.SEARCH_KEY}:" prefix' ie_md += f'; "{ie.SEARCH_KEY}:" prefix'
@ -40,7 +37,7 @@ def main():
' - ' + md + '\n' ' - ' + md + '\n'
for md in gen_ies_md(ies)) for md in gen_ies_md(ies))
with io.open(outfile, 'w', encoding='utf-8') as outf: with open(outfile, 'w', encoding='utf-8') as outf:
outf.write(out) outf.write(out)

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import io
import optparse import optparse
import os.path import os.path
import re import re
@ -32,14 +29,14 @@ def main():
outfile, = args outfile, = args
with io.open(README_FILE, encoding='utf-8') as f: with open(README_FILE, encoding='utf-8') as f:
readme = f.read() readme = f.read()
readme = filter_excluded_sections(readme) readme = filter_excluded_sections(readme)
readme = move_sections(readme) readme = move_sections(readme)
readme = filter_options(readme) readme = filter_options(readme)
with io.open(outfile, 'w', encoding='utf-8') as outf: with open(outfile, 'w', encoding='utf-8') as outf:
outf.write(PREFIX + readme) outf.write(PREFIX + readme)

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import json import json
import os import os
import re import re
@ -27,7 +25,7 @@ tarball_file = next(x for x in pypi_release['urls'] if x['filename'].endswith('.
sha256sum = tarball_file['digests']['sha256'] sha256sum = tarball_file['digests']['sha256']
url = tarball_file['url'] url = tarball_file['url']
with open(filename, 'r') as r: with open(filename) as r:
formulae_text = r.read() formulae_text = r.read()
formulae_text = re.sub(r'sha256 "[0-9a-f]*?"', 'sha256 "%s"' % sha256sum, formulae_text) formulae_text = re.sub(r'sha256 "[0-9a-f]*?"', 'sha256 "%s"' % sha256sum, formulae_text)

@ -4,7 +4,7 @@ import sys
import subprocess import subprocess
with open('yt_dlp/version.py', 'rt') as f: with open('yt_dlp/version.py') as f:
exec(compile(f.read(), 'yt_dlp/version.py', 'exec')) exec(compile(f.read(), 'yt_dlp/version.py', 'exec'))
old_version = locals()['__version__'] old_version = locals()['__version__']

@ -1,11 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import os import os
from os.path import dirname as dirn from os.path import dirname as dirn
import sys import sys
sys.path.insert(0, dirn(dirn((os.path.abspath(__file__))))) sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
import yt_dlp import yt_dlp
ZSH_COMPLETION_FILE = "completions/zsh/_yt-dlp" ZSH_COMPLETION_FILE = "completions/zsh/_yt-dlp"

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
import os import os
import platform import platform
import sys import sys

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
import os.path import os.path
import warnings import warnings
import sys import sys

@ -1,7 +1,4 @@
from __future__ import unicode_literals
import errno import errno
import io
import hashlib import hashlib
import json import json
import os.path import os.path
@ -35,10 +32,10 @@ def get_params(override=None):
'parameters.json') 'parameters.json')
LOCAL_PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), LOCAL_PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)),
'local_parameters.json') 'local_parameters.json')
with io.open(PARAMETERS_FILE, encoding='utf-8') as pf: with open(PARAMETERS_FILE, encoding='utf-8') as pf:
parameters = json.load(pf) parameters = json.load(pf)
if os.path.exists(LOCAL_PARAMETERS_FILE): if os.path.exists(LOCAL_PARAMETERS_FILE):
with io.open(LOCAL_PARAMETERS_FILE, encoding='utf-8') as pf: with open(LOCAL_PARAMETERS_FILE, encoding='utf-8') as pf:
parameters.update(json.load(pf)) parameters.update(json.load(pf))
if override: if override:
parameters.update(override) parameters.update(override)
@ -63,7 +60,7 @@ def report_warning(message):
_msg_header = '\033[0;33mWARNING:\033[0m' _msg_header = '\033[0;33mWARNING:\033[0m'
else: else:
_msg_header = 'WARNING:' _msg_header = 'WARNING:'
output = '%s %s\n' % (_msg_header, message) output = f'{_msg_header} {message}\n'
if 'b' in getattr(sys.stderr, 'mode', ''): if 'b' in getattr(sys.stderr, 'mode', ''):
output = output.encode(preferredencoding()) output = output.encode(preferredencoding())
sys.stderr.write(output) sys.stderr.write(output)
@ -74,7 +71,7 @@ class FakeYDL(YoutubeDL):
# Different instances of the downloader can't share the same dictionary # Different instances of the downloader can't share the same dictionary
# some test set the "sublang" parameter, which would break the md5 checks. # some test set the "sublang" parameter, which would break the md5 checks.
params = get_params(override=override) params = get_params(override=override)
super(FakeYDL, self).__init__(params, auto_init=False) super().__init__(params, auto_init=False)
self.result = [] self.result = []
def to_screen(self, s, skip_eol=None): def to_screen(self, s, skip_eol=None):
@ -99,8 +96,7 @@ class FakeYDL(YoutubeDL):
def gettestcases(include_onlymatching=False): def gettestcases(include_onlymatching=False):
for ie in yt_dlp.extractor.gen_extractors(): for ie in yt_dlp.extractor.gen_extractors():
for tc in ie.get_testcases(include_onlymatching): yield from ie.get_testcases(include_onlymatching)
yield tc
md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest() md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest()
@ -113,33 +109,30 @@ def expect_value(self, got, expected, field):
self.assertTrue( self.assertTrue(
isinstance(got, compat_str), isinstance(got, compat_str),
'Expected a %s object, but got %s for field %s' % ( f'Expected a {compat_str.__name__} object, but got {type(got).__name__} for field {field}')
compat_str.__name__, type(got).__name__, field))
self.assertTrue( self.assertTrue(
match_rex.match(got), match_rex.match(got),
'field %s (value: %r) should match %r' % (field, got, match_str)) f'field {field} (value: {got!r}) should match {match_str!r}')
elif isinstance(expected, compat_str) and expected.startswith('startswith:'): elif isinstance(expected, compat_str) and expected.startswith('startswith:'):
start_str = expected[len('startswith:'):] start_str = expected[len('startswith:'):]
self.assertTrue( self.assertTrue(
isinstance(got, compat_str), isinstance(got, compat_str),
'Expected a %s object, but got %s for field %s' % ( f'Expected a {compat_str.__name__} object, but got {type(got).__name__} for field {field}')
compat_str.__name__, type(got).__name__, field))
self.assertTrue( self.assertTrue(
got.startswith(start_str), got.startswith(start_str),
'field %s (value: %r) should start with %r' % (field, got, start_str)) f'field {field} (value: {got!r}) should start with {start_str!r}')
elif isinstance(expected, compat_str) and expected.startswith('contains:'): elif isinstance(expected, compat_str) and expected.startswith('contains:'):
contains_str = expected[len('contains:'):] contains_str = expected[len('contains:'):]
self.assertTrue( self.assertTrue(
isinstance(got, compat_str), isinstance(got, compat_str),
'Expected a %s object, but got %s for field %s' % ( f'Expected a {compat_str.__name__} object, but got {type(got).__name__} for field {field}')
compat_str.__name__, type(got).__name__, field))
self.assertTrue( self.assertTrue(
contains_str in got, contains_str in got,
'field %s (value: %r) should contain %r' % (field, got, contains_str)) f'field {field} (value: {got!r}) should contain {contains_str!r}')
elif isinstance(expected, type): elif isinstance(expected, type):
self.assertTrue( self.assertTrue(
isinstance(got, expected), isinstance(got, expected),
'Expected type %r for field %s, but got value %r of type %r' % (expected, field, got, type(got))) f'Expected type {expected!r} for field {field}, but got value {got!r} of type {type(got)!r}')
elif isinstance(expected, dict) and isinstance(got, dict): elif isinstance(expected, dict) and isinstance(got, dict):
expect_dict(self, got, expected) expect_dict(self, got, expected)
elif isinstance(expected, list) and isinstance(got, list): elif isinstance(expected, list) and isinstance(got, list):
@ -159,13 +152,12 @@ def expect_value(self, got, expected, field):
if isinstance(expected, compat_str) and expected.startswith('md5:'): if isinstance(expected, compat_str) and expected.startswith('md5:'):
self.assertTrue( self.assertTrue(
isinstance(got, compat_str), isinstance(got, compat_str),
'Expected field %s to be a unicode object, but got value %r of type %r' % (field, got, type(got))) f'Expected field {field} to be a unicode object, but got value {got!r} of type {type(got)!r}')
got = 'md5:' + md5(got) got = 'md5:' + md5(got)
elif isinstance(expected, compat_str) and re.match(r'^(?:min|max)?count:\d+', expected): elif isinstance(expected, compat_str) and re.match(r'^(?:min|max)?count:\d+', expected):
self.assertTrue( self.assertTrue(
isinstance(got, (list, dict)), isinstance(got, (list, dict)),
'Expected field %s to be a list or a dict, but it is of type %s' % ( f'Expected field {field} to be a list or a dict, but it is of type {type(got).__name__}')
field, type(got).__name__))
op, _, expected_num = expected.partition(':') op, _, expected_num = expected.partition(':')
expected_num = int(expected_num) expected_num = int(expected_num)
if op == 'mincount': if op == 'mincount':
@ -185,7 +177,7 @@ def expect_value(self, got, expected, field):
return return
self.assertEqual( self.assertEqual(
expected, got, expected, got,
'Invalid value for field %s, expected %r, got %r' % (field, expected, got)) f'Invalid value for field {field}, expected {expected!r}, got {got!r}')
def expect_dict(self, got_dict, expected_dict): def expect_dict(self, got_dict, expected_dict):
@ -260,13 +252,13 @@ def expect_info_dict(self, got_dict, expected_dict):
info_dict_str = '' info_dict_str = ''
if len(missing_keys) != len(expected_dict): if len(missing_keys) != len(expected_dict):
info_dict_str += ''.join( info_dict_str += ''.join(
' %s: %s,\n' % (_repr(k), _repr(v)) f' {_repr(k)}: {_repr(v)},\n'
for k, v in test_info_dict.items() if k not in missing_keys) for k, v in test_info_dict.items() if k not in missing_keys)
if info_dict_str: if info_dict_str:
info_dict_str += '\n' info_dict_str += '\n'
info_dict_str += ''.join( info_dict_str += ''.join(
' %s: %s,\n' % (_repr(k), _repr(test_info_dict[k])) f' {_repr(k)}: {_repr(test_info_dict[k])},\n'
for k in missing_keys) for k in missing_keys)
write_string( write_string(
'\n\'info_dict\': {\n' + info_dict_str + '},\n', out=sys.stderr) '\n\'info_dict\': {\n' + info_dict_str + '},\n', out=sys.stderr)
@ -295,21 +287,21 @@ def assertRegexpMatches(self, text, regexp, msg=None):
def assertGreaterEqual(self, got, expected, msg=None): def assertGreaterEqual(self, got, expected, msg=None):
if not (got >= expected): if not (got >= expected):
if msg is None: if msg is None:
msg = '%r not greater than or equal to %r' % (got, expected) msg = f'{got!r} not greater than or equal to {expected!r}'
self.assertTrue(got >= expected, msg) self.assertTrue(got >= expected, msg)
def assertLessEqual(self, got, expected, msg=None): def assertLessEqual(self, got, expected, msg=None):
if not (got <= expected): if not (got <= expected):
if msg is None: if msg is None:
msg = '%r not less than or equal to %r' % (got, expected) msg = f'{got!r} not less than or equal to {expected!r}'
self.assertTrue(got <= expected, msg) self.assertTrue(got <= expected, msg)
def assertEqual(self, got, expected, msg=None): def assertEqual(self, got, expected, msg=None):
if not (got == expected): if not (got == expected):
if msg is None: if msg is None:
msg = '%r not equal to %r' % (got, expected) msg = f'{got!r} not equal to {expected!r}'
self.assertTrue(got == expected, msg) self.assertTrue(got == expected, msg)

@ -1,9 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import io
import os import os
import sys import sys
import unittest import unittest
@ -1011,8 +1007,7 @@ jwplayer("mediaplayer").setup({"abouttext":"Visit Indie DB","aboutlink":"http:\/
] ]
for m3u8_file, m3u8_url, expected_formats, expected_subs in _TEST_CASES: for m3u8_file, m3u8_url, expected_formats, expected_subs in _TEST_CASES:
with io.open('./test/testdata/m3u8/%s.m3u8' % m3u8_file, with open('./test/testdata/m3u8/%s.m3u8' % m3u8_file, encoding='utf-8') as f:
mode='r', encoding='utf-8') as f:
formats, subs = self.ie._parse_m3u8_formats_and_subtitles( formats, subs = self.ie._parse_m3u8_formats_and_subtitles(
f.read(), m3u8_url, ext='mp4') f.read(), m3u8_url, ext='mp4')
self.ie._sort_formats(formats) self.ie._sort_formats(formats)
@ -1357,8 +1352,7 @@ jwplayer("mediaplayer").setup({"abouttext":"Visit Indie DB","aboutlink":"http:\/
] ]
for mpd_file, mpd_url, mpd_base_url, expected_formats, expected_subtitles in _TEST_CASES: for mpd_file, mpd_url, mpd_base_url, expected_formats, expected_subtitles in _TEST_CASES:
with io.open('./test/testdata/mpd/%s.mpd' % mpd_file, with open('./test/testdata/mpd/%s.mpd' % mpd_file, encoding='utf-8') as f:
mode='r', encoding='utf-8') as f:
formats, subtitles = self.ie._parse_mpd_formats_and_subtitles( formats, subtitles = self.ie._parse_mpd_formats_and_subtitles(
compat_etree_fromstring(f.read().encode('utf-8')), compat_etree_fromstring(f.read().encode('utf-8')),
mpd_base_url=mpd_base_url, mpd_url=mpd_url) mpd_base_url=mpd_base_url, mpd_url=mpd_url)
@ -1549,8 +1543,7 @@ jwplayer("mediaplayer").setup({"abouttext":"Visit Indie DB","aboutlink":"http:\/
] ]
for ism_file, ism_url, expected_formats, expected_subtitles in _TEST_CASES: for ism_file, ism_url, expected_formats, expected_subtitles in _TEST_CASES:
with io.open('./test/testdata/ism/%s.Manifest' % ism_file, with open('./test/testdata/ism/%s.Manifest' % ism_file, encoding='utf-8') as f:
mode='r', encoding='utf-8') as f:
formats, subtitles = self.ie._parse_ism_formats_and_subtitles( formats, subtitles = self.ie._parse_ism_formats_and_subtitles(
compat_etree_fromstring(f.read().encode('utf-8')), ism_url=ism_url) compat_etree_fromstring(f.read().encode('utf-8')), ism_url=ism_url)
self.ie._sort_formats(formats) self.ie._sort_formats(formats)
@ -1576,8 +1569,7 @@ jwplayer("mediaplayer").setup({"abouttext":"Visit Indie DB","aboutlink":"http:\/
] ]
for f4m_file, f4m_url, expected_formats in _TEST_CASES: for f4m_file, f4m_url, expected_formats in _TEST_CASES:
with io.open('./test/testdata/f4m/%s.f4m' % f4m_file, with open('./test/testdata/f4m/%s.f4m' % f4m_file, encoding='utf-8') as f:
mode='r', encoding='utf-8') as f:
formats = self.ie._parse_f4m_formats( formats = self.ie._parse_f4m_formats(
compat_etree_fromstring(f.read().encode('utf-8')), compat_etree_fromstring(f.read().encode('utf-8')),
f4m_url, None) f4m_url, None)
@ -1624,8 +1616,7 @@ jwplayer("mediaplayer").setup({"abouttext":"Visit Indie DB","aboutlink":"http:\/
] ]
for xspf_file, xspf_url, expected_entries in _TEST_CASES: for xspf_file, xspf_url, expected_entries in _TEST_CASES:
with io.open('./test/testdata/xspf/%s.xspf' % xspf_file, with open('./test/testdata/xspf/%s.xspf' % xspf_file, encoding='utf-8') as f:
mode='r', encoding='utf-8') as f:
entries = self.ie._parse_xspf( entries = self.ie._parse_xspf(
compat_etree_fromstring(f.read().encode('utf-8')), compat_etree_fromstring(f.read().encode('utf-8')),
xspf_file, xspf_url=xspf_url, xspf_base_url=xspf_url) xspf_file, xspf_url=xspf_url, xspf_base_url=xspf_url)

@ -1,8 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -25,7 +21,7 @@ TEST_URL = 'http://localhost/sample.mp4'
class YDL(FakeYDL): class YDL(FakeYDL):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(YDL, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.downloaded_info_dicts = [] self.downloaded_info_dicts = []
self.msgs = [] self.msgs = []
@ -551,11 +547,11 @@ class TestYoutubeDL(unittest.TestCase):
def s_formats(lang, autocaption=False): def s_formats(lang, autocaption=False):
return [{ return [{
'ext': ext, 'ext': ext,
'url': 'http://localhost/video.%s.%s' % (lang, ext), 'url': f'http://localhost/video.{lang}.{ext}',
'_auto': autocaption, '_auto': autocaption,
} for ext in ['vtt', 'srt', 'ass']] } for ext in ['vtt', 'srt', 'ass']]
subtitles = dict((l, s_formats(l)) for l in ['en', 'fr', 'es']) subtitles = {l: s_formats(l) for l in ['en', 'fr', 'es']}
auto_captions = dict((l, s_formats(l, True)) for l in ['it', 'pt', 'es']) auto_captions = {l: s_formats(l, True) for l in ['it', 'pt', 'es']}
info_dict = { info_dict = {
'id': 'test', 'id': 'test',
'title': 'Test', 'title': 'Test',
@ -580,7 +576,7 @@ class TestYoutubeDL(unittest.TestCase):
result = get_info({'writesubtitles': True}) result = get_info({'writesubtitles': True})
subs = result['requested_subtitles'] subs = result['requested_subtitles']
self.assertTrue(subs) self.assertTrue(subs)
self.assertEqual(set(subs.keys()), set(['en'])) self.assertEqual(set(subs.keys()), {'en'})
self.assertTrue(subs['en'].get('data') is None) self.assertTrue(subs['en'].get('data') is None)
self.assertEqual(subs['en']['ext'], 'ass') self.assertEqual(subs['en']['ext'], 'ass')
@ -591,39 +587,39 @@ class TestYoutubeDL(unittest.TestCase):
result = get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']}) result = get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']})
subs = result['requested_subtitles'] subs = result['requested_subtitles']
self.assertTrue(subs) self.assertTrue(subs)
self.assertEqual(set(subs.keys()), set(['es', 'fr'])) self.assertEqual(set(subs.keys()), {'es', 'fr'})
result = get_info({'writesubtitles': True, 'subtitleslangs': ['all', '-en']}) result = get_info({'writesubtitles': True, 'subtitleslangs': ['all', '-en']})
subs = result['requested_subtitles'] subs = result['requested_subtitles']
self.assertTrue(subs) self.assertTrue(subs)
self.assertEqual(set(subs.keys()), set(['es', 'fr'])) self.assertEqual(set(subs.keys()), {'es', 'fr'})
result = get_info({'writesubtitles': True, 'subtitleslangs': ['en', 'fr', '-en']}) result = get_info({'writesubtitles': True, 'subtitleslangs': ['en', 'fr', '-en']})
subs = result['requested_subtitles'] subs = result['requested_subtitles']
self.assertTrue(subs) self.assertTrue(subs)
self.assertEqual(set(subs.keys()), set(['fr'])) self.assertEqual(set(subs.keys()), {'fr'})
result = get_info({'writesubtitles': True, 'subtitleslangs': ['-en', 'en']}) result = get_info({'writesubtitles': True, 'subtitleslangs': ['-en', 'en']})
subs = result['requested_subtitles'] subs = result['requested_subtitles']
self.assertTrue(subs) self.assertTrue(subs)
self.assertEqual(set(subs.keys()), set(['en'])) self.assertEqual(set(subs.keys()), {'en'})
result = get_info({'writesubtitles': True, 'subtitleslangs': ['e.+']}) result = get_info({'writesubtitles': True, 'subtitleslangs': ['e.+']})
subs = result['requested_subtitles'] subs = result['requested_subtitles']
self.assertTrue(subs) self.assertTrue(subs)
self.assertEqual(set(subs.keys()), set(['es', 'en'])) self.assertEqual(set(subs.keys()), {'es', 'en'})
result = get_info({'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']}) result = get_info({'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
subs = result['requested_subtitles'] subs = result['requested_subtitles']
self.assertTrue(subs) self.assertTrue(subs)
self.assertEqual(set(subs.keys()), set(['es', 'pt'])) self.assertEqual(set(subs.keys()), {'es', 'pt'})
self.assertFalse(subs['es']['_auto']) self.assertFalse(subs['es']['_auto'])
self.assertTrue(subs['pt']['_auto']) self.assertTrue(subs['pt']['_auto'])
result = get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']}) result = get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
subs = result['requested_subtitles'] subs = result['requested_subtitles']
self.assertTrue(subs) self.assertTrue(subs)
self.assertEqual(set(subs.keys()), set(['es', 'pt'])) self.assertEqual(set(subs.keys()), {'es', 'pt'})
self.assertTrue(subs['es']['_auto']) self.assertTrue(subs['es']['_auto'])
self.assertTrue(subs['pt']['_auto']) self.assertTrue(subs['pt']['_auto'])
@ -1082,7 +1078,7 @@ class TestYoutubeDL(unittest.TestCase):
class _YDL(YDL): class _YDL(YDL):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(_YDL, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def trouble(self, s, tb=None): def trouble(self, s, tb=None):
pass pass

@ -1,8 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
import os import os
import re import re
import sys import sys

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -81,11 +78,11 @@ class TestAllURLsMatching(unittest.TestCase):
url = tc['url'] url = tc['url']
for ie in ies: for ie in ies:
if type(ie).__name__ in ('GenericIE', tc['name'] + 'IE'): if type(ie).__name__ in ('GenericIE', tc['name'] + 'IE'):
self.assertTrue(ie.suitable(url), '%s should match URL %r' % (type(ie).__name__, url)) self.assertTrue(ie.suitable(url), f'{type(ie).__name__} should match URL {url!r}')
else: else:
self.assertFalse( self.assertFalse(
ie.suitable(url), ie.suitable(url),
'%s should not match URL %r . That URL belongs to %s.' % (type(ie).__name__, url, tc['name'])) f'{type(ie).__name__} should not match URL {url!r} . That URL belongs to {tc["name"]}.')
def test_keywords(self): def test_keywords(self):
self.assertMatch(':ytsubs', ['youtube:subscriptions']) self.assertMatch(':ytsubs', ['youtube:subscriptions'])
@ -120,7 +117,7 @@ class TestAllURLsMatching(unittest.TestCase):
for (ie_name, ie_list) in name_accu.items(): for (ie_name, ie_list) in name_accu.items():
self.assertEqual( self.assertEqual(
len(ie_list), 1, len(ie_list), 1,
'Multiple extractors with the same IE_NAME "%s" (%s)' % (ie_name, ', '.join(ie_list))) f'Multiple extractors with the same IE_NAME "{ie_name}" ({", ".join(ie_list)})')
if __name__ == '__main__': if __name__ == '__main__':

@ -1,8 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
import shutil import shutil
# Allow direct execution # Allow direct execution

@ -1,8 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -48,7 +44,7 @@ class TestCompat(unittest.TestCase):
all_names = yt_dlp.compat.__all__ all_names = yt_dlp.compat.__all__
present_names = set(filter( present_names = set(filter(
lambda c: '_' in c and not c.startswith('_'), lambda c: '_' in c and not c.startswith('_'),
dir(yt_dlp.compat))) - set(['unicode_literals']) dir(yt_dlp.compat))) - {'unicode_literals'}
self.assertEqual(all_names, sorted(present_names)) self.assertEqual(all_names, sorted(present_names))
def test_compat_urllib_parse_unquote(self): def test_compat_urllib_parse_unquote(self):

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -21,7 +18,6 @@ from test.helper import (
import hashlib import hashlib
import io
import json import json
import socket import socket
@ -46,7 +42,7 @@ class YoutubeDL(yt_dlp.YoutubeDL):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.to_stderr = self.to_screen self.to_stderr = self.to_screen
self.processed_info_dicts = [] self.processed_info_dicts = []
super(YoutubeDL, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def report_warning(self, message): def report_warning(self, message):
# Don't accept warnings during tests # Don't accept warnings during tests
@ -54,7 +50,7 @@ class YoutubeDL(yt_dlp.YoutubeDL):
def process_info(self, info_dict): def process_info(self, info_dict):
self.processed_info_dicts.append(info_dict.copy()) self.processed_info_dicts.append(info_dict.copy())
return super(YoutubeDL, self).process_info(info_dict) return super().process_info(info_dict)
def _file_md5(fn): def _file_md5(fn):
@ -80,7 +76,7 @@ class TestDownload(unittest.TestCase):
def strclass(cls): def strclass(cls):
"""From 2.7's unittest; 2.6 had _strclass so we can't import it.""" """From 2.7's unittest; 2.6 had _strclass so we can't import it."""
return '%s.%s' % (cls.__module__, cls.__name__) return f'{cls.__module__}.{cls.__name__}'
add_ie = getattr(self, self._testMethodName).add_ie add_ie = getattr(self, self._testMethodName).add_ie
return '%s (%s)%s:' % (self._testMethodName, return '%s (%s)%s:' % (self._testMethodName,
@ -179,7 +175,7 @@ def generator(test_case, tname):
report_warning('%s failed due to network errors, skipping...' % tname) report_warning('%s failed due to network errors, skipping...' % tname)
return return
print('Retrying: {0} failed tries\n\n##########\n\n'.format(try_num)) print(f'Retrying: {try_num} failed tries\n\n##########\n\n')
try_num += 1 try_num += 1
else: else:
@ -245,7 +241,7 @@ def generator(test_case, tname):
self.assertTrue( self.assertTrue(
os.path.exists(info_json_fn), os.path.exists(info_json_fn),
'Missing info file %s' % info_json_fn) 'Missing info file %s' % info_json_fn)
with io.open(info_json_fn, encoding='utf-8') as infof: with open(info_json_fn, encoding='utf-8') as infof:
info_dict = json.load(infof) info_dict = json.load(infof)
expect_info_dict(self, info_dict, tc.get('info_dict', {})) expect_info_dict(self, info_dict, tc.get('info_dict', {}))
finally: finally:

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import re import re
@ -66,7 +63,7 @@ class HTTPTestRequestHandler(compat_http_server.BaseHTTPRequestHandler):
assert False assert False
class FakeLogger(object): class FakeLogger:
def debug(self, msg): def debug(self, msg):
pass pass

@ -1,8 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
import unittest import unittest
import sys import sys
@ -45,7 +41,7 @@ class TestExecution(unittest.TestCase):
finally: finally:
try: try:
os.remove('yt_dlp/extractor/lazy_extractors.py') os.remove('yt_dlp/extractor/lazy_extractors.py')
except (IOError, OSError): except OSError:
pass pass

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -41,7 +38,7 @@ class HTTPTestRequestHandler(compat_http_server.BaseHTTPRequestHandler):
assert False assert False
class FakeLogger(object): class FakeLogger:
def debug(self, msg): def debug(self, msg):
pass pass
@ -117,23 +114,23 @@ class TestProxy(unittest.TestCase):
self.geo_proxy_thread.start() self.geo_proxy_thread.start()
def test_proxy(self): def test_proxy(self):
geo_proxy = '127.0.0.1:{0}'.format(self.geo_port) geo_proxy = f'127.0.0.1:{self.geo_port}'
ydl = YoutubeDL({ ydl = YoutubeDL({
'proxy': '127.0.0.1:{0}'.format(self.port), 'proxy': f'127.0.0.1:{self.port}',
'geo_verification_proxy': geo_proxy, 'geo_verification_proxy': geo_proxy,
}) })
url = 'http://foo.com/bar' url = 'http://foo.com/bar'
response = ydl.urlopen(url).read().decode('utf-8') response = ydl.urlopen(url).read().decode('utf-8')
self.assertEqual(response, 'normal: {0}'.format(url)) self.assertEqual(response, f'normal: {url}')
req = compat_urllib_request.Request(url) req = compat_urllib_request.Request(url)
req.add_header('Ytdl-request-proxy', geo_proxy) req.add_header('Ytdl-request-proxy', geo_proxy)
response = ydl.urlopen(req).read().decode('utf-8') response = ydl.urlopen(req).read().decode('utf-8')
self.assertEqual(response, 'geo: {0}'.format(url)) self.assertEqual(response, f'geo: {url}')
def test_proxy_with_idn(self): def test_proxy_with_idn(self):
ydl = YoutubeDL({ ydl = YoutubeDL({
'proxy': '127.0.0.1:{0}'.format(self.port), 'proxy': f'127.0.0.1:{self.port}',
}) })
url = 'http://中文.tw/' url = 'http://中文.tw/'
response = ydl.urlopen(url).read().decode('utf-8') response = ydl.urlopen(url).read().decode('utf-8')

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -12,7 +9,7 @@ from test.helper import FakeYDL, is_download_test
from yt_dlp.extractor import IqiyiIE from yt_dlp.extractor import IqiyiIE
class WarningLogger(object): class WarningLogger:
def __init__(self): def __init__(self):
self.messages = [] self.messages = []

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import os import os
import sys import sys
import unittest import unittest

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import os import os
from os.path import join from os.path import join
import subprocess import subprocess

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
import os import os
import sys import sys
import unittest import unittest
@ -14,7 +11,7 @@ from yt_dlp.utils import DownloadError
class YoutubeDL(yt_dlp.YoutubeDL): class YoutubeDL(yt_dlp.YoutubeDL):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(YoutubeDL, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.to_stderr = self.to_screen self.to_stderr = self.to_screen

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -54,7 +52,7 @@ class BaseTestSubtitles(unittest.TestCase):
if sub_info.get('data') is None: if sub_info.get('data') is None:
uf = self.DL.urlopen(sub_info['url']) uf = self.DL.urlopen(sub_info['url'])
sub_info['data'] = uf.read().decode('utf-8') sub_info['data'] = uf.read().decode('utf-8')
return dict((l, sub_info['data']) for l, sub_info in subtitles.items()) return {l: sub_info['data'] for l, sub_info in subtitles.items()}
@is_download_test @is_download_test
@ -163,7 +161,7 @@ class TestVimeoSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['de', 'en', 'es', 'fr'])) self.assertEqual(set(subtitles.keys()), {'de', 'en', 'es', 'fr'})
self.assertEqual(md5(subtitles['en']), '8062383cf4dec168fc40a088aa6d5888') self.assertEqual(md5(subtitles['en']), '8062383cf4dec168fc40a088aa6d5888')
self.assertEqual(md5(subtitles['fr']), 'b6191146a6c5d3a452244d853fde6dc8') self.assertEqual(md5(subtitles['fr']), 'b6191146a6c5d3a452244d853fde6dc8')
@ -186,7 +184,7 @@ class TestWallaSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['heb'])) self.assertEqual(set(subtitles.keys()), {'heb'})
self.assertEqual(md5(subtitles['heb']), 'e758c5d7cb982f6bef14f377ec7a3920') self.assertEqual(md5(subtitles['heb']), 'e758c5d7cb982f6bef14f377ec7a3920')
def test_nosubtitles(self): def test_nosubtitles(self):
@ -208,7 +206,7 @@ class TestCeskaTelevizeSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['cs'])) self.assertEqual(set(subtitles.keys()), {'cs'})
self.assertTrue(len(subtitles['cs']) > 20000) self.assertTrue(len(subtitles['cs']) > 20000)
def test_nosubtitles(self): def test_nosubtitles(self):
@ -229,7 +227,7 @@ class TestLyndaSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['en'])) self.assertEqual(set(subtitles.keys()), {'en'})
self.assertEqual(md5(subtitles['en']), '09bbe67222259bed60deaa26997d73a7') self.assertEqual(md5(subtitles['en']), '09bbe67222259bed60deaa26997d73a7')
@ -242,7 +240,7 @@ class TestNPOSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['nl'])) self.assertEqual(set(subtitles.keys()), {'nl'})
self.assertEqual(md5(subtitles['nl']), 'fc6435027572b63fb4ab143abd5ad3f4') self.assertEqual(md5(subtitles['nl']), 'fc6435027572b63fb4ab143abd5ad3f4')
@ -252,13 +250,13 @@ class TestMTVSubtitles(BaseTestSubtitles):
IE = ComedyCentralIE IE = ComedyCentralIE
def getInfoDict(self): def getInfoDict(self):
return super(TestMTVSubtitles, self).getInfoDict()['entries'][0] return super().getInfoDict()['entries'][0]
def test_allsubtitles(self): def test_allsubtitles(self):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['en'])) self.assertEqual(set(subtitles.keys()), {'en'})
self.assertEqual(md5(subtitles['en']), '78206b8d8a0cfa9da64dc026eea48961') self.assertEqual(md5(subtitles['en']), '78206b8d8a0cfa9da64dc026eea48961')
@ -271,7 +269,7 @@ class TestNRKSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['no'])) self.assertEqual(set(subtitles.keys()), {'no'})
self.assertEqual(md5(subtitles['no']), '544fa917d3197fcbee64634559221cc2') self.assertEqual(md5(subtitles['no']), '544fa917d3197fcbee64634559221cc2')
@ -284,7 +282,7 @@ class TestRaiPlaySubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['it'])) self.assertEqual(set(subtitles.keys()), {'it'})
self.assertEqual(md5(subtitles['it']), 'b1d90a98755126b61e667567a1f6680a') self.assertEqual(md5(subtitles['it']), 'b1d90a98755126b61e667567a1f6680a')
def test_subtitles_array_key(self): def test_subtitles_array_key(self):
@ -292,7 +290,7 @@ class TestRaiPlaySubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['it'])) self.assertEqual(set(subtitles.keys()), {'it'})
self.assertEqual(md5(subtitles['it']), '4b3264186fbb103508abe5311cfcb9cd') self.assertEqual(md5(subtitles['it']), '4b3264186fbb103508abe5311cfcb9cd')
@ -305,7 +303,7 @@ class TestVikiSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['en'])) self.assertEqual(set(subtitles.keys()), {'en'})
self.assertEqual(md5(subtitles['en']), '53cb083a5914b2d84ef1ab67b880d18a') self.assertEqual(md5(subtitles['en']), '53cb083a5914b2d84ef1ab67b880d18a')
@ -320,7 +318,7 @@ class TestThePlatformSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['en'])) self.assertEqual(set(subtitles.keys()), {'en'})
self.assertEqual(md5(subtitles['en']), '97e7670cbae3c4d26ae8bcc7fdd78d4b') self.assertEqual(md5(subtitles['en']), '97e7670cbae3c4d26ae8bcc7fdd78d4b')
@ -333,7 +331,7 @@ class TestThePlatformFeedSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['en'])) self.assertEqual(set(subtitles.keys()), {'en'})
self.assertEqual(md5(subtitles['en']), '48649a22e82b2da21c9a67a395eedade') self.assertEqual(md5(subtitles['en']), '48649a22e82b2da21c9a67a395eedade')
@ -348,7 +346,7 @@ class TestRtveSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['es'])) self.assertEqual(set(subtitles.keys()), {'es'})
self.assertEqual(md5(subtitles['es']), '69e70cae2d40574fb7316f31d6eb7fca') self.assertEqual(md5(subtitles['es']), '69e70cae2d40574fb7316f31d6eb7fca')
@ -361,7 +359,7 @@ class TestDemocracynowSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['en'])) self.assertEqual(set(subtitles.keys()), {'en'})
self.assertEqual(md5(subtitles['en']), 'acaca989e24a9e45a6719c9b3d60815c') self.assertEqual(md5(subtitles['en']), 'acaca989e24a9e45a6719c9b3d60815c')
def test_subtitles_in_page(self): def test_subtitles_in_page(self):
@ -369,7 +367,7 @@ class TestDemocracynowSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['en'])) self.assertEqual(set(subtitles.keys()), {'en'})
self.assertEqual(md5(subtitles['en']), 'acaca989e24a9e45a6719c9b3d60815c') self.assertEqual(md5(subtitles['en']), 'acaca989e24a9e45a6719c9b3d60815c')
@ -382,7 +380,7 @@ class TestPBSSubtitles(BaseTestSubtitles):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True
self.DL.params['allsubtitles'] = True self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles() subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['en'])) self.assertEqual(set(subtitles.keys()), {'en'})
def test_subtitles_dfxp_format(self): def test_subtitles_dfxp_format(self):
self.DL.params['writesubtitles'] = True self.DL.params['writesubtitles'] = True

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys

@ -1,8 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -266,7 +262,7 @@ class TestUtil(unittest.TestCase):
def test_expand_path(self): def test_expand_path(self):
def env(var): def env(var):
return '%{0}%'.format(var) if sys.platform == 'win32' else '${0}'.format(var) return f'%{var}%' if sys.platform == 'win32' else f'${var}'
compat_setenv('yt_dlp_EXPATH_PATH', 'expanded') compat_setenv('yt_dlp_EXPATH_PATH', 'expanded')
self.assertEqual(expand_path(env('yt_dlp_EXPATH_PATH')), 'expanded') self.assertEqual(expand_path(env('yt_dlp_EXPATH_PATH')), 'expanded')
@ -666,8 +662,7 @@ class TestUtil(unittest.TestCase):
def get_page(pagenum): def get_page(pagenum):
firstid = pagenum * pagesize firstid = pagenum * pagesize
upto = min(size, pagenum * pagesize + pagesize) upto = min(size, pagenum * pagesize + pagesize)
for i in range(firstid, upto): yield from range(firstid, upto)
yield i
pl = OnDemandPagedList(get_page, pagesize) pl = OnDemandPagedList(get_page, pagesize)
got = pl.getslice(*sliceargs) got = pl.getslice(*sliceargs)
@ -736,7 +731,7 @@ class TestUtil(unittest.TestCase):
multipart_encode({b'field': b'value'}, boundary='AAAAAA')[0], multipart_encode({b'field': b'value'}, boundary='AAAAAA')[0],
b'--AAAAAA\r\nContent-Disposition: form-data; name="field"\r\n\r\nvalue\r\n--AAAAAA--\r\n') b'--AAAAAA\r\nContent-Disposition: form-data; name="field"\r\n\r\nvalue\r\n--AAAAAA--\r\n')
self.assertEqual( self.assertEqual(
multipart_encode({'欄位'.encode('utf-8'): ''.encode('utf-8')}, boundary='AAAAAA')[0], multipart_encode({'欄位'.encode(): ''.encode()}, boundary='AAAAAA')[0],
b'--AAAAAA\r\nContent-Disposition: form-data; name="\xe6\xac\x84\xe4\xbd\x8d"\r\n\r\n\xe5\x80\xbc\r\n--AAAAAA--\r\n') b'--AAAAAA\r\nContent-Disposition: form-data; name="\xe6\xac\x84\xe4\xbd\x8d"\r\n\r\n\xe5\x80\xbc\r\n--AAAAAA--\r\n')
self.assertRaises( self.assertRaises(
ValueError, multipart_encode, {b'field': b'value'}, boundary='value') ValueError, multipart_encode, {b'field': b'value'}, boundary='value')
@ -1397,7 +1392,7 @@ ffmpeg version 2.4.4 Copyright (c) 2000-2014 the FFmpeg ...'''), '2.4.4')
<p begin="3" dur="-1">Ignored, three</p> <p begin="3" dur="-1">Ignored, three</p>
</div> </div>
</body> </body>
</tt>'''.encode('utf-8') </tt>'''.encode()
srt_data = '''1 srt_data = '''1
00:00:00,000 --> 00:00:01,000 00:00:00,000 --> 00:00:01,000
The following line contains Chinese characters and special symbols The following line contains Chinese characters and special symbols
@ -1415,14 +1410,14 @@ Line
''' '''
self.assertEqual(dfxp2srt(dfxp_data), srt_data) self.assertEqual(dfxp2srt(dfxp_data), srt_data)
dfxp_data_no_default_namespace = '''<?xml version="1.0" encoding="UTF-8"?> dfxp_data_no_default_namespace = b'''<?xml version="1.0" encoding="UTF-8"?>
<tt xml:lang="en" xmlns:tts="http://www.w3.org/ns/ttml#parameter"> <tt xml:lang="en" xmlns:tts="http://www.w3.org/ns/ttml#parameter">
<body> <body>
<div xml:lang="en"> <div xml:lang="en">
<p begin="0" end="1">The first line</p> <p begin="0" end="1">The first line</p>
</div> </div>
</body> </body>
</tt>'''.encode('utf-8') </tt>'''
srt_data = '''1 srt_data = '''1
00:00:00,000 --> 00:00:01,000 00:00:00,000 --> 00:00:01,000
The first line The first line
@ -1430,7 +1425,7 @@ The first line
''' '''
self.assertEqual(dfxp2srt(dfxp_data_no_default_namespace), srt_data) self.assertEqual(dfxp2srt(dfxp_data_no_default_namespace), srt_data)
dfxp_data_with_style = '''<?xml version="1.0" encoding="utf-8"?> dfxp_data_with_style = b'''<?xml version="1.0" encoding="utf-8"?>
<tt xmlns="http://www.w3.org/2006/10/ttaf1" xmlns:ttp="http://www.w3.org/2006/10/ttaf1#parameter" ttp:timeBase="media" xmlns:tts="http://www.w3.org/2006/10/ttaf1#style" xml:lang="en" xmlns:ttm="http://www.w3.org/2006/10/ttaf1#metadata"> <tt xmlns="http://www.w3.org/2006/10/ttaf1" xmlns:ttp="http://www.w3.org/2006/10/ttaf1#parameter" ttp:timeBase="media" xmlns:tts="http://www.w3.org/2006/10/ttaf1#style" xml:lang="en" xmlns:ttm="http://www.w3.org/2006/10/ttaf1#metadata">
<head> <head>
<styling> <styling>
@ -1448,7 +1443,7 @@ The first line
<p style="s1" tts:textDecoration="underline" begin="00:00:09.56" id="p2" end="00:00:12.36"><span style="s2" tts:color="lime">inner<br /> </span>style</p> <p style="s1" tts:textDecoration="underline" begin="00:00:09.56" id="p2" end="00:00:12.36"><span style="s2" tts:color="lime">inner<br /> </span>style</p>
</div> </div>
</body> </body>
</tt>'''.encode('utf-8') </tt>'''
srt_data = '''1 srt_data = '''1
00:00:02,080 --> 00:00:05,840 00:00:02,080 --> 00:00:05,840
<font color="white" face="sansSerif" size="16">default style<font color="red">custom style</font></font> <font color="white" face="sansSerif" size="16">default style<font color="red">custom style</font></font>

@ -1,8 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
import unittest import unittest
import sys import sys

@ -1,7 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
@ -21,7 +18,7 @@ import yt_dlp.extractor
class YoutubeDL(yt_dlp.YoutubeDL): class YoutubeDL(yt_dlp.YoutubeDL):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(YoutubeDL, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.to_stderr = self.to_screen self.to_stderr = self.to_screen
@ -52,7 +49,7 @@ class TestAnnotations(unittest.TestCase):
ydl.download([TEST_ID]) ydl.download([TEST_ID])
self.assertTrue(os.path.exists(ANNOTATIONS_FILE)) self.assertTrue(os.path.exists(ANNOTATIONS_FILE))
annoxml = None annoxml = None
with io.open(ANNOTATIONS_FILE, 'r', encoding='utf-8') as annof: with open(ANNOTATIONS_FILE, encoding='utf-8') as annof:
annoxml = xml.etree.ElementTree.parse(annof) annoxml = xml.etree.ElementTree.parse(annof)
self.assertTrue(annoxml is not None, 'Failed to parse annotations XML') self.assertTrue(annoxml is not None, 'Failed to parse annotations XML')
root = annoxml.getroot() root = annoxml.getroot()

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys

@ -1,14 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Allow direct execution # Allow direct execution
import os import os
import sys import sys
import unittest import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import io
import re import re
import string import string
import urllib.request import urllib.request
@ -149,7 +145,7 @@ def t_factory(name, sig_func, url_pattern):
if not os.path.exists(fn): if not os.path.exists(fn):
urllib.request.urlretrieve(url, fn) urllib.request.urlretrieve(url, fn)
with io.open(fn, encoding='utf-8') as testf: with open(fn, encoding='utf-8') as testf:
jscode = testf.read() jscode = testf.read()
self.assertEqual(sig_func(jscode, sig_input), expected_sig) self.assertEqual(sig_func(jscode, sig_input), expected_sig)

@ -1,8 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
from __future__ import absolute_import, unicode_literals
import collections import collections
import contextlib import contextlib
import datetime import datetime
@ -165,7 +161,7 @@ if compat_os_name == 'nt':
import ctypes import ctypes
class YoutubeDL(object): class YoutubeDL:
"""YoutubeDL class. """YoutubeDL class.
YoutubeDL objects are the ones responsible of downloading the YoutubeDL objects are the ones responsible of downloading the
@ -501,7 +497,7 @@ class YoutubeDL(object):
care about HLS. (only for youtube) care about HLS. (only for youtube)
""" """
_NUMERIC_FIELDS = set(( _NUMERIC_FIELDS = {
'width', 'height', 'tbr', 'abr', 'asr', 'vbr', 'fps', 'filesize', 'filesize_approx', 'width', 'height', 'tbr', 'abr', 'asr', 'vbr', 'fps', 'filesize', 'filesize_approx',
'timestamp', 'release_timestamp', 'timestamp', 'release_timestamp',
'duration', 'view_count', 'like_count', 'dislike_count', 'repost_count', 'duration', 'view_count', 'like_count', 'dislike_count', 'repost_count',
@ -509,7 +505,7 @@ class YoutubeDL(object):
'start_time', 'end_time', 'start_time', 'end_time',
'chapter_number', 'season_number', 'episode_number', 'chapter_number', 'season_number', 'episode_number',
'track_number', 'disc_number', 'release_year', 'track_number', 'disc_number', 'release_year',
)) }
_format_fields = { _format_fields = {
# NB: Keep in sync with the docstring of extractor/common.py # NB: Keep in sync with the docstring of extractor/common.py
@ -576,7 +572,7 @@ class YoutubeDL(object):
def check_deprecated(param, option, suggestion): def check_deprecated(param, option, suggestion):
if self.params.get(param) is not None: if self.params.get(param) is not None:
self.report_warning('%s is deprecated. Use %s instead' % (option, suggestion)) self.report_warning(f'{option} is deprecated. Use {suggestion} instead')
return True return True
return False return False
@ -693,7 +689,7 @@ class YoutubeDL(object):
with locked_file(fn, 'r', encoding='utf-8') as archive_file: with locked_file(fn, 'r', encoding='utf-8') as archive_file:
for line in archive_file: for line in archive_file:
self.archive.add(line.strip()) self.archive.add(line.strip())
except IOError as ioe: except OSError as ioe:
if ioe.errno != errno.ENOENT: if ioe.errno != errno.ENOENT:
raise raise
return False return False
@ -990,11 +986,9 @@ class YoutubeDL(object):
outtmpl_dict.update({ outtmpl_dict.update({
k: sanitize(v) for k, v in DEFAULT_OUTTMPL.items() k: sanitize(v) for k, v in DEFAULT_OUTTMPL.items()
if outtmpl_dict.get(k) is None}) if outtmpl_dict.get(k) is None})
for key, val in outtmpl_dict.items(): for _, val in outtmpl_dict.items():
if isinstance(val, bytes): if isinstance(val, bytes):
self.report_warning( self.report_warning('Parameter outtmpl is bytes, but should be a unicode string')
'Parameter outtmpl is bytes, but should be a unicode string. '
'Put from __future__ import unicode_literals at the top of your code file or consider switching to Python 3.x.')
return outtmpl_dict return outtmpl_dict
def get_output_path(self, dir_type='', filename=None): def get_output_path(self, dir_type='', filename=None):
@ -1013,7 +1007,7 @@ class YoutubeDL(object):
# '%%' intact for template dict substitution step. Working around # '%%' intact for template dict substitution step. Working around
# with boundary-alike separator hack. # with boundary-alike separator hack.
sep = ''.join([random.choice(ascii_letters) for _ in range(32)]) sep = ''.join([random.choice(ascii_letters) for _ in range(32)])
outtmpl = outtmpl.replace('%%', '%{0}%'.format(sep)).replace('$$', '${0}$'.format(sep)) outtmpl = outtmpl.replace('%%', f'%{sep}%').replace('$$', f'${sep}$')
# outtmpl should be expand_path'ed before template dict substitution # outtmpl should be expand_path'ed before template dict substitution
# because meta fields may contain env variables we don't want to # because meta fields may contain env variables we don't want to
@ -1173,7 +1167,7 @@ class YoutubeDL(object):
fmt = outer_mobj.group('format') fmt = outer_mobj.group('format')
if fmt == 's' and value is not None and key in field_size_compat_map.keys(): if fmt == 's' and value is not None and key in field_size_compat_map.keys():
fmt = '0{:d}d'.format(field_size_compat_map[key]) fmt = f'0{field_size_compat_map[key]:d}d'
value = default if value is None else value if replacement is None else replacement value = default if value is None else value if replacement is None else replacement
@ -1188,7 +1182,7 @@ class YoutubeDL(object):
value = map(str, variadic(value) if '#' in flags else [value]) value = map(str, variadic(value) if '#' in flags else [value])
value, fmt = ' '.join(map(compat_shlex_quote, value)), str_fmt value, fmt = ' '.join(map(compat_shlex_quote, value)), str_fmt
elif fmt[-1] == 'B': # bytes elif fmt[-1] == 'B': # bytes
value = f'%{str_fmt}'.encode('utf-8') % str(value).encode('utf-8') value = f'%{str_fmt}'.encode() % str(value).encode('utf-8')
value, fmt = value.decode('utf-8', 'ignore'), 's' value, fmt = value.decode('utf-8', 'ignore'), 's'
elif fmt[-1] == 'U': # unicode normalized elif fmt[-1] == 'U': # unicode normalized
value, fmt = unicodedata.normalize( value, fmt = unicodedata.normalize(
@ -1301,7 +1295,7 @@ class YoutubeDL(object):
if date is not None: if date is not None:
dateRange = self.params.get('daterange', DateRange()) dateRange = self.params.get('daterange', DateRange())
if date not in dateRange: if date not in dateRange:
return '%s upload date is not in range %s' % (date_from_str(date).isoformat(), dateRange) return f'{date_from_str(date).isoformat()} upload date is not in range {dateRange}'
view_count = info_dict.get('view_count') view_count = info_dict.get('view_count')
if view_count is not None: if view_count is not None:
min_views = self.params.get('min_views') min_views = self.params.get('min_views')
@ -1765,14 +1759,14 @@ class YoutubeDL(object):
x_forwarded_for = ie_result.get('__x_forwarded_for_ip') x_forwarded_for = ie_result.get('__x_forwarded_for_ip')
self.to_screen('[%s] playlist %s: %s' % (ie_result['extractor'], playlist, msg % n_entries)) self.to_screen(f'[{ie_result["extractor"]}] playlist {playlist}: {msg % n_entries}')
failures = 0 failures = 0
max_failures = self.params.get('skip_playlist_after_errors') or float('inf') max_failures = self.params.get('skip_playlist_after_errors') or float('inf')
for i, entry_tuple in enumerate(entries, 1): for i, entry_tuple in enumerate(entries, 1):
playlist_index, entry = entry_tuple playlist_index, entry = entry_tuple
if 'playlist-index' in self.params.get('compat_opts', []): if 'playlist-index' in self.params.get('compat_opts', []):
playlist_index = playlistitems[i - 1] if playlistitems else i + playliststart - 1 playlist_index = playlistitems[i - 1] if playlistitems else i + playliststart - 1
self.to_screen('[download] Downloading video %s of %s' % (i, n_entries)) self.to_screen(f'[download] Downloading video {i} of {n_entries}')
# This __x_forwarded_for_ip thing is a bit ugly but requires # This __x_forwarded_for_ip thing is a bit ugly but requires
# minimal changes # minimal changes
if x_forwarded_for: if x_forwarded_for:
@ -1940,7 +1934,7 @@ class YoutubeDL(object):
def syntax_error(note, start): def syntax_error(note, start):
message = ( message = (
'Invalid format specification: ' 'Invalid format specification: '
'{0}\n\t{1}\n\t{2}^'.format(note, format_spec, ' ' * start[1])) '{}\n\t{}\n\t{}^'.format(note, format_spec, ' ' * start[1]))
return SyntaxError(message) return SyntaxError(message)
PICKFIRST = 'PICKFIRST' PICKFIRST = 'PICKFIRST'
@ -2044,7 +2038,7 @@ class YoutubeDL(object):
raise syntax_error('Expected a selector', start) raise syntax_error('Expected a selector', start)
current_selector = FormatSelector(MERGE, (selector_1, selector_2), []) current_selector = FormatSelector(MERGE, (selector_1, selector_2), [])
else: else:
raise syntax_error('Operator not recognized: "{0}"'.format(string), start) raise syntax_error(f'Operator not recognized: "{string}"', start)
elif type == tokenize.ENDMARKER: elif type == tokenize.ENDMARKER:
break break
if current_selector: if current_selector:
@ -2244,7 +2238,7 @@ class YoutubeDL(object):
except tokenize.TokenError: except tokenize.TokenError:
raise syntax_error('Missing closing/opening brackets or parenthesis', (0, len(format_spec))) raise syntax_error('Missing closing/opening brackets or parenthesis', (0, len(format_spec)))
class TokenIterator(object): class TokenIterator:
def __init__(self, tokens): def __init__(self, tokens):
self.tokens = tokens self.tokens = tokens
self.counter = 0 self.counter = 0
@ -2644,7 +2638,7 @@ class YoutubeDL(object):
if max_downloads_reached: if max_downloads_reached:
break break
write_archive = set(f.get('__write_download_archive', False) for f in formats_to_download) write_archive = {f.get('__write_download_archive', False) for f in formats_to_download}
assert write_archive.issubset({True, False, 'ignore'}) assert write_archive.issubset({True, False, 'ignore'})
if True in write_archive and False not in write_archive: if True in write_archive and False not in write_archive:
self.record_download_archive(info_dict) self.record_download_archive(info_dict)
@ -2712,7 +2706,7 @@ class YoutubeDL(object):
for lang in requested_langs: for lang in requested_langs:
formats = available_subs.get(lang) formats = available_subs.get(lang)
if formats is None: if formats is None:
self.report_warning('%s subtitles not available for %s' % (lang, video_id)) self.report_warning(f'{lang} subtitles not available for {video_id}')
continue continue
for ext in formats_preference: for ext in formats_preference:
if ext == 'best': if ext == 'best':
@ -2755,7 +2749,7 @@ class YoutubeDL(object):
tmpl = format_tmpl(tmpl) tmpl = format_tmpl(tmpl)
self.to_screen(f'[info] Writing {tmpl!r} to: {filename}') self.to_screen(f'[info] Writing {tmpl!r} to: {filename}')
if self._ensure_dir_exists(filename): if self._ensure_dir_exists(filename):
with io.open(filename, 'a', encoding='utf-8') as f: with open(filename, 'a', encoding='utf-8') as f:
f.write(self.evaluate_outtmpl(tmpl, info_copy) + '\n') f.write(self.evaluate_outtmpl(tmpl, info_copy) + '\n')
def __forced_printings(self, info_dict, filename, incomplete): def __forced_printings(self, info_dict, filename, incomplete):
@ -2920,11 +2914,11 @@ class YoutubeDL(object):
else: else:
try: try:
self.to_screen('[info] Writing video annotations to: ' + annofn) self.to_screen('[info] Writing video annotations to: ' + annofn)
with io.open(encodeFilename(annofn), 'w', encoding='utf-8') as annofile: with open(encodeFilename(annofn), 'w', encoding='utf-8') as annofile:
annofile.write(info_dict['annotations']) annofile.write(info_dict['annotations'])
except (KeyError, TypeError): except (KeyError, TypeError):
self.report_warning('There are no annotations to write.') self.report_warning('There are no annotations to write.')
except (OSError, IOError): except OSError:
self.report_error('Cannot write annotations file: ' + annofn) self.report_error('Cannot write annotations file: ' + annofn)
return return
@ -2943,13 +2937,13 @@ class YoutubeDL(object):
return True return True
try: try:
self.to_screen(f'[info] Writing internet shortcut (.{link_type}) to: {linkfn}') self.to_screen(f'[info] Writing internet shortcut (.{link_type}) to: {linkfn}')
with io.open(encodeFilename(to_high_limit_path(linkfn)), 'w', encoding='utf-8', with open(encodeFilename(to_high_limit_path(linkfn)), 'w', encoding='utf-8',
newline='\r\n' if link_type == 'url' else '\n') as linkfile: newline='\r\n' if link_type == 'url' else '\n') as linkfile:
template_vars = {'url': url} template_vars = {'url': url}
if link_type == 'desktop': if link_type == 'desktop':
template_vars['filename'] = linkfn[:-(len(link_type) + 1)] template_vars['filename'] = linkfn[:-(len(link_type) + 1)]
linkfile.write(LINK_TEMPLATES[link_type] % template_vars) linkfile.write(LINK_TEMPLATES[link_type] % template_vars)
except (OSError, IOError): except OSError:
self.report_error(f'Cannot write internet shortcut {linkfn}') self.report_error(f'Cannot write internet shortcut {linkfn}')
return False return False
return True return True
@ -3014,10 +3008,10 @@ class YoutubeDL(object):
return False return False
# Check extension # Check extension
exts = set(format.get('ext') for format in formats) exts = {format.get('ext') for format in formats}
COMPATIBLE_EXTS = ( COMPATIBLE_EXTS = (
set(('mp3', 'mp4', 'm4a', 'm4p', 'm4b', 'm4r', 'm4v', 'ismv', 'isma')), {'mp3', 'mp4', 'm4a', 'm4p', 'm4b', 'm4r', 'm4v', 'ismv', 'isma'},
set(('webm',)), {'webm'},
) )
for ext_sets in COMPATIBLE_EXTS: for ext_sets in COMPATIBLE_EXTS:
if ext_sets.issuperset(exts): if ext_sets.issuperset(exts):
@ -3050,7 +3044,7 @@ class YoutubeDL(object):
os.path.splitext(filename)[0] os.path.splitext(filename)[0]
if filename_real_ext in (old_ext, new_ext) if filename_real_ext in (old_ext, new_ext)
else filename) else filename)
return '%s.%s' % (filename_wo_ext, ext) return f'{filename_wo_ext}.{ext}'
# Ensure filename always has a correct extension for successful merge # Ensure filename always has a correct extension for successful merge
full_filename = correct_ext(full_filename) full_filename = correct_ext(full_filename)
@ -3135,10 +3129,10 @@ class YoutubeDL(object):
except network_exceptions as err: except network_exceptions as err:
self.report_error('unable to download video data: %s' % error_to_compat_str(err)) self.report_error('unable to download video data: %s' % error_to_compat_str(err))
return return
except (OSError, IOError) as err: except OSError as err:
raise UnavailableVideoError(err) raise UnavailableVideoError(err)
except (ContentTooShortError, ) as err: except (ContentTooShortError, ) as err:
self.report_error('content too short (expected %s bytes and served %s)' % (err.expected, err.downloaded)) self.report_error(f'content too short (expected {err.expected} bytes and served {err.downloaded})')
return return
if success and full_filename != '-': if success and full_filename != '-':
@ -3343,7 +3337,7 @@ class YoutubeDL(object):
self.to_screen('Deleting original file %s (pass -k to keep)' % old_filename) self.to_screen('Deleting original file %s (pass -k to keep)' % old_filename)
try: try:
os.remove(encodeFilename(old_filename)) os.remove(encodeFilename(old_filename))
except (IOError, OSError): except OSError:
self.report_warning('Unable to remove downloaded original file') self.report_warning('Unable to remove downloaded original file')
if old_filename in infodict['__files_to_move']: if old_filename in infodict['__files_to_move']:
del infodict['__files_to_move'][old_filename] del infodict['__files_to_move'][old_filename]
@ -3388,7 +3382,7 @@ class YoutubeDL(object):
break break
else: else:
return return
return '%s %s' % (extractor.lower(), video_id) return f'{extractor.lower()} {video_id}'
def in_download_archive(self, info_dict): def in_download_archive(self, info_dict):
fn = self.params.get('download_archive') fn = self.params.get('download_archive')
@ -3791,7 +3785,7 @@ class YoutubeDL(object):
try: try:
write_json_file(self.sanitize_info(ie_result, self.params.get('clean_infojson', True)), infofn) write_json_file(self.sanitize_info(ie_result, self.params.get('clean_infojson', True)), infofn)
return True return True
except (OSError, IOError): except OSError:
self.report_error(f'Cannot write {label} metadata to JSON file {infofn}') self.report_error(f'Cannot write {label} metadata to JSON file {infofn}')
return None return None
@ -3812,9 +3806,9 @@ class YoutubeDL(object):
else: else:
try: try:
self.to_screen(f'[info] Writing {label} description to: {descfn}') self.to_screen(f'[info] Writing {label} description to: {descfn}')
with io.open(encodeFilename(descfn), 'w', encoding='utf-8') as descfile: with open(encodeFilename(descfn), 'w', encoding='utf-8') as descfile:
descfile.write(ie_result['description']) descfile.write(ie_result['description'])
except (OSError, IOError): except OSError:
self.report_error(f'Cannot write {label} description file {descfn}') self.report_error(f'Cannot write {label} description file {descfn}')
return None return None
return True return True
@ -3848,12 +3842,12 @@ class YoutubeDL(object):
try: try:
# Use newline='' to prevent conversion of newline characters # Use newline='' to prevent conversion of newline characters
# See https://github.com/ytdl-org/youtube-dl/issues/10268 # See https://github.com/ytdl-org/youtube-dl/issues/10268
with io.open(sub_filename, 'w', encoding='utf-8', newline='') as subfile: with open(sub_filename, 'w', encoding='utf-8', newline='') as subfile:
subfile.write(sub_info['data']) subfile.write(sub_info['data'])
sub_info['filepath'] = sub_filename sub_info['filepath'] = sub_filename
ret.append((sub_filename, sub_filename_final)) ret.append((sub_filename, sub_filename_final))
continue continue
except (OSError, IOError): except OSError:
self.report_error(f'Cannot write video subtitles file {sub_filename}') self.report_error(f'Cannot write video subtitles file {sub_filename}')
return None return None

@ -1,11 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8
f'You are using an unsupported version of Python. Only Python versions 3.6 and above are supported by yt-dlp' # noqa: F541 f'You are using an unsupported version of Python. Only Python versions 3.6 and above are supported by yt-dlp' # noqa: F541
__license__ = 'Public Domain' __license__ = 'Public Domain'
import io
import itertools import itertools
import os import os
import random import random
@ -67,13 +64,12 @@ def get_urls(urls, batchfile, verbose):
'Ctrl+Z' if compat_os_name == 'nt' else 'Ctrl+D')) 'Ctrl+Z' if compat_os_name == 'nt' else 'Ctrl+D'))
batchfd = sys.stdin batchfd = sys.stdin
else: else:
batchfd = io.open( batchfd = open(
expand_path(batchfile), expand_path(batchfile), encoding='utf-8', errors='ignore')
'r', encoding='utf-8', errors='ignore')
batch_urls = read_batch_urls(batchfd) batch_urls = read_batch_urls(batchfd)
if verbose: if verbose:
write_string('[debug] Batch file urls: ' + repr(batch_urls) + '\n') write_string('[debug] Batch file urls: ' + repr(batch_urls) + '\n')
except IOError: except OSError:
sys.exit('ERROR: batch file %s could not be read' % batchfile) sys.exit('ERROR: batch file %s could not be read' % batchfile)
_enc = preferredencoding() _enc = preferredencoding()
return [ return [

@ -1,6 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import unicode_literals
# Execute with # Execute with
# $ python -m yt_dlp # $ python -m yt_dlp

@ -1,5 +1,3 @@
from __future__ import unicode_literals
from math import ceil from math import ceil
from .compat import ( from .compat import (

@ -1,7 +1,4 @@
from __future__ import unicode_literals
import errno import errno
import io
import json import json
import os import os
import re import re
@ -15,7 +12,7 @@ from .utils import (
) )
class Cache(object): class Cache:
def __init__(self, ydl): def __init__(self, ydl):
self._ydl = ydl self._ydl = ydl
@ -31,7 +28,7 @@ class Cache(object):
'invalid section %r' % section 'invalid section %r' % section
assert re.match(r'^[a-zA-Z0-9_.-]+$', key), 'invalid key %r' % key assert re.match(r'^[a-zA-Z0-9_.-]+$', key), 'invalid key %r' % key
return os.path.join( return os.path.join(
self._get_root_dir(), section, '%s.%s' % (key, dtype)) self._get_root_dir(), section, f'{key}.{dtype}')
@property @property
def enabled(self): def enabled(self):
@ -54,8 +51,7 @@ class Cache(object):
write_json_file(data, fn) write_json_file(data, fn)
except Exception: except Exception:
tb = traceback.format_exc() tb = traceback.format_exc()
self._ydl.report_warning( self._ydl.report_warning(f'Writing cache to {fn!r} failed: {tb}')
'Writing cache to %r failed: %s' % (fn, tb))
def load(self, section, key, dtype='json', default=None): def load(self, section, key, dtype='json', default=None):
assert dtype in ('json',) assert dtype in ('json',)
@ -66,17 +62,16 @@ class Cache(object):
cache_fn = self._get_cache_fn(section, key, dtype) cache_fn = self._get_cache_fn(section, key, dtype)
try: try:
try: try:
with io.open(cache_fn, 'r', encoding='utf-8') as cachef: with open(cache_fn, encoding='utf-8') as cachef:
self._ydl.write_debug(f'Loading {section}.{key} from cache') self._ydl.write_debug(f'Loading {section}.{key} from cache')
return json.load(cachef) return json.load(cachef)
except ValueError: except ValueError:
try: try:
file_size = os.path.getsize(cache_fn) file_size = os.path.getsize(cache_fn)
except (OSError, IOError) as oe: except OSError as oe:
file_size = str(oe) file_size = str(oe)
self._ydl.report_warning( self._ydl.report_warning(f'Cache retrieval from {cache_fn} failed ({file_size})')
'Cache retrieval from %s failed (%s)' % (cache_fn, file_size)) except OSError:
except IOError:
pass # No cache available pass # No cache available
return default return default

@ -1,5 +1,3 @@
# coding: utf-8
import asyncio import asyncio
import base64 import base64
import collections import collections

@ -125,7 +125,7 @@ def extract_cookies_from_browser(browser_name, profile=None, logger=YDLLogger(),
elif browser_name in CHROMIUM_BASED_BROWSERS: elif browser_name in CHROMIUM_BASED_BROWSERS:
return _extract_chrome_cookies(browser_name, profile, keyring, logger) return _extract_chrome_cookies(browser_name, profile, keyring, logger)
else: else:
raise ValueError('unknown browser: {}'.format(browser_name)) raise ValueError(f'unknown browser: {browser_name}')
def _extract_firefox_cookies(profile, logger): def _extract_firefox_cookies(profile, logger):
@ -144,8 +144,8 @@ def _extract_firefox_cookies(profile, logger):
cookie_database_path = _find_most_recently_used_file(search_root, 'cookies.sqlite', logger) cookie_database_path = _find_most_recently_used_file(search_root, 'cookies.sqlite', logger)
if cookie_database_path is None: if cookie_database_path is None:
raise FileNotFoundError('could not find firefox cookies database in {}'.format(search_root)) raise FileNotFoundError(f'could not find firefox cookies database in {search_root}')
logger.debug('Extracting cookies from: "{}"'.format(cookie_database_path)) logger.debug(f'Extracting cookies from: "{cookie_database_path}"')
with tempfile.TemporaryDirectory(prefix='yt_dlp') as tmpdir: with tempfile.TemporaryDirectory(prefix='yt_dlp') as tmpdir:
cursor = None cursor = None
@ -164,7 +164,7 @@ def _extract_firefox_cookies(profile, logger):
path=path, path_specified=bool(path), secure=is_secure, expires=expiry, discard=False, path=path, path_specified=bool(path), secure=is_secure, expires=expiry, discard=False,
comment=None, comment_url=None, rest={}) comment=None, comment_url=None, rest={})
jar.set_cookie(cookie) jar.set_cookie(cookie)
logger.info('Extracted {} cookies from firefox'.format(len(jar))) logger.info(f'Extracted {len(jar)} cookies from firefox')
return jar return jar
finally: finally:
if cursor is not None: if cursor is not None:
@ -179,7 +179,7 @@ def _firefox_browser_dir():
elif sys.platform == 'darwin': elif sys.platform == 'darwin':
return os.path.expanduser('~/Library/Application Support/Firefox') return os.path.expanduser('~/Library/Application Support/Firefox')
else: else:
raise ValueError('unsupported platform: {}'.format(sys.platform)) raise ValueError(f'unsupported platform: {sys.platform}')
def _get_chromium_based_browser_settings(browser_name): def _get_chromium_based_browser_settings(browser_name):
@ -219,7 +219,7 @@ def _get_chromium_based_browser_settings(browser_name):
}[browser_name] }[browser_name]
else: else:
raise ValueError('unsupported platform: {}'.format(sys.platform)) raise ValueError(f'unsupported platform: {sys.platform}')
# Linux keyring names can be determined by snooping on dbus while opening the browser in KDE: # Linux keyring names can be determined by snooping on dbus while opening the browser in KDE:
# dbus-monitor "interface='org.kde.KWallet'" "type=method_return" # dbus-monitor "interface='org.kde.KWallet'" "type=method_return"
@ -242,7 +242,7 @@ def _get_chromium_based_browser_settings(browser_name):
def _extract_chrome_cookies(browser_name, profile, keyring, logger): def _extract_chrome_cookies(browser_name, profile, keyring, logger):
logger.info('Extracting cookies from {}'.format(browser_name)) logger.info(f'Extracting cookies from {browser_name}')
if not SQLITE_AVAILABLE: if not SQLITE_AVAILABLE:
logger.warning(('Cannot extract cookies from {} without sqlite3 support. ' logger.warning(('Cannot extract cookies from {} without sqlite3 support. '
@ -260,13 +260,13 @@ def _extract_chrome_cookies(browser_name, profile, keyring, logger):
if config['supports_profiles']: if config['supports_profiles']:
search_root = os.path.join(config['browser_dir'], profile) search_root = os.path.join(config['browser_dir'], profile)
else: else:
logger.error('{} does not support profiles'.format(browser_name)) logger.error(f'{browser_name} does not support profiles')
search_root = config['browser_dir'] search_root = config['browser_dir']
cookie_database_path = _find_most_recently_used_file(search_root, 'Cookies', logger) cookie_database_path = _find_most_recently_used_file(search_root, 'Cookies', logger)
if cookie_database_path is None: if cookie_database_path is None:
raise FileNotFoundError('could not find {} cookies database in "{}"'.format(browser_name, search_root)) raise FileNotFoundError(f'could not find {browser_name} cookies database in "{search_root}"')
logger.debug('Extracting cookies from: "{}"'.format(cookie_database_path)) logger.debug(f'Extracting cookies from: "{cookie_database_path}"')
decryptor = get_cookie_decryptor(config['browser_dir'], config['keyring_name'], logger, keyring=keyring) decryptor = get_cookie_decryptor(config['browser_dir'], config['keyring_name'], logger, keyring=keyring)
@ -295,13 +295,13 @@ def _extract_chrome_cookies(browser_name, profile, keyring, logger):
unencrypted_cookies += 1 unencrypted_cookies += 1
jar.set_cookie(cookie) jar.set_cookie(cookie)
if failed_cookies > 0: if failed_cookies > 0:
failed_message = ' ({} could not be decrypted)'.format(failed_cookies) failed_message = f' ({failed_cookies} could not be decrypted)'
else: else:
failed_message = '' failed_message = ''
logger.info('Extracted {} cookies from {}{}'.format(len(jar), browser_name, failed_message)) logger.info(f'Extracted {len(jar)} cookies from {browser_name}{failed_message}')
counts = decryptor.cookie_counts.copy() counts = decryptor.cookie_counts.copy()
counts['unencrypted'] = unencrypted_cookies counts['unencrypted'] = unencrypted_cookies
logger.debug('cookie version breakdown: {}'.format(counts)) logger.debug(f'cookie version breakdown: {counts}')
return jar return jar
finally: finally:
if cursor is not None: if cursor is not None:
@ -492,7 +492,7 @@ def _extract_safari_cookies(profile, logger):
if profile is not None: if profile is not None:
logger.error('safari does not support profiles') logger.error('safari does not support profiles')
if sys.platform != 'darwin': if sys.platform != 'darwin':
raise ValueError('unsupported platform: {}'.format(sys.platform)) raise ValueError(f'unsupported platform: {sys.platform}')
cookies_path = os.path.expanduser('~/Library/Cookies/Cookies.binarycookies') cookies_path = os.path.expanduser('~/Library/Cookies/Cookies.binarycookies')
@ -506,7 +506,7 @@ def _extract_safari_cookies(profile, logger):
cookies_data = f.read() cookies_data = f.read()
jar = parse_safari_cookies(cookies_data, logger=logger) jar = parse_safari_cookies(cookies_data, logger=logger)
logger.info('Extracted {} cookies from safari'.format(len(jar))) logger.info(f'Extracted {len(jar)} cookies from safari')
return jar return jar
@ -522,7 +522,7 @@ class DataParser:
def read_bytes(self, num_bytes): def read_bytes(self, num_bytes):
if num_bytes < 0: if num_bytes < 0:
raise ParserError('invalid read of {} bytes'.format(num_bytes)) raise ParserError(f'invalid read of {num_bytes} bytes')
end = self.cursor + num_bytes end = self.cursor + num_bytes
if end > len(self._data): if end > len(self._data):
raise ParserError('reached end of input') raise ParserError('reached end of input')
@ -533,7 +533,7 @@ class DataParser:
def expect_bytes(self, expected_value, message): def expect_bytes(self, expected_value, message):
value = self.read_bytes(len(expected_value)) value = self.read_bytes(len(expected_value))
if value != expected_value: if value != expected_value:
raise ParserError('unexpected value: {} != {} ({})'.format(value, expected_value, message)) raise ParserError(f'unexpected value: {value} != {expected_value} ({message})')
def read_uint(self, big_endian=False): def read_uint(self, big_endian=False):
data_format = '>I' if big_endian else '<I' data_format = '>I' if big_endian else '<I'
@ -557,7 +557,7 @@ class DataParser:
self._logger.debug('skipping {} bytes ({}): {}'.format( self._logger.debug('skipping {} bytes ({}): {}'.format(
num_bytes, description, self.read_bytes(num_bytes))) num_bytes, description, self.read_bytes(num_bytes)))
elif num_bytes < 0: elif num_bytes < 0:
raise ParserError('invalid skip of {} bytes'.format(num_bytes)) raise ParserError(f'invalid skip of {num_bytes} bytes')
def skip_to(self, offset, description='unknown'): def skip_to(self, offset, description='unknown'):
self.skip(offset - self.cursor, description) self.skip(offset - self.cursor, description)
@ -584,7 +584,7 @@ def _parse_safari_cookies_page(data, jar, logger):
number_of_cookies = p.read_uint() number_of_cookies = p.read_uint()
record_offsets = [p.read_uint() for _ in range(number_of_cookies)] record_offsets = [p.read_uint() for _ in range(number_of_cookies)]
if number_of_cookies == 0: if number_of_cookies == 0:
logger.debug('a cookies page of size {} has no cookies'.format(len(data))) logger.debug(f'a cookies page of size {len(data)} has no cookies')
return return
p.skip_to(record_offsets[0], 'unknown page header field') p.skip_to(record_offsets[0], 'unknown page header field')
@ -730,7 +730,7 @@ def _choose_linux_keyring(logger):
SelectBackend SelectBackend
""" """
desktop_environment = _get_linux_desktop_environment(os.environ) desktop_environment = _get_linux_desktop_environment(os.environ)
logger.debug('detected desktop environment: {}'.format(desktop_environment.name)) logger.debug(f'detected desktop environment: {desktop_environment.name}')
if desktop_environment == _LinuxDesktopEnvironment.KDE: if desktop_environment == _LinuxDesktopEnvironment.KDE:
linux_keyring = _LinuxKeyring.KWALLET linux_keyring = _LinuxKeyring.KWALLET
elif desktop_environment == _LinuxDesktopEnvironment.OTHER: elif desktop_environment == _LinuxDesktopEnvironment.OTHER:
@ -764,10 +764,10 @@ def _get_kwallet_network_wallet(logger):
return default_wallet return default_wallet
else: else:
network_wallet = stdout.decode('utf-8').strip() network_wallet = stdout.decode('utf-8').strip()
logger.debug('NetworkWallet = "{}"'.format(network_wallet)) logger.debug(f'NetworkWallet = "{network_wallet}"')
return network_wallet return network_wallet
except Exception as e: except Exception as e:
logger.warning('exception while obtaining NetworkWallet: {}'.format(e)) logger.warning(f'exception while obtaining NetworkWallet: {e}')
return default_wallet return default_wallet
@ -785,8 +785,8 @@ def _get_kwallet_password(browser_keyring_name, logger):
try: try:
proc = Popen([ proc = Popen([
'kwallet-query', 'kwallet-query',
'--read-password', '{} Safe Storage'.format(browser_keyring_name), '--read-password', f'{browser_keyring_name} Safe Storage',
'--folder', '{} Keys'.format(browser_keyring_name), '--folder', f'{browser_keyring_name} Keys',
network_wallet network_wallet
], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) ], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
@ -818,7 +818,7 @@ def _get_kwallet_password(browser_keyring_name, logger):
def _get_gnome_keyring_password(browser_keyring_name, logger): def _get_gnome_keyring_password(browser_keyring_name, logger):
if not SECRETSTORAGE_AVAILABLE: if not SECRETSTORAGE_AVAILABLE:
logger.error('secretstorage not available {}'.format(SECRETSTORAGE_UNAVAILABLE_REASON)) logger.error(f'secretstorage not available {SECRETSTORAGE_UNAVAILABLE_REASON}')
return b'' return b''
# the Gnome keyring does not seem to organise keys in the same way as KWallet, # the Gnome keyring does not seem to organise keys in the same way as KWallet,
# using `dbus-monitor` during startup, it can be observed that chromium lists all keys # using `dbus-monitor` during startup, it can be observed that chromium lists all keys
@ -827,7 +827,7 @@ def _get_gnome_keyring_password(browser_keyring_name, logger):
with contextlib.closing(secretstorage.dbus_init()) as con: with contextlib.closing(secretstorage.dbus_init()) as con:
col = secretstorage.get_default_collection(con) col = secretstorage.get_default_collection(con)
for item in col.get_all_items(): for item in col.get_all_items():
if item.get_label() == '{} Safe Storage'.format(browser_keyring_name): if item.get_label() == f'{browser_keyring_name} Safe Storage':
return item.get_secret() return item.get_secret()
else: else:
logger.error('failed to read from keyring') logger.error('failed to read from keyring')
@ -861,7 +861,7 @@ def _get_mac_keyring_password(browser_keyring_name, logger):
['security', 'find-generic-password', ['security', 'find-generic-password',
'-w', # write password to stdout '-w', # write password to stdout
'-a', browser_keyring_name, # match 'account' '-a', browser_keyring_name, # match 'account'
'-s', '{} Safe Storage'.format(browser_keyring_name)], # match 'service' '-s', f'{browser_keyring_name} Safe Storage'], # match 'service'
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
stdout, stderr = proc.communicate_or_kill() stdout, stderr = proc.communicate_or_kill()
@ -879,7 +879,7 @@ def _get_windows_v10_key(browser_root, logger):
logger.error('could not find local state file') logger.error('could not find local state file')
return None return None
logger.debug(f'Found local state file at "{path}"') logger.debug(f'Found local state file at "{path}"')
with open(path, 'r', encoding='utf8') as f: with open(path, encoding='utf8') as f:
data = json.load(f) data = json.load(f)
try: try:
base64_key = data['os_crypt']['encrypted_key'] base64_key = data['os_crypt']['encrypted_key']
@ -966,7 +966,7 @@ def _open_database_copy(database_path, tmpdir):
def _get_column_names(cursor, table_name): def _get_column_names(cursor, table_name):
table_info = cursor.execute('PRAGMA table_info({})'.format(table_name)).fetchall() table_info = cursor.execute(f'PRAGMA table_info({table_name})').fetchall()
return [row[1].decode('utf-8') for row in table_info] return [row[1].decode('utf-8') for row in table_info]

@ -1,5 +1,3 @@
from __future__ import unicode_literals
from ..compat import compat_str from ..compat import compat_str
from ..utils import ( from ..utils import (
determine_protocol, determine_protocol,

@ -1,5 +1,3 @@
from __future__ import division, unicode_literals
import os import os
import re import re
import time import time
@ -25,7 +23,7 @@ from ..minicurses import (
) )
class FileDownloader(object): class FileDownloader:
"""File Downloader class. """File Downloader class.
File downloader objects are the ones responsible of downloading the File downloader objects are the ones responsible of downloading the
@ -219,7 +217,7 @@ class FileDownloader(object):
while True: while True:
try: try:
return func(self, *args, **kwargs) return func(self, *args, **kwargs)
except (IOError, OSError) as err: except OSError as err:
retry = retry + 1 retry = retry + 1
if retry > file_access_retries or err.errno not in (errno.EACCES, errno.EINVAL): if retry > file_access_retries or err.errno not in (errno.EACCES, errno.EINVAL):
if not fatal: if not fatal:
@ -486,4 +484,4 @@ class FileDownloader(object):
if exe is None: if exe is None:
exe = os.path.basename(str_args[0]) exe = os.path.basename(str_args[0])
self.write_debug('%s command line: %s' % (exe, shell_quote(str_args))) self.write_debug(f'{exe} command line: {shell_quote(str_args)}')

@ -1,4 +1,3 @@
from __future__ import unicode_literals
import time import time
from ..downloader import get_suitable_downloader from ..downloader import get_suitable_downloader
@ -46,7 +45,7 @@ class DashSegmentsFD(FragmentFD):
if real_downloader: if real_downloader:
self.to_screen( self.to_screen(
'[%s] Fragment downloads will be delegated to %s' % (self.FD_NAME, real_downloader.get_basename())) f'[{self.FD_NAME}] Fragment downloads will be delegated to {real_downloader.get_basename()}')
info_dict['fragments'] = list(fragments_to_download) info_dict['fragments'] = list(fragments_to_download)
fd = real_downloader(self.ydl, self.params) fd = real_downloader(self.ydl, self.params)
return fd.real_download(filename, info_dict) return fd.real_download(filename, info_dict)

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import os.path import os.path
import re import re
import subprocess import subprocess
@ -56,7 +54,7 @@ class ExternalFD(FragmentFD):
} }
if filename != '-': if filename != '-':
fsize = os.path.getsize(encodeFilename(tmpfilename)) fsize = os.path.getsize(encodeFilename(tmpfilename))
self.to_screen('\r[%s] Downloaded %s bytes' % (self.get_basename(), fsize)) self.to_screen(f'\r[{self.get_basename()}] Downloaded {fsize} bytes')
self.try_rename(tmpfilename, filename) self.try_rename(tmpfilename, filename)
status.update({ status.update({
'downloaded_bytes': fsize, 'downloaded_bytes': fsize,
@ -157,7 +155,7 @@ class ExternalFD(FragmentFD):
fragment_filename = '%s-Frag%d' % (tmpfilename, frag_index) fragment_filename = '%s-Frag%d' % (tmpfilename, frag_index)
try: try:
src, _ = self.sanitize_open(fragment_filename, 'rb') src, _ = self.sanitize_open(fragment_filename, 'rb')
except IOError as err: except OSError as err:
if skip_unavailable_fragments and frag_index > 1: if skip_unavailable_fragments and frag_index > 1:
self.report_skip_fragment(frag_index, err) self.report_skip_fragment(frag_index, err)
continue continue
@ -179,7 +177,7 @@ class CurlFD(ExternalFD):
cmd = [self.exe, '--location', '-o', tmpfilename, '--compressed'] cmd = [self.exe, '--location', '-o', tmpfilename, '--compressed']
if info_dict.get('http_headers') is not None: if info_dict.get('http_headers') is not None:
for key, val in info_dict['http_headers'].items(): for key, val in info_dict['http_headers'].items():
cmd += ['--header', '%s: %s' % (key, val)] cmd += ['--header', f'{key}: {val}']
cmd += self._bool_option('--continue-at', 'continuedl', '-', '0') cmd += self._bool_option('--continue-at', 'continuedl', '-', '0')
cmd += self._valueless_option('--silent', 'noprogress') cmd += self._valueless_option('--silent', 'noprogress')
@ -216,7 +214,7 @@ class AxelFD(ExternalFD):
cmd = [self.exe, '-o', tmpfilename] cmd = [self.exe, '-o', tmpfilename]
if info_dict.get('http_headers') is not None: if info_dict.get('http_headers') is not None:
for key, val in info_dict['http_headers'].items(): for key, val in info_dict['http_headers'].items():
cmd += ['-H', '%s: %s' % (key, val)] cmd += ['-H', f'{key}: {val}']
cmd += self._configuration_args() cmd += self._configuration_args()
cmd += ['--', info_dict['url']] cmd += ['--', info_dict['url']]
return cmd return cmd
@ -229,7 +227,7 @@ class WgetFD(ExternalFD):
cmd = [self.exe, '-O', tmpfilename, '-nv', '--no-cookies', '--compression=auto'] cmd = [self.exe, '-O', tmpfilename, '-nv', '--no-cookies', '--compression=auto']
if info_dict.get('http_headers') is not None: if info_dict.get('http_headers') is not None:
for key, val in info_dict['http_headers'].items(): for key, val in info_dict['http_headers'].items():
cmd += ['--header', '%s: %s' % (key, val)] cmd += ['--header', f'{key}: {val}']
cmd += self._option('--limit-rate', 'ratelimit') cmd += self._option('--limit-rate', 'ratelimit')
retry = self._option('--tries', 'retries') retry = self._option('--tries', 'retries')
if len(retry) == 2: if len(retry) == 2:
@ -240,7 +238,7 @@ class WgetFD(ExternalFD):
proxy = self.params.get('proxy') proxy = self.params.get('proxy')
if proxy: if proxy:
for var in ('http_proxy', 'https_proxy'): for var in ('http_proxy', 'https_proxy'):
cmd += ['--execute', '%s=%s' % (var, proxy)] cmd += ['--execute', f'{var}={proxy}']
cmd += self._valueless_option('--no-check-certificate', 'nocheckcertificate') cmd += self._valueless_option('--no-check-certificate', 'nocheckcertificate')
cmd += self._configuration_args() cmd += self._configuration_args()
cmd += ['--', info_dict['url']] cmd += ['--', info_dict['url']]
@ -271,7 +269,7 @@ class Aria2cFD(ExternalFD):
if info_dict.get('http_headers') is not None: if info_dict.get('http_headers') is not None:
for key, val in info_dict['http_headers'].items(): for key, val in info_dict['http_headers'].items():
cmd += ['--header', '%s: %s' % (key, val)] cmd += ['--header', f'{key}: {val}']
cmd += self._option('--max-overall-download-limit', 'ratelimit') cmd += self._option('--max-overall-download-limit', 'ratelimit')
cmd += self._option('--interface', 'source_address') cmd += self._option('--interface', 'source_address')
cmd += self._option('--all-proxy', 'proxy') cmd += self._option('--all-proxy', 'proxy')
@ -289,10 +287,10 @@ class Aria2cFD(ExternalFD):
dn = os.path.dirname(tmpfilename) dn = os.path.dirname(tmpfilename)
if dn: if dn:
if not os.path.isabs(dn): if not os.path.isabs(dn):
dn = '.%s%s' % (os.path.sep, dn) dn = f'.{os.path.sep}{dn}'
cmd += ['--dir', dn + os.path.sep] cmd += ['--dir', dn + os.path.sep]
if 'fragments' not in info_dict: if 'fragments' not in info_dict:
cmd += ['--out', '.%s%s' % (os.path.sep, os.path.basename(tmpfilename))] cmd += ['--out', f'.{os.path.sep}{os.path.basename(tmpfilename)}']
cmd += ['--auto-file-renaming=false'] cmd += ['--auto-file-renaming=false']
if 'fragments' in info_dict: if 'fragments' in info_dict:
@ -320,7 +318,7 @@ class HttpieFD(ExternalFD):
if info_dict.get('http_headers') is not None: if info_dict.get('http_headers') is not None:
for key, val in info_dict['http_headers'].items(): for key, val in info_dict['http_headers'].items():
cmd += ['%s:%s' % (key, val)] cmd += [f'{key}:{val}']
return cmd return cmd
@ -393,7 +391,7 @@ class FFmpegFD(ExternalFD):
headers = handle_youtubedl_headers(info_dict['http_headers']) headers = handle_youtubedl_headers(info_dict['http_headers'])
args += [ args += [
'-headers', '-headers',
''.join('%s: %s\r\n' % (key, val) for key, val in headers.items())] ''.join(f'{key}: {val}\r\n' for key, val in headers.items())]
env = None env = None
proxy = self.params.get('proxy') proxy = self.params.get('proxy')

@ -1,5 +1,3 @@
from __future__ import division, unicode_literals
import io import io
import itertools import itertools
import time import time

@ -1,5 +1,3 @@
from __future__ import division, unicode_literals
import threading import threading
from .common import FileDownloader from .common import FileDownloader

@ -1,5 +1,3 @@
from __future__ import division, unicode_literals
import http.client import http.client
import json import json
import math import math
@ -172,8 +170,7 @@ class FragmentFD(FileDownloader):
total_frags_str += ' (not including %d ad)' % ad_frags total_frags_str += ' (not including %d ad)' % ad_frags
else: else:
total_frags_str = 'unknown (live)' total_frags_str = 'unknown (live)'
self.to_screen( self.to_screen(f'[{self.FD_NAME}] Total fragments: {total_frags_str}')
'[%s] Total fragments: %s' % (self.FD_NAME, total_frags_str))
self.report_destination(ctx['filename']) self.report_destination(ctx['filename'])
dl = HttpQuietDownloader( dl = HttpQuietDownloader(
self.ydl, self.ydl,
@ -342,8 +339,7 @@ class FragmentFD(FileDownloader):
total_frags_str += ' (not including %d ad)' % ad_frags total_frags_str += ' (not including %d ad)' % ad_frags
else: else:
total_frags_str = 'unknown (live)' total_frags_str = 'unknown (live)'
self.to_screen( self.to_screen(f'[{self.FD_NAME}] Total fragments: {total_frags_str}')
'[%s] Total fragments: %s' % (self.FD_NAME, total_frags_str))
tmpfilename = self.temp_name(ctx['filename']) tmpfilename = self.temp_name(ctx['filename'])

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import re import re
import io import io
import binascii import binascii
@ -102,8 +100,7 @@ class HlsFD(FragmentFD):
if real_downloader and not real_downloader.supports_manifest(s): if real_downloader and not real_downloader.supports_manifest(s):
real_downloader = None real_downloader = None
if real_downloader: if real_downloader:
self.to_screen( self.to_screen(f'[{self.FD_NAME}] Fragment downloads will be delegated to {real_downloader.get_basename()}')
'[%s] Fragment downloads will be delegated to %s' % (self.FD_NAME, real_downloader.get_basename()))
def is_ad_fragment_start(s): def is_ad_fragment_start(s):
return (s.startswith('#ANVATO-SEGMENT-INFO') and 'type=ad' in s return (s.startswith('#ANVATO-SEGMENT-INFO') and 'type=ad' in s

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import os import os
import ssl import ssl
import time import time
@ -221,10 +219,12 @@ class HttpFD(FileDownloader):
min_data_len = self.params.get('min_filesize') min_data_len = self.params.get('min_filesize')
max_data_len = self.params.get('max_filesize') max_data_len = self.params.get('max_filesize')
if min_data_len is not None and data_len < min_data_len: if min_data_len is not None and data_len < min_data_len:
self.to_screen('\r[download] File is smaller than min-filesize (%s bytes < %s bytes). Aborting.' % (data_len, min_data_len)) self.to_screen(
f'\r[download] File is smaller than min-filesize ({data_len} bytes < {min_data_len} bytes). Aborting.')
return False return False
if max_data_len is not None and data_len > max_data_len: if max_data_len is not None and data_len > max_data_len:
self.to_screen('\r[download] File is larger than max-filesize (%s bytes > %s bytes). Aborting.' % (data_len, max_data_len)) self.to_screen(
f'\r[download] File is larger than max-filesize ({data_len} bytes > {max_data_len} bytes). Aborting.')
return False return False
byte_counter = 0 + ctx.resume_len byte_counter = 0 + ctx.resume_len
@ -265,7 +265,7 @@ class HttpFD(FileDownloader):
assert ctx.stream is not None assert ctx.stream is not None
ctx.filename = self.undo_temp_name(ctx.tmpfilename) ctx.filename = self.undo_temp_name(ctx.tmpfilename)
self.report_destination(ctx.filename) self.report_destination(ctx.filename)
except (OSError, IOError) as err: except OSError as err:
self.report_error('unable to open for writing: %s' % str(err)) self.report_error('unable to open for writing: %s' % str(err))
return False return False
@ -277,7 +277,7 @@ class HttpFD(FileDownloader):
try: try:
ctx.stream.write(data_block) ctx.stream.write(data_block)
except (IOError, OSError) as err: except OSError as err:
self.to_stderr('\n') self.to_stderr('\n')
self.report_error('unable to write data: %s' % str(err)) self.report_error('unable to write data: %s' % str(err))
return False return False

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import time import time
import binascii import binascii
import io import io

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import io import io
import quopri import quopri
import re import re

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import threading import threading
from .common import FileDownloader from .common import FileDownloader

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import os import os
import re import re
import subprocess import subprocess

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import os import os
import subprocess import subprocess
@ -32,7 +30,7 @@ class RtspFD(FileDownloader):
retval = subprocess.call(args) retval = subprocess.call(args)
if retval == 0: if retval == 0:
fsize = os.path.getsize(encodeFilename(tmpfilename)) fsize = os.path.getsize(encodeFilename(tmpfilename))
self.to_screen('\r[%s] %s bytes' % (args[0], fsize)) self.to_screen(f'\r[{args[0]}] {fsize} bytes')
self.try_rename(tmpfilename, filename) self.try_rename(tmpfilename, filename)
self._hook_progress({ self._hook_progress({
'downloaded_bytes': fsize, 'downloaded_bytes': fsize,

@ -1,5 +1,3 @@
from __future__ import division, unicode_literals
import json import json
import time import time

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import hashlib import hashlib
import hmac import hmac
import re import re

@ -1,7 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .amp import AMPIE from .amp import AMPIE
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (

@ -1,7 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_str from ..compat import compat_str
from ..utils import ( from ..utils import (

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor

@ -1,7 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (
clean_html, clean_html,

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import base64 import base64
import binascii import binascii
import json import json

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_parse_qs, compat_parse_qs,

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import json import json
import re import re
import time import time

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import functools import functools
import re import re

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import json import json
from .turner import TurnerBaseIE from .turner import TurnerBaseIE

@ -1,7 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .theplatform import ThePlatformIE from .theplatform import ThePlatformIE
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import functools import functools
import re import re

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_str from ..compat import compat_str
from ..utils import ( from ..utils import (

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import json import json
from .common import InfoExtractor from .common import InfoExtractor

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_str from ..compat import compat_str
from ..utils import ( from ..utils import (

@ -1,5 +1,3 @@
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (
parse_iso8601, parse_iso8601,

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (
clean_html, clean_html,

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from .youtube import YoutubeIE from .youtube import YoutubeIE
from .vimeo import VimeoIE from .vimeo import VimeoIE

@ -1,4 +1,3 @@
# coding: utf-8
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import int_or_none from ..utils import int_or_none

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import re import re
from .theplatform import ThePlatformIE from .theplatform import ThePlatformIE

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import json import json
from .common import InfoExtractor from .common import InfoExtractor

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (
determine_ext, determine_ext,

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import re import re
import urllib.parse import urllib.parse

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import base64 import base64
import hashlib import hashlib
import json import json

@ -1,5 +1,3 @@
from __future__ import unicode_literals
from .nfl import NFLTokenGenerator from .nfl import NFLTokenGenerator
__all__ = [ __all__ = [

@ -1,6 +1,3 @@
from __future__ import unicode_literals
class TokenGenerator: class TokenGenerator:
def generate(self, anvack, mcp_id): def generate(self, anvack, mcp_id):
raise NotImplementedError('This method must be implemented by subclasses') raise NotImplementedError('This method must be implemented by subclasses')

@ -1,5 +1,3 @@
from __future__ import unicode_literals
import json import json
from .common import TokenGenerator from .common import TokenGenerator

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import re import re
from .yahoo import YahooIE from .yahoo import YahooIE

@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save