From 5a727063c54a2353b0bb58644c74e7f74f553800 Mon Sep 17 00:00:00 2001
From: pukkandan <pukkandan.ytdlp@gmail.com>
Date: Mon, 11 Apr 2022 14:03:13 +0530
Subject: [PATCH 1/9] [FFmpegMetadataPP] Remove `\0` from metadata

---
 yt_dlp/postprocessor/ffmpeg.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py
index 27d06cbde8..78c6f91074 100644
--- a/yt_dlp/postprocessor/ffmpeg.py
+++ b/yt_dlp/postprocessor/ffmpeg.py
@@ -737,6 +737,7 @@ def add(meta_list, info_list=None):
                 str(info[key]) for key in [f'{meta_prefix}_'] + list(variadic(info_list or meta_list))
                 if info.get(key) is not None), None)
             if value not in ('', None):
+                value = value.replace('\0', '')  # nul character cannot be passed in command line
                 metadata['common'].update({meta_f: value for meta_f in variadic(meta_list)})
 
         # See [1-4] for some info on media metadata/metadata supported
-- 
GitLab


From ab96d1ad1bcdb943aa6519980e5383ca91f7da2b Mon Sep 17 00:00:00 2001
From: felix <felix.von.s@posteo.de>
Date: Sun, 19 Sep 2021 13:16:11 +0200
Subject: [PATCH 2/9] [cleanup] Remove unused scripts/tests (#2173)

Authored by fstirlitz, pukkandan
---
 devscripts/buildserver.py                     | 435 ---------
 devscripts/create-github-release.py           | 112 ---
 devscripts/gh-pages.unused/add-version.py     |  43 -
 .../gh-pages.unused/generate-download.py      |  22 -
 devscripts/gh-pages.unused/sign-versions.py   |  34 -
 .../gh-pages.unused/update-copyright.py       |  21 -
 devscripts/gh-pages.unused/update-feed.py     |  76 --
 devscripts/gh-pages.unused/update-sites.py    |  37 -
 devscripts/posix-locale.sh                    |   6 -
 devscripts/release.sh                         | 143 ---
 devscripts/show-downloads-statistics.py       |  49 -
 devscripts/wine-py2exe.sh                     |  58 --
 test/swftests.unused/.gitignore               |   1 -
 test/swftests.unused/ArrayAccess.as           |  19 -
 test/swftests.unused/ClassCall.as             |  17 -
 test/swftests.unused/ClassConstruction.as     |  15 -
 test/swftests.unused/ConstArrayAccess.as      |  18 -
 test/swftests.unused/ConstantInt.as           |  12 -
 test/swftests.unused/DictCall.as              |  10 -
 test/swftests.unused/EqualsOperator.as        |  10 -
 test/swftests.unused/LocalVars.as             |  13 -
 test/swftests.unused/MemberAssignment.as      |  22 -
 test/swftests.unused/NeOperator.as            |  24 -
 test/swftests.unused/PrivateCall.as           |  21 -
 test/swftests.unused/PrivateVoidCall.as       |  22 -
 test/swftests.unused/StaticAssignment.as      |  13 -
 test/swftests.unused/StaticRetrieval.as       |  16 -
 test/swftests.unused/StringBasics.as          |  11 -
 test/swftests.unused/StringCharCodeAt.as      |  11 -
 test/swftests.unused/StringConversion.as      |  11 -
 test/test_swfinterp.py.disabled               |  80 --
 test/test_unicode_literals.py.disabled        |  63 --
 yt_dlp/swfinterp.py.disabled                  | 834 ------------------
 33 files changed, 2279 deletions(-)
 delete mode 100644 devscripts/buildserver.py
 delete mode 100644 devscripts/create-github-release.py
 delete mode 100644 devscripts/gh-pages.unused/add-version.py
 delete mode 100644 devscripts/gh-pages.unused/generate-download.py
 delete mode 100644 devscripts/gh-pages.unused/sign-versions.py
 delete mode 100644 devscripts/gh-pages.unused/update-copyright.py
 delete mode 100644 devscripts/gh-pages.unused/update-feed.py
 delete mode 100644 devscripts/gh-pages.unused/update-sites.py
 delete mode 100755 devscripts/posix-locale.sh
 delete mode 100755 devscripts/release.sh
 delete mode 100644 devscripts/show-downloads-statistics.py
 delete mode 100755 devscripts/wine-py2exe.sh
 delete mode 100644 test/swftests.unused/.gitignore
 delete mode 100644 test/swftests.unused/ArrayAccess.as
 delete mode 100644 test/swftests.unused/ClassCall.as
 delete mode 100644 test/swftests.unused/ClassConstruction.as
 delete mode 100644 test/swftests.unused/ConstArrayAccess.as
 delete mode 100644 test/swftests.unused/ConstantInt.as
 delete mode 100644 test/swftests.unused/DictCall.as
 delete mode 100644 test/swftests.unused/EqualsOperator.as
 delete mode 100644 test/swftests.unused/LocalVars.as
 delete mode 100644 test/swftests.unused/MemberAssignment.as
 delete mode 100644 test/swftests.unused/NeOperator.as
 delete mode 100644 test/swftests.unused/PrivateCall.as
 delete mode 100644 test/swftests.unused/PrivateVoidCall.as
 delete mode 100644 test/swftests.unused/StaticAssignment.as
 delete mode 100644 test/swftests.unused/StaticRetrieval.as
 delete mode 100644 test/swftests.unused/StringBasics.as
 delete mode 100644 test/swftests.unused/StringCharCodeAt.as
 delete mode 100644 test/swftests.unused/StringConversion.as
 delete mode 100644 test/test_swfinterp.py.disabled
 delete mode 100644 test/test_unicode_literals.py.disabled
 delete mode 100644 yt_dlp/swfinterp.py.disabled

diff --git a/devscripts/buildserver.py b/devscripts/buildserver.py
deleted file mode 100644
index cd544b816e..0000000000
--- a/devscripts/buildserver.py
+++ /dev/null
@@ -1,435 +0,0 @@
-# UNUSED
-
-#!/usr/bin/python3
-
-import argparse
-import ctypes
-import functools
-import shutil
-import subprocess
-import sys
-import tempfile
-import threading
-import traceback
-import os.path
-
-sys.path.insert(0, os.path.dirname(os.path.dirname((os.path.abspath(__file__)))))
-from yt_dlp.compat import (
-    compat_input,
-    compat_http_server,
-    compat_str,
-    compat_urlparse,
-)
-
-# These are not used outside of buildserver.py thus not in compat.py
-
-try:
-    import winreg as compat_winreg
-except ImportError:  # Python 2
-    import _winreg as compat_winreg
-
-try:
-    import socketserver as compat_socketserver
-except ImportError:  # Python 2
-    import SocketServer as compat_socketserver
-
-
-class BuildHTTPServer(compat_socketserver.ThreadingMixIn, compat_http_server.HTTPServer):
-    allow_reuse_address = True
-
-
-advapi32 = ctypes.windll.advapi32
-
-SC_MANAGER_ALL_ACCESS = 0xf003f
-SC_MANAGER_CREATE_SERVICE = 0x02
-SERVICE_WIN32_OWN_PROCESS = 0x10
-SERVICE_AUTO_START = 0x2
-SERVICE_ERROR_NORMAL = 0x1
-DELETE = 0x00010000
-SERVICE_STATUS_START_PENDING = 0x00000002
-SERVICE_STATUS_RUNNING = 0x00000004
-SERVICE_ACCEPT_STOP = 0x1
-
-SVCNAME = 'youtubedl_builder'
-
-LPTSTR = ctypes.c_wchar_p
-START_CALLBACK = ctypes.WINFUNCTYPE(None, ctypes.c_int, ctypes.POINTER(LPTSTR))
-
-
-class SERVICE_TABLE_ENTRY(ctypes.Structure):
-    _fields_ = [
-        ('lpServiceName', LPTSTR),
-        ('lpServiceProc', START_CALLBACK)
-    ]
-
-
-HandlerEx = ctypes.WINFUNCTYPE(
-    ctypes.c_int,     # return
-    ctypes.c_int,     # dwControl
-    ctypes.c_int,     # dwEventType
-    ctypes.c_void_p,  # lpEventData,
-    ctypes.c_void_p,  # lpContext,
-)
-
-
-def _ctypes_array(c_type, py_array):
-    ar = (c_type * len(py_array))()
-    ar[:] = py_array
-    return ar
-
-
-def win_OpenSCManager():
-    res = advapi32.OpenSCManagerW(None, None, SC_MANAGER_ALL_ACCESS)
-    if not res:
-        raise Exception('Opening service manager failed - '
-                        'are you running this as administrator?')
-    return res
-
-
-def win_install_service(service_name, cmdline):
-    manager = win_OpenSCManager()
-    try:
-        h = advapi32.CreateServiceW(
-            manager, service_name, None,
-            SC_MANAGER_CREATE_SERVICE, SERVICE_WIN32_OWN_PROCESS,
-            SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
-            cmdline, None, None, None, None, None)
-        if not h:
-            raise OSError('Service creation failed: %s' % ctypes.FormatError())
-
-        advapi32.CloseServiceHandle(h)
-    finally:
-        advapi32.CloseServiceHandle(manager)
-
-
-def win_uninstall_service(service_name):
-    manager = win_OpenSCManager()
-    try:
-        h = advapi32.OpenServiceW(manager, service_name, DELETE)
-        if not h:
-            raise OSError('Could not find service %s: %s' % (
-                service_name, ctypes.FormatError()))
-
-        try:
-            if not advapi32.DeleteService(h):
-                raise OSError('Deletion failed: %s' % ctypes.FormatError())
-        finally:
-            advapi32.CloseServiceHandle(h)
-    finally:
-        advapi32.CloseServiceHandle(manager)
-
-
-def win_service_report_event(service_name, msg, is_error=True):
-    with open('C:/sshkeys/log', 'a', encoding='utf-8') as f:
-        f.write(msg + '\n')
-
-    event_log = advapi32.RegisterEventSourceW(None, service_name)
-    if not event_log:
-        raise OSError('Could not report event: %s' % ctypes.FormatError())
-
-    try:
-        type_id = 0x0001 if is_error else 0x0004
-        event_id = 0xc0000000 if is_error else 0x40000000
-        lines = _ctypes_array(LPTSTR, [msg])
-
-        if not advapi32.ReportEventW(
-                event_log, type_id, 0, event_id, None, len(lines), 0,
-                lines, None):
-            raise OSError('Event reporting failed: %s' % ctypes.FormatError())
-    finally:
-        advapi32.DeregisterEventSource(event_log)
-
-
-def win_service_handler(stop_event, *args):
-    try:
-        raise ValueError('Handler called with args ' + repr(args))
-        TODO
-    except Exception as e:
-        tb = traceback.format_exc()
-        msg = str(e) + '\n' + tb
-        win_service_report_event(service_name, msg, is_error=True)
-        raise
-
-
-def win_service_set_status(handle, status_code):
-    svcStatus = SERVICE_STATUS()
-    svcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS
-    svcStatus.dwCurrentState = status_code
-    svcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
-
-    svcStatus.dwServiceSpecificExitCode = 0
-
-    if not advapi32.SetServiceStatus(handle, ctypes.byref(svcStatus)):
-        raise OSError('SetServiceStatus failed: %r' % ctypes.FormatError())
-
-
-def win_service_main(service_name, real_main, argc, argv_raw):
-    try:
-        # args = [argv_raw[i].value for i in range(argc)]
-        stop_event = threading.Event()
-        handler = HandlerEx(functools.partial(stop_event, win_service_handler))
-        h = advapi32.RegisterServiceCtrlHandlerExW(service_name, handler, None)
-        if not h:
-            raise OSError('Handler registration failed: %s' %
-                          ctypes.FormatError())
-
-        TODO
-    except Exception as e:
-        tb = traceback.format_exc()
-        msg = str(e) + '\n' + tb
-        win_service_report_event(service_name, msg, is_error=True)
-        raise
-
-
-def win_service_start(service_name, real_main):
-    try:
-        cb = START_CALLBACK(
-            functools.partial(win_service_main, service_name, real_main))
-        dispatch_table = _ctypes_array(SERVICE_TABLE_ENTRY, [
-            SERVICE_TABLE_ENTRY(
-                service_name,
-                cb
-            ),
-            SERVICE_TABLE_ENTRY(None, ctypes.cast(None, START_CALLBACK))
-        ])
-
-        if not advapi32.StartServiceCtrlDispatcherW(dispatch_table):
-            raise OSError('ctypes start failed: %s' % ctypes.FormatError())
-    except Exception as e:
-        tb = traceback.format_exc()
-        msg = str(e) + '\n' + tb
-        win_service_report_event(service_name, msg, is_error=True)
-        raise
-
-
-def main(args=None):
-    parser = argparse.ArgumentParser()
-    parser.add_argument('-i', '--install',
-                        action='store_const', dest='action', const='install',
-                        help='Launch at Windows startup')
-    parser.add_argument('-u', '--uninstall',
-                        action='store_const', dest='action', const='uninstall',
-                        help='Remove Windows service')
-    parser.add_argument('-s', '--service',
-                        action='store_const', dest='action', const='service',
-                        help='Run as a Windows service')
-    parser.add_argument('-b', '--bind', metavar='<host:port>',
-                        action='store', default='0.0.0.0:8142',
-                        help='Bind to host:port (default %default)')
-    options = parser.parse_args(args=args)
-
-    if options.action == 'install':
-        fn = os.path.abspath(__file__).replace('v:', '\\\\vboxsrv\\vbox')
-        cmdline = '%s %s -s -b %s' % (sys.executable, fn, options.bind)
-        win_install_service(SVCNAME, cmdline)
-        return
-
-    if options.action == 'uninstall':
-        win_uninstall_service(SVCNAME)
-        return
-
-    if options.action == 'service':
-        win_service_start(SVCNAME, main)
-        return
-
-    host, port_str = options.bind.split(':')
-    port = int(port_str)
-
-    print('Listening on %s:%d' % (host, port))
-    srv = BuildHTTPServer((host, port), BuildHTTPRequestHandler)
-    thr = threading.Thread(target=srv.serve_forever)
-    thr.start()
-    compat_input('Press ENTER to shut down')
-    srv.shutdown()
-    thr.join()
-
-
-def rmtree(path):
-    for name in os.listdir(path):
-        fname = os.path.join(path, name)
-        if os.path.isdir(fname):
-            rmtree(fname)
-        else:
-            os.chmod(fname, 0o666)
-            os.remove(fname)
-    os.rmdir(path)
-
-
-class BuildError(Exception):
-    def __init__(self, output, code=500):
-        self.output = output
-        self.code = code
-
-    def __str__(self):
-        return self.output
-
-
-class HTTPError(BuildError):
-    pass
-
-
-class PythonBuilder(object):
-    def __init__(self, **kwargs):
-        python_version = kwargs.pop('python', '3.4')
-        python_path = None
-        for node in ('Wow6432Node\\', ''):
-            try:
-                key = compat_winreg.OpenKey(
-                    compat_winreg.HKEY_LOCAL_MACHINE,
-                    r'SOFTWARE\%sPython\PythonCore\%s\InstallPath' % (node, python_version))
-                try:
-                    python_path, _ = compat_winreg.QueryValueEx(key, '')
-                finally:
-                    compat_winreg.CloseKey(key)
-                break
-            except Exception:
-                pass
-
-        if not python_path:
-            raise BuildError('No such Python version: %s' % python_version)
-
-        self.pythonPath = python_path
-
-        super(PythonBuilder, self).__init__(**kwargs)
-
-
-class GITInfoBuilder(object):
-    def __init__(self, **kwargs):
-        try:
-            self.user, self.repoName = kwargs['path'][:2]
-            self.rev = kwargs.pop('rev')
-        except ValueError:
-            raise BuildError('Invalid path')
-        except KeyError as e:
-            raise BuildError('Missing mandatory parameter "%s"' % e.args[0])
-
-        path = os.path.join(os.environ['APPDATA'], 'Build archive', self.repoName, self.user)
-        if not os.path.exists(path):
-            os.makedirs(path)
-        self.basePath = tempfile.mkdtemp(dir=path)
-        self.buildPath = os.path.join(self.basePath, 'build')
-
-        super(GITInfoBuilder, self).__init__(**kwargs)
-
-
-class GITBuilder(GITInfoBuilder):
-    def build(self):
-        try:
-            subprocess.check_output(['git', 'clone', 'git://github.com/%s/%s.git' % (self.user, self.repoName), self.buildPath])
-            subprocess.check_output(['git', 'checkout', self.rev], cwd=self.buildPath)
-        except subprocess.CalledProcessError as e:
-            raise BuildError(e.output)
-
-        super(GITBuilder, self).build()
-
-
-class YoutubeDLBuilder(object):
-    authorizedUsers = ['fraca7', 'phihag', 'rg3', 'FiloSottile', 'ytdl-org']
-
-    def __init__(self, **kwargs):
-        if self.repoName != 'yt-dlp':
-            raise BuildError('Invalid repository "%s"' % self.repoName)
-        if self.user not in self.authorizedUsers:
-            raise HTTPError('Unauthorized user "%s"' % self.user, 401)
-
-        super(YoutubeDLBuilder, self).__init__(**kwargs)
-
-    def build(self):
-        try:
-            proc = subprocess.Popen([os.path.join(self.pythonPath, 'python.exe'), 'setup.py', 'py2exe'], stdin=subprocess.PIPE, cwd=self.buildPath)
-            proc.wait()
-            #subprocess.check_output([os.path.join(self.pythonPath, 'python.exe'), 'setup.py', 'py2exe'],
-            #                        cwd=self.buildPath)
-        except subprocess.CalledProcessError as e:
-            raise BuildError(e.output)
-
-        super(YoutubeDLBuilder, self).build()
-
-
-class DownloadBuilder(object):
-    def __init__(self, **kwargs):
-        self.handler = kwargs.pop('handler')
-        self.srcPath = os.path.join(self.buildPath, *tuple(kwargs['path'][2:]))
-        self.srcPath = os.path.abspath(os.path.normpath(self.srcPath))
-        if not self.srcPath.startswith(self.buildPath):
-            raise HTTPError(self.srcPath, 401)
-
-        super(DownloadBuilder, self).__init__(**kwargs)
-
-    def build(self):
-        if not os.path.exists(self.srcPath):
-            raise HTTPError('No such file', 404)
-        if os.path.isdir(self.srcPath):
-            raise HTTPError('Is a directory: %s' % self.srcPath, 401)
-
-        self.handler.send_response(200)
-        self.handler.send_header('Content-Type', 'application/octet-stream')
-        self.handler.send_header('Content-Disposition', 'attachment; filename=%s' % os.path.split(self.srcPath)[-1])
-        self.handler.send_header('Content-Length', str(os.stat(self.srcPath).st_size))
-        self.handler.end_headers()
-
-        with open(self.srcPath, 'rb') as src:
-            shutil.copyfileobj(src, self.handler.wfile)
-
-        super(DownloadBuilder, self).build()
-
-
-class CleanupTempDir(object):
-    def build(self):
-        try:
-            rmtree(self.basePath)
-        except Exception as e:
-            print('WARNING deleting "%s": %s' % (self.basePath, e))
-
-        super(CleanupTempDir, self).build()
-
-
-class Null(object):
-    def __init__(self, **kwargs):
-        pass
-
-    def start(self):
-        pass
-
-    def close(self):
-        pass
-
-    def build(self):
-        pass
-
-
-class Builder(PythonBuilder, GITBuilder, YoutubeDLBuilder, DownloadBuilder, CleanupTempDir, Null):
-    pass
-
-
-class BuildHTTPRequestHandler(compat_http_server.BaseHTTPRequestHandler):
-    actionDict = {'build': Builder, 'download': Builder}  # They're the same, no more caching.
-
-    def do_GET(self):
-        path = compat_urlparse.urlparse(self.path)
-        paramDict = dict([(key, value[0]) for key, value in compat_urlparse.parse_qs(path.query).items()])
-        action, _, path = path.path.strip('/').partition('/')
-        if path:
-            path = path.split('/')
-            if action in self.actionDict:
-                try:
-                    builder = self.actionDict[action](path=path, handler=self, **paramDict)
-                    builder.start()
-                    try:
-                        builder.build()
-                    finally:
-                        builder.close()
-                except BuildError as e:
-                    self.send_response(e.code)
-                    msg = compat_str(e).encode('UTF-8')
-                    self.send_header('Content-Type', 'text/plain; charset=UTF-8')
-                    self.send_header('Content-Length', len(msg))
-                    self.end_headers()
-                    self.wfile.write(msg)
-            else:
-                self.send_response(500, 'Unknown build method "%s"' % action)
-        else:
-            self.send_response(500, 'Malformed URL')
-
-if __name__ == '__main__':
-    main()
diff --git a/devscripts/create-github-release.py b/devscripts/create-github-release.py
deleted file mode 100644
index 53b3e0f485..0000000000
--- a/devscripts/create-github-release.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# Unused
-
-#!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import io
-import json
-import mimetypes
-import netrc
-import optparse
-import os
-import re
-import sys
-
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-
-from yt_dlp.compat import (
-    compat_basestring,
-    compat_getpass,
-    compat_print,
-    compat_urllib_request,
-)
-from yt_dlp.utils import (
-    make_HTTPS_handler,
-    sanitized_Request,
-)
-
-
-class GitHubReleaser(object):
-    _API_URL = 'https://api.github.com/repos/ytdl-org/youtube-dl/releases'
-    _UPLOADS_URL = 'https://uploads.github.com/repos/ytdl-org/youtube-dl/releases/%s/assets?name=%s'
-    _NETRC_MACHINE = 'github.com'
-
-    def __init__(self, debuglevel=0):
-        self._init_github_account()
-        https_handler = make_HTTPS_handler({}, debuglevel=debuglevel)
-        self._opener = compat_urllib_request.build_opener(https_handler)
-
-    def _init_github_account(self):
-        try:
-            info = netrc.netrc().authenticators(self._NETRC_MACHINE)
-            if info is not None:
-                self._token = info[2]
-                compat_print('Using GitHub credentials found in .netrc...')
-                return
-            else:
-                compat_print('No GitHub credentials found in .netrc')
-        except (IOError, netrc.NetrcParseError):
-            compat_print('Unable to parse .netrc')
-        self._token = compat_getpass(
-            'Type your GitHub PAT (personal access token) and press [Return]: ')
-
-    def _call(self, req):
-        if isinstance(req, compat_basestring):
-            req = sanitized_Request(req)
-        req.add_header('Authorization', 'token %s' % self._token)
-        response = self._opener.open(req).read().decode('utf-8')
-        return json.loads(response)
-
-    def list_releases(self):
-        return self._call(self._API_URL)
-
-    def create_release(self, tag_name, name=None, body='', draft=False, prerelease=False):
-        data = {
-            'tag_name': tag_name,
-            'target_commitish': 'master',
-            'name': name,
-            'body': body,
-            'draft': draft,
-            'prerelease': prerelease,
-        }
-        req = sanitized_Request(self._API_URL, json.dumps(data).encode('utf-8'))
-        return self._call(req)
-
-    def create_asset(self, release_id, asset):
-        asset_name = os.path.basename(asset)
-        url = self._UPLOADS_URL % (release_id, asset_name)
-        # Our files are small enough to be loaded directly into memory.
-        data = open(asset, 'rb').read()
-        req = sanitized_Request(url, data)
-        mime_type, _ = mimetypes.guess_type(asset_name)
-        req.add_header('Content-Type', mime_type or 'application/octet-stream')
-        return self._call(req)
-
-
-def main():
-    parser = optparse.OptionParser(usage='%prog CHANGELOG VERSION BUILDPATH')
-    options, args = parser.parse_args()
-    if len(args) != 3:
-        parser.error('Expected a version and a build directory')
-
-    changelog_file, version, build_path = args
-
-    with io.open(changelog_file, encoding='utf-8') as inf:
-        changelog = inf.read()
-
-    mobj = re.search(r'(?s)version %s\n{2}(.+?)\n{3}' % version, changelog)
-    body = mobj.group(1) if mobj else ''
-
-    releaser = GitHubReleaser()
-
-    new_release = releaser.create_release(
-        version, name='yt-dlp %s' % version, body=body)
-    release_id = new_release['id']
-
-    for asset in os.listdir(build_path):
-        compat_print('Uploading %s...' % asset)
-        releaser.create_asset(release_id, os.path.join(build_path, asset))
-
-
-if __name__ == '__main__':
-    main()
diff --git a/devscripts/gh-pages.unused/add-version.py b/devscripts/gh-pages.unused/add-version.py
deleted file mode 100644
index 9ea01374d6..0000000000
--- a/devscripts/gh-pages.unused/add-version.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import json
-import sys
-import hashlib
-import os.path
-
-
-if len(sys.argv) <= 1:
-    print('Specify the version number as parameter')
-    sys.exit()
-version = sys.argv[1]
-
-with open('update/LATEST_VERSION', 'w') as f:
-    f.write(version)
-
-versions_info = json.load(open('update/versions.json'))
-if 'signature' in versions_info:
-    del versions_info['signature']
-
-new_version = {}
-
-filenames = {
-    'bin': 'yt-dlp',
-    'exe': 'yt-dlp.exe',
-    'tar': 'yt-dlp-%s.tar.gz' % version}
-build_dir = os.path.join('..', '..', 'build', version)
-for key, filename in filenames.items():
-    url = 'https://yt-dl.org/downloads/%s/%s' % (version, filename)
-    fn = os.path.join(build_dir, filename)
-    with open(fn, 'rb') as f:
-        data = f.read()
-    if not data:
-        raise ValueError('File %s is empty!' % fn)
-    sha256sum = hashlib.sha256(data).hexdigest()
-    new_version[key] = (url, sha256sum)
-
-versions_info['versions'][version] = new_version
-versions_info['latest'] = version
-
-with open('update/versions.json', 'w') as jsonf:
-    json.dump(versions_info, jsonf, indent=4, sort_keys=True)
diff --git a/devscripts/gh-pages.unused/generate-download.py b/devscripts/gh-pages.unused/generate-download.py
deleted file mode 100644
index a873d32ee4..0000000000
--- a/devscripts/gh-pages.unused/generate-download.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import json
-
-versions_info = json.load(open('update/versions.json'))
-version = versions_info['latest']
-version_dict = versions_info['versions'][version]
-
-# Read template page
-with open('download.html.in', 'r', encoding='utf-8') as tmplf:
-    template = tmplf.read()
-
-template = template.replace('@PROGRAM_VERSION@', version)
-template = template.replace('@PROGRAM_URL@', version_dict['bin'][0])
-template = template.replace('@PROGRAM_SHA256SUM@', version_dict['bin'][1])
-template = template.replace('@EXE_URL@', version_dict['exe'][0])
-template = template.replace('@EXE_SHA256SUM@', version_dict['exe'][1])
-template = template.replace('@TAR_URL@', version_dict['tar'][0])
-template = template.replace('@TAR_SHA256SUM@', version_dict['tar'][1])
-with open('download.html', 'w', encoding='utf-8') as dlf:
-    dlf.write(template)
diff --git a/devscripts/gh-pages.unused/sign-versions.py b/devscripts/gh-pages.unused/sign-versions.py
deleted file mode 100644
index fa389c3587..0000000000
--- a/devscripts/gh-pages.unused/sign-versions.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python3
-from __future__ import unicode_literals, with_statement
-
-import rsa
-import json
-from binascii import hexlify
-
-try:
-    input = raw_input
-except NameError:
-    pass
-
-versions_info = json.load(open('update/versions.json'))
-if 'signature' in versions_info:
-    del versions_info['signature']
-
-print('Enter the PKCS1 private key, followed by a blank line:')
-privkey = b''
-while True:
-    try:
-        line = input()
-    except EOFError:
-        break
-    if line == '':
-        break
-    privkey += line.encode('ascii') + b'\n'
-privkey = rsa.PrivateKey.load_pkcs1(privkey)
-
-signature = hexlify(rsa.pkcs1.sign(json.dumps(versions_info, sort_keys=True).encode('utf-8'), privkey, 'SHA-256')).decode()
-print('signature: ' + signature)
-
-versions_info['signature'] = signature
-with open('update/versions.json', 'w') as versionsf:
-    json.dump(versions_info, versionsf, indent=4, sort_keys=True)
diff --git a/devscripts/gh-pages.unused/update-copyright.py b/devscripts/gh-pages.unused/update-copyright.py
deleted file mode 100644
index e122d0283f..0000000000
--- a/devscripts/gh-pages.unused/update-copyright.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import with_statement, unicode_literals
-
-import datetime
-import glob
-import io  # For Python 2 compatibility
-import os
-import re
-
-year = str(datetime.datetime.now().year)
-for fn in glob.glob('*.html*'):
-    with io.open(fn, encoding='utf-8') as f:
-        content = f.read()
-    newc = re.sub(r'(?P<copyright>Copyright © 2011-)(?P<year>[0-9]{4})', 'Copyright © 2011-' + year, content)
-    if content != newc:
-        tmpFn = fn + '.part'
-        with io.open(tmpFn, 'wt', encoding='utf-8') as outf:
-            outf.write(newc)
-        os.rename(tmpFn, fn)
diff --git a/devscripts/gh-pages.unused/update-feed.py b/devscripts/gh-pages.unused/update-feed.py
deleted file mode 100644
index c9f2fdb07c..0000000000
--- a/devscripts/gh-pages.unused/update-feed.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import datetime
-import io
-import json
-import textwrap
-
-
-atom_template = textwrap.dedent("""\
-    <?xml version="1.0" encoding="utf-8"?>
-    <feed xmlns="http://www.w3.org/2005/Atom">
-        <link rel="self" href="http://ytdl-org.github.io/youtube-dl/update/releases.atom" />
-        <title>yt-dlp releases</title>
-        <id>https://yt-dl.org/feed/yt-dlp-updates-feed</id>
-        <updated>@TIMESTAMP@</updated>
-        @ENTRIES@
-    </feed>""")
-
-entry_template = textwrap.dedent("""
-    <entry>
-        <id>https://yt-dl.org/feed/yt-dlp-updates-feed/yt-dlp-@VERSION@</id>
-        <title>New version @VERSION@</title>
-        <link href="http://ytdl-org.github.io/yt-dlp" />
-        <content type="xhtml">
-            <div xmlns="http://www.w3.org/1999/xhtml">
-                Downloads available at <a href="https://yt-dl.org/downloads/@VERSION@/">https://yt-dl.org/downloads/@VERSION@/</a>
-            </div>
-        </content>
-        <author>
-            <name>The yt-dlp maintainers</name>
-        </author>
-        <updated>@TIMESTAMP@</updated>
-    </entry>
-    """)
-
-now = datetime.datetime.now()
-now_iso = now.isoformat() + 'Z'
-
-atom_template = atom_template.replace('@TIMESTAMP@', now_iso)
-
-versions_info = json.load(open('update/versions.json'))
-versions = list(versions_info['versions'].keys())
-versions.sort()
-
-entries = []
-for v in versions:
-    fields = v.split('.')
-    year, month, day = map(int, fields[:3])
-    faked = 0
-    patchlevel = 0
-    while True:
-        try:
-            datetime.date(year, month, day)
-        except ValueError:
-            day -= 1
-            faked += 1
-            assert day > 0
-            continue
-        break
-    if len(fields) >= 4:
-        try:
-            patchlevel = int(fields[3])
-        except ValueError:
-            patchlevel = 1
-    timestamp = '%04d-%02d-%02dT00:%02d:%02dZ' % (year, month, day, faked, patchlevel)
-
-    entry = entry_template.replace('@TIMESTAMP@', timestamp)
-    entry = entry.replace('@VERSION@', v)
-    entries.append(entry)
-
-entries_str = textwrap.indent(''.join(entries), '\t')
-atom_template = atom_template.replace('@ENTRIES@', entries_str)
-
-with io.open('update/releases.atom', 'w', encoding='utf-8') as atom_file:
-    atom_file.write(atom_template)
diff --git a/devscripts/gh-pages.unused/update-sites.py b/devscripts/gh-pages.unused/update-sites.py
deleted file mode 100644
index b53685fccd..0000000000
--- a/devscripts/gh-pages.unused/update-sites.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import sys
-import os
-import textwrap
-
-# We must be able to import yt_dlp
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
-
-import yt_dlp
-
-
-def main():
-    with open('supportedsites.html.in', 'r', encoding='utf-8') as tmplf:
-        template = tmplf.read()
-
-    ie_htmls = []
-    for ie in yt_dlp.list_extractors(age_limit=None):
-        ie_html = '<b>{}</b>'.format(ie.IE_NAME)
-        ie_desc = getattr(ie, 'IE_DESC', None)
-        if ie_desc is False:
-            continue
-        elif ie_desc is not None:
-            ie_html += ': {}'.format(ie.IE_DESC)
-        if not ie.working():
-            ie_html += ' (Currently broken)'
-        ie_htmls.append('<li>{}</li>'.format(ie_html))
-
-    template = template.replace('@SITES@', textwrap.indent('\n'.join(ie_htmls), '\t'))
-
-    with open('supportedsites.html', 'w', encoding='utf-8') as sitesf:
-        sitesf.write(template)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/devscripts/posix-locale.sh b/devscripts/posix-locale.sh
deleted file mode 100755
index 0aa7a592d7..0000000000
--- a/devscripts/posix-locale.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-
-# source this file in your shell to get a POSIX locale (which will break many programs, but that's kind of the point)
-
-export LC_ALL=POSIX
-export LANG=POSIX
-export LANGUAGE=POSIX
diff --git a/devscripts/release.sh b/devscripts/release.sh
deleted file mode 100755
index 188b166e64..0000000000
--- a/devscripts/release.sh
+++ /dev/null
@@ -1,143 +0,0 @@
-# Unused
-
-#!/bin/bash
-
-# IMPORTANT: the following assumptions are made
-# * the GH repo is on the origin remote
-# * the gh-pages branch is named so locally
-# * the git config user.signingkey is properly set
-
-# You will need
-# pip install coverage nose rsa wheel
-
-# TODO
-# release notes
-# make hash on local files
-
-set -e
-
-skip_tests=true
-gpg_sign_commits=""
-buildserver='localhost:8142'
-
-while true
-do
-case "$1" in
-    --run-tests)
-        skip_tests=false
-        shift
-    ;;
-    --gpg-sign-commits|-S)
-        gpg_sign_commits="-S"
-        shift
-    ;;
-    --buildserver)
-        buildserver="$2"
-        shift 2
-    ;;
-    --*)
-        echo "ERROR: unknown option $1"
-        exit 1
-    ;;
-    *)
-        break
-    ;;
-esac
-done
-
-if [ -z "$1" ]; then echo "ERROR: specify version number like this: $0 1994.09.06"; exit 1; fi
-version="$1"
-major_version=$(echo "$version" | sed -n 's#^\([0-9]*\.[0-9]*\.[0-9]*\).*#\1#p')
-if test "$major_version" '!=' "$(date '+%Y.%m.%d')"; then
-    echo "$version does not start with today's date!"
-    exit 1
-fi
-
-if [ ! -z "`git tag | grep "$version"`" ]; then echo 'ERROR: version already present'; exit 1; fi
-if [ ! -z "`git status --porcelain | grep -v CHANGELOG`" ]; then echo 'ERROR: the working directory is not clean; commit or stash changes'; exit 1; fi
-useless_files=$(find yt_dlp -type f -not -name '*.py')
-if [ ! -z "$useless_files" ]; then echo "ERROR: Non-.py files in yt_dlp: $useless_files"; exit 1; fi
-if [ ! -f "updates_key.pem" ]; then echo 'ERROR: updates_key.pem missing'; exit 1; fi
-if ! type pandoc >/dev/null 2>/dev/null; then echo 'ERROR: pandoc is missing'; exit 1; fi
-if ! python3 -c 'import rsa' 2>/dev/null; then echo 'ERROR: python3-rsa is missing'; exit 1; fi
-if ! python3 -c 'import wheel' 2>/dev/null; then echo 'ERROR: wheel is missing'; exit 1; fi
-
-read -p "Is Changelog up to date? (y/n) " -n 1
-if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi
-
-/bin/echo -e "\n### First of all, testing..."
-make clean
-if $skip_tests ; then
-    echo 'SKIPPING TESTS'
-else
-    nosetests --verbose --with-coverage --cover-package=yt_dlp --cover-html test --stop || exit 1
-fi
-
-/bin/echo -e "\n### Changing version in version.py..."
-sed -i "s/__version__ = '.*'/__version__ = '$version'/" yt_dlp/version.py
-
-/bin/echo -e "\n### Changing version in Changelog..."
-sed -i "s/<unreleased>/$version/" Changelog.md
-
-/bin/echo -e "\n### Committing documentation, templates and yt_dlp/version.py..."
-make README.md CONTRIBUTING.md issuetemplates supportedsites
-git add README.md CONTRIBUTING.md .github/ISSUE_TEMPLATE/1_broken_site.md .github/ISSUE_TEMPLATE/2_site_support_request.md .github/ISSUE_TEMPLATE/3_site_feature_request.md .github/ISSUE_TEMPLATE/4_bug_report.md .github/ISSUE_TEMPLATE/5_feature_request.md .github/ISSUE_TEMPLATE/6_question.md docs/supportedsites.md yt_dlp/version.py Changelog.md
-git commit $gpg_sign_commits -m "release $version"
-
-/bin/echo -e "\n### Now tagging, signing and pushing..."
-git tag -s -m "Release $version" "$version"
-git show "$version"
-read -p "Is it good, can I push? (y/n) " -n 1
-if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi
-echo
-MASTER=$(git rev-parse --abbrev-ref HEAD)
-git push origin $MASTER:master
-git push origin "$version"
-
-/bin/echo -e "\n### OK, now it is time to build the binaries..."
-REV=$(git rev-parse HEAD)
-make yt-dlp yt-dlp.tar.gz
-read -p "VM running? (y/n) " -n 1
-wget "http://$buildserver/build/ytdl-org/youtube-dl/yt-dlp.exe?rev=$REV" -O yt-dlp.exe
-mkdir -p "build/$version"
-mv yt-dlp yt-dlp.exe "build/$version"
-mv yt-dlp.tar.gz "build/$version/yt-dlp-$version.tar.gz"
-RELEASE_FILES="yt-dlp yt-dlp.exe yt-dlp-$version.tar.gz"
-(cd build/$version/ && md5sum $RELEASE_FILES > MD5SUMS)
-(cd build/$version/ && sha1sum $RELEASE_FILES > SHA1SUMS)
-(cd build/$version/ && sha256sum $RELEASE_FILES > SHA2-256SUMS)
-(cd build/$version/ && sha512sum $RELEASE_FILES > SHA2-512SUMS)
-
-/bin/echo -e "\n### Signing and uploading the new binaries to GitHub..."
-for f in $RELEASE_FILES; do gpg --passphrase-repeat 5 --detach-sig "build/$version/$f"; done
-
-ROOT=$(pwd)
-python devscripts/create-github-release.py Changelog.md $version "$ROOT/build/$version"
-
-ssh ytdl@yt-dl.org "sh html/update_latest.sh $version"
-
-/bin/echo -e "\n### Now switching to gh-pages..."
-git clone --branch gh-pages --single-branch . build/gh-pages
-(
-    set -e
-    ORIGIN_URL=$(git config --get remote.origin.url)
-    cd build/gh-pages
-    "$ROOT/devscripts/gh-pages/add-version.py" $version
-    "$ROOT/devscripts/gh-pages/update-feed.py"
-    "$ROOT/devscripts/gh-pages/sign-versions.py" < "$ROOT/updates_key.pem"
-    "$ROOT/devscripts/gh-pages/generate-download.py"
-    "$ROOT/devscripts/gh-pages/update-copyright.py"
-    "$ROOT/devscripts/gh-pages/update-sites.py"
-    git add *.html *.html.in update
-    git commit $gpg_sign_commits -m "release $version"
-    git push "$ROOT" gh-pages
-    git push "$ORIGIN_URL" gh-pages
-)
-rm -rf build
-
-make pypi-files
-echo "Uploading to PyPi ..."
-python setup.py sdist bdist_wheel upload
-make clean
-
-/bin/echo -e "\n### DONE!"
diff --git a/devscripts/show-downloads-statistics.py b/devscripts/show-downloads-statistics.py
deleted file mode 100644
index 4855aa7c85..0000000000
--- a/devscripts/show-downloads-statistics.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Unused
-
-#!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import itertools
-import json
-import os
-import re
-import sys
-
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-
-from yt_dlp.compat import (
-    compat_print,
-    compat_urllib_request,
-)
-from yt_dlp.utils import format_bytes
-
-
-def format_size(bytes):
-    return '%s (%d bytes)' % (format_bytes(bytes), bytes)
-
-
-total_bytes = 0
-
-for page in itertools.count(1):
-    releases = json.loads(compat_urllib_request.urlopen(
-        'https://api.github.com/repos/ytdl-org/youtube-dl/releases?page=%s' % page
-    ).read().decode('utf-8'))
-
-    if not releases:
-        break
-
-    for release in releases:
-        compat_print(release['name'])
-        for asset in release['assets']:
-            asset_name = asset['name']
-            total_bytes += asset['download_count'] * asset['size']
-            if all(not re.match(p, asset_name) for p in (
-                    r'^yt-dlp$',
-                    r'^yt-dlp-\d{4}\.\d{2}\.\d{2}(?:\.\d+)?\.tar\.gz$',
-                    r'^yt-dlp\.exe$')):
-                continue
-            compat_print(
-                ' %s size: %s downloads: %d'
-                % (asset_name, format_size(asset['size']), asset['download_count']))
-
-compat_print('total downloads traffic: %s' % format_size(total_bytes))
diff --git a/devscripts/wine-py2exe.sh b/devscripts/wine-py2exe.sh
deleted file mode 100755
index 8bc8ce55b3..0000000000
--- a/devscripts/wine-py2exe.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-# UNUSED
-
-#!/bin/bash
-
-# Run with as parameter a setup.py that works in the current directory
-# e.g. no os.chdir()
-# It will run twice, the first time will crash
-
-set -e
-
-SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )"
-
-if [ ! -d wine-py2exe ]; then
-
-    sudo apt-get install wine1.3 axel bsdiff
-
-    mkdir wine-py2exe
-    cd wine-py2exe
-    export WINEPREFIX=`pwd`
-
-    axel -a "http://www.python.org/ftp/python/2.7/python-2.7.msi"
-    axel -a "http://downloads.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe"
-    #axel -a "http://winetricks.org/winetricks"
-
-    # http://appdb.winehq.org/objectManager.php?sClass=version&iId=21957
-    echo "Follow python setup on screen"
-    wine msiexec /i python-2.7.msi
-    
-    echo "Follow py2exe setup on screen"
-    wine py2exe-0.6.9.win32-py2.7.exe
-    
-    #echo "Follow Microsoft Visual C++ 2008 Redistributable Package setup on screen"
-    #bash winetricks vcrun2008
-
-    rm py2exe-0.6.9.win32-py2.7.exe
-    rm python-2.7.msi
-    #rm winetricks
-    
-    # http://bugs.winehq.org/show_bug.cgi?id=3591
-    
-    mv drive_c/Python27/Lib/site-packages/py2exe/run.exe drive_c/Python27/Lib/site-packages/py2exe/run.exe.backup
-    bspatch drive_c/Python27/Lib/site-packages/py2exe/run.exe.backup drive_c/Python27/Lib/site-packages/py2exe/run.exe "$SCRIPT_DIR/SizeOfImage.patch"
-    mv drive_c/Python27/Lib/site-packages/py2exe/run_w.exe drive_c/Python27/Lib/site-packages/py2exe/run_w.exe.backup
-    bspatch drive_c/Python27/Lib/site-packages/py2exe/run_w.exe.backup drive_c/Python27/Lib/site-packages/py2exe/run_w.exe "$SCRIPT_DIR/SizeOfImage_w.patch"
-
-    cd -
-    
-else
-
-    export WINEPREFIX="$( cd wine-py2exe && pwd )"
-
-fi
-
-wine "C:\\Python27\\python.exe" "$1" py2exe > "py2exe.log" 2>&1 || true
-echo '# Copying python27.dll' >> "py2exe.log"
-cp "$WINEPREFIX/drive_c/windows/system32/python27.dll" build/bdist.win32/winexe/bundle-2.7/
-wine "C:\\Python27\\python.exe" "$1" py2exe >> "py2exe.log" 2>&1
-
diff --git a/test/swftests.unused/.gitignore b/test/swftests.unused/.gitignore
deleted file mode 100644
index da97ff7caf..0000000000
--- a/test/swftests.unused/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.swf
diff --git a/test/swftests.unused/ArrayAccess.as b/test/swftests.unused/ArrayAccess.as
deleted file mode 100644
index e22caa3860..0000000000
--- a/test/swftests.unused/ArrayAccess.as
+++ /dev/null
@@ -1,19 +0,0 @@
-// input: [["a", "b", "c", "d"]]
-// output: ["c", "b", "a", "d"]
-
-package {
-public class ArrayAccess {
-    public static function main(ar:Array):Array {
-    	var aa:ArrayAccess = new ArrayAccess();
-    	return aa.f(ar, 2);
-    }
-
-    private function f(ar:Array, num:Number):Array{
-        var x:String = ar[0];
-        var y:String = ar[num % ar.length];
-        ar[0] = y;
-        ar[num] = x;
-        return ar;
-    }
-}
-}
diff --git a/test/swftests.unused/ClassCall.as b/test/swftests.unused/ClassCall.as
deleted file mode 100644
index aef58daf37..0000000000
--- a/test/swftests.unused/ClassCall.as
+++ /dev/null
@@ -1,17 +0,0 @@
-// input: []
-// output: 121
-
-package {
-public class ClassCall {
-    public static function main():int{
-    	var f:OtherClass = new OtherClass();
-        return f.func(100,20);
-    }
-}
-}
-
-class OtherClass {
-	public function func(x: int, y: int):int {
-		return x+y+1;
-	}
-}
diff --git a/test/swftests.unused/ClassConstruction.as b/test/swftests.unused/ClassConstruction.as
deleted file mode 100644
index 436479f8fc..0000000000
--- a/test/swftests.unused/ClassConstruction.as
+++ /dev/null
@@ -1,15 +0,0 @@
-// input: []
-// output: 0
-
-package {
-public class ClassConstruction {
-    public static function main():int{
-    	var f:Foo = new Foo();
-        return 0;
-    }
-}
-}
-
-class Foo {
-
-}
diff --git a/test/swftests.unused/ConstArrayAccess.as b/test/swftests.unused/ConstArrayAccess.as
deleted file mode 100644
index 07dc3f4606..0000000000
--- a/test/swftests.unused/ConstArrayAccess.as
+++ /dev/null
@@ -1,18 +0,0 @@
-// input: []
-// output: 4
-
-package {
-public class ConstArrayAccess {
-	private static const x:int = 2;
-	private static const ar:Array = ["42", "3411"];
-
-    public static function main():int{
-        var c:ConstArrayAccess = new ConstArrayAccess();
-        return c.f();
-    }
-
-    public function f(): int {
-    	return ar[1].length;
-    }
-}
-}
diff --git a/test/swftests.unused/ConstantInt.as b/test/swftests.unused/ConstantInt.as
deleted file mode 100644
index e0bbb6166f..0000000000
--- a/test/swftests.unused/ConstantInt.as
+++ /dev/null
@@ -1,12 +0,0 @@
-// input: []
-// output: 2
-
-package {
-public class ConstantInt {
-	private static const x:int = 2;
-
-    public static function main():int{
-        return x;
-    }
-}
-}
diff --git a/test/swftests.unused/DictCall.as b/test/swftests.unused/DictCall.as
deleted file mode 100644
index c2d174cc2e..0000000000
--- a/test/swftests.unused/DictCall.as
+++ /dev/null
@@ -1,10 +0,0 @@
-// input: [{"x": 1, "y": 2}]
-// output: 3
-
-package {
-public class DictCall {
-    public static function main(d:Object):int{
-        return d.x + d.y;
-    }
-}
-}
diff --git a/test/swftests.unused/EqualsOperator.as b/test/swftests.unused/EqualsOperator.as
deleted file mode 100644
index 837a69a46f..0000000000
--- a/test/swftests.unused/EqualsOperator.as
+++ /dev/null
@@ -1,10 +0,0 @@
-// input: []
-// output: false
-
-package {
-public class EqualsOperator {
-    public static function main():Boolean{
-        return 1 == 2;
-    }
-}
-}
diff --git a/test/swftests.unused/LocalVars.as b/test/swftests.unused/LocalVars.as
deleted file mode 100644
index b2911a9f3e..0000000000
--- a/test/swftests.unused/LocalVars.as
+++ /dev/null
@@ -1,13 +0,0 @@
-// input: [1, 2]
-// output: 3
-
-package {
-public class LocalVars {
-    public static function main(a:int, b:int):int{
-        var c:int = a + b + b;
-        var d:int = c - b;
-        var e:int = d;
-        return e;
-    }
-}
-}
diff --git a/test/swftests.unused/MemberAssignment.as b/test/swftests.unused/MemberAssignment.as
deleted file mode 100644
index dcba5e3ffc..0000000000
--- a/test/swftests.unused/MemberAssignment.as
+++ /dev/null
@@ -1,22 +0,0 @@
-// input: [1]
-// output: 2
-
-package {
-public class MemberAssignment {
-    public var v:int;
-
-    public function g():int {
-        return this.v;
-    }
-
-    public function f(a:int):int{
-        this.v = a;
-        return this.v + this.g();
-    }
-
-    public static function main(a:int): int {
-        var v:MemberAssignment = new MemberAssignment();
-        return v.f(a);
-    }
-}
-}
diff --git a/test/swftests.unused/NeOperator.as b/test/swftests.unused/NeOperator.as
deleted file mode 100644
index 61dcbc4e9a..0000000000
--- a/test/swftests.unused/NeOperator.as
+++ /dev/null
@@ -1,24 +0,0 @@
-// input: []
-// output: 123
-
-package {
-public class NeOperator {
-    public static function main(): int {
-        var res:int = 0;
-        if (1 != 2) {
-            res += 3;
-        } else {
-            res += 4;
-        }
-        if (2 != 2) {
-            res += 10;
-        } else {
-            res += 20;
-        }
-        if (9 == 9) {
-            res += 100;
-        }
-        return res;
-    }
-}
-}
diff --git a/test/swftests.unused/PrivateCall.as b/test/swftests.unused/PrivateCall.as
deleted file mode 100644
index f1c110a379..0000000000
--- a/test/swftests.unused/PrivateCall.as
+++ /dev/null
@@ -1,21 +0,0 @@
-// input: []
-// output: 9
-
-package {
-public class PrivateCall {
-    public static function main():int{
-    	var f:OtherClass = new OtherClass();
-        return f.func();
-    }
-}
-}
-
-class OtherClass {
-	private function pf():int {
-		return 9;
-	}
-
-	public function func():int {
-		return this.pf();
-	}
-}
diff --git a/test/swftests.unused/PrivateVoidCall.as b/test/swftests.unused/PrivateVoidCall.as
deleted file mode 100644
index 2cc0167974..0000000000
--- a/test/swftests.unused/PrivateVoidCall.as
+++ /dev/null
@@ -1,22 +0,0 @@
-// input: []
-// output: 9
-
-package {
-public class PrivateVoidCall {
-    public static function main():int{
-        var f:OtherClass = new OtherClass();
-        f.func();
-        return 9;
-    }
-}
-}
-
-class OtherClass {
-    private function pf():void {
-        ;
-    }
-
-    public function func():void {
-        this.pf();
-    }
-}
diff --git a/test/swftests.unused/StaticAssignment.as b/test/swftests.unused/StaticAssignment.as
deleted file mode 100644
index b061c219d2..0000000000
--- a/test/swftests.unused/StaticAssignment.as
+++ /dev/null
@@ -1,13 +0,0 @@
-// input: [1]
-// output: 1
-
-package {
-public class StaticAssignment {
-	public static var v:int;
-
-    public static function main(a:int):int{
-        v = a;
-        return v;
-    }
-}
-}
diff --git a/test/swftests.unused/StaticRetrieval.as b/test/swftests.unused/StaticRetrieval.as
deleted file mode 100644
index c8352d819d..0000000000
--- a/test/swftests.unused/StaticRetrieval.as
+++ /dev/null
@@ -1,16 +0,0 @@
-// input: []
-// output: 1
-
-package {
-public class StaticRetrieval {
-	public static var v:int;
-
-    public static function main():int{
-        if (v) {
-        	return 0;
-        } else {
-        	return 1;
-        }
-    }
-}
-}
diff --git a/test/swftests.unused/StringBasics.as b/test/swftests.unused/StringBasics.as
deleted file mode 100644
index d27430b139..0000000000
--- a/test/swftests.unused/StringBasics.as
+++ /dev/null
@@ -1,11 +0,0 @@
-// input: []
-// output: 3
-
-package {
-public class StringBasics {
-    public static function main():int{
-        var s:String = "abc";
-        return s.length;
-    }
-}
-}
diff --git a/test/swftests.unused/StringCharCodeAt.as b/test/swftests.unused/StringCharCodeAt.as
deleted file mode 100644
index c20d74d657..0000000000
--- a/test/swftests.unused/StringCharCodeAt.as
+++ /dev/null
@@ -1,11 +0,0 @@
-// input: []
-// output: 9897
-
-package {
-public class StringCharCodeAt {
-    public static function main():int{
-        var s:String = "abc";
-        return s.charCodeAt(1) * 100 + s.charCodeAt();
-    }
-}
-}
diff --git a/test/swftests.unused/StringConversion.as b/test/swftests.unused/StringConversion.as
deleted file mode 100644
index c976f50420..0000000000
--- a/test/swftests.unused/StringConversion.as
+++ /dev/null
@@ -1,11 +0,0 @@
-// input: []
-// output: 2
-
-package {
-public class StringConversion {
-    public static function main():int{
-        var s:String = String(99);
-        return s.length;
-    }
-}
-}
diff --git a/test/test_swfinterp.py.disabled b/test/test_swfinterp.py.disabled
deleted file mode 100644
index 5d5b21e6d2..0000000000
--- a/test/test_swfinterp.py.disabled
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env python3
-from __future__ import unicode_literals
-
-# Allow direct execution
-import os
-import sys
-import unittest
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-
-
-import errno
-import io
-import json
-import re
-import subprocess
-
-from yt_dlp.swfinterp import SWFInterpreter
-
-
-TEST_DIR = os.path.join(
-    os.path.dirname(os.path.abspath(__file__)), 'swftests')
-
-
-class TestSWFInterpreter(unittest.TestCase):
-    pass
-
-
-def _make_testfunc(testfile):
-    m = re.match(r'^(.*)\.(as)$', testfile)
-    if not m:
-        return
-    test_id = m.group(1)
-
-    def test_func(self):
-        as_file = os.path.join(TEST_DIR, testfile)
-        swf_file = os.path.join(TEST_DIR, test_id + '.swf')
-        if ((not os.path.exists(swf_file))
-                or os.path.getmtime(swf_file) < os.path.getmtime(as_file)):
-            # Recompile
-            try:
-                subprocess.check_call([
-                    'mxmlc', '-output', swf_file,
-                    '-static-link-runtime-shared-libraries', as_file])
-            except OSError as ose:
-                if ose.errno == errno.ENOENT:
-                    print('mxmlc not found! Skipping test.')
-                    return
-                raise
-
-        with open(swf_file, 'rb') as swf_f:
-            swf_content = swf_f.read()
-        swfi = SWFInterpreter(swf_content)
-
-        with io.open(as_file, 'r', encoding='utf-8') as as_f:
-            as_content = as_f.read()
-
-        def _find_spec(key):
-            m = re.search(
-                r'(?m)^//\s*%s:\s*(.*?)\n' % re.escape(key), as_content)
-            if not m:
-                raise ValueError('Cannot find %s in %s' % (key, testfile))
-            return json.loads(m.group(1))
-
-        input_args = _find_spec('input')
-        output = _find_spec('output')
-
-        swf_class = swfi.extract_class(test_id)
-        func = swfi.extract_function(swf_class, 'main')
-        res = func(input_args)
-        self.assertEqual(res, output)
-
-    test_func.__name__ = str('test_swf_' + test_id)
-    setattr(TestSWFInterpreter, test_func.__name__, test_func)
-
-
-for testfile in os.listdir(TEST_DIR):
-    _make_testfunc(testfile)
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/test/test_unicode_literals.py.disabled b/test/test_unicode_literals.py.disabled
deleted file mode 100644
index 6c1b7ec915..0000000000
--- a/test/test_unicode_literals.py.disabled
+++ /dev/null
@@ -1,63 +0,0 @@
-from __future__ import unicode_literals
-
-# Allow direct execution
-import os
-import sys
-import unittest
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-
-import io
-import re
-
-rootDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-IGNORED_FILES = [
-    'setup.py',  # http://bugs.python.org/issue13943
-    'conf.py',
-    'buildserver.py',
-]
-
-IGNORED_DIRS = [
-    '.git',
-    '.tox',
-]
-
-from test.helper import assertRegexpMatches
-
-
-class TestUnicodeLiterals(unittest.TestCase):
-    def test_all_files(self):
-        for dirpath, dirnames, filenames in os.walk(rootDir):
-            for ignore_dir in IGNORED_DIRS:
-                if ignore_dir in dirnames:
-                    # If we remove the directory from dirnames os.walk won't
-                    # recurse into it
-                    dirnames.remove(ignore_dir)
-            for basename in filenames:
-                if not basename.endswith('.py'):
-                    continue
-                if basename in IGNORED_FILES:
-                    continue
-
-                fn = os.path.join(dirpath, basename)
-                with io.open(fn, encoding='utf-8') as inf:
-                    code = inf.read()
-
-                if "'" not in code and '"' not in code:
-                    continue
-                assertRegexpMatches(
-                    self,
-                    code,
-                    r'(?:(?:#.*?|\s*)\n)*from __future__ import (?:[a-z_]+,\s*)*unicode_literals',
-                    'unicode_literals import  missing in %s' % fn)
-
-                m = re.search(r'(?<=\s)u[\'"](?!\)|,|$)', code)
-                if m is not None:
-                    self.assertTrue(
-                        m is None,
-                        'u present in %s, around %s' % (
-                            fn, code[m.start() - 10:m.end() + 10]))
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/yt_dlp/swfinterp.py.disabled b/yt_dlp/swfinterp.py.disabled
deleted file mode 100644
index 0c71585753..0000000000
--- a/yt_dlp/swfinterp.py.disabled
+++ /dev/null
@@ -1,834 +0,0 @@
-from __future__ import unicode_literals
-
-import collections
-import io
-import zlib
-
-from .compat import (
-    compat_str,
-    compat_struct_unpack,
-)
-from .utils import (
-    ExtractorError,
-)
-
-
-def _extract_tags(file_contents):
-    if file_contents[1:3] != b'WS':
-        raise ExtractorError(
-            'Not an SWF file; header is %r' % file_contents[:3])
-    if file_contents[:1] == b'C':
-        content = zlib.decompress(file_contents[8:])
-    else:
-        raise NotImplementedError(
-            'Unsupported compression format %r' %
-            file_contents[:1])
-
-    # Determine number of bits in framesize rectangle
-    framesize_nbits = compat_struct_unpack('!B', content[:1])[0] >> 3
-    framesize_len = (5 + 4 * framesize_nbits + 7) // 8
-
-    pos = framesize_len + 2 + 2
-    while pos < len(content):
-        header16 = compat_struct_unpack('<H', content[pos:pos + 2])[0]
-        pos += 2
-        tag_code = header16 >> 6
-        tag_len = header16 & 0x3f
-        if tag_len == 0x3f:
-            tag_len = compat_struct_unpack('<I', content[pos:pos + 4])[0]
-            pos += 4
-        assert pos + tag_len <= len(content), \
-            ('Tag %d ends at %d+%d - that\'s longer than the file (%d)'
-                % (tag_code, pos, tag_len, len(content)))
-        yield (tag_code, content[pos:pos + tag_len])
-        pos += tag_len
-
-
-class _AVMClass_Object(object):
-    def __init__(self, avm_class):
-        self.avm_class = avm_class
-
-    def __repr__(self):
-        return '%s#%x' % (self.avm_class.name, id(self))
-
-
-class _ScopeDict(dict):
-    def __init__(self, avm_class):
-        super(_ScopeDict, self).__init__()
-        self.avm_class = avm_class
-
-    def __repr__(self):
-        return '%s__Scope(%s)' % (
-            self.avm_class.name,
-            super(_ScopeDict, self).__repr__())
-
-
-class _AVMClass(object):
-    def __init__(self, name_idx, name, static_properties=None):
-        self.name_idx = name_idx
-        self.name = name
-        self.method_names = {}
-        self.method_idxs = {}
-        self.methods = {}
-        self.method_pyfunctions = {}
-        self.static_properties = static_properties if static_properties else {}
-
-        self.variables = _ScopeDict(self)
-        self.constants = {}
-
-    def make_object(self):
-        return _AVMClass_Object(self)
-
-    def __repr__(self):
-        return '_AVMClass(%s)' % (self.name)
-
-    def register_methods(self, methods):
-        self.method_names.update(methods.items())
-        self.method_idxs.update(dict(
-            (idx, name)
-            for name, idx in methods.items()))
-
-
-class _Multiname(object):
-    def __init__(self, kind):
-        self.kind = kind
-
-    def __repr__(self):
-        return '[MULTINAME kind: 0x%x]' % self.kind
-
-
-def _read_int(reader):
-    res = 0
-    shift = 0
-    for _ in range(5):
-        buf = reader.read(1)
-        assert len(buf) == 1
-        b = compat_struct_unpack('<B', buf)[0]
-        res = res | ((b & 0x7f) << shift)
-        if b & 0x80 == 0:
-            break
-        shift += 7
-    return res
-
-
-def _u30(reader):
-    res = _read_int(reader)
-    assert res & 0xf0000000 == 0
-    return res
-
-
-_u32 = _read_int
-
-
-def _s32(reader):
-    v = _read_int(reader)
-    if v & 0x80000000 != 0:
-        v = - ((v ^ 0xffffffff) + 1)
-    return v
-
-
-def _s24(reader):
-    bs = reader.read(3)
-    assert len(bs) == 3
-    last_byte = b'\xff' if (ord(bs[2:3]) >= 0x80) else b'\x00'
-    return compat_struct_unpack('<i', bs + last_byte)[0]
-
-
-def _read_string(reader):
-    slen = _u30(reader)
-    resb = reader.read(slen)
-    assert len(resb) == slen
-    return resb.decode('utf-8')
-
-
-def _read_bytes(count, reader):
-    assert count >= 0
-    resb = reader.read(count)
-    assert len(resb) == count
-    return resb
-
-
-def _read_byte(reader):
-    resb = _read_bytes(1, reader=reader)
-    res = compat_struct_unpack('<B', resb)[0]
-    return res
-
-
-StringClass = _AVMClass('(no name idx)', 'String')
-ByteArrayClass = _AVMClass('(no name idx)', 'ByteArray')
-TimerClass = _AVMClass('(no name idx)', 'Timer')
-TimerEventClass = _AVMClass('(no name idx)', 'TimerEvent', {'TIMER': 'timer'})
-_builtin_classes = {
-    StringClass.name: StringClass,
-    ByteArrayClass.name: ByteArrayClass,
-    TimerClass.name: TimerClass,
-    TimerEventClass.name: TimerEventClass,
-}
-
-
-class _Undefined(object):
-    def __bool__(self):
-        return False
-    __nonzero__ = __bool__
-
-    def __hash__(self):
-        return 0
-
-    def __str__(self):
-        return 'undefined'
-    __repr__ = __str__
-
-
-undefined = _Undefined()
-
-
-class SWFInterpreter(object):
-    def __init__(self, file_contents):
-        self._patched_functions = {
-            (TimerClass, 'addEventListener'): lambda params: undefined,
-        }
-        code_tag = next(tag
-                        for tag_code, tag in _extract_tags(file_contents)
-                        if tag_code == 82)
-        p = code_tag.index(b'\0', 4) + 1
-        code_reader = io.BytesIO(code_tag[p:])
-
-        # Parse ABC (AVM2 ByteCode)
-
-        # Define a couple convenience methods
-        u30 = lambda *args: _u30(*args, reader=code_reader)
-        s32 = lambda *args: _s32(*args, reader=code_reader)
-        u32 = lambda *args: _u32(*args, reader=code_reader)
-        read_bytes = lambda *args: _read_bytes(*args, reader=code_reader)
-        read_byte = lambda *args: _read_byte(*args, reader=code_reader)
-
-        # minor_version + major_version
-        read_bytes(2 + 2)
-
-        # Constant pool
-        int_count = u30()
-        self.constant_ints = [0]
-        for _c in range(1, int_count):
-            self.constant_ints.append(s32())
-        self.constant_uints = [0]
-        uint_count = u30()
-        for _c in range(1, uint_count):
-            self.constant_uints.append(u32())
-        double_count = u30()
-        read_bytes(max(0, (double_count - 1)) * 8)
-        string_count = u30()
-        self.constant_strings = ['']
-        for _c in range(1, string_count):
-            s = _read_string(code_reader)
-            self.constant_strings.append(s)
-        namespace_count = u30()
-        for _c in range(1, namespace_count):
-            read_bytes(1)  # kind
-            u30()  # name
-        ns_set_count = u30()
-        for _c in range(1, ns_set_count):
-            count = u30()
-            for _c2 in range(count):
-                u30()
-        multiname_count = u30()
-        MULTINAME_SIZES = {
-            0x07: 2,  # QName
-            0x0d: 2,  # QNameA
-            0x0f: 1,  # RTQName
-            0x10: 1,  # RTQNameA
-            0x11: 0,  # RTQNameL
-            0x12: 0,  # RTQNameLA
-            0x09: 2,  # Multiname
-            0x0e: 2,  # MultinameA
-            0x1b: 1,  # MultinameL
-            0x1c: 1,  # MultinameLA
-        }
-        self.multinames = ['']
-        for _c in range(1, multiname_count):
-            kind = u30()
-            assert kind in MULTINAME_SIZES, 'Invalid multiname kind %r' % kind
-            if kind == 0x07:
-                u30()  # namespace_idx
-                name_idx = u30()
-                self.multinames.append(self.constant_strings[name_idx])
-            elif kind == 0x09:
-                name_idx = u30()
-                u30()
-                self.multinames.append(self.constant_strings[name_idx])
-            else:
-                self.multinames.append(_Multiname(kind))
-                for _c2 in range(MULTINAME_SIZES[kind]):
-                    u30()
-
-        # Methods
-        method_count = u30()
-        MethodInfo = collections.namedtuple(
-            'MethodInfo',
-            ['NEED_ARGUMENTS', 'NEED_REST'])
-        method_infos = []
-        for method_id in range(method_count):
-            param_count = u30()
-            u30()  # return type
-            for _ in range(param_count):
-                u30()  # param type
-            u30()  # name index (always 0 for youtube)
-            flags = read_byte()
-            if flags & 0x08 != 0:
-                # Options present
-                option_count = u30()
-                for c in range(option_count):
-                    u30()  # val
-                    read_bytes(1)  # kind
-            if flags & 0x80 != 0:
-                # Param names present
-                for _ in range(param_count):
-                    u30()  # param name
-            mi = MethodInfo(flags & 0x01 != 0, flags & 0x04 != 0)
-            method_infos.append(mi)
-
-        # Metadata
-        metadata_count = u30()
-        for _c in range(metadata_count):
-            u30()  # name
-            item_count = u30()
-            for _c2 in range(item_count):
-                u30()  # key
-                u30()  # value
-
-        def parse_traits_info():
-            trait_name_idx = u30()
-            kind_full = read_byte()
-            kind = kind_full & 0x0f
-            attrs = kind_full >> 4
-            methods = {}
-            constants = None
-            if kind == 0x00:  # Slot
-                u30()  # Slot id
-                u30()  # type_name_idx
-                vindex = u30()
-                if vindex != 0:
-                    read_byte()  # vkind
-            elif kind == 0x06:  # Const
-                u30()  # Slot id
-                u30()  # type_name_idx
-                vindex = u30()
-                vkind = 'any'
-                if vindex != 0:
-                    vkind = read_byte()
-                if vkind == 0x03:  # Constant_Int
-                    value = self.constant_ints[vindex]
-                elif vkind == 0x04:  # Constant_UInt
-                    value = self.constant_uints[vindex]
-                else:
-                    return {}, None  # Ignore silently for now
-                constants = {self.multinames[trait_name_idx]: value}
-            elif kind in (0x01, 0x02, 0x03):  # Method / Getter / Setter
-                u30()  # disp_id
-                method_idx = u30()
-                methods[self.multinames[trait_name_idx]] = method_idx
-            elif kind == 0x04:  # Class
-                u30()  # slot_id
-                u30()  # classi
-            elif kind == 0x05:  # Function
-                u30()  # slot_id
-                function_idx = u30()
-                methods[function_idx] = self.multinames[trait_name_idx]
-            else:
-                raise ExtractorError('Unsupported trait kind %d' % kind)
-
-            if attrs & 0x4 != 0:  # Metadata present
-                metadata_count = u30()
-                for _c3 in range(metadata_count):
-                    u30()  # metadata index
-
-            return methods, constants
-
-        # Classes
-        class_count = u30()
-        classes = []
-        for class_id in range(class_count):
-            name_idx = u30()
-
-            cname = self.multinames[name_idx]
-            avm_class = _AVMClass(name_idx, cname)
-            classes.append(avm_class)
-
-            u30()  # super_name idx
-            flags = read_byte()
-            if flags & 0x08 != 0:  # Protected namespace is present
-                u30()  # protected_ns_idx
-            intrf_count = u30()
-            for _c2 in range(intrf_count):
-                u30()
-            u30()  # iinit
-            trait_count = u30()
-            for _c2 in range(trait_count):
-                trait_methods, trait_constants = parse_traits_info()
-                avm_class.register_methods(trait_methods)
-                if trait_constants:
-                    avm_class.constants.update(trait_constants)
-
-        assert len(classes) == class_count
-        self._classes_by_name = dict((c.name, c) for c in classes)
-
-        for avm_class in classes:
-            avm_class.cinit_idx = u30()
-            trait_count = u30()
-            for _c2 in range(trait_count):
-                trait_methods, trait_constants = parse_traits_info()
-                avm_class.register_methods(trait_methods)
-                if trait_constants:
-                    avm_class.constants.update(trait_constants)
-
-        # Scripts
-        script_count = u30()
-        for _c in range(script_count):
-            u30()  # init
-            trait_count = u30()
-            for _c2 in range(trait_count):
-                parse_traits_info()
-
-        # Method bodies
-        method_body_count = u30()
-        Method = collections.namedtuple('Method', ['code', 'local_count'])
-        self._all_methods = []
-        for _c in range(method_body_count):
-            method_idx = u30()
-            u30()  # max_stack
-            local_count = u30()
-            u30()  # init_scope_depth
-            u30()  # max_scope_depth
-            code_length = u30()
-            code = read_bytes(code_length)
-            m = Method(code, local_count)
-            self._all_methods.append(m)
-            for avm_class in classes:
-                if method_idx in avm_class.method_idxs:
-                    avm_class.methods[avm_class.method_idxs[method_idx]] = m
-            exception_count = u30()
-            for _c2 in range(exception_count):
-                u30()  # from
-                u30()  # to
-                u30()  # target
-                u30()  # exc_type
-                u30()  # var_name
-            trait_count = u30()
-            for _c2 in range(trait_count):
-                parse_traits_info()
-
-        assert p + code_reader.tell() == len(code_tag)
-
-    def patch_function(self, avm_class, func_name, f):
-        self._patched_functions[(avm_class, func_name)] = f
-
-    def extract_class(self, class_name, call_cinit=True):
-        try:
-            res = self._classes_by_name[class_name]
-        except KeyError:
-            raise ExtractorError('Class %r not found' % class_name)
-
-        if call_cinit and hasattr(res, 'cinit_idx'):
-            res.register_methods({'$cinit': res.cinit_idx})
-            res.methods['$cinit'] = self._all_methods[res.cinit_idx]
-            cinit = self.extract_function(res, '$cinit')
-            cinit([])
-
-        return res
-
-    def extract_function(self, avm_class, func_name):
-        p = self._patched_functions.get((avm_class, func_name))
-        if p:
-            return p
-        if func_name in avm_class.method_pyfunctions:
-            return avm_class.method_pyfunctions[func_name]
-        if func_name in self._classes_by_name:
-            return self._classes_by_name[func_name].make_object()
-        if func_name not in avm_class.methods:
-            raise ExtractorError('Cannot find function %s.%s' % (
-                avm_class.name, func_name))
-        m = avm_class.methods[func_name]
-
-        def resfunc(args):
-            # Helper functions
-            coder = io.BytesIO(m.code)
-            s24 = lambda: _s24(coder)
-            u30 = lambda: _u30(coder)
-
-            registers = [avm_class.variables] + list(args) + [None] * m.local_count
-            stack = []
-            scopes = collections.deque([
-                self._classes_by_name, avm_class.constants, avm_class.variables])
-            while True:
-                opcode = _read_byte(coder)
-                if opcode == 9:  # label
-                    pass  # Spec says: "Do nothing."
-                elif opcode == 16:  # jump
-                    offset = s24()
-                    coder.seek(coder.tell() + offset)
-                elif opcode == 17:  # iftrue
-                    offset = s24()
-                    value = stack.pop()
-                    if value:
-                        coder.seek(coder.tell() + offset)
-                elif opcode == 18:  # iffalse
-                    offset = s24()
-                    value = stack.pop()
-                    if not value:
-                        coder.seek(coder.tell() + offset)
-                elif opcode == 19:  # ifeq
-                    offset = s24()
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    if value2 == value1:
-                        coder.seek(coder.tell() + offset)
-                elif opcode == 20:  # ifne
-                    offset = s24()
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    if value2 != value1:
-                        coder.seek(coder.tell() + offset)
-                elif opcode == 21:  # iflt
-                    offset = s24()
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    if value1 < value2:
-                        coder.seek(coder.tell() + offset)
-                elif opcode == 32:  # pushnull
-                    stack.append(None)
-                elif opcode == 33:  # pushundefined
-                    stack.append(undefined)
-                elif opcode == 36:  # pushbyte
-                    v = _read_byte(coder)
-                    stack.append(v)
-                elif opcode == 37:  # pushshort
-                    v = u30()
-                    stack.append(v)
-                elif opcode == 38:  # pushtrue
-                    stack.append(True)
-                elif opcode == 39:  # pushfalse
-                    stack.append(False)
-                elif opcode == 40:  # pushnan
-                    stack.append(float('NaN'))
-                elif opcode == 42:  # dup
-                    value = stack[-1]
-                    stack.append(value)
-                elif opcode == 44:  # pushstring
-                    idx = u30()
-                    stack.append(self.constant_strings[idx])
-                elif opcode == 48:  # pushscope
-                    new_scope = stack.pop()
-                    scopes.append(new_scope)
-                elif opcode == 66:  # construct
-                    arg_count = u30()
-                    args = list(reversed(
-                        [stack.pop() for _ in range(arg_count)]))
-                    obj = stack.pop()
-                    res = obj.avm_class.make_object()
-                    stack.append(res)
-                elif opcode == 70:  # callproperty
-                    index = u30()
-                    mname = self.multinames[index]
-                    arg_count = u30()
-                    args = list(reversed(
-                        [stack.pop() for _ in range(arg_count)]))
-                    obj = stack.pop()
-
-                    if obj == StringClass:
-                        if mname == 'String':
-                            assert len(args) == 1
-                            assert isinstance(args[0], (
-                                int, compat_str, _Undefined))
-                            if args[0] == undefined:
-                                res = 'undefined'
-                            else:
-                                res = compat_str(args[0])
-                            stack.append(res)
-                            continue
-                        else:
-                            raise NotImplementedError(
-                                'Function String.%s is not yet implemented'
-                                % mname)
-                    elif isinstance(obj, _AVMClass_Object):
-                        func = self.extract_function(obj.avm_class, mname)
-                        res = func(args)
-                        stack.append(res)
-                        continue
-                    elif isinstance(obj, _AVMClass):
-                        func = self.extract_function(obj, mname)
-                        res = func(args)
-                        stack.append(res)
-                        continue
-                    elif isinstance(obj, _ScopeDict):
-                        if mname in obj.avm_class.method_names:
-                            func = self.extract_function(obj.avm_class, mname)
-                            res = func(args)
-                        else:
-                            res = obj[mname]
-                        stack.append(res)
-                        continue
-                    elif isinstance(obj, compat_str):
-                        if mname == 'split':
-                            assert len(args) == 1
-                            assert isinstance(args[0], compat_str)
-                            if args[0] == '':
-                                res = list(obj)
-                            else:
-                                res = obj.split(args[0])
-                            stack.append(res)
-                            continue
-                        elif mname == 'charCodeAt':
-                            assert len(args) <= 1
-                            idx = 0 if len(args) == 0 else args[0]
-                            assert isinstance(idx, int)
-                            res = ord(obj[idx])
-                            stack.append(res)
-                            continue
-                    elif isinstance(obj, list):
-                        if mname == 'slice':
-                            assert len(args) == 1
-                            assert isinstance(args[0], int)
-                            res = obj[args[0]:]
-                            stack.append(res)
-                            continue
-                        elif mname == 'join':
-                            assert len(args) == 1
-                            assert isinstance(args[0], compat_str)
-                            res = args[0].join(obj)
-                            stack.append(res)
-                            continue
-                    raise NotImplementedError(
-                        'Unsupported property %r on %r'
-                        % (mname, obj))
-                elif opcode == 71:  # returnvoid
-                    res = undefined
-                    return res
-                elif opcode == 72:  # returnvalue
-                    res = stack.pop()
-                    return res
-                elif opcode == 73:  # constructsuper
-                    # Not yet implemented, just hope it works without it
-                    arg_count = u30()
-                    args = list(reversed(
-                        [stack.pop() for _ in range(arg_count)]))
-                    obj = stack.pop()
-                elif opcode == 74:  # constructproperty
-                    index = u30()
-                    arg_count = u30()
-                    args = list(reversed(
-                        [stack.pop() for _ in range(arg_count)]))
-                    obj = stack.pop()
-
-                    mname = self.multinames[index]
-                    assert isinstance(obj, _AVMClass)
-
-                    # We do not actually call the constructor for now;
-                    # we just pretend it does nothing
-                    stack.append(obj.make_object())
-                elif opcode == 79:  # callpropvoid
-                    index = u30()
-                    mname = self.multinames[index]
-                    arg_count = u30()
-                    args = list(reversed(
-                        [stack.pop() for _ in range(arg_count)]))
-                    obj = stack.pop()
-                    if isinstance(obj, _AVMClass_Object):
-                        func = self.extract_function(obj.avm_class, mname)
-                        res = func(args)
-                        assert res is undefined
-                        continue
-                    if isinstance(obj, _ScopeDict):
-                        assert mname in obj.avm_class.method_names
-                        func = self.extract_function(obj.avm_class, mname)
-                        res = func(args)
-                        assert res is undefined
-                        continue
-                    if mname == 'reverse':
-                        assert isinstance(obj, list)
-                        obj.reverse()
-                    else:
-                        raise NotImplementedError(
-                            'Unsupported (void) property %r on %r'
-                            % (mname, obj))
-                elif opcode == 86:  # newarray
-                    arg_count = u30()
-                    arr = []
-                    for i in range(arg_count):
-                        arr.append(stack.pop())
-                    arr = arr[::-1]
-                    stack.append(arr)
-                elif opcode == 93:  # findpropstrict
-                    index = u30()
-                    mname = self.multinames[index]
-                    for s in reversed(scopes):
-                        if mname in s:
-                            res = s
-                            break
-                    else:
-                        res = scopes[0]
-                    if mname not in res and mname in _builtin_classes:
-                        stack.append(_builtin_classes[mname])
-                    else:
-                        stack.append(res[mname])
-                elif opcode == 94:  # findproperty
-                    index = u30()
-                    mname = self.multinames[index]
-                    for s in reversed(scopes):
-                        if mname in s:
-                            res = s
-                            break
-                    else:
-                        res = avm_class.variables
-                    stack.append(res)
-                elif opcode == 96:  # getlex
-                    index = u30()
-                    mname = self.multinames[index]
-                    for s in reversed(scopes):
-                        if mname in s:
-                            scope = s
-                            break
-                    else:
-                        scope = avm_class.variables
-
-                    if mname in scope:
-                        res = scope[mname]
-                    elif mname in _builtin_classes:
-                        res = _builtin_classes[mname]
-                    else:
-                        # Assume uninitialized
-                        # TODO warn here
-                        res = undefined
-                    stack.append(res)
-                elif opcode == 97:  # setproperty
-                    index = u30()
-                    value = stack.pop()
-                    idx = self.multinames[index]
-                    if isinstance(idx, _Multiname):
-                        idx = stack.pop()
-                    obj = stack.pop()
-                    obj[idx] = value
-                elif opcode == 98:  # getlocal
-                    index = u30()
-                    stack.append(registers[index])
-                elif opcode == 99:  # setlocal
-                    index = u30()
-                    value = stack.pop()
-                    registers[index] = value
-                elif opcode == 102:  # getproperty
-                    index = u30()
-                    pname = self.multinames[index]
-                    if pname == 'length':
-                        obj = stack.pop()
-                        assert isinstance(obj, (compat_str, list))
-                        stack.append(len(obj))
-                    elif isinstance(pname, compat_str):  # Member access
-                        obj = stack.pop()
-                        if isinstance(obj, _AVMClass):
-                            res = obj.static_properties[pname]
-                            stack.append(res)
-                            continue
-
-                        assert isinstance(obj, (dict, _ScopeDict)),\
-                            'Accessing member %r on %r' % (pname, obj)
-                        res = obj.get(pname, undefined)
-                        stack.append(res)
-                    else:  # Assume attribute access
-                        idx = stack.pop()
-                        assert isinstance(idx, int)
-                        obj = stack.pop()
-                        assert isinstance(obj, list)
-                        stack.append(obj[idx])
-                elif opcode == 104:  # initproperty
-                    index = u30()
-                    value = stack.pop()
-                    idx = self.multinames[index]
-                    if isinstance(idx, _Multiname):
-                        idx = stack.pop()
-                    obj = stack.pop()
-                    obj[idx] = value
-                elif opcode == 115:  # convert_
-                    value = stack.pop()
-                    intvalue = int(value)
-                    stack.append(intvalue)
-                elif opcode == 128:  # coerce
-                    u30()
-                elif opcode == 130:  # coerce_a
-                    value = stack.pop()
-                    # um, yes, it's any value
-                    stack.append(value)
-                elif opcode == 133:  # coerce_s
-                    assert isinstance(stack[-1], (type(None), compat_str))
-                elif opcode == 147:  # decrement
-                    value = stack.pop()
-                    assert isinstance(value, int)
-                    stack.append(value - 1)
-                elif opcode == 149:  # typeof
-                    value = stack.pop()
-                    return {
-                        _Undefined: 'undefined',
-                        compat_str: 'String',
-                        int: 'Number',
-                        float: 'Number',
-                    }[type(value)]
-                elif opcode == 160:  # add
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    res = value1 + value2
-                    stack.append(res)
-                elif opcode == 161:  # subtract
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    res = value1 - value2
-                    stack.append(res)
-                elif opcode == 162:  # multiply
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    res = value1 * value2
-                    stack.append(res)
-                elif opcode == 164:  # modulo
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    res = value1 % value2
-                    stack.append(res)
-                elif opcode == 168:  # bitand
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    assert isinstance(value1, int)
-                    assert isinstance(value2, int)
-                    res = value1 & value2
-                    stack.append(res)
-                elif opcode == 171:  # equals
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    result = value1 == value2
-                    stack.append(result)
-                elif opcode == 175:  # greaterequals
-                    value2 = stack.pop()
-                    value1 = stack.pop()
-                    result = value1 >= value2
-                    stack.append(result)
-                elif opcode == 192:  # increment_i
-                    value = stack.pop()
-                    assert isinstance(value, int)
-                    stack.append(value + 1)
-                elif opcode == 208:  # getlocal_0
-                    stack.append(registers[0])
-                elif opcode == 209:  # getlocal_1
-                    stack.append(registers[1])
-                elif opcode == 210:  # getlocal_2
-                    stack.append(registers[2])
-                elif opcode == 211:  # getlocal_3
-                    stack.append(registers[3])
-                elif opcode == 212:  # setlocal_0
-                    registers[0] = stack.pop()
-                elif opcode == 213:  # setlocal_1
-                    registers[1] = stack.pop()
-                elif opcode == 214:  # setlocal_2
-                    registers[2] = stack.pop()
-                elif opcode == 215:  # setlocal_3
-                    registers[3] = stack.pop()
-                else:
-                    raise NotImplementedError(
-                        'Unsupported opcode %d' % opcode)
-
-        avm_class.method_pyfunctions[func_name] = resfunc
-        return resfunc
-- 
GitLab


From cfb0511d822b39748c5a64dfe86b61ff8d5af176 Mon Sep 17 00:00:00 2001
From: felix <felix.von.s@posteo.de>
Date: Thu, 30 Dec 2021 13:23:36 +0100
Subject: [PATCH 3/9] [cleanup] Remove unused code paths (#2173)

Notes:

* `_windows_write_string`: Fixed in 3.6
  * https://bugs.python.org/issue1602
  * PEP: https://www.python.org/dev/peps/pep-0528

* Windows UTF-8 fix: Fixed in 3.3
  * https://bugs.python.org/issue13216

* `__loader__`: is always present in 3.3+
  * https://bugs.python.org/issue14646

* `workaround_optparse_bug9161`: Fixed in 2.7
  * https://bugs.python.org/issue9161

Authored by: fstirlitz
---
 test/helper.py                     |   2 +-
 test/test_execution.py             |   3 +-
 test/test_http.py                  |  29 +---
 test/test_utils.py                 |   3 -
 yt_dlp/YoutubeDL.py                |   6 -
 yt_dlp/__init__.py                 |   9 --
 yt_dlp/__main__.py                 |   3 +-
 yt_dlp/compat.py                   |  24 +--
 yt_dlp/extractor/bpb.py            |   1 -
 yt_dlp/extractor/common.py         |   4 +-
 yt_dlp/extractor/commonmistakes.py |   6 +-
 yt_dlp/extractor/generic.py        |   4 -
 yt_dlp/update.py                   |  36 +----
 yt_dlp/utils.py                    | 247 +++--------------------------
 14 files changed, 32 insertions(+), 345 deletions(-)

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


From f9934b96145af8ac5dfdcbf684827aeaea9912a7 Mon Sep 17 00:00:00 2001
From: pukkandan <pukkandan.ytdlp@gmail.com>
Date: Tue, 12 Apr 2022 01:39:26 +0530
Subject: [PATCH 4/9] [cleanup] Mark some compat variables for removal (#2173)

Authored by fstirlitz, pukkandan
---
 test/test_compat.py                         | 36 -----------
 test/test_youtube_signature.py              |  5 +-
 yt_dlp/YoutubeDL.py                         | 16 ++---
 yt_dlp/compat.py                            | 71 ++++++++++-----------
 yt_dlp/downloader/ism.py                    | 22 +++----
 yt_dlp/extractor/abematv.py                 |  8 +--
 yt_dlp/extractor/adobepass.py               |  3 +-
 yt_dlp/extractor/afreecatv.py               |  5 +-
 yt_dlp/extractor/bbc.py                     |  4 +-
 yt_dlp/extractor/brightcove.py              |  4 +-
 yt_dlp/extractor/common.py                  | 11 ++--
 yt_dlp/extractor/crunchyroll.py             | 10 +--
 yt_dlp/extractor/generic.py                 |  6 +-
 yt_dlp/extractor/microsoftvirtualacademy.py |  9 +--
 yt_dlp/extractor/mildom.py                  |  4 +-
 yt_dlp/extractor/mixcloud.py                |  3 +-
 yt_dlp/extractor/mtv.py                     |  5 +-
 yt_dlp/extractor/noz.py                     |  3 +-
 yt_dlp/extractor/openload.py                |  3 +-
 yt_dlp/extractor/soundcloud.py              |  3 +-
 yt_dlp/extractor/udemy.py                   |  3 +-
 yt_dlp/extractor/vimeo.py                   |  3 +-
 yt_dlp/options.py                           | 21 +++---
 yt_dlp/postprocessor/sponskrub.py           |  4 +-
 yt_dlp/utils.py                             | 44 ++++++-------
 yt_dlp/webvtt.py                            |  1 -
 26 files changed, 121 insertions(+), 186 deletions(-)

diff --git a/test/test_compat.py b/test/test_compat.py
index c9bc4d7fb5..6cbffd6feb 100644
--- a/test/test_compat.py
+++ b/test/test_compat.py
@@ -13,14 +13,10 @@
 from yt_dlp.compat import (
     compat_getenv,
     compat_setenv,
-    compat_etree_Element,
     compat_etree_fromstring,
     compat_expanduser,
-    compat_shlex_split,
     compat_str,
     compat_struct_unpack,
-    compat_urllib_parse_quote,
-    compat_urllib_parse_quote_plus,
     compat_urllib_parse_unquote,
     compat_urllib_parse_unquote_plus,
     compat_urllib_parse_urlencode,
@@ -55,27 +51,6 @@ def test_all_present(self):
             dir(yt_dlp.compat))) - set(['unicode_literals'])
         self.assertEqual(all_names, sorted(present_names))
 
-    def test_compat_urllib_parse_quote(self):
-        self.assertEqual(compat_urllib_parse_quote('abc def'), 'abc%20def')
-        self.assertEqual(compat_urllib_parse_quote('/user/abc+def'), '/user/abc%2Bdef')
-        self.assertEqual(compat_urllib_parse_quote('/user/abc+def', safe='+'), '%2Fuser%2Fabc+def')
-        self.assertEqual(compat_urllib_parse_quote(''), '')
-        self.assertEqual(compat_urllib_parse_quote('%'), '%25')
-        self.assertEqual(compat_urllib_parse_quote('%', safe='%'), '%')
-        self.assertEqual(compat_urllib_parse_quote('津波'), '%E6%B4%A5%E6%B3%A2')
-        self.assertEqual(
-            compat_urllib_parse_quote('''<meta property="og:description" content="▁▂▃▄%▅▆▇█" />
-%<a href="https://ar.wikipedia.org/wiki/تسونامي">%a''', safe='<>=":%/ \r\n'),
-            '''<meta property="og:description" content="%E2%96%81%E2%96%82%E2%96%83%E2%96%84%%E2%96%85%E2%96%86%E2%96%87%E2%96%88" />
-%<a href="https://ar.wikipedia.org/wiki/%D8%AA%D8%B3%D9%88%D9%86%D8%A7%D9%85%D9%8A">%a''')
-        self.assertEqual(
-            compat_urllib_parse_quote('''(^◣_◢^)っ︻デ═一    ⇀    ⇀    ⇀    ⇀    ⇀    ↶%I%Break%25Things%''', safe='% '),
-            '''%28%5E%E2%97%A3_%E2%97%A2%5E%29%E3%81%A3%EF%B8%BB%E3%83%87%E2%95%90%E4%B8%80    %E2%87%80    %E2%87%80    %E2%87%80    %E2%87%80    %E2%87%80    %E2%86%B6%I%Break%25Things%''')
-
-    def test_compat_urllib_parse_quote_plus(self):
-        self.assertEqual(compat_urllib_parse_quote_plus('abc def'), 'abc+def')
-        self.assertEqual(compat_urllib_parse_quote_plus('/abc def'), '%2Fabc+def')
-
     def test_compat_urllib_parse_unquote(self):
         self.assertEqual(compat_urllib_parse_unquote('abc%20def'), 'abc def')
         self.assertEqual(compat_urllib_parse_unquote('%7e/abc+def'), '~/abc+def')
@@ -109,17 +84,6 @@ def test_compat_urllib_parse_urlencode(self):
         self.assertEqual(compat_urllib_parse_urlencode([(b'abc', 'def')]), 'abc=def')
         self.assertEqual(compat_urllib_parse_urlencode([(b'abc', b'def')]), 'abc=def')
 
-    def test_compat_shlex_split(self):
-        self.assertEqual(compat_shlex_split('-option "one two"'), ['-option', 'one two'])
-        self.assertEqual(compat_shlex_split('-option "one\ntwo" \n -flag'), ['-option', 'one\ntwo', '-flag'])
-        self.assertEqual(compat_shlex_split('-val 中文'), ['-val', '中文'])
-
-    def test_compat_etree_Element(self):
-        try:
-            compat_etree_Element.items
-        except AttributeError:
-            self.fail('compat_etree_Element is not a type')
-
     def test_compat_etree_fromstring(self):
         xml = '''
             <root foo="bar" spam="中文">
diff --git a/test/test_youtube_signature.py b/test/test_youtube_signature.py
index bbbba073f8..6412acce04 100644
--- a/test/test_youtube_signature.py
+++ b/test/test_youtube_signature.py
@@ -11,11 +11,12 @@
 import io
 import re
 import string
+import urllib.request
 
 from test.helper import FakeYDL, is_download_test
 from yt_dlp.extractor import YoutubeIE
 from yt_dlp.jsinterp import JSInterpreter
-from yt_dlp.compat import compat_str, compat_urlretrieve
+from yt_dlp.compat import compat_str
 
 _SIG_TESTS = [
     (
@@ -147,7 +148,7 @@ def test_func(self):
             fn = os.path.join(self.TESTDATA_DIR, basename)
 
             if not os.path.exists(fn):
-                compat_urlretrieve(url, fn)
+                urllib.request.urlretrieve(url, fn)
             with io.open(fn, encoding='utf-8') as testf:
                 jscode = testf.read()
             self.assertEqual(sig_func(jscode, sig_input), expected_sig)
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py
index c626ea3fd1..4bf5a8942c 100644
--- a/yt_dlp/YoutubeDL.py
+++ b/yt_dlp/YoutubeDL.py
@@ -26,24 +26,20 @@
 import traceback
 import random
 import unicodedata
+import urllib.request
 
 from enum import Enum
 from string import ascii_letters
 
 from .compat import (
-    compat_basestring,
     compat_brotli,
     compat_get_terminal_size,
-    compat_kwargs,
-    compat_numeric_types,
     compat_os_name,
     compat_pycrypto_AES,
     compat_shlex_quote,
     compat_str,
-    compat_tokenize_tokenize,
     compat_urllib_error,
     compat_urllib_request,
-    compat_urllib_request_DataHandler,
     windows_enable_vt_mode,
 )
 from .cookies import load_cookies
@@ -682,7 +678,7 @@ def check_deprecated(param, option, suggestion):
             pp_def = dict(pp_def_raw)
             when = pp_def.pop('when', 'post_process')
             self.add_post_processor(
-                get_postprocessor(pp_def.pop('key'))(self, **compat_kwargs(pp_def)),
+                get_postprocessor(pp_def.pop('key'))(self, **pp_def),
                 when=when)
 
         self._setup_opener()
@@ -2244,7 +2240,7 @@ def final_selector(ctx):
 
         stream = io.BytesIO(format_spec.encode('utf-8'))
         try:
-            tokens = list(_remove_unused_ops(compat_tokenize_tokenize(stream.readline)))
+            tokens = list(_remove_unused_ops(tokenize.tokenize(stream.readline)))
         except tokenize.TokenError:
             raise syntax_error('Missing closing/opening brackets or parenthesis', (0, len(format_spec)))
 
@@ -2406,7 +2402,7 @@ def sanitize_string_field(info, string_field):
         def sanitize_numeric_fields(info):
             for numeric_field in self._NUMERIC_FIELDS:
                 field = info.get(numeric_field)
-                if field is None or isinstance(field, compat_numeric_types):
+                if field is None or isinstance(field, (int, float)):
                     continue
                 report_force_conversion(numeric_field, 'numeric', 'int')
                 info[numeric_field] = int_or_none(field)
@@ -3589,7 +3585,7 @@ def list_subtitles(self, video_id, subtitles, name='subtitles'):
 
     def urlopen(self, req):
         """ Start an HTTP download """
-        if isinstance(req, compat_basestring):
+        if isinstance(req, str):
             req = sanitized_Request(req)
         return self._opener.open(req, timeout=self._socket_timeout)
 
@@ -3739,7 +3735,7 @@ def _setup_opener(self):
         https_handler = make_HTTPS_handler(self.params, debuglevel=debuglevel)
         ydlh = YoutubeDLHandler(self.params, debuglevel=debuglevel)
         redirect_handler = YoutubeDLRedirectHandler()
-        data_handler = compat_urllib_request_DataHandler()
+        data_handler = urllib.request.DataHandler()
 
         # When passing our own FileHandler instance, build_opener won't add the
         # default FileHandler and allows us to disable the file protocol, which
diff --git a/yt_dlp/compat.py b/yt_dlp/compat.py
index 6128ff5243..5bac87c105 100644
--- a/yt_dlp/compat.py
+++ b/yt_dlp/compat.py
@@ -81,10 +81,6 @@ def compat_realpath(path):
     compat_realpath = os.path.realpath
 
 
-def compat_print(s):
-    assert isinstance(s, compat_str)
-    print(s)
-
 try:
     compat_Pattern = re.Pattern
 except AttributeError:
@@ -173,61 +169,64 @@ def windows_enable_vt_mode():  # TODO: Do this the proper way https://bugs.pytho
 
 #  Deprecated
 
-compat_basestring = str
-compat_chr = chr
-compat_filter = filter
-compat_input = input
-compat_integer_types = (int, )
-compat_kwargs = lambda kwargs: kwargs
-compat_map = map
-compat_numeric_types = (int, float, complex)
-compat_str = str
-compat_xpath = lambda xpath: xpath
-compat_zip = zip
-workaround_optparse_bug9161 = lambda: None
-
-compat_collections_abc = collections.abc
-compat_HTMLParser = html.parser.HTMLParser
-compat_HTTPError = urllib.error.HTTPError
-compat_Struct = struct.Struct
 compat_b64decode = base64.b64decode
+compat_chr = chr
 compat_cookiejar = http.cookiejar
-compat_cookiejar_Cookie = compat_cookiejar.Cookie
-compat_cookies = http.cookies
-compat_cookies_SimpleCookie = compat_cookies.SimpleCookie
-compat_etree_Element = etree.Element
-compat_etree_register_namespace = etree.register_namespace
+compat_cookiejar_Cookie = http.cookiejar.Cookie
+compat_cookies_SimpleCookie = http.cookies.SimpleCookie
 compat_get_terminal_size = shutil.get_terminal_size
 compat_getenv = os.getenv
 compat_getpass = getpass.getpass
 compat_html_entities = html.entities
-compat_html_entities_html5 = compat_html_entities.html5
+compat_html_entities_html5 = html.entities.html5
+compat_HTMLParser = html.parser.HTMLParser
 compat_http_client = http.client
 compat_http_server = http.server
+compat_HTTPError = urllib.error.HTTPError
 compat_itertools_count = itertools.count
 compat_parse_qs = urllib.parse.parse_qs
-compat_shlex_split = shlex.split
-compat_socket_create_connection = socket.create_connection
+compat_str = str
 compat_struct_pack = struct.pack
 compat_struct_unpack = struct.unpack
-compat_subprocess_get_DEVNULL = lambda: DEVNULL
 compat_tokenize_tokenize = tokenize.tokenize
 compat_urllib_error = urllib.error
-compat_urllib_parse = urllib.parse
-compat_urllib_parse_quote = urllib.parse.quote
-compat_urllib_parse_quote_plus = urllib.parse.quote_plus
 compat_urllib_parse_unquote = urllib.parse.unquote
 compat_urllib_parse_unquote_plus = urllib.parse.unquote_plus
-compat_urllib_parse_unquote_to_bytes = urllib.parse.unquote_to_bytes
 compat_urllib_parse_urlencode = urllib.parse.urlencode
 compat_urllib_parse_urlparse = urllib.parse.urlparse
-compat_urllib_parse_urlunparse = urllib.parse.urlunparse
 compat_urllib_request = urllib.request
+compat_urlparse = compat_urllib_parse = urllib.parse
+
+
+# To be removed
+
+compat_basestring = str
+compat_collections_abc = collections.abc
+compat_cookies = http.cookies
+compat_etree_Element = etree.Element
+compat_etree_register_namespace = etree.register_namespace
+compat_filter = filter
+compat_input = input
+compat_integer_types = (int, )
+compat_kwargs = lambda kwargs: kwargs
+compat_map = map
+compat_numeric_types = (int, float, complex)
+compat_print = print
+compat_shlex_split = shlex.split
+compat_socket_create_connection = socket.create_connection
+compat_Struct = struct.Struct
+compat_subprocess_get_DEVNULL = lambda: DEVNULL
+compat_urllib_parse_quote = urllib.parse.quote
+compat_urllib_parse_quote_plus = urllib.parse.quote_plus
+compat_urllib_parse_unquote_to_bytes = urllib.parse.unquote_to_bytes
+compat_urllib_parse_urlunparse = urllib.parse.urlunparse
 compat_urllib_request_DataHandler = urllib.request.DataHandler
 compat_urllib_response = urllib.response
-compat_urlparse = urllib.parse
 compat_urlretrieve = urllib.request.urlretrieve
 compat_xml_parse_error = etree.ParseError
+compat_xpath = lambda xpath: xpath
+compat_zip = zip
+workaround_optparse_bug9161 = lambda: None
 
 
 # Set public objects
diff --git a/yt_dlp/downloader/ism.py b/yt_dlp/downloader/ism.py
index 4d5618c836..2ba36085ea 100644
--- a/yt_dlp/downloader/ism.py
+++ b/yt_dlp/downloader/ism.py
@@ -3,25 +3,25 @@
 import time
 import binascii
 import io
+import struct
 
 from .fragment import FragmentFD
 from ..compat import (
-    compat_Struct,
     compat_urllib_error,
 )
 
 
-u8 = compat_Struct('>B')
-u88 = compat_Struct('>Bx')
-u16 = compat_Struct('>H')
-u1616 = compat_Struct('>Hxx')
-u32 = compat_Struct('>I')
-u64 = compat_Struct('>Q')
+u8 = struct.Struct('>B')
+u88 = struct.Struct('>Bx')
+u16 = struct.Struct('>H')
+u1616 = struct.Struct('>Hxx')
+u32 = struct.Struct('>I')
+u64 = struct.Struct('>Q')
 
-s88 = compat_Struct('>bx')
-s16 = compat_Struct('>h')
-s1616 = compat_Struct('>hxx')
-s32 = compat_Struct('>i')
+s88 = struct.Struct('>bx')
+s16 = struct.Struct('>h')
+s1616 = struct.Struct('>hxx')
+s32 = struct.Struct('>i')
 
 unity_matrix = (s32.pack(0x10000) + s32.pack(0) * 3) * 2 + s32.pack(0x40000000)
 
diff --git a/yt_dlp/extractor/abematv.py b/yt_dlp/extractor/abematv.py
index a839f0c1f5..c7db054751 100644
--- a/yt_dlp/extractor/abematv.py
+++ b/yt_dlp/extractor/abematv.py
@@ -5,13 +5,14 @@
 import hmac
 import re
 import struct
+import urllib.response
+import uuid
 from base64 import urlsafe_b64encode
 from binascii import unhexlify
 
 from .common import InfoExtractor
 from ..aes import aes_ecb_decrypt
 from ..compat import (
-    compat_urllib_response,
     compat_urllib_parse_urlparse,
     compat_urllib_request,
 )
@@ -19,7 +20,6 @@
     ExtractorError,
     decode_base,
     int_or_none,
-    random_uuidv4,
     request_to_url,
     time_seconds,
     update_url_query,
@@ -141,7 +141,7 @@ def abematv_license_open(self, url):
         url = request_to_url(url)
         ticket = compat_urllib_parse_urlparse(url).netloc
         response_data = self._get_videokey_from_ticket(ticket)
-        return compat_urllib_response.addinfourl(io.BytesIO(response_data), headers={
+        return urllib.response.addinfourl(io.BytesIO(response_data), headers={
             'Content-Length': len(response_data),
         }, url=url, code=200)
 
@@ -253,7 +253,7 @@ def _get_device_token(self):
         if self._USERTOKEN:
             return self._USERTOKEN
 
-        self._DEVICE_ID = random_uuidv4()
+        self._DEVICE_ID = str(uuid.uuid4())
         aks = self._generate_aks(self._DEVICE_ID)
         user_data = self._download_json(
             'https://api.abema.io/v1/users', None, note='Authorizing',
diff --git a/yt_dlp/extractor/adobepass.py b/yt_dlp/extractor/adobepass.py
index 5d98301b8b..1292484c69 100644
--- a/yt_dlp/extractor/adobepass.py
+++ b/yt_dlp/extractor/adobepass.py
@@ -8,7 +8,6 @@
 
 from .common import InfoExtractor
 from ..compat import (
-    compat_kwargs,
     compat_urlparse,
     compat_getpass
 )
@@ -1365,7 +1364,7 @@ def _download_webpage_handle(self, *args, **kwargs):
         headers.update(kwargs.get('headers', {}))
         kwargs['headers'] = headers
         return super(AdobePassIE, self)._download_webpage_handle(
-            *args, **compat_kwargs(kwargs))
+            *args, **kwargs)
 
     @staticmethod
     def _get_mvpd_resource(provider_id, title, guid, rating):
diff --git a/yt_dlp/extractor/afreecatv.py b/yt_dlp/extractor/afreecatv.py
index 28946e9ddc..44bfb8bc24 100644
--- a/yt_dlp/extractor/afreecatv.py
+++ b/yt_dlp/extractor/afreecatv.py
@@ -5,7 +5,6 @@
 import re
 
 from .common import InfoExtractor
-from ..compat import compat_xpath
 from ..utils import (
     ExtractorError,
     OnDemandPagedList,
@@ -282,7 +281,7 @@ def _real_extract(self, url):
         else:
             raise ExtractorError('Unable to download video info')
 
-        video_element = video_xml.findall(compat_xpath('./track/video'))[-1]
+        video_element = video_xml.findall('./track/video')[-1]
         if video_element is None or video_element.text is None:
             raise ExtractorError(
                 'Video %s does not exist' % video_id, expected=True)
@@ -312,7 +311,7 @@ def _real_extract(self, url):
 
         if not video_url:
             entries = []
-            file_elements = video_element.findall(compat_xpath('./file'))
+            file_elements = video_element.findall('./file')
             one = len(file_elements) == 1
             for file_num, file_element in enumerate(file_elements, start=1):
                 file_url = url_or_none(file_element.text)
diff --git a/yt_dlp/extractor/bbc.py b/yt_dlp/extractor/bbc.py
index 29ad7ded77..5bc8d3110c 100644
--- a/yt_dlp/extractor/bbc.py
+++ b/yt_dlp/extractor/bbc.py
@@ -1,6 +1,7 @@
 # coding: utf-8
 from __future__ import unicode_literals
 
+import xml.etree.ElementTree
 import functools
 import itertools
 import json
@@ -8,7 +9,6 @@
 
 from .common import InfoExtractor
 from ..compat import (
-    compat_etree_Element,
     compat_HTTPError,
     compat_str,
     compat_urllib_error,
@@ -318,7 +318,7 @@ def _get_subtitles(self, media, programme_id):
                 continue
             captions = self._download_xml(
                 cc_url, programme_id, 'Downloading captions', fatal=False)
-            if not isinstance(captions, compat_etree_Element):
+            if not isinstance(captions, xml.etree.ElementTree.Element):
                 continue
             subtitles['en'] = [
                 {
diff --git a/yt_dlp/extractor/brightcove.py b/yt_dlp/extractor/brightcove.py
index dcd332b435..60c853898a 100644
--- a/yt_dlp/extractor/brightcove.py
+++ b/yt_dlp/extractor/brightcove.py
@@ -4,6 +4,7 @@
 import base64
 import re
 import struct
+import xml.etree.ElementTree
 
 from .adobepass import AdobePassIE
 from .common import InfoExtractor
@@ -12,7 +13,6 @@
     compat_HTTPError,
     compat_parse_qs,
     compat_urlparse,
-    compat_xml_parse_error,
 )
 from ..utils import (
     clean_html,
@@ -166,7 +166,7 @@ def _build_brightcove_url(cls, object_str):
 
         try:
             object_doc = compat_etree_fromstring(object_str.encode('utf-8'))
-        except compat_xml_parse_error:
+        except xml.etree.ElementTree.ParseError:
             return
 
         fv_el = find_xpath_attr(object_doc, './param', 'name', 'flashVars')
diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py
index 48f302f86f..8da21a3dc5 100644
--- a/yt_dlp/extractor/common.py
+++ b/yt_dlp/extractor/common.py
@@ -3,6 +3,7 @@
 
 import base64
 import collections
+import xml.etree.ElementTree
 import hashlib
 import itertools
 import json
@@ -17,7 +18,6 @@
 from ..compat import (
     compat_cookiejar_Cookie,
     compat_cookies_SimpleCookie,
-    compat_etree_Element,
     compat_etree_fromstring,
     compat_expanduser,
     compat_getpass,
@@ -30,7 +30,6 @@
     compat_urllib_parse_urlencode,
     compat_urllib_request,
     compat_urlparse,
-    compat_xml_parse_error,
 )
 from ..downloader import FileDownloader
 from ..downloader.f4m import (
@@ -951,7 +950,7 @@ def _download_xml_handle(
             fatal=True, encoding=None, data=None, headers={}, query={},
             expected_status=None):
         """
-        Return a tuple (xml as an compat_etree_Element, URL handle).
+        Return a tuple (xml as an xml.etree.ElementTree.Element, URL handle).
 
         See _download_webpage docstring for arguments specification.
         """
@@ -972,7 +971,7 @@ def _download_xml(
             transform_source=None, fatal=True, encoding=None,
             data=None, headers={}, query={}, expected_status=None):
         """
-        Return the xml as an compat_etree_Element.
+        Return the xml as an xml.etree.ElementTree.Element.
 
         See _download_webpage docstring for arguments specification.
         """
@@ -988,7 +987,7 @@ def _parse_xml(self, xml_string, video_id, transform_source=None, fatal=True):
             xml_string = transform_source(xml_string)
         try:
             return compat_etree_fromstring(xml_string.encode('utf-8'))
-        except compat_xml_parse_error as ve:
+        except xml.etree.ElementTree.ParseError as ve:
             errmsg = '%s: Failed to parse XML ' % video_id
             if fatal:
                 raise ExtractorError(errmsg, cause=ve)
@@ -2008,7 +2007,7 @@ def _extract_f4m_formats(self, manifest_url, video_id, preference=None, quality=
     def _parse_f4m_formats(self, manifest, manifest_url, video_id, preference=None, quality=None, f4m_id=None,
                            transform_source=lambda s: fix_xml_ampersands(s).strip(),
                            fatal=True, m3u8_id=None):
-        if not isinstance(manifest, compat_etree_Element) and not fatal:
+        if not isinstance(manifest, xml.etree.ElementTree.Element) and not fatal:
             return []
 
         # currently yt-dlp cannot decode the playerVerificationChallenge as Akamai uses Adobe Alchemy
diff --git a/yt_dlp/extractor/crunchyroll.py b/yt_dlp/extractor/crunchyroll.py
index 7edb645f82..d7696bbd9c 100644
--- a/yt_dlp/extractor/crunchyroll.py
+++ b/yt_dlp/extractor/crunchyroll.py
@@ -6,13 +6,13 @@
 import json
 import zlib
 
+import xml.etree.ElementTree
 from hashlib import sha1
 from math import pow, sqrt, floor
 from .common import InfoExtractor
 from .vrv import VRVBaseIE
 from ..compat import (
     compat_b64decode,
-    compat_etree_Element,
     compat_etree_fromstring,
     compat_str,
     compat_urllib_parse_urlencode,
@@ -395,7 +395,7 @@ def _get_subtitles(self, video_id, webpage):
                 'Downloading subtitles for ' + sub_name, data={
                     'subtitle_script_id': sub_id,
                 })
-            if not isinstance(sub_doc, compat_etree_Element):
+            if not isinstance(sub_doc, xml.etree.ElementTree.Element):
                 continue
             sid = sub_doc.get('id')
             iv = xpath_text(sub_doc, 'iv', 'subtitle iv')
@@ -525,7 +525,7 @@ def _real_extract(self, url):
                         'video_quality': stream_quality,
                         'current_page': url,
                     })
-                if isinstance(streamdata, compat_etree_Element):
+                if isinstance(streamdata, xml.etree.ElementTree.Element):
                     stream_info = streamdata.find('./{default}preload/stream_info')
                     if stream_info is not None:
                         stream_infos.append(stream_info)
@@ -536,7 +536,7 @@ def _real_extract(self, url):
                         'video_format': stream_format,
                         'video_encode_quality': stream_quality,
                     })
-                if isinstance(stream_info, compat_etree_Element):
+                if isinstance(stream_info, xml.etree.ElementTree.Element):
                     stream_infos.append(stream_info)
                 for stream_info in stream_infos:
                     video_encode_id = xpath_text(stream_info, './video_encode_id')
@@ -611,7 +611,7 @@ def _real_extract(self, url):
 
         season = episode = episode_number = duration = None
 
-        if isinstance(metadata, compat_etree_Element):
+        if isinstance(metadata, xml.etree.ElementTree.Element):
             season = xpath_text(metadata, 'series_title')
             episode = xpath_text(metadata, 'episode_title')
             episode_number = int_or_none(xpath_text(metadata, 'episode_number'))
diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py
index f11fc844d9..fd620217ed 100644
--- a/yt_dlp/extractor/generic.py
+++ b/yt_dlp/extractor/generic.py
@@ -4,6 +4,7 @@
 
 import os
 import re
+import xml.etree.ElementTree
 
 from .common import InfoExtractor
 from .youtube import YoutubeIE
@@ -12,7 +13,6 @@
     compat_str,
     compat_urllib_parse_unquote,
     compat_urlparse,
-    compat_xml_parse_error,
 )
 from ..utils import (
     determine_ext,
@@ -2827,7 +2827,7 @@ def _real_extract(self, url):
         try:
             try:
                 doc = compat_etree_fromstring(webpage)
-            except compat_xml_parse_error:
+            except xml.etree.ElementTree.ParseError:
                 doc = compat_etree_fromstring(webpage.encode('utf-8'))
             if doc.tag == 'rss':
                 self.report_detected('RSS feed')
@@ -2862,7 +2862,7 @@ def _real_extract(self, url):
                 self.report_detected('F4M manifest')
                 self._sort_formats(info_dict['formats'])
                 return info_dict
-        except compat_xml_parse_error:
+        except xml.etree.ElementTree.ParseError:
             pass
 
         # Is it a Camtasia project?
diff --git a/yt_dlp/extractor/microsoftvirtualacademy.py b/yt_dlp/extractor/microsoftvirtualacademy.py
index 46abd2a6d0..9255a79641 100644
--- a/yt_dlp/extractor/microsoftvirtualacademy.py
+++ b/yt_dlp/extractor/microsoftvirtualacademy.py
@@ -3,9 +3,6 @@
 import re
 
 from .common import InfoExtractor
-from ..compat import (
-    compat_xpath,
-)
 from ..utils import (
     int_or_none,
     parse_duration,
@@ -70,9 +67,9 @@ def _real_extract(self, url):
 
         formats = []
 
-        for sources in settings.findall(compat_xpath('.//MediaSources')):
+        for sources in settings.findall('.//MediaSources'):
             sources_type = sources.get('videoType')
-            for source in sources.findall(compat_xpath('./MediaSource')):
+            for source in sources.findall('./MediaSource'):
                 video_url = source.text
                 if not video_url or not video_url.startswith('http'):
                     continue
@@ -101,7 +98,7 @@ def _real_extract(self, url):
         self._sort_formats(formats)
 
         subtitles = {}
-        for source in settings.findall(compat_xpath('.//MarkerResourceSource')):
+        for source in settings.findall('.//MarkerResourceSource'):
             subtitle_url = source.text
             if not subtitle_url:
                 continue
diff --git a/yt_dlp/extractor/mildom.py b/yt_dlp/extractor/mildom.py
index 5f2df29c6f..4de8e9ef4d 100644
--- a/yt_dlp/extractor/mildom.py
+++ b/yt_dlp/extractor/mildom.py
@@ -3,6 +3,7 @@
 
 import functools
 import json
+import uuid
 
 from .common import InfoExtractor
 from ..utils import (
@@ -11,7 +12,6 @@
     ExtractorError,
     float_or_none,
     OnDemandPagedList,
-    random_uuidv4,
     traverse_obj,
 )
 
@@ -21,7 +21,7 @@ class MildomBaseIE(InfoExtractor):
 
     def _call_api(self, url, video_id, query=None, note='Downloading JSON metadata', body=None):
         if not self._GUEST_ID:
-            self._GUEST_ID = f'pc-gp-{random_uuidv4()}'
+            self._GUEST_ID = f'pc-gp-{str(uuid.uuid4())}'
 
         content = self._download_json(
             url, video_id, note=note, data=json.dumps(body).encode() if body else None,
diff --git a/yt_dlp/extractor/mixcloud.py b/yt_dlp/extractor/mixcloud.py
index c2dd078ac4..b19e59b1a5 100644
--- a/yt_dlp/extractor/mixcloud.py
+++ b/yt_dlp/extractor/mixcloud.py
@@ -9,7 +9,6 @@
     compat_ord,
     compat_str,
     compat_urllib_parse_unquote,
-    compat_zip
 )
 from ..utils import (
     ExtractorError,
@@ -76,7 +75,7 @@ def _decrypt_xor_cipher(key, ciphertext):
         """Encrypt/Decrypt XOR cipher. Both ways are possible because it's XOR."""
         return ''.join([
             compat_chr(compat_ord(ch) ^ compat_ord(k))
-            for ch, k in compat_zip(ciphertext, itertools.cycle(key))])
+            for ch, k in zip(ciphertext, itertools.cycle(key))])
 
     def _real_extract(self, url):
         username, slug = self._match_valid_url(url).groups()
diff --git a/yt_dlp/extractor/mtv.py b/yt_dlp/extractor/mtv.py
index be5de0a70c..cff314e272 100644
--- a/yt_dlp/extractor/mtv.py
+++ b/yt_dlp/extractor/mtv.py
@@ -6,7 +6,6 @@
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
-    compat_xpath,
 )
 from ..utils import (
     ExtractorError,
@@ -167,9 +166,9 @@ def _get_video_info(self, itemdoc, use_hls=True):
                 itemdoc, './/{http://search.yahoo.com/mrss/}category',
                 'scheme', 'urn:mtvn:video_title')
         if title_el is None:
-            title_el = itemdoc.find(compat_xpath('.//{http://search.yahoo.com/mrss/}title'))
+            title_el = itemdoc.find('.//{http://search.yahoo.com/mrss/}title')
         if title_el is None:
-            title_el = itemdoc.find(compat_xpath('.//title'))
+            title_el = itemdoc.find('.//title')
             if title_el.text is None:
                 title_el = None
 
diff --git a/yt_dlp/extractor/noz.py b/yt_dlp/extractor/noz.py
index ccafd77232..bdc2efcd7b 100644
--- a/yt_dlp/extractor/noz.py
+++ b/yt_dlp/extractor/noz.py
@@ -4,7 +4,6 @@
 from .common import InfoExtractor
 from ..compat import (
     compat_urllib_parse_unquote,
-    compat_xpath,
 )
 from ..utils import (
     int_or_none,
@@ -50,7 +49,7 @@ def _real_extract(self, url):
         duration = int_or_none(xpath_text(
             doc, './/article/movie/file/duration'))
         formats = []
-        for qnode in doc.findall(compat_xpath('.//article/movie/file/qualities/qual')):
+        for qnode in doc.findall('.//article/movie/file/qualities/qual'):
             http_url_ele = find_xpath_attr(
                 qnode, './html_urls/video_url', 'format', 'video/mp4')
             http_url = http_url_ele.text if http_url_ele is not None else None
diff --git a/yt_dlp/extractor/openload.py b/yt_dlp/extractor/openload.py
index fe4740aaed..c19d04900f 100644
--- a/yt_dlp/extractor/openload.py
+++ b/yt_dlp/extractor/openload.py
@@ -8,7 +8,6 @@
 
 from ..compat import (
     compat_urlparse,
-    compat_kwargs,
 )
 from ..utils import (
     check_executable,
@@ -158,7 +157,7 @@ def _load_cookies(self):
                 cookie['rest'] = {'httpOnly': None}
             if 'expiry' in cookie:
                 cookie['expire_time'] = cookie['expiry']
-            self.extractor._set_cookie(**compat_kwargs(cookie))
+            self.extractor._set_cookie(**cookie)
 
     def get(self, url, html=None, video_id=None, note=None, note2='Executing JS on webpage', headers={}, jscode='saveAndExit();'):
         """
diff --git a/yt_dlp/extractor/soundcloud.py b/yt_dlp/extractor/soundcloud.py
index bbc79c2be0..749e6dda39 100644
--- a/yt_dlp/extractor/soundcloud.py
+++ b/yt_dlp/extractor/soundcloud.py
@@ -12,7 +12,6 @@
 )
 from ..compat import (
     compat_HTTPError,
-    compat_kwargs,
     compat_str,
 )
 from ..utils import (
@@ -96,7 +95,7 @@ def _download_json(self, *args, **kwargs):
             query['client_id'] = self._CLIENT_ID
             kwargs['query'] = query
             try:
-                return super()._download_json(*args, **compat_kwargs(kwargs))
+                return super()._download_json(*args, **kwargs)
             except ExtractorError as e:
                 if isinstance(e.cause, compat_HTTPError) and e.cause.code in (401, 403):
                     self._store_client_id(None)
diff --git a/yt_dlp/extractor/udemy.py b/yt_dlp/extractor/udemy.py
index 235f89713c..77485247fd 100644
--- a/yt_dlp/extractor/udemy.py
+++ b/yt_dlp/extractor/udemy.py
@@ -5,7 +5,6 @@
 from .common import InfoExtractor
 from ..compat import (
     compat_HTTPError,
-    compat_kwargs,
     compat_str,
     compat_urllib_request,
     compat_urlparse,
@@ -132,7 +131,7 @@ def _download_webpage_handle(self, *args, **kwargs):
         headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'
         kwargs['headers'] = headers
         ret = super(UdemyIE, self)._download_webpage_handle(
-            *args, **compat_kwargs(kwargs))
+            *args, **kwargs)
         if not ret:
             return ret
         webpage, _ = ret
diff --git a/yt_dlp/extractor/vimeo.py b/yt_dlp/extractor/vimeo.py
index 972fb480bb..a00b387f3e 100644
--- a/yt_dlp/extractor/vimeo.py
+++ b/yt_dlp/extractor/vimeo.py
@@ -8,7 +8,6 @@
 
 from .common import InfoExtractor
 from ..compat import (
-    compat_kwargs,
     compat_HTTPError,
     compat_str,
     compat_urlparse,
@@ -109,7 +108,7 @@ def _extract_xsrft_and_vuid(self, webpage):
     def _extract_vimeo_config(self, webpage, video_id, *args, **kwargs):
         vimeo_config = self._search_regex(
             r'vimeo\.config\s*=\s*(?:({.+?})|_extend\([^,]+,\s+({.+?})\));',
-            webpage, 'vimeo config', *args, **compat_kwargs(kwargs))
+            webpage, 'vimeo config', *args, **kwargs)
         if vimeo_config:
             return self._parse_json(vimeo_config, video_id)
 
diff --git a/yt_dlp/options.py b/yt_dlp/options.py
index 67db6d0676..8839b44d4b 100644
--- a/yt_dlp/options.py
+++ b/yt_dlp/options.py
@@ -3,14 +3,13 @@
 import os.path
 import optparse
 import re
+import shlex
 import sys
 
 from .compat import (
     compat_expanduser,
     compat_get_terminal_size,
     compat_getenv,
-    compat_kwargs,
-    compat_shlex_split,
 )
 from .utils import (
     Config,
@@ -223,14 +222,12 @@ def _dict_from_options_callback(
     fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
     fmt.format_option_strings = _format_option_string
 
-    kw = {
-        'version': __version__,
-        'formatter': fmt,
-        'usage': '%prog [OPTIONS] URL [URL...]',
-        'conflict_handler': 'resolve',
-    }
-
-    parser = _YoutubeDLOptionParser(**compat_kwargs(kw))
+    parser = _YoutubeDLOptionParser(
+        version=__version__,
+        formatter=fmt,
+        usage='%prog [OPTIONS] URL [URL...]',
+        conflict_handler='resolve'
+    )
 
     general = optparse.OptionGroup(parser, 'General Options')
     general.add_option(
@@ -833,7 +830,7 @@ def _dict_from_options_callback(
         callback_kwargs={
             'allowed_keys': r'ffmpeg_[io]\d*|%s' % '|'.join(map(re.escape, list_external_downloaders())),
             'default_key': 'default',
-            'process': compat_shlex_split
+            'process': shlex.split
         }, help=(
             'Give these arguments to the external downloader. '
             'Specify the downloader name and the arguments separated by a colon ":". '
@@ -1339,7 +1336,7 @@ def _dict_from_options_callback(
         callback_kwargs={
             'allowed_keys': r'\w+(?:\+\w+)?',
             'default_key': 'default-compat',
-            'process': compat_shlex_split,
+            'process': shlex.split,
             'multiple_keys': False
         }, help=(
             'Give these arguments to the postprocessors. '
diff --git a/yt_dlp/postprocessor/sponskrub.py b/yt_dlp/postprocessor/sponskrub.py
index 86149aeefd..59cf0e0c3e 100644
--- a/yt_dlp/postprocessor/sponskrub.py
+++ b/yt_dlp/postprocessor/sponskrub.py
@@ -1,9 +1,9 @@
 from __future__ import unicode_literals
 import os
+import shlex
 import subprocess
 
 from .common import PostProcessor
-from ..compat import compat_shlex_split
 from ..utils import (
     check_executable,
     cli_option,
@@ -79,7 +79,7 @@ def run(self, information):
         if not self.cutout:
             cmd += ['-chapter']
         cmd += cli_option(self._downloader.params, '-proxy', 'proxy')
-        cmd += compat_shlex_split(self.args)  # For backward compatibility
+        cmd += shlex.split(self.args)  # For backward compatibility
         cmd += self._configuration_args(self._exe_name, use_compat=False)
         cmd += ['--', information['id'], filename, temp_filename]
         cmd = [encodeArgument(i) for i in cmd]
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 324b54e787..3f70b1f603 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -41,12 +41,13 @@
 import xml.etree.ElementTree
 import zlib
 import mimetypes
+import urllib.parse
+import shlex
 
 from .compat import (
     compat_HTMLParseError,
     compat_HTMLParser,
     compat_HTTPError,
-    compat_basestring,
     compat_brotli,
     compat_chr,
     compat_cookiejar,
@@ -55,28 +56,19 @@
     compat_html_entities,
     compat_html_entities_html5,
     compat_http_client,
-    compat_integer_types,
-    compat_numeric_types,
-    compat_kwargs,
     compat_os_name,
     compat_parse_qs,
-    compat_shlex_split,
     compat_shlex_quote,
     compat_str,
     compat_struct_pack,
     compat_struct_unpack,
     compat_urllib_error,
-    compat_urllib_parse,
     compat_urllib_parse_urlencode,
     compat_urllib_parse_urlparse,
-    compat_urllib_parse_urlunparse,
-    compat_urllib_parse_quote,
-    compat_urllib_parse_quote_plus,
     compat_urllib_parse_unquote_plus,
     compat_urllib_request,
     compat_urlparse,
     compat_websockets,
-    compat_xpath,
 )
 
 from .socks import (
@@ -340,7 +332,7 @@ def xpath_with_ns(path, ns_map):
 
 def xpath_element(node, xpath, name=None, fatal=False, default=NO_DEFAULT):
     def _find_xpath(xpath):
-        return node.find(compat_xpath(xpath))
+        return node.find(xpath)
 
     if isinstance(xpath, (str, compat_str)):
         n = _find_xpath(xpath)
@@ -1193,7 +1185,7 @@ class XAttrUnavailableError(YoutubeDLError):
 
 
 def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
-    hc = http_class(*args, **compat_kwargs(kwargs))
+    hc = http_class(*args, **kwargs)
     source_address = ydl_handler._params.get('source_address')
 
     if source_address is not None:
@@ -2401,7 +2393,7 @@ def str_or_none(v, default=None):
 
 def str_to_int(int_str):
     """ A more relaxed version of int_or_none """
-    if isinstance(int_str, compat_integer_types):
+    if isinstance(int_str, int):
         return int_str
     elif isinstance(int_str, compat_str):
         int_str = re.sub(r'[,\.\+]', '', int_str)
@@ -2442,7 +2434,7 @@ def request_to_url(req):
 def strftime_or_none(timestamp, date_format, default=None):
     datetime_object = None
     try:
-        if isinstance(timestamp, compat_numeric_types):  # unix timestamp
+        if isinstance(timestamp, (int, float)):  # unix timestamp
             datetime_object = datetime.datetime.utcfromtimestamp(timestamp)
         elif isinstance(timestamp, compat_str):  # assume YYYYMMDD
             datetime_object = datetime.datetime.strptime(timestamp, '%Y%m%d')
@@ -2452,7 +2444,7 @@ def strftime_or_none(timestamp, date_format, default=None):
 
 
 def parse_duration(s):
-    if not isinstance(s, compat_basestring):
+    if not isinstance(s, str):
         return None
     s = s.strip()
     if not s:
@@ -2789,7 +2781,7 @@ def lowercase_escape(s):
 
 def escape_rfc3986(s):
     """Escape non-ASCII characters as suggested by RFC 3986"""
-    return compat_urllib_parse.quote(s, b"%/;:@&=+$,!~*'()?#[]")
+    return urllib.parse.quote(s, b"%/;:@&=+$,!~*'()?#[]")
 
 
 def escape_url(url):
@@ -2975,7 +2967,7 @@ def encode_compat_str(string, encoding=preferredencoding(), errors='strict'):
 def parse_age_limit(s):
     if type(s) == int:
         return s if 0 <= s <= 21 else None
-    if not isinstance(s, compat_basestring):
+    if not isinstance(s, str):
         return None
     m = re.match(r'^(?P<age>\d{1,2})\+?$', s)
     if m:
@@ -3405,7 +3397,7 @@ def _match_one(filter_part, dct, incomplete):
             comparison_value = comparison_value.replace(r'\%s' % m['quote'], m['quote'])
         actual_value = dct.get(m['key'])
         numeric_comparison = None
-        if isinstance(actual_value, compat_numeric_types):
+        if isinstance(actual_value, (int, float)):
             # If the original field is a string and matching comparisonvalue is
             # a number we should respect the origin of the original field
             # and process comparison value as a string (see
@@ -4859,9 +4851,9 @@ def iri_to_uri(iri):
 
     net_location = ''
     if iri_parts.username:
-        net_location += compat_urllib_parse_quote(iri_parts.username, safe=r"!$%&'()*+,~")
+        net_location += urllib.parse.quote(iri_parts.username, safe=r"!$%&'()*+,~")
         if iri_parts.password is not None:
-            net_location += ':' + compat_urllib_parse_quote(iri_parts.password, safe=r"!$%&'()*+,~")
+            net_location += ':' + urllib.parse.quote(iri_parts.password, safe=r"!$%&'()*+,~")
         net_location += '@'
 
     net_location += iri_parts.hostname.encode('idna').decode('utf-8')  # Punycode for Unicode hostnames.
@@ -4869,19 +4861,19 @@ def iri_to_uri(iri):
     if iri_parts.port is not None and iri_parts.port != 80:
         net_location += ':' + str(iri_parts.port)
 
-    return compat_urllib_parse_urlunparse(
+    return urllib.parse.urlunparse(
         (iri_parts.scheme,
             net_location,
 
-            compat_urllib_parse_quote_plus(iri_parts.path, safe=r"!$%&'()*+,/:;=@|~"),
+            urllib.parse.quote_plus(iri_parts.path, safe=r"!$%&'()*+,/:;=@|~"),
 
             # Unsure about the `safe` argument, since this is a legacy way of handling parameters.
-            compat_urllib_parse_quote_plus(iri_parts.params, safe=r"!$%&'()*+,/:;=@|~"),
+            urllib.parse.quote_plus(iri_parts.params, safe=r"!$%&'()*+,/:;=@|~"),
 
             # Not totally sure about the `safe` argument, since the source does not explicitly mention the query URI component.
-            compat_urllib_parse_quote_plus(iri_parts.query, safe=r"!$%&'()*+,/:;=?@{|}~"),
+            urllib.parse.quote_plus(iri_parts.query, safe=r"!$%&'()*+,/:;=?@{|}~"),
 
-            compat_urllib_parse_quote_plus(iri_parts.fragment, safe=r"!#$%&'()*+,/:;=?@{|}~")))
+            urllib.parse.quote_plus(iri_parts.fragment, safe=r"!#$%&'()*+,/:;=?@{|}~")))
 
     # Source for `safe` arguments: https://url.spec.whatwg.org/#percent-encoded-bytes.
 
@@ -5233,7 +5225,7 @@ def read_file(filename, default=[]):
         try:
             # FIXME: https://github.com/ytdl-org/youtube-dl/commit/dfe5fa49aed02cf36ba9f743b11b0903554b5e56
             contents = optionf.read()
-            res = compat_shlex_split(contents, comments=True)
+            res = shlex.split(contents, comments=True)
         finally:
             optionf.close()
         return res
diff --git a/yt_dlp/webvtt.py b/yt_dlp/webvtt.py
index 962aa57ad6..c78078f17d 100644
--- a/yt_dlp/webvtt.py
+++ b/yt_dlp/webvtt.py
@@ -15,7 +15,6 @@
 import io
 from .utils import int_or_none, timetuple_from_msec
 from .compat import (
-    compat_str as str,
     compat_Pattern,
     compat_Match,
 )
-- 
GitLab


From 86e5f3ed2e6e71eb81ea4c9e26288f16119ffd0c Mon Sep 17 00:00:00 2001
From: pukkandan <pukkandan.ytdlp@gmail.com>
Date: Mon, 11 Apr 2022 20:40:28 +0530
Subject: [PATCH 5/9] [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
---
 CONTRIBUTING.md                               |   1 -
 devscripts/bash-completion.py                 |   4 +-
 devscripts/check-porn.py                      |  10 +-
 devscripts/fish-completion.py                 |   4 +-
 devscripts/generate_aes_testdata.py           |   2 -
 devscripts/lazy_load_template.py              |   1 -
 devscripts/make_contributing.py               |   7 +-
 devscripts/make_issue_template.py             |   7 +-
 devscripts/make_lazy_extractors.py            |  13 +--
 devscripts/make_readme.py                     |   8 +-
 devscripts/make_supportedsites.py             |   9 +-
 devscripts/prepare_manpage.py                 |   7 +-
 devscripts/update-formulae.py                 |   4 +-
 devscripts/update-version.py                  |   2 +-
 devscripts/zsh-completion.py                  |   4 +-
 pyinst.py                                     |   1 -
 setup.py                                      |   1 -
 test/helper.py                                |  48 ++++----
 test/test_InfoExtractor.py                    |  19 +---
 test/test_YoutubeDL.py                        |  30 +++--
 test/test_YoutubeDLCookieJar.py               |   4 -
 test/test_aes.py                              |   2 -
 test/test_age_restriction.py                  |   2 -
 test/test_all_urls.py                         |   9 +-
 test/test_cache.py                            |   4 -
 test/test_compat.py                           |   6 +-
 test/test_download.py                         |  14 +--
 test/test_downloader_http.py                  |   5 +-
 test/test_execution.py                        |   6 +-
 test/test_http.py                             |  15 +--
 test/test_iqiyi_sdk_interpreter.py            |   5 +-
 test/test_jsinterp.py                         |   3 -
 test/test_netrc.py                            |   3 -
 test/test_overwrites.py                       |   2 -
 test/test_post_hooks.py                       |   5 +-
 test/test_postprocessors.py                   |   3 -
 test/test_socks.py                            |   3 -
 test/test_subtitles.py                        |  38 +++----
 test/test_update.py.disabled                  |   3 -
 test/test_utils.py                            |  21 ++--
 test/test_verbose_output.py                   |   4 -
 test/test_write_annotations.py.disabled       |   7 +-
 test/test_youtube_lists.py                    |   2 -
 test/test_youtube_misc.py                     |   2 -
 test/test_youtube_signature.py                |   6 +-
 yt_dlp/YoutubeDL.py                           |  80 +++++++-------
 yt_dlp/__init__.py                            |  10 +-
 yt_dlp/__main__.py                            |   2 -
 yt_dlp/aes.py                                 |   2 -
 yt_dlp/cache.py                               |  19 ++--
 yt_dlp/compat.py                              |   2 -
 yt_dlp/cookies.py                             |  58 +++++-----
 yt_dlp/downloader/__init__.py                 |   2 -
 yt_dlp/downloader/common.py                   |   8 +-
 yt_dlp/downloader/dash.py                     |   3 +-
 yt_dlp/downloader/external.py                 |  24 ++--
 yt_dlp/downloader/f4m.py                      |   2 -
 yt_dlp/downloader/fc2.py                      |   2 -
 yt_dlp/downloader/fragment.py                 |   8 +-
 yt_dlp/downloader/hls.py                      |   5 +-
 yt_dlp/downloader/http.py                     |  12 +-
 yt_dlp/downloader/ism.py                      |   2 -
 yt_dlp/downloader/mhtml.py                    |   3 -
 yt_dlp/downloader/niconico.py                 |   3 -
 yt_dlp/downloader/rtmp.py                     |   2 -
 yt_dlp/downloader/rtsp.py                     |   4 +-
 yt_dlp/downloader/youtube_live_chat.py        |   2 -
 yt_dlp/extractor/abc.py                       |   2 -
 yt_dlp/extractor/abcnews.py                   |   4 -
 yt_dlp/extractor/abcotvs.py                   |   4 -
 yt_dlp/extractor/academicearth.py             |   2 -
 yt_dlp/extractor/acast.py                     |   4 -
 yt_dlp/extractor/adn.py                       |   3 -
 yt_dlp/extractor/adobeconnect.py              |   3 -
 yt_dlp/extractor/adobepass.py                 |   3 -
 yt_dlp/extractor/adobetv.py                   |   2 -
 yt_dlp/extractor/adultswim.py                 |   3 -
 yt_dlp/extractor/aenetworks.py                |   4 -
 yt_dlp/extractor/afreecatv.py                 |   3 -
 yt_dlp/extractor/airmozilla.py                |   3 -
 yt_dlp/extractor/aliexpress.py                |   3 -
 yt_dlp/extractor/aljazeera.py                 |   3 -
 yt_dlp/extractor/allocine.py                  |   3 -
 yt_dlp/extractor/alphaporno.py                |   2 -
 yt_dlp/extractor/alsace20tv.py                |   3 -
 yt_dlp/extractor/alura.py                     |   3 -
 yt_dlp/extractor/amara.py                     |   3 -
 yt_dlp/extractor/amazon.py                    |   1 -
 yt_dlp/extractor/amcnetworks.py               |   3 -
 yt_dlp/extractor/americastestkitchen.py       |   3 -
 yt_dlp/extractor/amp.py                       |   3 -
 yt_dlp/extractor/animelab.py                  |   3 -
 yt_dlp/extractor/animeondemand.py             |   2 -
 yt_dlp/extractor/ant1newsgr.py                |   3 -
 yt_dlp/extractor/anvato.py                    |   3 -
 .../anvato_token_generator/__init__.py        |   2 -
 .../anvato_token_generator/common.py          |   3 -
 .../extractor/anvato_token_generator/nfl.py   |   2 -
 yt_dlp/extractor/aol.py                       |   3 -
 yt_dlp/extractor/apa.py                       |   3 -
 yt_dlp/extractor/aparat.py                    |   3 -
 yt_dlp/extractor/appleconnect.py              |   3 -
 yt_dlp/extractor/applepodcasts.py             |   3 -
 yt_dlp/extractor/appletrailers.py             |   2 -
 yt_dlp/extractor/archiveorg.py                |   7 +-
 yt_dlp/extractor/arcpublishing.py             |   3 -
 yt_dlp/extractor/ard.py                       |   3 -
 yt_dlp/extractor/arkena.py                    |   3 -
 yt_dlp/extractor/arnes.py                     |   3 -
 yt_dlp/extractor/arte.py                      |   3 -
 yt_dlp/extractor/asiancrush.py                |   3 -
 yt_dlp/extractor/atresplayer.py               |   4 -
 yt_dlp/extractor/atttechchannel.py            |   2 -
 yt_dlp/extractor/atvat.py                     |   3 -
 yt_dlp/extractor/audimedia.py                 |   3 -
 yt_dlp/extractor/audioboom.py                 |   3 -
 yt_dlp/extractor/audiomack.py                 |   3 -
 yt_dlp/extractor/audius.py                    |   3 -
 yt_dlp/extractor/awaan.py                     |   3 -
 yt_dlp/extractor/aws.py                       |   3 -
 yt_dlp/extractor/azmedien.py                  |   3 -
 yt_dlp/extractor/baidu.py                     |   4 -
 yt_dlp/extractor/banbye.py                    |   3 -
 yt_dlp/extractor/bandaichannel.py             |   3 -
 yt_dlp/extractor/bandcamp.py                  |   3 -
 yt_dlp/extractor/bannedvideo.py               |   2 -
 yt_dlp/extractor/bbc.py                       |   3 -
 yt_dlp/extractor/beatport.py                  |   3 -
 yt_dlp/extractor/beeg.py                      |   2 -
 yt_dlp/extractor/behindkink.py                |   4 -
 yt_dlp/extractor/bellmedia.py                 |   4 -
 yt_dlp/extractor/bet.py                       |   2 -
 yt_dlp/extractor/bfi.py                       |   3 -
 yt_dlp/extractor/bfmtv.py                     |   3 -
 yt_dlp/extractor/bibeltv.py                   |   3 -
 yt_dlp/extractor/bigflix.py                   |   3 -
 yt_dlp/extractor/bigo.py                      |   3 -
 yt_dlp/extractor/bild.py                      |   3 -
 yt_dlp/extractor/bilibili.py                  |   2 -
 yt_dlp/extractor/biobiochiletv.py             |   3 -
 yt_dlp/extractor/biqle.py                     |   3 -
 yt_dlp/extractor/bitchute.py                  |   3 -
 yt_dlp/extractor/bitwave.py                   |   2 -
 yt_dlp/extractor/blackboardcollaborate.py     |   4 -
 yt_dlp/extractor/bleacherreport.py            |   3 -
 yt_dlp/extractor/blinkx.py                    |   2 -
 yt_dlp/extractor/blogger.py                   |   3 -
 yt_dlp/extractor/bloomberg.py                 |   3 -
 yt_dlp/extractor/bokecc.py                    |   4 -
 yt_dlp/extractor/bongacams.py                 |   3 -
 yt_dlp/extractor/bostonglobe.py               |   3 -
 yt_dlp/extractor/box.py                       |   3 -
 yt_dlp/extractor/bpb.py                       |   3 -
 yt_dlp/extractor/br.py                        |   3 -
 yt_dlp/extractor/bravotv.py                   |   3 -
 yt_dlp/extractor/breakcom.py                  |   3 -
 yt_dlp/extractor/breitbart.py                 |   2 -
 yt_dlp/extractor/brightcove.py                |   3 -
 yt_dlp/extractor/businessinsider.py           |   3 -
 yt_dlp/extractor/buzzfeed.py                  |   3 -
 yt_dlp/extractor/byutv.py                     |   3 -
 yt_dlp/extractor/c56.py                       |   4 -
 yt_dlp/extractor/cableav.py                   |   1 -
 yt_dlp/extractor/callin.py                    |   1 -
 yt_dlp/extractor/caltrans.py                  |   3 -
 yt_dlp/extractor/cam4.py                      |   3 -
 yt_dlp/extractor/camdemy.py                   |   3 -
 yt_dlp/extractor/cammodels.py                 |   3 -
 yt_dlp/extractor/camwithher.py                |   2 -
 yt_dlp/extractor/canalalpha.py                |   3 -
 yt_dlp/extractor/canalc2.py                   |   3 -
 yt_dlp/extractor/canalplus.py                 |   4 -
 yt_dlp/extractor/canvas.py                    |   1 -
 yt_dlp/extractor/carambatv.py                 |   3 -
 yt_dlp/extractor/cartoonnetwork.py            |   3 -
 yt_dlp/extractor/cbc.py                       |   3 -
 yt_dlp/extractor/cbs.py                       |   2 -
 yt_dlp/extractor/cbsinteractive.py            |   4 -
 yt_dlp/extractor/cbslocal.py                  |   3 -
 yt_dlp/extractor/cbsnews.py                   |   3 -
 yt_dlp/extractor/cbssports.py                 |   3 -
 yt_dlp/extractor/ccc.py                       |   3 -
 yt_dlp/extractor/ccma.py                      |   3 -
 yt_dlp/extractor/cctv.py                      |   3 -
 yt_dlp/extractor/cda.py                       |   3 -
 yt_dlp/extractor/ceskatelevize.py             |   3 -
 yt_dlp/extractor/cgtn.py                      |   3 -
 yt_dlp/extractor/channel9.py                  |   2 -
 yt_dlp/extractor/charlierose.py               |   2 -
 yt_dlp/extractor/chaturbate.py                |   2 -
 yt_dlp/extractor/chilloutzone.py              |   2 -
 yt_dlp/extractor/chingari.py                  |   3 -
 yt_dlp/extractor/chirbit.py                   |   3 -
 yt_dlp/extractor/cinchcast.py                 |   3 -
 yt_dlp/extractor/cinemax.py                   |   4 -
 yt_dlp/extractor/ciscolive.py                 |   3 -
 yt_dlp/extractor/ciscowebex.py                |   3 -
 yt_dlp/extractor/cjsw.py                      |   4 -
 yt_dlp/extractor/cliphunter.py                |   2 -
 yt_dlp/extractor/clippit.py                   |   4 -
 yt_dlp/extractor/cliprs.py                    |   3 -
 yt_dlp/extractor/clipsyndicate.py             |   2 -
 yt_dlp/extractor/closertotruth.py             |   3 -
 yt_dlp/extractor/cloudflarestream.py          |   3 -
 yt_dlp/extractor/cloudy.py                    |   3 -
 yt_dlp/extractor/clubic.py                    |   3 -
 yt_dlp/extractor/clyp.py                      |   2 -
 yt_dlp/extractor/cmt.py                       |   2 -
 yt_dlp/extractor/cnbc.py                      |   4 -
 yt_dlp/extractor/cnn.py                       |   3 -
 yt_dlp/extractor/comedycentral.py             |   2 -
 yt_dlp/extractor/common.py                    |  37 +++----
 yt_dlp/extractor/commonmistakes.py            |   2 -
 yt_dlp/extractor/commonprotocols.py           |   3 -
 yt_dlp/extractor/condenast.py                 |   3 -
 yt_dlp/extractor/contv.py                     |   3 -
 yt_dlp/extractor/corus.py                     |   4 -
 yt_dlp/extractor/coub.py                      |   3 -
 yt_dlp/extractor/cozytv.py                    |   3 -
 yt_dlp/extractor/cpac.py                      |   3 -
 yt_dlp/extractor/cracked.py                   |   2 -
 yt_dlp/extractor/crackle.py                   |   3 -
 yt_dlp/extractor/craftsy.py                   |   3 -
 yt_dlp/extractor/crooksandliars.py            |   2 -
 yt_dlp/extractor/crowdbunker.py               |   3 -
 yt_dlp/extractor/crunchyroll.py               |   3 -
 yt_dlp/extractor/cspan.py                     |   2 -
 yt_dlp/extractor/ctsnews.py                   |   3 -
 yt_dlp/extractor/ctv.py                       |   3 -
 yt_dlp/extractor/ctvnews.py                   |   3 -
 yt_dlp/extractor/cultureunplugged.py          |   2 -
 yt_dlp/extractor/curiositystream.py           |   3 -
 yt_dlp/extractor/cwtv.py                      |   3 -
 yt_dlp/extractor/cybrary.py                   |   3 +-
 yt_dlp/extractor/daftsex.py                   |   3 -
 yt_dlp/extractor/dailymail.py                 |   3 -
 yt_dlp/extractor/dailymotion.py               |   3 -
 yt_dlp/extractor/damtomo.py                   |   3 -
 yt_dlp/extractor/daum.py                      |   4 -
 yt_dlp/extractor/dbtv.py                      |   3 -
 yt_dlp/extractor/dctp.py                      |   3 -
 yt_dlp/extractor/deezer.py                    |   2 -
 yt_dlp/extractor/defense.py                   |   2 -
 yt_dlp/extractor/democracynow.py              |   3 -
 yt_dlp/extractor/dfb.py                       |   3 -
 yt_dlp/extractor/dhm.py                       |   2 -
 yt_dlp/extractor/digg.py                      |   2 -
 yt_dlp/extractor/digitalconcerthall.py        |   3 -
 yt_dlp/extractor/digiteka.py                  |   3 -
 yt_dlp/extractor/discovery.py                 |   2 -
 yt_dlp/extractor/discoverygo.py               |   2 -
 yt_dlp/extractor/discoveryvr.py               |   3 -
 yt_dlp/extractor/disney.py                    |   3 -
 yt_dlp/extractor/dispeak.py                   |   2 -
 yt_dlp/extractor/dlive.py                     |   2 -
 yt_dlp/extractor/doodstream.py                |   3 -
 yt_dlp/extractor/dotsub.py                    |   2 -
 yt_dlp/extractor/douyutv.py                   |   3 -
 yt_dlp/extractor/dplay.py                     |   3 -
 yt_dlp/extractor/drbonanza.py                 |   3 -
 yt_dlp/extractor/dreisat.py                   |   2 -
 yt_dlp/extractor/drooble.py                   |   3 -
 yt_dlp/extractor/dropbox.py                   |   3 -
 yt_dlp/extractor/dropout.py                   |   1 -
 yt_dlp/extractor/drtuber.py                   |   2 -
 yt_dlp/extractor/drtv.py                      |   3 -
 yt_dlp/extractor/dtube.py                     |   3 -
 yt_dlp/extractor/duboku.py                    |   3 -
 yt_dlp/extractor/dumpert.py                   |   3 -
 yt_dlp/extractor/dvtv.py                      |   3 -
 yt_dlp/extractor/dw.py                        |   3 -
 yt_dlp/extractor/eagleplatform.py             |   3 -
 yt_dlp/extractor/ebaumsworld.py               |   2 -
 yt_dlp/extractor/echomsk.py                   |   3 -
 yt_dlp/extractor/egghead.py                   |   3 -
 yt_dlp/extractor/ehow.py                      |   2 -
 yt_dlp/extractor/eighttracks.py               |   3 -
 yt_dlp/extractor/einthusan.py                 |   3 -
 yt_dlp/extractor/eitb.py                      |   3 -
 yt_dlp/extractor/ellentube.py                 |   3 -
 yt_dlp/extractor/elonet.py                    |   3 -
 yt_dlp/extractor/elpais.py                    |   3 -
 yt_dlp/extractor/embedly.py                   |   3 -
 yt_dlp/extractor/engadget.py                  |   2 -
 yt_dlp/extractor/epicon.py                    |   3 -
 yt_dlp/extractor/eporner.py                   |   4 -
 yt_dlp/extractor/eroprofile.py                |   2 -
 yt_dlp/extractor/ertgr.py                     |   3 -
 yt_dlp/extractor/escapist.py                  |   2 -
 yt_dlp/extractor/espn.py                      |   2 -
 yt_dlp/extractor/esri.py                      |   3 -
 yt_dlp/extractor/europa.py                    |   3 -
 yt_dlp/extractor/europeantour.py              |   3 -
 yt_dlp/extractor/euscreen.py                  |   3 -
 yt_dlp/extractor/everyonesmixtape.py          |   3 -
 yt_dlp/extractor/expotv.py                    |   2 -
 yt_dlp/extractor/expressen.py                 |   3 -
 yt_dlp/extractor/extractors.py                |   2 -
 yt_dlp/extractor/extremetube.py               |   2 -
 yt_dlp/extractor/eyedotv.py                   |   3 -
 yt_dlp/extractor/facebook.py                  |   3 -
 yt_dlp/extractor/fancode.py                   |   3 -
 yt_dlp/extractor/faz.py                       |   3 -
 yt_dlp/extractor/fc2.py                       |   3 -
 yt_dlp/extractor/fczenit.py                   |   3 -
 yt_dlp/extractor/filmmodu.py                  |   3 -
 yt_dlp/extractor/filmon.py                    |   3 -
 yt_dlp/extractor/filmweb.py                   |   3 -
 yt_dlp/extractor/firsttv.py                   |   3 -
 yt_dlp/extractor/fivetv.py                    |   4 -
 yt_dlp/extractor/flickr.py                    |   2 -
 yt_dlp/extractor/folketinget.py               |   3 -
 yt_dlp/extractor/footyroom.py                 |   3 -
 yt_dlp/extractor/formula1.py                  |   3 -
 yt_dlp/extractor/fourtube.py                  |   2 -
 yt_dlp/extractor/fox.py                       |   3 -
 yt_dlp/extractor/fox9.py                      |   3 -
 yt_dlp/extractor/foxgay.py                    |   2 -
 yt_dlp/extractor/foxnews.py                   |   2 -
 yt_dlp/extractor/foxsports.py                 |   2 -
 yt_dlp/extractor/fptplay.py                   |   3 -
 yt_dlp/extractor/franceculture.py             |   3 -
 yt_dlp/extractor/franceinter.py               |   3 -
 yt_dlp/extractor/francetv.py                  |   5 -
 yt_dlp/extractor/freesound.py                 |   2 -
 yt_dlp/extractor/freespeech.py                |   2 -
 yt_dlp/extractor/frontendmasters.py           |   3 -
 yt_dlp/extractor/fujitv.py                    |   2 -
 yt_dlp/extractor/funimation.py                |   3 -
 yt_dlp/extractor/funk.py                      |   4 -
 yt_dlp/extractor/fusion.py                    |   2 -
 yt_dlp/extractor/fxnetworks.py                |   3 -
 yt_dlp/extractor/gab.py                       |   3 -
 yt_dlp/extractor/gaia.py                      |   4 -
 yt_dlp/extractor/gameinformer.py              |   3 -
 yt_dlp/extractor/gamejolt.py                  |   1 -
 yt_dlp/extractor/gamespot.py                  |   2 -
 yt_dlp/extractor/gamestar.py                  |   4 -
 yt_dlp/extractor/gaskrank.py                  |   3 -
 yt_dlp/extractor/gazeta.py                    |   4 -
 yt_dlp/extractor/gdcvault.py                  |   2 -
 yt_dlp/extractor/gedidigital.py               |   3 -
 yt_dlp/extractor/generic.py                   |  10 +-
 yt_dlp/extractor/gettr.py                     |   3 -
 yt_dlp/extractor/gfycat.py                    |   3 -
 yt_dlp/extractor/giantbomb.py                 |   2 -
 yt_dlp/extractor/giga.py                      |   3 -
 yt_dlp/extractor/gigya.py                     |   2 -
 yt_dlp/extractor/glide.py                     |   3 -
 yt_dlp/extractor/globo.py                     |   3 -
 yt_dlp/extractor/glomex.py                    |   3 -
 yt_dlp/extractor/go.py                        |   3 -
 yt_dlp/extractor/godtube.py                   |   3 -
 yt_dlp/extractor/gofile.py                    |   1 -
 yt_dlp/extractor/golem.py                     |   3 -
 yt_dlp/extractor/googledrive.py               |   2 -
 yt_dlp/extractor/googlepodcasts.py            |   3 -
 yt_dlp/extractor/googlesearch.py              |   2 -
 yt_dlp/extractor/gopro.py                     |   3 -
 yt_dlp/extractor/goshgay.py                   |   3 -
 yt_dlp/extractor/gotostage.py                 |   3 -
 yt_dlp/extractor/gputechconf.py               |   3 -
 yt_dlp/extractor/gronkh.py                    |   3 -
 yt_dlp/extractor/groupon.py                   |   2 -
 yt_dlp/extractor/hbo.py                       |   3 -
 yt_dlp/extractor/hearthisat.py                |   4 -
 yt_dlp/extractor/heise.py                     |   3 -
 yt_dlp/extractor/hellporno.py                 |   2 -
 yt_dlp/extractor/helsinki.py                  |   4 -
 yt_dlp/extractor/hentaistigma.py              |   2 -
 yt_dlp/extractor/hgtv.py                      |   3 -
 yt_dlp/extractor/hidive.py                    |   1 -
 yt_dlp/extractor/historicfilms.py             |   2 -
 yt_dlp/extractor/hitbox.py                    |   3 -
 yt_dlp/extractor/hitrecord.py                 |   2 -
 yt_dlp/extractor/hketv.py                     |   3 -
 yt_dlp/extractor/hotnewhiphop.py              |   2 -
 yt_dlp/extractor/hotstar.py                   |   3 -
 yt_dlp/extractor/howcast.py                   |   2 -
 yt_dlp/extractor/howstuffworks.py             |   2 -
 yt_dlp/extractor/hrfensehen.py                |   3 -
 yt_dlp/extractor/hrti.py                      |   3 -
 yt_dlp/extractor/hse.py                       |   1 -
 yt_dlp/extractor/huajiao.py                   |   3 -
 yt_dlp/extractor/huffpost.py                  |   2 -
 yt_dlp/extractor/hungama.py                   |   3 -
 yt_dlp/extractor/huya.py                      |   3 -
 yt_dlp/extractor/hypem.py                     |   2 -
 yt_dlp/extractor/ichinanalive.py              |   3 -
 yt_dlp/extractor/ign.py                       |   2 -
 yt_dlp/extractor/iheart.py                    |   3 -
 yt_dlp/extractor/imdb.py                      |   2 -
 yt_dlp/extractor/imggaming.py                 |   3 -
 yt_dlp/extractor/imgur.py                     |   2 -
 yt_dlp/extractor/ina.py                       |   3 -
 yt_dlp/extractor/inc.py                       |   2 -
 yt_dlp/extractor/indavideo.py                 |   3 -
 yt_dlp/extractor/infoq.py                     |   4 -
 yt_dlp/extractor/instagram.py                 |   2 -
 yt_dlp/extractor/internazionale.py            |   3 -
 yt_dlp/extractor/internetvideoarchive.py      |   2 -
 yt_dlp/extractor/iprima.py                    |   3 -
 yt_dlp/extractor/iqiyi.py                     |   3 -
 yt_dlp/extractor/itprotv.py                   |   2 -
 yt_dlp/extractor/itv.py                       |   3 -
 yt_dlp/extractor/ivi.py                       |   3 -
 yt_dlp/extractor/ivideon.py                   |   4 -
 yt_dlp/extractor/iwara.py                     |   2 -
 yt_dlp/extractor/izlesene.py                  |   3 -
 yt_dlp/extractor/jable.py                     |   3 -
 yt_dlp/extractor/jamendo.py                   |   3 -
 yt_dlp/extractor/jeuxvideo.py                 |   5 -
 yt_dlp/extractor/joj.py                       |   3 -
 yt_dlp/extractor/jove.py                      |   3 -
 yt_dlp/extractor/jwplatform.py                |   3 -
 yt_dlp/extractor/kakao.py                     |   4 -
 yt_dlp/extractor/kaltura.py                   |   3 -
 yt_dlp/extractor/kanalplay.py                 |   4 -
 yt_dlp/extractor/karaoketv.py                 |   3 -
 yt_dlp/extractor/karrierevideos.py            |   3 -
 yt_dlp/extractor/keezmovies.py                |   2 -
 yt_dlp/extractor/kelbyone.py                  |   3 -
 yt_dlp/extractor/ketnet.py                    |   2 -
 yt_dlp/extractor/khanacademy.py               |   2 -
 yt_dlp/extractor/kickstarter.py               |   3 -
 yt_dlp/extractor/kinja.py                     |   3 -
 yt_dlp/extractor/kinopoisk.py                 |   3 -
 yt_dlp/extractor/konserthusetplay.py          |   3 -
 yt_dlp/extractor/koo.py                       |   2 -
 yt_dlp/extractor/krasview.py                  |   3 -
 yt_dlp/extractor/ku6.py                       |   2 -
 yt_dlp/extractor/kusi.py                      |   3 -
 yt_dlp/extractor/kuwo.py                      |   3 -
 yt_dlp/extractor/la7.py                       |   3 -
 yt_dlp/extractor/laola1tv.py                  |   3 -
 yt_dlp/extractor/lastfm.py                    |   3 -
 yt_dlp/extractor/lbry.py                      |   3 -
 yt_dlp/extractor/lci.py                       |   3 -
 yt_dlp/extractor/lcp.py                       |   3 -
 yt_dlp/extractor/lecture2go.py                |   3 -
 yt_dlp/extractor/lecturio.py                  |   3 -
 yt_dlp/extractor/leeco.py                     |   3 -
 yt_dlp/extractor/lego.py                      |   3 -
 yt_dlp/extractor/lemonde.py                   |   2 -
 yt_dlp/extractor/lenta.py                     |   3 -
 yt_dlp/extractor/libraryofcongress.py         |   3 -
 yt_dlp/extractor/libsyn.py                    |   4 -
 yt_dlp/extractor/lifenews.py                  |   3 -
 yt_dlp/extractor/limelight.py                 |   3 -
 yt_dlp/extractor/line.py                      |   4 -
 yt_dlp/extractor/linkedin.py                  |   3 -
 yt_dlp/extractor/linuxacademy.py              |   2 -
 yt_dlp/extractor/litv.py                      |   3 -
 yt_dlp/extractor/livejournal.py               |   3 -
 yt_dlp/extractor/livestream.py                |   2 -
 yt_dlp/extractor/lnkgo.py                     |   4 -
 yt_dlp/extractor/localnews8.py                |   4 -
 yt_dlp/extractor/lovehomeporn.py              |   3 -
 yt_dlp/extractor/lrt.py                       |   4 -
 yt_dlp/extractor/lynda.py                     |   2 -
 yt_dlp/extractor/m6.py                        |   3 -
 yt_dlp/extractor/magentamusik360.py           |   3 -
 yt_dlp/extractor/mailru.py                    |   3 -
 yt_dlp/extractor/mainstreaming.py             |   1 -
 yt_dlp/extractor/malltv.py                    |   3 -
 yt_dlp/extractor/mangomolo.py                 |   3 -
 yt_dlp/extractor/manoto.py                    |   3 -
 yt_dlp/extractor/manyvids.py                  |   3 -
 yt_dlp/extractor/maoritv.py                   |   3 -
 yt_dlp/extractor/markiza.py                   |   3 -
 yt_dlp/extractor/massengeschmacktv.py         |   2 -
 yt_dlp/extractor/matchtv.py                   |   3 -
 yt_dlp/extractor/mdr.py                       |   3 -
 yt_dlp/extractor/medaltv.py                   |   3 -
 yt_dlp/extractor/mediaite.py                  |   3 -
 yt_dlp/extractor/mediaklikk.py                |   3 -
 yt_dlp/extractor/medialaan.py                 |   2 -
 yt_dlp/extractor/mediaset.py                  |   3 -
 yt_dlp/extractor/mediasite.py                 |   3 -
 yt_dlp/extractor/medici.py                    |   3 -
 yt_dlp/extractor/megaphone.py                 |   3 -
 yt_dlp/extractor/megatvcom.py                 |   3 -
 yt_dlp/extractor/meipai.py                    |   3 -
 yt_dlp/extractor/melonvod.py                  |   3 -
 yt_dlp/extractor/meta.py                      |   3 -
 yt_dlp/extractor/metacafe.py                  |   2 -
 yt_dlp/extractor/metacritic.py                |   2 -
 yt_dlp/extractor/mgoon.py                     |   4 -
 yt_dlp/extractor/mgtv.py                      |   3 -
 yt_dlp/extractor/miaopai.py                   |   3 -
 yt_dlp/extractor/microsoftstream.py           |   3 -
 yt_dlp/extractor/microsoftvirtualacademy.py   |   2 -
 yt_dlp/extractor/mildom.py                    |   3 -
 yt_dlp/extractor/minds.py                     |   3 -
 yt_dlp/extractor/ministrygrid.py              |   2 -
 yt_dlp/extractor/minoto.py                    |   4 -
 yt_dlp/extractor/miomio.py                    |   3 -
 yt_dlp/extractor/mirrativ.py                  |   2 -
 yt_dlp/extractor/mit.py                       |   2 -
 yt_dlp/extractor/mitele.py                    |   3 -
 yt_dlp/extractor/mixch.py                     |   2 -
 yt_dlp/extractor/mixcloud.py                  |   2 -
 yt_dlp/extractor/mlb.py                       |   2 -
 yt_dlp/extractor/mlssoccer.py                 |   3 -
 yt_dlp/extractor/mnet.py                      |   3 -
 yt_dlp/extractor/moevideo.py                  |   4 -
 yt_dlp/extractor/mofosex.py                   |   2 -
 yt_dlp/extractor/mojvideo.py                  |   4 -
 yt_dlp/extractor/morningstar.py               |   4 -
 yt_dlp/extractor/motherless.py                |   2 -
 yt_dlp/extractor/motorsport.py                |   3 -
 yt_dlp/extractor/movieclips.py                |   3 -
 yt_dlp/extractor/moviepilot.py                |   3 -
 yt_dlp/extractor/moviezine.py                 |   4 -
 yt_dlp/extractor/movingimage.py               |   2 -
 yt_dlp/extractor/msn.py                       |   3 -
 yt_dlp/extractor/mtv.py                       |   3 -
 yt_dlp/extractor/muenchentv.py                |   3 -
 yt_dlp/extractor/murrtube.py                  |   3 -
 yt_dlp/extractor/musescore.py                 |   3 -
 yt_dlp/extractor/musicdex.py                  |   3 -
 yt_dlp/extractor/mwave.py                     |   2 -
 yt_dlp/extractor/mxplayer.py                  |   3 -
 yt_dlp/extractor/mychannels.py                |   4 -
 yt_dlp/extractor/myspace.py                   |   3 -
 yt_dlp/extractor/myspass.py                   |   3 -
 yt_dlp/extractor/myvi.py                      |   3 -
 yt_dlp/extractor/myvideoge.py                 |   3 -
 yt_dlp/extractor/myvidster.py                 |   2 -
 yt_dlp/extractor/n1.py                        |   3 -
 yt_dlp/extractor/nate.py                      |   3 -
 yt_dlp/extractor/nationalgeographic.py        |   2 -
 yt_dlp/extractor/naver.py                     |   3 -
 yt_dlp/extractor/nba.py                       |   2 -
 yt_dlp/extractor/nbc.py                       |   2 -
 yt_dlp/extractor/ndr.py                       |   3 -
 yt_dlp/extractor/ndtv.py                      |   3 -
 yt_dlp/extractor/nebula.py                    |   3 -
 yt_dlp/extractor/nerdcubed.py                 |   3 -
 yt_dlp/extractor/neteasemusic.py              |   3 -
 yt_dlp/extractor/netzkino.py                  |   4 -
 yt_dlp/extractor/newgrounds.py                |   3 -
 yt_dlp/extractor/newstube.py                  |   3 -
 yt_dlp/extractor/newsy.py                     |   3 -
 yt_dlp/extractor/nextmedia.py                 |   3 -
 yt_dlp/extractor/nexx.py                      |   3 -
 yt_dlp/extractor/nfb.py                       |   3 -
 yt_dlp/extractor/nfhsnetwork.py               |   3 -
 yt_dlp/extractor/nfl.py                       |   3 -
 yt_dlp/extractor/nhk.py                       |   2 -
 yt_dlp/extractor/nhl.py                       |   3 -
 yt_dlp/extractor/nick.py                      |   4 -
 yt_dlp/extractor/niconico.py                  |   3 -
 yt_dlp/extractor/ninecninemedia.py            |   3 -
 yt_dlp/extractor/ninegag.py                   |   2 -
 yt_dlp/extractor/ninenow.py                   |   3 -
 yt_dlp/extractor/nintendo.py                  |   3 -
 yt_dlp/extractor/nitter.py                    |   3 -
 yt_dlp/extractor/njpwworld.py                 |   3 -
 yt_dlp/extractor/nobelprize.py                |   3 -
 yt_dlp/extractor/noco.py                      |   3 -
 yt_dlp/extractor/nonktube.py                  |   2 -
 yt_dlp/extractor/noodlemagazine.py            |   3 -
 yt_dlp/extractor/noovo.py                     |   3 -
 yt_dlp/extractor/normalboots.py               |   3 -
 yt_dlp/extractor/nosvideo.py                  |   3 -
 yt_dlp/extractor/nova.py                      |   3 -
 yt_dlp/extractor/novaplay.py                  |   1 -
 yt_dlp/extractor/nowness.py                   |   3 -
 yt_dlp/extractor/noz.py                       |   3 -
 yt_dlp/extractor/npo.py                       |   2 -
 yt_dlp/extractor/npr.py                       |   2 -
 yt_dlp/extractor/nrk.py                       |   3 -
 yt_dlp/extractor/nrl.py                       |   3 -
 yt_dlp/extractor/ntvcojp.py                   |   3 -
 yt_dlp/extractor/ntvde.py                     |   3 -
 yt_dlp/extractor/ntvru.py                     |   3 -
 yt_dlp/extractor/nuevo.py                     |   3 -
 yt_dlp/extractor/nuvid.py                     |   2 -
 yt_dlp/extractor/nytimes.py                   |   3 -
 yt_dlp/extractor/nzherald.py                  |   3 -
 yt_dlp/extractor/nzz.py                       |   3 -
 yt_dlp/extractor/odatv.py                     |   3 -
 yt_dlp/extractor/odnoklassniki.py             |   3 -
 yt_dlp/extractor/oktoberfesttv.py             |   3 -
 yt_dlp/extractor/olympics.py                  |   3 -
 yt_dlp/extractor/on24.py                      |   3 -
 yt_dlp/extractor/once.py                      |   3 -
 yt_dlp/extractor/ondemandkorea.py             |   3 -
 yt_dlp/extractor/onefootball.py               |   3 -
 yt_dlp/extractor/onet.py                      |   3 -
 yt_dlp/extractor/onionstudios.py              |   3 -
 yt_dlp/extractor/ooyala.py                    |   2 -
 yt_dlp/extractor/opencast.py                  |   3 -
 yt_dlp/extractor/openload.py                  |  11 +-
 yt_dlp/extractor/openrec.py                   |   3 -
 yt_dlp/extractor/ora.py                       |   3 -
 yt_dlp/extractor/orf.py                       |   3 -
 yt_dlp/extractor/outsidetv.py                 |   3 -
 yt_dlp/extractor/packtpub.py                  |   2 -
 yt_dlp/extractor/palcomp3.py                  |   4 -
 yt_dlp/extractor/pandoratv.py                 |   4 -
 yt_dlp/extractor/paramountplus.py             |   1 -
 yt_dlp/extractor/parliamentliveuk.py          |   3 -
 yt_dlp/extractor/parlview.py                  |   3 -
 yt_dlp/extractor/patreon.py                   |   3 -
 yt_dlp/extractor/pbs.py                       |   3 -
 yt_dlp/extractor/pearvideo.py                 |   3 -
 yt_dlp/extractor/peekvids.py                  |   3 -
 yt_dlp/extractor/peertube.py                  |   3 -
 yt_dlp/extractor/peertv.py                    |   3 -
 yt_dlp/extractor/peloton.py                   |   3 -
 yt_dlp/extractor/people.py                    |   3 -
 yt_dlp/extractor/performgroup.py              |   4 -
 yt_dlp/extractor/periscope.py                 |   3 -
 yt_dlp/extractor/philharmoniedeparis.py       |   3 -
 yt_dlp/extractor/phoenix.py                   |   3 -
 yt_dlp/extractor/photobucket.py               |   2 -
 yt_dlp/extractor/piapro.py                    |   3 -
 yt_dlp/extractor/picarto.py                   |   3 -
 yt_dlp/extractor/piksel.py                    |   3 -
 yt_dlp/extractor/pinkbike.py                  |   3 -
 yt_dlp/extractor/pinterest.py                 |   3 -
 yt_dlp/extractor/pixivsketch.py               |   3 -
 yt_dlp/extractor/pladform.py                  |   3 -
 yt_dlp/extractor/planetmarathi.py             |   3 -
 yt_dlp/extractor/platzi.py                    |   3 -
 yt_dlp/extractor/playfm.py                    |   4 -
 yt_dlp/extractor/playplustv.py                |   3 -
 yt_dlp/extractor/plays.py                     |   3 -
 yt_dlp/extractor/playstuff.py                 |   2 -
 yt_dlp/extractor/playtvak.py                  |   3 -
 yt_dlp/extractor/playvid.py                   |   2 -
 yt_dlp/extractor/playwire.py                  |   3 -
 yt_dlp/extractor/pluralsight.py               |   2 -
 yt_dlp/extractor/plutotv.py                   |   3 -
 yt_dlp/extractor/podomatic.py                 |   2 -
 yt_dlp/extractor/pokemon.py                   |   3 -
 yt_dlp/extractor/pokergo.py                   |   3 -
 yt_dlp/extractor/polsatgo.py                  |   3 -
 yt_dlp/extractor/polskieradio.py              |   3 -
 yt_dlp/extractor/popcorntimes.py              |   4 -
 yt_dlp/extractor/popcorntv.py                 |   3 -
 yt_dlp/extractor/porn91.py                    |   3 -
 yt_dlp/extractor/porncom.py                   |   2 -
 yt_dlp/extractor/pornez.py                    |   2 -
 yt_dlp/extractor/pornflip.py                  |   3 -
 yt_dlp/extractor/pornhd.py                    |   3 -
 yt_dlp/extractor/pornhub.py                   |   3 -
 yt_dlp/extractor/pornotube.py                 |   2 -
 yt_dlp/extractor/pornovoisines.py             |   4 -
 yt_dlp/extractor/pornoxo.py                   |   3 -
 yt_dlp/extractor/presstv.py                   |   4 -
 yt_dlp/extractor/projectveritas.py            |   3 -
 yt_dlp/extractor/prosiebensat1.py             |   3 -
 yt_dlp/extractor/prx.py                       |   3 -
 yt_dlp/extractor/puhutv.py                    |   3 -
 yt_dlp/extractor/puls4.py                     |   3 -
 yt_dlp/extractor/pyvideo.py                   |   2 -
 yt_dlp/extractor/qqmusic.py                   |   3 -
 yt_dlp/extractor/r7.py                        |   3 -
 yt_dlp/extractor/radiko.py                    |   3 -
 yt_dlp/extractor/radiobremen.py               |   4 -
 yt_dlp/extractor/radiocanada.py               |   4 -
 yt_dlp/extractor/radiode.py                   |   2 -
 yt_dlp/extractor/radiofrance.py               |   3 -
 yt_dlp/extractor/radiojavan.py                |   2 -
 yt_dlp/extractor/radiokapital.py              |   2 -
 yt_dlp/extractor/radiozet.py                  |   1 -
 yt_dlp/extractor/rai.py                       |   3 -
 yt_dlp/extractor/raywenderlich.py             |   2 -
 yt_dlp/extractor/rbmaradio.py                 |   3 -
 yt_dlp/extractor/rcs.py                       |   3 -
 yt_dlp/extractor/rcti.py                      |   3 -
 yt_dlp/extractor/rds.py                       |   3 -
 yt_dlp/extractor/redbulltv.py                 |   4 -
 yt_dlp/extractor/redgifs.py                   |   1 -
 yt_dlp/extractor/redtube.py                   |   2 -
 yt_dlp/extractor/regiotv.py                   |   3 -
 yt_dlp/extractor/rentv.py                     |   3 -
 yt_dlp/extractor/restudy.py                   |   3 -
 yt_dlp/extractor/reuters.py                   |   3 -
 yt_dlp/extractor/reverbnation.py              |   2 -
 yt_dlp/extractor/rice.py                      |   3 -
 yt_dlp/extractor/rmcdecouverte.py             |   4 -
 yt_dlp/extractor/rockstargames.py             |   3 -
 yt_dlp/extractor/rokfin.py                    |   1 -
 yt_dlp/extractor/roosterteeth.py              |   1 -
 yt_dlp/extractor/rottentomatoes.py            |   2 -
 yt_dlp/extractor/rozhlas.py                   |   3 -
 yt_dlp/extractor/rtbf.py                      |   3 -
 yt_dlp/extractor/rte.py                       |   3 -
 yt_dlp/extractor/rtl2.py                      |   3 -
 yt_dlp/extractor/rtlnl.py                     |   3 -
 yt_dlp/extractor/rtnews.py                    |   3 -
 yt_dlp/extractor/rtp.py                       |   3 -
 yt_dlp/extractor/rtrfm.py                     |   2 -
 yt_dlp/extractor/rts.py                       |   3 -
 yt_dlp/extractor/rtve.py                      |   3 -
 yt_dlp/extractor/rtvnh.py                     |   3 -
 yt_dlp/extractor/rtvs.py                      |   3 -
 yt_dlp/extractor/ruhd.py                      |   3 -
 yt_dlp/extractor/rule34video.py               |   2 -
 yt_dlp/extractor/rumble.py                    |   3 -
 yt_dlp/extractor/rutube.py                    |   3 -
 yt_dlp/extractor/rutv.py                      |   3 -
 yt_dlp/extractor/ruutu.py                     |   3 -
 yt_dlp/extractor/ruv.py                       |   3 -
 yt_dlp/extractor/safari.py                    |   3 -
 yt_dlp/extractor/saitosan.py                  |   4 -
 yt_dlp/extractor/samplefocus.py               |   3 -
 yt_dlp/extractor/sapo.py                      |   3 -
 yt_dlp/extractor/savefrom.py                  |   3 -
 yt_dlp/extractor/sbs.py                       |   3 -
 yt_dlp/extractor/screencast.py                |   3 -
 yt_dlp/extractor/screencastomatic.py          |   3 -
 yt_dlp/extractor/scrippsnetworks.py           |   3 -
 yt_dlp/extractor/scte.py                      |   2 -
 yt_dlp/extractor/seeker.py                    |   3 -
 yt_dlp/extractor/senategov.py                 |   3 -
 yt_dlp/extractor/sendtonews.py                |   3 -
 yt_dlp/extractor/servus.py                    |   3 -
 yt_dlp/extractor/sevenplus.py                 |   3 -
 yt_dlp/extractor/sexu.py                      |   2 -
 yt_dlp/extractor/seznamzpravy.py              |   3 -
 yt_dlp/extractor/shahid.py                    |   3 -
 yt_dlp/extractor/shared.py                    |   2 -
 yt_dlp/extractor/shemaroome.py                |   3 -
 yt_dlp/extractor/showroomlive.py              |   3 -
 yt_dlp/extractor/simplecast.py                |   3 -
 yt_dlp/extractor/sina.py                      |   4 -
 yt_dlp/extractor/sixplay.py                   |   4 -
 yt_dlp/extractor/skeb.py                      |   3 -
 yt_dlp/extractor/sky.py                       |   3 -
 yt_dlp/extractor/skyit.py                     |   3 -
 yt_dlp/extractor/skylinewebcams.py            |   3 -
 yt_dlp/extractor/skynewsarabia.py             |   3 -
 yt_dlp/extractor/skynewsau.py                 |   3 -
 yt_dlp/extractor/slideshare.py                |   2 -
 yt_dlp/extractor/slideslive.py                |   3 -
 yt_dlp/extractor/slutload.py                  |   2 -
 yt_dlp/extractor/snotr.py                     |   4 -
 yt_dlp/extractor/sohu.py                      |   3 -
 yt_dlp/extractor/sonyliv.py                   |   3 -
 yt_dlp/extractor/soundcloud.py                |   3 -
 yt_dlp/extractor/soundgasm.py                 |   3 -
 yt_dlp/extractor/southpark.py                 |   3 -
 yt_dlp/extractor/sovietscloset.py             |   3 -
 yt_dlp/extractor/spankbang.py                 |   2 -
 yt_dlp/extractor/spankwire.py                 |   2 -
 yt_dlp/extractor/spiegel.py                   |   3 -
 yt_dlp/extractor/spiegeltv.py                 |   2 -
 yt_dlp/extractor/spike.py                     |   2 -
 yt_dlp/extractor/sport5.py                    |   4 -
 yt_dlp/extractor/sportbox.py                  |   3 -
 yt_dlp/extractor/sportdeutschland.py          |   3 -
 yt_dlp/extractor/spotify.py                   |   3 -
 yt_dlp/extractor/spreaker.py                  |   3 -
 yt_dlp/extractor/springboardplatform.py       |   3 -
 yt_dlp/extractor/sprout.py                    |   3 -
 yt_dlp/extractor/srgssr.py                    |   4 -
 yt_dlp/extractor/srmediathek.py               |   3 -
 yt_dlp/extractor/stanfordoc.py                |   2 -
 yt_dlp/extractor/startv.py                    |   3 -
 yt_dlp/extractor/steam.py                     |   2 -
 yt_dlp/extractor/stitcher.py                  |   2 -
 yt_dlp/extractor/storyfire.py                 |   3 -
 yt_dlp/extractor/streamable.py                |   3 -
 yt_dlp/extractor/streamanity.py               |   3 -
 yt_dlp/extractor/streamcloud.py               |   3 -
 yt_dlp/extractor/streamcz.py                  |   1 -
 yt_dlp/extractor/streamff.py                  |   1 -
 yt_dlp/extractor/streetvoice.py               |   3 -
 yt_dlp/extractor/stretchinternet.py           |   2 -
 yt_dlp/extractor/stripchat.py                 |   3 -
 yt_dlp/extractor/stv.py                       |   4 -
 yt_dlp/extractor/sunporno.py                  |   2 -
 yt_dlp/extractor/sverigesradio.py             |   3 -
 yt_dlp/extractor/svt.py                       |   3 -
 yt_dlp/extractor/swrmediathek.py              |   3 -
 yt_dlp/extractor/syfy.py                      |   2 -
 yt_dlp/extractor/sztvhu.py                    |   3 -
 yt_dlp/extractor/tagesschau.py                |   3 -
 yt_dlp/extractor/tass.py                      |   3 -
 yt_dlp/extractor/tastytrade.py                |   2 -
 yt_dlp/extractor/tbs.py                       |   3 -
 yt_dlp/extractor/tdslifeway.py                |   2 -
 yt_dlp/extractor/teachable.py                 |   2 -
 yt_dlp/extractor/teachertube.py               |   3 -
 yt_dlp/extractor/teachingchannel.py           |   2 -
 yt_dlp/extractor/teamcoco.py                  |   3 -
 yt_dlp/extractor/teamtreehouse.py             |   3 -
 yt_dlp/extractor/techtalks.py                 |   2 -
 yt_dlp/extractor/tele13.py                    |   3 -
 yt_dlp/extractor/tele5.py                     |   3 -
 yt_dlp/extractor/telebruxelles.py             |   3 -
 yt_dlp/extractor/telecinco.py                 |   3 -
 yt_dlp/extractor/telegraaf.py                 |   3 -
 yt_dlp/extractor/telemb.py                    |   3 -
 yt_dlp/extractor/telemundo.py                 |   3 -
 yt_dlp/extractor/telequebec.py                |   3 -
 yt_dlp/extractor/teletask.py                  |   2 -
 yt_dlp/extractor/telewebion.py                |   3 -
 yt_dlp/extractor/tennistv.py                  |   3 -
 yt_dlp/extractor/tenplay.py                   |   3 -
 yt_dlp/extractor/testurl.py                   |   2 -
 yt_dlp/extractor/tf1.py                       |   3 -
 yt_dlp/extractor/tfo.py                       |   3 -
 yt_dlp/extractor/theintercept.py              |   3 -
 yt_dlp/extractor/theplatform.py               |   3 -
 yt_dlp/extractor/thestar.py                   |   3 -
 yt_dlp/extractor/thesun.py                    |   2 -
 yt_dlp/extractor/theta.py                     |   3 -
 yt_dlp/extractor/theweatherchannel.py         |   3 -
 yt_dlp/extractor/thisamericanlife.py          |   2 -
 yt_dlp/extractor/thisav.py                    |   4 -
 yt_dlp/extractor/thisoldhouse.py              |   3 -
 yt_dlp/extractor/threeqsdn.py                 |   2 -
 yt_dlp/extractor/threespeak.py                |   3 -
 yt_dlp/extractor/tiktok.py                    |   3 -
 yt_dlp/extractor/tinypic.py                   |   2 -
 yt_dlp/extractor/tmz.py                       |   3 -
 yt_dlp/extractor/tnaflix.py                   |   2 -
 yt_dlp/extractor/toggle.py                    |   3 -
 yt_dlp/extractor/tokentube.py                 |   3 -
 yt_dlp/extractor/tonline.py                   |   3 -
 yt_dlp/extractor/toongoggles.py               |   4 -
 yt_dlp/extractor/toutv.py                     |   3 -
 yt_dlp/extractor/toypics.py                   |   3 -
 yt_dlp/extractor/traileraddict.py             |   2 -
 yt_dlp/extractor/trilulilu.py                 |   3 -
 yt_dlp/extractor/trovo.py                     |   3 -
 yt_dlp/extractor/trueid.py                    |   3 -
 yt_dlp/extractor/trunews.py                   |   2 -
 yt_dlp/extractor/trutv.py                     |   4 -
 yt_dlp/extractor/tube8.py                     |   2 -
 yt_dlp/extractor/tubitv.py                    |   3 -
 yt_dlp/extractor/tudou.py                     |   4 -
 yt_dlp/extractor/tumblr.py                    |   4 -
 yt_dlp/extractor/tunein.py                    |   3 -
 yt_dlp/extractor/tunepk.py                    |   2 -
 yt_dlp/extractor/turbo.py                     |   3 -
 yt_dlp/extractor/turner.py                    |   3 -
 yt_dlp/extractor/tv2.py                       |   3 -
 yt_dlp/extractor/tv2dk.py                     |   3 -
 yt_dlp/extractor/tv2hu.py                     |   2 -
 yt_dlp/extractor/tv4.py                       |   3 -
 yt_dlp/extractor/tv5mondeplus.py              |   3 -
 yt_dlp/extractor/tv5unis.py                   |   4 -
 yt_dlp/extractor/tva.py                       |   3 -
 yt_dlp/extractor/tvanouvelles.py              |   3 -
 yt_dlp/extractor/tvc.py                       |   3 -
 yt_dlp/extractor/tver.py                      |   3 -
 yt_dlp/extractor/tvigle.py                    |   4 -
 yt_dlp/extractor/tvland.py                    |   3 -
 yt_dlp/extractor/tvn24.py                     |   3 -
 yt_dlp/extractor/tvnet.py                     |   3 -
 yt_dlp/extractor/tvnoe.py                     |   3 -
 yt_dlp/extractor/tvnow.py                     |   3 -
 yt_dlp/extractor/tvopengr.py                  |   3 -
 yt_dlp/extractor/tvp.py                       |   3 -
 yt_dlp/extractor/tvplay.py                    |   3 -
 yt_dlp/extractor/tvplayer.py                  |   3 -
 yt_dlp/extractor/tweakers.py                  |   2 -
 yt_dlp/extractor/twentyfourvideo.py           |   4 -
 yt_dlp/extractor/twentymin.py                 |   3 -
 yt_dlp/extractor/twentythreevideo.py          |   3 -
 yt_dlp/extractor/twitcasting.py               |   3 -
 yt_dlp/extractor/twitch.py                    |   3 -
 yt_dlp/extractor/twitter.py                   |   3 -
 yt_dlp/extractor/udemy.py                     |   2 -
 yt_dlp/extractor/udn.py                       |   3 -
 yt_dlp/extractor/ufctv.py                     |   3 -
 yt_dlp/extractor/ukcolumn.py                  |   2 -
 yt_dlp/extractor/uktvplay.py                  |   3 -
 yt_dlp/extractor/umg.py                       |   3 -
 yt_dlp/extractor/unistra.py                   |   2 -
 yt_dlp/extractor/unity.py                     |   2 -
 yt_dlp/extractor/uol.py                       |   3 -
 yt_dlp/extractor/uplynk.py                    |   3 -
 yt_dlp/extractor/urort.py                     |   3 -
 yt_dlp/extractor/urplay.py                    |   3 -
 yt_dlp/extractor/usanetwork.py                |   3 -
 yt_dlp/extractor/usatoday.py                  |   3 -
 yt_dlp/extractor/ustream.py                   |   2 -
 yt_dlp/extractor/ustudio.py                   |   3 -
 yt_dlp/extractor/utreon.py                    |   3 -
 yt_dlp/extractor/varzesh3.py                  |   3 -
 yt_dlp/extractor/vbox7.py                     |   3 -
 yt_dlp/extractor/veehd.py                     |   2 -
 yt_dlp/extractor/veo.py                       |   3 -
 yt_dlp/extractor/veoh.py                      |   2 -
 yt_dlp/extractor/vesti.py                     |   3 -
 yt_dlp/extractor/vevo.py                      |   2 -
 yt_dlp/extractor/vgtv.py                      |   3 -
 yt_dlp/extractor/vh1.py                       |   3 -
 yt_dlp/extractor/vice.py                      |   3 -
 yt_dlp/extractor/vidbit.py                    |   2 -
 yt_dlp/extractor/viddler.py                   |   3 -
 yt_dlp/extractor/videa.py                     |   3 -
 yt_dlp/extractor/videocampus_sachsen.py       |   1 -
 yt_dlp/extractor/videodetective.py            |   2 -
 yt_dlp/extractor/videofyme.py                 |   2 -
 yt_dlp/extractor/videomore.py                 |   3 -
 yt_dlp/extractor/videopress.py                |   3 -
 yt_dlp/extractor/vidio.py                     |   4 -
 yt_dlp/extractor/vidlii.py                    |   3 -
 yt_dlp/extractor/vidzi.py                     |   3 -
 yt_dlp/extractor/vier.py                      |   3 -
 yt_dlp/extractor/viewlift.py                  |   2 -
 yt_dlp/extractor/viidea.py                    |   2 -
 yt_dlp/extractor/viki.py                      |   2 -
 yt_dlp/extractor/vimeo.py                     |   3 -
 yt_dlp/extractor/vimm.py                      |   1 -
 yt_dlp/extractor/vimple.py                    |   2 -
 yt_dlp/extractor/vine.py                      |   4 -
 yt_dlp/extractor/viqeo.py                     |   3 -
 yt_dlp/extractor/viu.py                       |   3 -
 yt_dlp/extractor/vk.py                        |   3 -
 yt_dlp/extractor/vlive.py                     |   3 -
 yt_dlp/extractor/vodlocker.py                 |   3 -
 yt_dlp/extractor/vodpl.py                     |   3 -
 yt_dlp/extractor/vodplatform.py               |   3 -
 yt_dlp/extractor/voicerepublic.py             |   2 -
 yt_dlp/extractor/voicy.py                     |   3 -
 yt_dlp/extractor/voot.py                      |   3 -
 yt_dlp/extractor/voxmedia.py                  |   3 -
 yt_dlp/extractor/vrak.py                      |   3 -
 yt_dlp/extractor/vrt.py                       |   4 -
 yt_dlp/extractor/vrv.py                       |   3 -
 yt_dlp/extractor/vshare.py                    |   3 -
 yt_dlp/extractor/vtm.py                       |   3 -
 yt_dlp/extractor/vuclip.py                    |   2 -
 yt_dlp/extractor/vupload.py                   |   3 -
 yt_dlp/extractor/vvvvid.py                    |   3 -
 yt_dlp/extractor/vyborymos.py                 |   3 -
 yt_dlp/extractor/vzaar.py                     |   3 -
 yt_dlp/extractor/wakanim.py                   |   3 -
 yt_dlp/extractor/walla.py                     |   3 -
 yt_dlp/extractor/wasdtv.py                    |   3 -
 yt_dlp/extractor/washingtonpost.py            |   3 -
 yt_dlp/extractor/wat.py                       |   3 -
 yt_dlp/extractor/watchbox.py                  |   4 -
 yt_dlp/extractor/watchindianporn.py           |   3 -
 yt_dlp/extractor/wdr.py                       |   3 -
 yt_dlp/extractor/webcaster.py                 |   3 -
 yt_dlp/extractor/webofstories.py              |   3 -
 yt_dlp/extractor/weibo.py                     |   3 -
 yt_dlp/extractor/weiqitv.py                   |   3 -
 yt_dlp/extractor/whowatch.py                  |   3 -
 yt_dlp/extractor/willow.py                    |   1 -
 yt_dlp/extractor/wimtv.py                     |   3 -
 yt_dlp/extractor/wistia.py                    |   2 -
 yt_dlp/extractor/worldstarhiphop.py           |   2 -
 yt_dlp/extractor/wppilot.py                   |   2 -
 yt_dlp/extractor/wsj.py                       |   3 -
 yt_dlp/extractor/wwe.py                       |   2 -
 yt_dlp/extractor/xbef.py                      |   2 -
 yt_dlp/extractor/xboxclips.py                 |   3 -
 yt_dlp/extractor/xfileshare.py                |   3 -
 yt_dlp/extractor/xhamster.py                  |   2 -
 yt_dlp/extractor/xiami.py                     |   3 -
 yt_dlp/extractor/ximalaya.py                  |   4 -
 yt_dlp/extractor/xinpianchang.py              |   3 -
 yt_dlp/extractor/xminus.py                    |   3 -
 yt_dlp/extractor/xnxx.py                      |   3 -
 yt_dlp/extractor/xstream.py                   |   3 -
 yt_dlp/extractor/xtube.py                     |   2 -
 yt_dlp/extractor/xuite.py                     |   3 -
 yt_dlp/extractor/xvideos.py                   |   2 -
 yt_dlp/extractor/xxxymovies.py                |   3 -
 yt_dlp/extractor/yahoo.py                     |   3 -
 yt_dlp/extractor/yandexdisk.py                |   3 -
 yt_dlp/extractor/yandexmusic.py               |   3 -
 yt_dlp/extractor/yandexvideo.py               |   3 -
 yt_dlp/extractor/yapfiles.py                  |   3 -
 yt_dlp/extractor/yesjapan.py                  |   3 -
 yt_dlp/extractor/yinyuetai.py                 |   3 -
 yt_dlp/extractor/ynet.py                      |   3 -
 yt_dlp/extractor/youjizz.py                   |   3 -
 yt_dlp/extractor/youku.py                     |   3 -
 yt_dlp/extractor/younow.py                    |   3 -
 yt_dlp/extractor/youporn.py                   |   2 -
 yt_dlp/extractor/yourporn.py                  |   2 -
 yt_dlp/extractor/yourupload.py                |   3 -
 yt_dlp/extractor/youtube.py                   |  62 +++++------
 yt_dlp/extractor/zapiks.py                    |   3 -
 yt_dlp/extractor/zattoo.py                    |   3 -
 yt_dlp/extractor/zdf.py                       |   3 -
 yt_dlp/extractor/zee5.py                      |  11 +-
 yt_dlp/extractor/zhihu.py                     |   3 -
 yt_dlp/extractor/zingmp3.py                   |   3 -
 yt_dlp/extractor/zoom.py                      |   4 -
 yt_dlp/extractor/zype.py                      |   3 -
 yt_dlp/jsinterp.py                            |  16 +--
 yt_dlp/options.py                             |  10 +-
 yt_dlp/postprocessor/common.py                |   4 +-
 yt_dlp/postprocessor/embedthumbnail.py        |   5 +-
 yt_dlp/postprocessor/exec.py                  |   2 -
 yt_dlp/postprocessor/ffmpeg.py                |  37 +++----
 .../postprocessor/movefilesafterdownload.py   |   3 +-
 yt_dlp/postprocessor/sponskrub.py             |   1 -
 yt_dlp/postprocessor/xattrpp.py               |   2 -
 yt_dlp/socks.py                               |  29 +++--
 yt_dlp/update.py                              |  20 ++--
 yt_dlp/utils.py                               | 103 +++++++++---------
 yt_dlp/webvtt.py                              |  11 +-
 ytdlp_plugins/extractor/sample.py             |   2 -
 ytdlp_plugins/postprocessor/sample.py         |   2 -
 1009 files changed, 375 insertions(+), 3224 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ea1893d15a..eff6becacb 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -178,7 +178,6 @@ ## Adding support for a new site
 1. Start with this simple template and save it to `yt_dlp/extractor/yourextractor.py`:
 
     ```python
-    # coding: utf-8
     from .common import InfoExtractor
     
     
diff --git a/devscripts/bash-completion.py b/devscripts/bash-completion.py
index 46b4b2ff55..23a9a5781d 100755
--- a/devscripts/bash-completion.py
+++ b/devscripts/bash-completion.py
@@ -1,11 +1,9 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 import os
 from os.path import dirname as dirn
 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
 
 BASH_COMPLETION_FILE = "completions/bash/yt-dlp"
diff --git a/devscripts/check-porn.py b/devscripts/check-porn.py
index 50f6bebc64..6188f68ec7 100644
--- a/devscripts/check-porn.py
+++ b/devscripts/check-porn.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 """
 This script employs a VERY basic heuristic ('porn' in webpage.lower()) to check
 if we are not 'age_limit' tagging some porn site
@@ -29,7 +27,7 @@
         try:
             webpage = compat_urllib_request.urlopen(test['url'], timeout=10).read()
         except Exception:
-            print('\nFail: {0}'.format(test['name']))
+            print('\nFail: {}'.format(test['name']))
             continue
 
         webpage = webpage.decode('utf8', 'replace')
@@ -39,7 +37,7 @@
     elif METHOD == 'LIST':
         domain = compat_urllib_parse_urlparse(test['url']).netloc
         if not domain:
-            print('\nFail: {0}'.format(test['name']))
+            print('\nFail: {}'.format(test['name']))
             continue
         domain = '.'.join(domain.split('.')[-2:])
 
@@ -47,11 +45,11 @@
 
     if RESULT and ('info_dict' not in test or 'age_limit' not in test['info_dict']
                    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']
                          and test['info_dict']['age_limit'] == 18):
-        print('\nPotential false negative: {0}'.format(test['name']))
+        print('\nPotential false negative: {}'.format(test['name']))
 
     else:
         sys.stdout.write('.')
diff --git a/devscripts/fish-completion.py b/devscripts/fish-completion.py
index fb45e02805..d958a5d6bc 100755
--- a/devscripts/fish-completion.py
+++ b/devscripts/fish-completion.py
@@ -1,12 +1,10 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 import optparse
 import os
 from os.path import dirname as dirn
 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
 from yt_dlp.utils import shell_quote
 
diff --git a/devscripts/generate_aes_testdata.py b/devscripts/generate_aes_testdata.py
index 0979eee5b9..308c74a204 100644
--- a/devscripts/generate_aes_testdata.py
+++ b/devscripts/generate_aes_testdata.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 import codecs
 import subprocess
 
diff --git a/devscripts/lazy_load_template.py b/devscripts/lazy_load_template.py
index da89e070de..0058915ae8 100644
--- a/devscripts/lazy_load_template.py
+++ b/devscripts/lazy_load_template.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 import re
 
 from ..utils import bug_reports_message, write_string
diff --git a/devscripts/make_contributing.py b/devscripts/make_contributing.py
index 6b1b8219c4..2562c4fd75 100755
--- a/devscripts/make_contributing.py
+++ b/devscripts/make_contributing.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import io
 import optparse
 import re
 
@@ -16,7 +13,7 @@ def main():
 
     infile, outfile = args
 
-    with io.open(infile, encoding='utf-8') as inf:
+    with open(infile, encoding='utf-8') as inf:
         readme = inf.read()
 
     bug_text = re.search(
@@ -26,7 +23,7 @@ def main():
 
     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)
 
 
diff --git a/devscripts/make_issue_template.py b/devscripts/make_issue_template.py
index 9020592317..878b94166a 100644
--- a/devscripts/make_issue_template.py
+++ b/devscripts/make_issue_template.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 import io
 import optparse
 
@@ -13,7 +11,7 @@ def main():
 
     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()
 
     # 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__']}
 
-    with io.open(outfile, 'w', encoding='utf-8') as outf:
+    with open(outfile, 'w', encoding='utf-8') as outf:
         outf.write(out)
 
+
 if __name__ == '__main__':
     main()
diff --git a/devscripts/make_lazy_extractors.py b/devscripts/make_lazy_extractors.py
index b58fb85e35..24e8cfa5b8 100644
--- a/devscripts/make_lazy_extractors.py
+++ b/devscripts/make_lazy_extractors.py
@@ -1,13 +1,10 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals, print_function
-
 from inspect import getsource
-import io
 import os
 from os.path import dirname as dirn
 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'
 if os.path.exists(lazy_extractors_filename):
@@ -25,7 +22,7 @@
 if os.path.exists(plugins_blocked_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()
 
 CLASS_PROPERTIES = ['ie_key', 'working', '_match_valid_url', 'suitable', '_match_id', 'get_temp_id']
@@ -72,7 +69,7 @@ def build_lazy_ie(ie, name):
 ordered_cls = []
 while classes:
     for c in classes[:]:
-        bases = set(c.__bases__) - set((object, InfoExtractor, SearchInfoExtractor))
+        bases = set(c.__bases__) - {object, InfoExtractor, SearchInfoExtractor}
         stop = False
         for b in bases:
             if b not in classes and b not in ordered_cls:
@@ -97,9 +94,9 @@ def build_lazy_ie(ie, name):
         names.append(name)
 
 module_contents.append(
-    '\n_ALL_CLASSES = [{0}]'.format(', '.join(names)))
+    '\n_ALL_CLASSES = [{}]'.format(', '.join(names)))
 
 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)
diff --git a/devscripts/make_readme.py b/devscripts/make_readme.py
index 3f56af7447..5d85bcc63a 100755
--- a/devscripts/make_readme.py
+++ b/devscripts/make_readme.py
@@ -2,10 +2,6 @@
 
 # yt-dlp --help | make_readme.py
 # This must be run in a console of correct width
-
-from __future__ import unicode_literals
-
-import io
 import sys
 import re
 
@@ -15,7 +11,7 @@
 if isinstance(helptext, bytes):
     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()
 
 header = oldreadme[:oldreadme.index('## General Options:')]
@@ -25,7 +21,7 @@
 options = re.sub(r'(?m)^  (\w.+)$', r'## \1', options)
 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(options)
     f.write(footer)
diff --git a/devscripts/make_supportedsites.py b/devscripts/make_supportedsites.py
index 729f60a0e7..26d25704ea 100644
--- a/devscripts/make_supportedsites.py
+++ b/devscripts/make_supportedsites.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import io
 import optparse
 import os
 import sys
@@ -23,11 +20,11 @@ def main():
 
     def gen_ies_md(ies):
         for ie in ies:
-            ie_md = '**{0}**'.format(ie.IE_NAME)
+            ie_md = f'**{ie.IE_NAME}**'
             if ie.IE_DESC is False:
                 continue
             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)
             if search_key is not None:
                 ie_md += f'; "{ie.SEARCH_KEY}:" prefix'
@@ -40,7 +37,7 @@ def gen_ies_md(ies):
         ' - ' + md + '\n'
         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)
 
 
diff --git a/devscripts/prepare_manpage.py b/devscripts/prepare_manpage.py
index 29c675f8ae..91e9ebcedc 100644
--- a/devscripts/prepare_manpage.py
+++ b/devscripts/prepare_manpage.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
-import io
 import optparse
 import os.path
 import re
@@ -32,14 +29,14 @@ def main():
 
     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 = filter_excluded_sections(readme)
     readme = move_sections(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)
 
 
diff --git a/devscripts/update-formulae.py b/devscripts/update-formulae.py
index 41bc1ac7a3..3a0bef52e5 100644
--- a/devscripts/update-formulae.py
+++ b/devscripts/update-formulae.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 import json
 import os
 import re
@@ -27,7 +25,7 @@
 sha256sum = tarball_file['digests']['sha256']
 url = tarball_file['url']
 
-with open(filename, 'r') as r:
+with open(filename) as r:
     formulae_text = r.read()
 
 formulae_text = re.sub(r'sha256 "[0-9a-f]*?"', 'sha256 "%s"' % sha256sum, formulae_text)
diff --git a/devscripts/update-version.py b/devscripts/update-version.py
index 0ee7bf2916..233cdaa76a 100644
--- a/devscripts/update-version.py
+++ b/devscripts/update-version.py
@@ -4,7 +4,7 @@
 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'))
 old_version = locals()['__version__']
 
diff --git a/devscripts/zsh-completion.py b/devscripts/zsh-completion.py
index 780df0de6c..677fe7373d 100755
--- a/devscripts/zsh-completion.py
+++ b/devscripts/zsh-completion.py
@@ -1,11 +1,9 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 import os
 from os.path import dirname as dirn
 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
 
 ZSH_COMPLETION_FILE = "completions/zsh/_yt-dlp"
diff --git a/pyinst.py b/pyinst.py
index e5934e04f0..1f72bd4be5 100644
--- a/pyinst.py
+++ b/pyinst.py
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
 import os
 import platform
 import sys
diff --git a/setup.py b/setup.py
index 503599c761..9eab7f1d7d 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
 import os.path
 import warnings
 import sys
diff --git a/test/helper.py b/test/helper.py
index 804e954a3b..d940e327cf 100644
--- a/test/helper.py
+++ b/test/helper.py
@@ -1,7 +1,4 @@
-from __future__ import unicode_literals
-
 import errno
-import io
 import hashlib
 import json
 import os.path
@@ -35,10 +32,10 @@ def get_params(override=None):
                                    'parameters.json')
     LOCAL_PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                          '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)
     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))
     if override:
         parameters.update(override)
@@ -63,7 +60,7 @@ def report_warning(message):
         _msg_header = '\033[0;33mWARNING:\033[0m'
     else:
         _msg_header = 'WARNING:'
-    output = '%s %s\n' % (_msg_header, message)
+    output = f'{_msg_header} {message}\n'
     if 'b' in getattr(sys.stderr, 'mode', ''):
         output = output.encode(preferredencoding())
     sys.stderr.write(output)
@@ -74,7 +71,7 @@ def __init__(self, override=None):
         # Different instances of the downloader can't share the same dictionary
         # some test set the "sublang" parameter, which would break the md5 checks.
         params = get_params(override=override)
-        super(FakeYDL, self).__init__(params, auto_init=False)
+        super().__init__(params, auto_init=False)
         self.result = []
 
     def to_screen(self, s, skip_eol=None):
@@ -99,8 +96,7 @@ def report_warning(self, message):
 
 def gettestcases(include_onlymatching=False):
     for ie in yt_dlp.extractor.gen_extractors():
-        for tc in ie.get_testcases(include_onlymatching):
-            yield tc
+        yield from ie.get_testcases(include_onlymatching)
 
 
 md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest()
@@ -113,33 +109,30 @@ def expect_value(self, got, expected, field):
 
         self.assertTrue(
             isinstance(got, compat_str),
-            'Expected a %s object, but got %s for field %s' % (
-                compat_str.__name__, type(got).__name__, field))
+            f'Expected a {compat_str.__name__} object, but got {type(got).__name__} for field {field}')
         self.assertTrue(
             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:'):
         start_str = expected[len('startswith:'):]
         self.assertTrue(
             isinstance(got, compat_str),
-            'Expected a %s object, but got %s for field %s' % (
-                compat_str.__name__, type(got).__name__, field))
+            f'Expected a {compat_str.__name__} object, but got {type(got).__name__} for field {field}')
         self.assertTrue(
             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:'):
         contains_str = expected[len('contains:'):]
         self.assertTrue(
             isinstance(got, compat_str),
-            'Expected a %s object, but got %s for field %s' % (
-                compat_str.__name__, type(got).__name__, field))
+            f'Expected a {compat_str.__name__} object, but got {type(got).__name__} for field {field}')
         self.assertTrue(
             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):
         self.assertTrue(
             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):
         expect_dict(self, got, expected)
     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:'):
             self.assertTrue(
                 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)
         elif isinstance(expected, compat_str) and re.match(r'^(?:min|max)?count:\d+', expected):
             self.assertTrue(
                 isinstance(got, (list, dict)),
-                'Expected field %s to be a list or a dict, but it is of type %s' % (
-                    field, type(got).__name__))
+                f'Expected field {field} to be a list or a dict, but it is of type {type(got).__name__}')
             op, _, expected_num = expected.partition(':')
             expected_num = int(expected_num)
             if op == 'mincount':
@@ -185,7 +177,7 @@ def expect_value(self, got, expected, field):
             return
         self.assertEqual(
             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):
@@ -260,13 +252,13 @@ def _repr(v):
         info_dict_str = ''
         if len(missing_keys) != len(expected_dict):
             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)
 
             if info_dict_str:
                 info_dict_str += '\n'
         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)
         write_string(
             '\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):
     if not (got >= expected):
         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)
 
 
 def assertLessEqual(self, got, expected, msg=None):
     if not (got <= expected):
         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)
 
 
 def assertEqual(self, got, expected, msg=None):
     if not (got == expected):
         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)
 
 
diff --git a/test/test_InfoExtractor.py b/test/test_InfoExtractor.py
index 866ded2433..4fd21bed4b 100644
--- a/test/test_InfoExtractor.py
+++ b/test/test_InfoExtractor.py
@@ -1,9 +1,5 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 # Allow direct execution
-import io
 import os
 import sys
 import unittest
@@ -1011,8 +1007,7 @@ def test_parse_m3u8_formats(self):
         ]
 
         for m3u8_file, m3u8_url, expected_formats, expected_subs in _TEST_CASES:
-            with io.open('./test/testdata/m3u8/%s.m3u8' % m3u8_file,
-                         mode='r', encoding='utf-8') as f:
+            with open('./test/testdata/m3u8/%s.m3u8' % m3u8_file, encoding='utf-8') as f:
                 formats, subs = self.ie._parse_m3u8_formats_and_subtitles(
                     f.read(), m3u8_url, ext='mp4')
                 self.ie._sort_formats(formats)
@@ -1357,8 +1352,7 @@ def test_parse_mpd_formats(self):
         ]
 
         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,
-                         mode='r', encoding='utf-8') as f:
+            with open('./test/testdata/mpd/%s.mpd' % mpd_file, encoding='utf-8') as f:
                 formats, subtitles = self.ie._parse_mpd_formats_and_subtitles(
                     compat_etree_fromstring(f.read().encode('utf-8')),
                     mpd_base_url=mpd_base_url, mpd_url=mpd_url)
@@ -1549,8 +1543,7 @@ def test_parse_ism_formats(self):
         ]
 
         for ism_file, ism_url, expected_formats, expected_subtitles in _TEST_CASES:
-            with io.open('./test/testdata/ism/%s.Manifest' % ism_file,
-                         mode='r', encoding='utf-8') as f:
+            with open('./test/testdata/ism/%s.Manifest' % ism_file, encoding='utf-8') as f:
                 formats, subtitles = self.ie._parse_ism_formats_and_subtitles(
                     compat_etree_fromstring(f.read().encode('utf-8')), ism_url=ism_url)
                 self.ie._sort_formats(formats)
@@ -1576,8 +1569,7 @@ def test_parse_f4m_formats(self):
         ]
 
         for f4m_file, f4m_url, expected_formats in _TEST_CASES:
-            with io.open('./test/testdata/f4m/%s.f4m' % f4m_file,
-                         mode='r', encoding='utf-8') as f:
+            with open('./test/testdata/f4m/%s.f4m' % f4m_file, encoding='utf-8') as f:
                 formats = self.ie._parse_f4m_formats(
                     compat_etree_fromstring(f.read().encode('utf-8')),
                     f4m_url, None)
@@ -1624,8 +1616,7 @@ def test_parse_xspf(self):
         ]
 
         for xspf_file, xspf_url, expected_entries in _TEST_CASES:
-            with io.open('./test/testdata/xspf/%s.xspf' % xspf_file,
-                         mode='r', encoding='utf-8') as f:
+            with open('./test/testdata/xspf/%s.xspf' % xspf_file, encoding='utf-8') as f:
                 entries = self.ie._parse_xspf(
                     compat_etree_fromstring(f.read().encode('utf-8')),
                     xspf_file, xspf_url=xspf_url, xspf_base_url=xspf_url)
diff --git a/test/test_YoutubeDL.py b/test/test_YoutubeDL.py
index c9108c5b6d..480c7539c8 100644
--- a/test/test_YoutubeDL.py
+++ b/test/test_YoutubeDL.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -25,7 +21,7 @@
 
 class YDL(FakeYDL):
     def __init__(self, *args, **kwargs):
-        super(YDL, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.downloaded_info_dicts = []
         self.msgs = []
 
@@ -551,11 +547,11 @@ def test_subtitles(self):
         def s_formats(lang, autocaption=False):
             return [{
                 'ext': ext,
-                'url': 'http://localhost/video.%s.%s' % (lang, ext),
+                'url': f'http://localhost/video.{lang}.{ext}',
                 '_auto': autocaption,
             } for ext in ['vtt', 'srt', 'ass']]
-        subtitles = dict((l, s_formats(l)) for l in ['en', 'fr', 'es'])
-        auto_captions = dict((l, s_formats(l, True)) for l in ['it', 'pt', 'es'])
+        subtitles = {l: s_formats(l) for l in ['en', 'fr', 'es']}
+        auto_captions = {l: s_formats(l, True) for l in ['it', 'pt', 'es']}
         info_dict = {
             'id': 'test',
             'title': 'Test',
@@ -580,7 +576,7 @@ def get_info(params={}):
         result = get_info({'writesubtitles': True})
         subs = result['requested_subtitles']
         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.assertEqual(subs['en']['ext'], 'ass')
 
@@ -591,39 +587,39 @@ def get_info(params={}):
         result = get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']})
         subs = result['requested_subtitles']
         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']})
         subs = result['requested_subtitles']
         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']})
         subs = result['requested_subtitles']
         self.assertTrue(subs)
-        self.assertEqual(set(subs.keys()), set(['fr']))
+        self.assertEqual(set(subs.keys()), {'fr'})
 
         result = get_info({'writesubtitles': True, 'subtitleslangs': ['-en', 'en']})
         subs = result['requested_subtitles']
         self.assertTrue(subs)
-        self.assertEqual(set(subs.keys()), set(['en']))
+        self.assertEqual(set(subs.keys()), {'en'})
 
         result = get_info({'writesubtitles': True, 'subtitleslangs': ['e.+']})
         subs = result['requested_subtitles']
         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']})
         subs = result['requested_subtitles']
         self.assertTrue(subs)
-        self.assertEqual(set(subs.keys()), set(['es', 'pt']))
+        self.assertEqual(set(subs.keys()), {'es', 'pt'})
         self.assertFalse(subs['es']['_auto'])
         self.assertTrue(subs['pt']['_auto'])
 
         result = get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
         subs = result['requested_subtitles']
         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['pt']['_auto'])
 
@@ -1082,7 +1078,7 @@ def test_ignoreerrors_for_playlist_with_url_transparent_iterable_entries(self):
 
         class _YDL(YDL):
             def __init__(self, *args, **kwargs):
-                super(_YDL, self).__init__(*args, **kwargs)
+                super().__init__(*args, **kwargs)
 
             def trouble(self, s, tb=None):
                 pass
diff --git a/test/test_YoutubeDLCookieJar.py b/test/test_YoutubeDLCookieJar.py
index c514413a45..1e5bedcaed 100644
--- a/test/test_YoutubeDLCookieJar.py
+++ b/test/test_YoutubeDLCookieJar.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import os
 import re
 import sys
diff --git a/test/test_aes.py b/test/test_aes.py
index 5c9273f8aa..34584a04f5 100644
--- a/test/test_aes.py
+++ b/test/test_aes.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
diff --git a/test/test_age_restriction.py b/test/test_age_restriction.py
index 70f9f48455..50d16a7297 100644
--- a/test/test_age_restriction.py
+++ b/test/test_age_restriction.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
diff --git a/test/test_all_urls.py b/test/test_all_urls.py
index 2d89366d45..d70da8cae5 100644
--- a/test/test_all_urls.py
+++ b/test/test_all_urls.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -81,11 +78,11 @@ def test_no_duplicates(self):
             url = tc['url']
             for ie in ies:
                 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:
                     self.assertFalse(
                         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):
         self.assertMatch(':ytsubs', ['youtube:subscriptions'])
@@ -120,7 +117,7 @@ def test_no_duplicated_ie_names(self):
         for (ie_name, ie_list) in name_accu.items():
             self.assertEqual(
                 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__':
diff --git a/test/test_cache.py b/test/test_cache.py
index 8c4f853872..4e4641ebad 100644
--- a/test/test_cache.py
+++ b/test/test_cache.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import shutil
 
 # Allow direct execution
diff --git a/test/test_compat.py b/test/test_compat.py
index 6cbffd6feb..31524c5abb 100644
--- a/test/test_compat.py
+++ b/test/test_compat.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -48,7 +44,7 @@ def test_all_present(self):
         all_names = yt_dlp.compat.__all__
         present_names = set(filter(
             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))
 
     def test_compat_urllib_parse_unquote(self):
diff --git a/test/test_download.py b/test/test_download.py
index 818a670fbd..3c6b55d984 100755
--- a/test/test_download.py
+++ b/test/test_download.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -21,7 +18,6 @@
 
 
 import hashlib
-import io
 import json
 import socket
 
@@ -46,7 +42,7 @@ class YoutubeDL(yt_dlp.YoutubeDL):
     def __init__(self, *args, **kwargs):
         self.to_stderr = self.to_screen
         self.processed_info_dicts = []
-        super(YoutubeDL, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def report_warning(self, message):
         # Don't accept warnings during tests
@@ -54,7 +50,7 @@ def report_warning(self, message):
 
     def process_info(self, info_dict):
         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):
@@ -80,7 +76,7 @@ def __str__(self):
 
         def strclass(cls):
             """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
         return '%s (%s)%s:' % (self._testMethodName,
@@ -179,7 +175,7 @@ def try_rm_tcs_files(tcs=None):
                         report_warning('%s failed due to network errors, skipping...' % tname)
                         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
                 else:
@@ -245,7 +241,7 @@ def try_rm_tcs_files(tcs=None):
                 self.assertTrue(
                     os.path.exists(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)
                 expect_info_dict(self, info_dict, tc.get('info_dict', {}))
         finally:
diff --git a/test/test_downloader_http.py b/test/test_downloader_http.py
index 03ae8c62a4..c511909c72 100644
--- a/test/test_downloader_http.py
+++ b/test/test_downloader_http.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import re
@@ -66,7 +63,7 @@ def do_GET(self):
             assert False
 
 
-class FakeLogger(object):
+class FakeLogger:
     def debug(self, msg):
         pass
 
diff --git a/test/test_execution.py b/test/test_execution.py
index 4981786e12..623f081655 100644
--- a/test/test_execution.py
+++ b/test/test_execution.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import unittest
 
 import sys
@@ -45,7 +41,7 @@ def test_lazy_extractors(self):
         finally:
             try:
                 os.remove('yt_dlp/extractor/lazy_extractors.py')
-            except (IOError, OSError):
+            except OSError:
                 pass
 
 
diff --git a/test/test_http.py b/test/test_http.py
index eec8684b1a..2106220eb2 100644
--- a/test/test_http.py
+++ b/test/test_http.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -41,7 +38,7 @@ def do_GET(self):
             assert False
 
 
-class FakeLogger(object):
+class FakeLogger:
     def debug(self, msg):
         pass
 
@@ -117,23 +114,23 @@ def setUp(self):
         self.geo_proxy_thread.start()
 
     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({
-            'proxy': '127.0.0.1:{0}'.format(self.port),
+            'proxy': f'127.0.0.1:{self.port}',
             'geo_verification_proxy': geo_proxy,
         })
         url = 'http://foo.com/bar'
         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.add_header('Ytdl-request-proxy', geo_proxy)
         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):
         ydl = YoutubeDL({
-            'proxy': '127.0.0.1:{0}'.format(self.port),
+            'proxy': f'127.0.0.1:{self.port}',
         })
         url = 'http://中文.tw/'
         response = ydl.urlopen(url).read().decode('utf-8')
diff --git a/test/test_iqiyi_sdk_interpreter.py b/test/test_iqiyi_sdk_interpreter.py
index adbae46903..57a7ed3a8a 100644
--- a/test/test_iqiyi_sdk_interpreter.py
+++ b/test/test_iqiyi_sdk_interpreter.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -12,7 +9,7 @@
 from yt_dlp.extractor import IqiyiIE
 
 
-class WarningLogger(object):
+class WarningLogger:
     def __init__(self):
         self.messages = []
 
diff --git a/test/test_jsinterp.py b/test/test_jsinterp.py
index e230b045fd..10a465cf95 100644
--- a/test/test_jsinterp.py
+++ b/test/test_jsinterp.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
diff --git a/test/test_netrc.py b/test/test_netrc.py
index 94a703406b..adc3a0ed1e 100644
--- a/test/test_netrc.py
+++ b/test/test_netrc.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import os
 import sys
 import unittest
diff --git a/test/test_overwrites.py b/test/test_overwrites.py
index f5d10a409b..8e0548db5b 100644
--- a/test/test_overwrites.py
+++ b/test/test_overwrites.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 import os
 from os.path import join
 import subprocess
diff --git a/test/test_post_hooks.py b/test/test_post_hooks.py
index 1555a23e0d..020203f2fa 100644
--- a/test/test_post_hooks.py
+++ b/test/test_post_hooks.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 import os
 import sys
 import unittest
@@ -14,7 +11,7 @@
 
 class YoutubeDL(yt_dlp.YoutubeDL):
     def __init__(self, *args, **kwargs):
-        super(YoutubeDL, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.to_stderr = self.to_screen
 
 
diff --git a/test/test_postprocessors.py b/test/test_postprocessors.py
index bbe998993f..e5893f7d2e 100644
--- a/test/test_postprocessors.py
+++ b/test/test_postprocessors.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
diff --git a/test/test_socks.py b/test/test_socks.py
index cf1f613ab4..02723b4698 100644
--- a/test/test_socks.py
+++ b/test/test_socks.py
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
diff --git a/test/test_subtitles.py b/test/test_subtitles.py
index 95e33e54ac..0be1842da9 100644
--- a/test/test_subtitles.py
+++ b/test/test_subtitles.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -54,7 +52,7 @@ def getSubtitles(self):
             if sub_info.get('data') is None:
                 uf = self.DL.urlopen(sub_info['url'])
                 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
@@ -163,7 +161,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         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['fr']), 'b6191146a6c5d3a452244d853fde6dc8')
 
@@ -186,7 +184,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['heb']))
+        self.assertEqual(set(subtitles.keys()), {'heb'})
         self.assertEqual(md5(subtitles['heb']), 'e758c5d7cb982f6bef14f377ec7a3920')
 
     def test_nosubtitles(self):
@@ -208,7 +206,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['cs']))
+        self.assertEqual(set(subtitles.keys()), {'cs'})
         self.assertTrue(len(subtitles['cs']) > 20000)
 
     def test_nosubtitles(self):
@@ -229,7 +227,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['en']))
+        self.assertEqual(set(subtitles.keys()), {'en'})
         self.assertEqual(md5(subtitles['en']), '09bbe67222259bed60deaa26997d73a7')
 
 
@@ -242,7 +240,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['nl']))
+        self.assertEqual(set(subtitles.keys()), {'nl'})
         self.assertEqual(md5(subtitles['nl']), 'fc6435027572b63fb4ab143abd5ad3f4')
 
 
@@ -252,13 +250,13 @@ class TestMTVSubtitles(BaseTestSubtitles):
     IE = ComedyCentralIE
 
     def getInfoDict(self):
-        return super(TestMTVSubtitles, self).getInfoDict()['entries'][0]
+        return super().getInfoDict()['entries'][0]
 
     def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['en']))
+        self.assertEqual(set(subtitles.keys()), {'en'})
         self.assertEqual(md5(subtitles['en']), '78206b8d8a0cfa9da64dc026eea48961')
 
 
@@ -271,7 +269,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['no']))
+        self.assertEqual(set(subtitles.keys()), {'no'})
         self.assertEqual(md5(subtitles['no']), '544fa917d3197fcbee64634559221cc2')
 
 
@@ -284,7 +282,7 @@ def test_subtitles_key(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['it']))
+        self.assertEqual(set(subtitles.keys()), {'it'})
         self.assertEqual(md5(subtitles['it']), 'b1d90a98755126b61e667567a1f6680a')
 
     def test_subtitles_array_key(self):
@@ -292,7 +290,7 @@ def test_subtitles_array_key(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['it']))
+        self.assertEqual(set(subtitles.keys()), {'it'})
         self.assertEqual(md5(subtitles['it']), '4b3264186fbb103508abe5311cfcb9cd')
 
 
@@ -305,7 +303,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['en']))
+        self.assertEqual(set(subtitles.keys()), {'en'})
         self.assertEqual(md5(subtitles['en']), '53cb083a5914b2d84ef1ab67b880d18a')
 
 
@@ -320,7 +318,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['en']))
+        self.assertEqual(set(subtitles.keys()), {'en'})
         self.assertEqual(md5(subtitles['en']), '97e7670cbae3c4d26ae8bcc7fdd78d4b')
 
 
@@ -333,7 +331,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['en']))
+        self.assertEqual(set(subtitles.keys()), {'en'})
         self.assertEqual(md5(subtitles['en']), '48649a22e82b2da21c9a67a395eedade')
 
 
@@ -348,7 +346,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['es']))
+        self.assertEqual(set(subtitles.keys()), {'es'})
         self.assertEqual(md5(subtitles['es']), '69e70cae2d40574fb7316f31d6eb7fca')
 
 
@@ -361,7 +359,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['en']))
+        self.assertEqual(set(subtitles.keys()), {'en'})
         self.assertEqual(md5(subtitles['en']), 'acaca989e24a9e45a6719c9b3d60815c')
 
     def test_subtitles_in_page(self):
@@ -369,7 +367,7 @@ def test_subtitles_in_page(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['en']))
+        self.assertEqual(set(subtitles.keys()), {'en'})
         self.assertEqual(md5(subtitles['en']), 'acaca989e24a9e45a6719c9b3d60815c')
 
 
@@ -382,7 +380,7 @@ def test_allsubtitles(self):
         self.DL.params['writesubtitles'] = True
         self.DL.params['allsubtitles'] = True
         subtitles = self.getSubtitles()
-        self.assertEqual(set(subtitles.keys()), set(['en']))
+        self.assertEqual(set(subtitles.keys()), {'en'})
 
     def test_subtitles_dfxp_format(self):
         self.DL.params['writesubtitles'] = True
diff --git a/test/test_update.py.disabled b/test/test_update.py.disabled
index 1e8edf0f6b..5f0794ae27 100644
--- a/test/test_update.py.disabled
+++ b/test/test_update.py.disabled
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
diff --git a/test/test_utils.py b/test/test_utils.py
index c1228c74ad..e0c862807e 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -266,7 +262,7 @@ def test_extract_basic_auth(self):
 
     def test_expand_path(self):
         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')
         self.assertEqual(expand_path(env('yt_dlp_EXPATH_PATH')), 'expanded')
@@ -666,8 +662,7 @@ def testPL(size, pagesize, sliceargs, expected):
             def get_page(pagenum):
                 firstid = pagenum * pagesize
                 upto = min(size, pagenum * pagesize + pagesize)
-                for i in range(firstid, upto):
-                    yield i
+                yield from range(firstid, upto)
 
             pl = OnDemandPagedList(get_page, pagesize)
             got = pl.getslice(*sliceargs)
@@ -736,7 +731,7 @@ def test_multipart_encode(self):
             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')
         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')
         self.assertRaises(
             ValueError, multipart_encode, {b'field': b'value'}, boundary='value')
@@ -1397,7 +1392,7 @@ def test_dfxp2srt(self):
                     <p begin="3" dur="-1">Ignored, three</p>
                 </div>
             </body>
-            </tt>'''.encode('utf-8')
+            </tt>'''.encode()
         srt_data = '''1
 00:00:00,000 --> 00:00:01,000
 The following line contains Chinese characters and special symbols
@@ -1415,14 +1410,14 @@ def test_dfxp2srt(self):
 '''
         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">
             <body>
                 <div xml:lang="en">
                     <p begin="0" end="1">The first line</p>
                 </div>
             </body>
-            </tt>'''.encode('utf-8')
+            </tt>'''
         srt_data = '''1
 00:00:00,000 --> 00:00:01,000
 The first line
@@ -1430,7 +1425,7 @@ def test_dfxp2srt(self):
 '''
         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">
   <head>
     <styling>
@@ -1448,7 +1443,7 @@ def test_dfxp2srt(self):
       <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>
   </body>
-</tt>'''.encode('utf-8')
+</tt>'''
         srt_data = '''1
 00:00:02,080 --> 00:00:05,840
 <font color="white" face="sansSerif" size="16">default style<font color="red">custom style</font></font>
diff --git a/test/test_verbose_output.py b/test/test_verbose_output.py
index cc606115fe..17aeafbc06 100644
--- a/test/test_verbose_output.py
+++ b/test/test_verbose_output.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import unittest
 
 import sys
diff --git a/test/test_write_annotations.py.disabled b/test/test_write_annotations.py.disabled
index 7e4d8bc5a9..4173fd09d1 100644
--- a/test/test_write_annotations.py.disabled
+++ b/test/test_write_annotations.py.disabled
@@ -1,7 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
@@ -21,7 +18,7 @@ import yt_dlp.extractor
 
 class YoutubeDL(yt_dlp.YoutubeDL):
     def __init__(self, *args, **kwargs):
-        super(YoutubeDL, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.to_stderr = self.to_screen
 
 
@@ -52,7 +49,7 @@ class TestAnnotations(unittest.TestCase):
         ydl.download([TEST_ID])
         self.assertTrue(os.path.exists(ANNOTATIONS_FILE))
         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)
         self.assertTrue(annoxml is not None, 'Failed to parse annotations XML')
         root = annoxml.getroot()
diff --git a/test/test_youtube_lists.py b/test/test_youtube_lists.py
index 455192b1f2..8691abb67a 100644
--- a/test/test_youtube_lists.py
+++ b/test/test_youtube_lists.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
diff --git a/test/test_youtube_misc.py b/test/test_youtube_misc.py
index 402681cad8..70d6d99491 100644
--- a/test/test_youtube_misc.py
+++ b/test/test_youtube_misc.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
diff --git a/test/test_youtube_signature.py b/test/test_youtube_signature.py
index 6412acce04..d751d53961 100644
--- a/test/test_youtube_signature.py
+++ b/test/test_youtube_signature.py
@@ -1,14 +1,10 @@
 #!/usr/bin/env python3
-
-from __future__ import unicode_literals
-
 # Allow direct execution
 import os
 import sys
 import unittest
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
-import io
 import re
 import string
 import urllib.request
@@ -149,7 +145,7 @@ def test_func(self):
 
             if not os.path.exists(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()
             self.assertEqual(sig_func(jscode, sig_input), expected_sig)
 
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py
index 4bf5a8942c..56f0346dcc 100644
--- a/yt_dlp/YoutubeDL.py
+++ b/yt_dlp/YoutubeDL.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import absolute_import, unicode_literals
-
 import collections
 import contextlib
 import datetime
@@ -165,7 +161,7 @@
     import ctypes
 
 
-class YoutubeDL(object):
+class YoutubeDL:
     """YoutubeDL class.
 
     YoutubeDL objects are the ones responsible of downloading the
@@ -501,7 +497,7 @@ class YoutubeDL(object):
                        care about HLS. (only for youtube)
     """
 
-    _NUMERIC_FIELDS = set((
+    _NUMERIC_FIELDS = {
         'width', 'height', 'tbr', 'abr', 'asr', 'vbr', 'fps', 'filesize', 'filesize_approx',
         'timestamp', 'release_timestamp',
         'duration', 'view_count', 'like_count', 'dislike_count', 'repost_count',
@@ -509,7 +505,7 @@ class YoutubeDL(object):
         'start_time', 'end_time',
         'chapter_number', 'season_number', 'episode_number',
         'track_number', 'disc_number', 'release_year',
-    ))
+    }
 
     _format_fields = {
         # NB: Keep in sync with the docstring of extractor/common.py
@@ -576,7 +572,7 @@ def __init__(self, params=None, auto_init=True):
 
         def check_deprecated(param, option, suggestion):
             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 False
 
@@ -693,7 +689,7 @@ def preload_download_archive(fn):
                 with locked_file(fn, 'r', encoding='utf-8') as archive_file:
                     for line in archive_file:
                         self.archive.add(line.strip())
-            except IOError as ioe:
+            except OSError as ioe:
                 if ioe.errno != errno.ENOENT:
                     raise
                 return False
@@ -990,11 +986,9 @@ def parse_outtmpl(self):
         outtmpl_dict.update({
             k: sanitize(v) for k, v in DEFAULT_OUTTMPL.items()
             if outtmpl_dict.get(k) is None})
-        for key, val in outtmpl_dict.items():
+        for _, val in outtmpl_dict.items():
             if isinstance(val, bytes):
-                self.report_warning(
-                    '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.')
+                self.report_warning('Parameter outtmpl is bytes, but should be a unicode string')
         return outtmpl_dict
 
     def get_output_path(self, dir_type='', filename=None):
@@ -1013,7 +1007,7 @@ def _outtmpl_expandpath(outtmpl):
         # '%%' intact for template dict substitution step. Working around
         # with boundary-alike separator hack.
         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
         # because meta fields may contain env variables we don't want to
@@ -1173,7 +1167,7 @@ def create_key(outer_mobj):
 
             fmt = outer_mobj.group('format')
             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
 
@@ -1188,7 +1182,7 @@ def create_key(outer_mobj):
                 value = map(str, variadic(value) if '#' in flags else [value])
                 value, fmt = ' '.join(map(compat_shlex_quote, value)), str_fmt
             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'
             elif fmt[-1] == 'U':  # unicode normalized
                 value, fmt = unicodedata.normalize(
@@ -1301,7 +1295,7 @@ def check_filter():
             if date is not None:
                 dateRange = self.params.get('daterange', 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')
             if view_count is not None:
                 min_views = self.params.get('min_views')
@@ -1765,14 +1759,14 @@ def get_entry(i):
 
         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
         max_failures = self.params.get('skip_playlist_after_errors') or float('inf')
         for i, entry_tuple in enumerate(entries, 1):
             playlist_index, entry = entry_tuple
             if 'playlist-index' in self.params.get('compat_opts', []):
                 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
             # minimal changes
             if x_forwarded_for:
@@ -1940,7 +1934,7 @@ def build_format_selector(self, format_spec):
         def syntax_error(note, start):
             message = (
                 '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)
 
         PICKFIRST = 'PICKFIRST'
@@ -2044,7 +2038,7 @@ def _parse_format_selection(tokens, inside_merge=False, inside_choice=False, ins
                             raise syntax_error('Expected a selector', start)
                         current_selector = FormatSelector(MERGE, (selector_1, selector_2), [])
                     else:
-                        raise syntax_error('Operator not recognized: "{0}"'.format(string), start)
+                        raise syntax_error(f'Operator not recognized: "{string}"', start)
                 elif type == tokenize.ENDMARKER:
                     break
             if current_selector:
@@ -2244,7 +2238,7 @@ def final_selector(ctx):
         except tokenize.TokenError:
             raise syntax_error('Missing closing/opening brackets or parenthesis', (0, len(format_spec)))
 
-        class TokenIterator(object):
+        class TokenIterator:
             def __init__(self, tokens):
                 self.tokens = tokens
                 self.counter = 0
@@ -2644,7 +2638,7 @@ def is_wellformed(f):
                 if max_downloads_reached:
                     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'})
             if True in write_archive and False not in write_archive:
                 self.record_download_archive(info_dict)
@@ -2712,7 +2706,7 @@ def process_subtitles(self, video_id, normal_subtitles, automatic_captions):
         for lang in requested_langs:
             formats = available_subs.get(lang)
             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
             for ext in formats_preference:
                 if ext == 'best':
@@ -2755,7 +2749,7 @@ def format_tmpl(tmpl):
             tmpl = format_tmpl(tmpl)
             self.to_screen(f'[info] Writing {tmpl!r} to: {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')
 
     def __forced_printings(self, info_dict, filename, incomplete):
@@ -2920,11 +2914,11 @@ def process_info(self, info_dict):
             else:
                 try:
                     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'])
                 except (KeyError, TypeError):
                     self.report_warning('There are no annotations to write.')
-                except (OSError, IOError):
+                except OSError:
                     self.report_error('Cannot write annotations file: ' + annofn)
                     return
 
@@ -2943,13 +2937,13 @@ def _write_link_file(link_type):
                 return True
             try:
                 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',
-                             newline='\r\n' if link_type == 'url' else '\n') as linkfile:
+                with open(encodeFilename(to_high_limit_path(linkfn)), 'w', encoding='utf-8',
+                          newline='\r\n' if link_type == 'url' else '\n') as linkfile:
                     template_vars = {'url': url}
                     if link_type == 'desktop':
                         template_vars['filename'] = linkfn[:-(len(link_type) + 1)]
                     linkfile.write(LINK_TEMPLATES[link_type] % template_vars)
-            except (OSError, IOError):
+            except OSError:
                 self.report_error(f'Cannot write internet shortcut {linkfn}')
                 return False
             return True
@@ -3014,10 +3008,10 @@ def compatible_formats(formats):
                             return False
 
                         # Check extension
-                        exts = set(format.get('ext') for format in formats)
+                        exts = {format.get('ext') for format in formats}
                         COMPATIBLE_EXTS = (
-                            set(('mp3', 'mp4', 'm4a', 'm4p', 'm4b', 'm4r', 'm4v', 'ismv', 'isma')),
-                            set(('webm',)),
+                            {'mp3', 'mp4', 'm4a', 'm4p', 'm4b', 'm4r', 'm4v', 'ismv', 'isma'},
+                            {'webm'},
                         )
                         for ext_sets in COMPATIBLE_EXTS:
                             if ext_sets.issuperset(exts):
@@ -3050,7 +3044,7 @@ def correct_ext(filename, ext=new_ext):
                             os.path.splitext(filename)[0]
                             if filename_real_ext in (old_ext, new_ext)
                             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
                     full_filename = correct_ext(full_filename)
@@ -3135,10 +3129,10 @@ def correct_ext(filename, ext=new_ext):
             except network_exceptions as err:
                 self.report_error('unable to download video data: %s' % error_to_compat_str(err))
                 return
-            except (OSError, IOError) as err:
+            except OSError as err:
                 raise UnavailableVideoError(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
 
             if success and full_filename != '-':
@@ -3343,7 +3337,7 @@ def run_pp(self, pp, infodict):
                 self.to_screen('Deleting original file %s (pass -k to keep)' % old_filename)
                 try:
                     os.remove(encodeFilename(old_filename))
-                except (IOError, OSError):
+                except OSError:
                     self.report_warning('Unable to remove downloaded original file')
                 if old_filename in infodict['__files_to_move']:
                     del infodict['__files_to_move'][old_filename]
@@ -3388,7 +3382,7 @@ def _make_archive_id(self, info_dict):
                     break
             else:
                 return
-        return '%s %s' % (extractor.lower(), video_id)
+        return f'{extractor.lower()} {video_id}'
 
     def in_download_archive(self, info_dict):
         fn = self.params.get('download_archive')
@@ -3791,7 +3785,7 @@ def _write_info_json(self, label, ie_result, infofn, overwrite=None):
         try:
             write_json_file(self.sanitize_info(ie_result, self.params.get('clean_infojson', True)), infofn)
             return True
-        except (OSError, IOError):
+        except OSError:
             self.report_error(f'Cannot write {label} metadata to JSON file {infofn}')
             return None
 
@@ -3812,9 +3806,9 @@ def _write_description(self, label, ie_result, descfn):
         else:
             try:
                 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'])
-            except (OSError, IOError):
+            except OSError:
                 self.report_error(f'Cannot write {label} description file {descfn}')
                 return None
         return True
@@ -3848,12 +3842,12 @@ def _write_subtitles(self, info_dict, filename):
                 try:
                     # Use newline='' to prevent conversion of newline characters
                     # 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'])
                     sub_info['filepath'] = sub_filename
                     ret.append((sub_filename, sub_filename_final))
                     continue
-                except (OSError, IOError):
+                except OSError:
                     self.report_error(f'Cannot write video subtitles file {sub_filename}')
                     return None
 
diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py
index 10dc221b4c..91bf5c4cea 100644
--- a/yt_dlp/__init__.py
+++ b/yt_dlp/__init__.py
@@ -1,11 +1,8 @@
 #!/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
 
 __license__ = 'Public Domain'
 
-import io
 import itertools
 import os
 import random
@@ -67,13 +64,12 @@ def get_urls(urls, batchfile, verbose):
                     'Ctrl+Z' if compat_os_name == 'nt' else 'Ctrl+D'))
                 batchfd = sys.stdin
             else:
-                batchfd = io.open(
-                    expand_path(batchfile),
-                    'r', encoding='utf-8', errors='ignore')
+                batchfd = open(
+                    expand_path(batchfile), encoding='utf-8', errors='ignore')
             batch_urls = read_batch_urls(batchfd)
             if verbose:
                 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)
     _enc = preferredencoding()
     return [
diff --git a/yt_dlp/__main__.py b/yt_dlp/__main__.py
index fb2726bd3f..c9d275b863 100644
--- a/yt_dlp/__main__.py
+++ b/yt_dlp/__main__.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python3
-from __future__ import unicode_literals
-
 # Execute with
 # $ python -m yt_dlp
 
diff --git a/yt_dlp/aes.py b/yt_dlp/aes.py
index b37f0dd392..e5d73f7406 100644
--- a/yt_dlp/aes.py
+++ b/yt_dlp/aes.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from math import ceil
 
 from .compat import (
diff --git a/yt_dlp/cache.py b/yt_dlp/cache.py
index e5cb193bce..f93ef85e72 100644
--- a/yt_dlp/cache.py
+++ b/yt_dlp/cache.py
@@ -1,7 +1,4 @@
-from __future__ import unicode_literals
-
 import errno
-import io
 import json
 import os
 import re
@@ -15,7 +12,7 @@
 )
 
 
-class Cache(object):
+class Cache:
     def __init__(self, ydl):
         self._ydl = ydl
 
@@ -31,7 +28,7 @@ def _get_cache_fn(self, section, key, dtype):
             'invalid section %r' % section
         assert re.match(r'^[a-zA-Z0-9_.-]+$', key), 'invalid key %r' % key
         return os.path.join(
-            self._get_root_dir(), section, '%s.%s' % (key, dtype))
+            self._get_root_dir(), section, f'{key}.{dtype}')
 
     @property
     def enabled(self):
@@ -54,8 +51,7 @@ def store(self, section, key, data, dtype='json'):
             write_json_file(data, fn)
         except Exception:
             tb = traceback.format_exc()
-            self._ydl.report_warning(
-                'Writing cache to %r failed: %s' % (fn, tb))
+            self._ydl.report_warning(f'Writing cache to {fn!r} failed: {tb}')
 
     def load(self, section, key, dtype='json', default=None):
         assert dtype in ('json',)
@@ -66,17 +62,16 @@ def load(self, section, key, dtype='json', default=None):
         cache_fn = self._get_cache_fn(section, key, dtype)
         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')
                     return json.load(cachef)
             except ValueError:
                 try:
                     file_size = os.path.getsize(cache_fn)
-                except (OSError, IOError) as oe:
+                except OSError as oe:
                     file_size = str(oe)
-                self._ydl.report_warning(
-                    'Cache retrieval from %s failed (%s)' % (cache_fn, file_size))
-        except IOError:
+                self._ydl.report_warning(f'Cache retrieval from {cache_fn} failed ({file_size})')
+        except OSError:
             pass  # No cache available
 
         return default
diff --git a/yt_dlp/compat.py b/yt_dlp/compat.py
index 5bac87c105..7a15004350 100644
--- a/yt_dlp/compat.py
+++ b/yt_dlp/compat.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 import asyncio
 import base64
 import collections
diff --git a/yt_dlp/cookies.py b/yt_dlp/cookies.py
index 3476595d3d..1d92fd8ce9 100644
--- a/yt_dlp/cookies.py
+++ b/yt_dlp/cookies.py
@@ -125,7 +125,7 @@ def extract_cookies_from_browser(browser_name, profile=None, logger=YDLLogger(),
     elif browser_name in CHROMIUM_BASED_BROWSERS:
         return _extract_chrome_cookies(browser_name, profile, keyring, logger)
     else:
-        raise ValueError('unknown browser: {}'.format(browser_name))
+        raise ValueError(f'unknown browser: {browser_name}')
 
 
 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)
     if cookie_database_path is None:
-        raise FileNotFoundError('could not find firefox cookies database in {}'.format(search_root))
-    logger.debug('Extracting cookies from: "{}"'.format(cookie_database_path))
+        raise FileNotFoundError(f'could not find firefox cookies database in {search_root}')
+    logger.debug(f'Extracting cookies from: "{cookie_database_path}"')
 
     with tempfile.TemporaryDirectory(prefix='yt_dlp') as tmpdir:
         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,
                         comment=None, comment_url=None, rest={})
                     jar.set_cookie(cookie)
-            logger.info('Extracted {} cookies from firefox'.format(len(jar)))
+            logger.info(f'Extracted {len(jar)} cookies from firefox')
             return jar
         finally:
             if cursor is not None:
@@ -179,7 +179,7 @@ def _firefox_browser_dir():
     elif sys.platform == 'darwin':
         return os.path.expanduser('~/Library/Application Support/Firefox')
     else:
-        raise ValueError('unsupported platform: {}'.format(sys.platform))
+        raise ValueError(f'unsupported platform: {sys.platform}')
 
 
 def _get_chromium_based_browser_settings(browser_name):
@@ -219,7 +219,7 @@ def _get_chromium_based_browser_settings(browser_name):
         }[browser_name]
 
     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:
     # 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):
-    logger.info('Extracting cookies from {}'.format(browser_name))
+    logger.info(f'Extracting cookies from {browser_name}')
 
     if not SQLITE_AVAILABLE:
         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']:
             search_root = os.path.join(config['browser_dir'], profile)
         else:
-            logger.error('{} does not support profiles'.format(browser_name))
+            logger.error(f'{browser_name} does not support profiles')
             search_root = config['browser_dir']
 
     cookie_database_path = _find_most_recently_used_file(search_root, 'Cookies', logger)
     if cookie_database_path is None:
-        raise FileNotFoundError('could not find {} cookies database in "{}"'.format(browser_name, search_root))
-    logger.debug('Extracting cookies from: "{}"'.format(cookie_database_path))
+        raise FileNotFoundError(f'could not find {browser_name} cookies database in "{search_root}"')
+    logger.debug(f'Extracting cookies from: "{cookie_database_path}"')
 
     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
                     jar.set_cookie(cookie)
             if failed_cookies > 0:
-                failed_message = ' ({} could not be decrypted)'.format(failed_cookies)
+                failed_message = f' ({failed_cookies} could not be decrypted)'
             else:
                 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['unencrypted'] = unencrypted_cookies
-            logger.debug('cookie version breakdown: {}'.format(counts))
+            logger.debug(f'cookie version breakdown: {counts}')
             return jar
         finally:
             if cursor is not None:
@@ -492,7 +492,7 @@ def _extract_safari_cookies(profile, logger):
     if profile is not None:
         logger.error('safari does not support profiles')
     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')
 
@@ -506,7 +506,7 @@ def _extract_safari_cookies(profile, logger):
         cookies_data = f.read()
 
     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
 
 
@@ -522,7 +522,7 @@ def __init__(self, data, logger):
 
     def read_bytes(self, num_bytes):
         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
         if end > len(self._data):
             raise ParserError('reached end of input')
@@ -533,7 +533,7 @@ def read_bytes(self, num_bytes):
     def expect_bytes(self, expected_value, message):
         value = self.read_bytes(len(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):
         data_format = '>I' if big_endian else '<I'
@@ -557,7 +557,7 @@ def skip(self, num_bytes, description='unknown'):
             self._logger.debug('skipping {} bytes ({}): {}'.format(
                 num_bytes, description, self.read_bytes(num_bytes)))
         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'):
         self.skip(offset - self.cursor, description)
@@ -584,7 +584,7 @@ def _parse_safari_cookies_page(data, jar, logger):
     number_of_cookies = p.read_uint()
     record_offsets = [p.read_uint() for _ in range(number_of_cookies)]
     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
 
     p.skip_to(record_offsets[0], 'unknown page header field')
@@ -730,7 +730,7 @@ def _choose_linux_keyring(logger):
     SelectBackend
     """
     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:
         linux_keyring = _LinuxKeyring.KWALLET
     elif desktop_environment == _LinuxDesktopEnvironment.OTHER:
@@ -764,10 +764,10 @@ def _get_kwallet_network_wallet(logger):
             return default_wallet
         else:
             network_wallet = stdout.decode('utf-8').strip()
-            logger.debug('NetworkWallet = "{}"'.format(network_wallet))
+            logger.debug(f'NetworkWallet = "{network_wallet}"')
             return network_wallet
     except Exception as e:
-        logger.warning('exception while obtaining NetworkWallet: {}'.format(e))
+        logger.warning(f'exception while obtaining NetworkWallet: {e}')
         return default_wallet
 
 
@@ -785,8 +785,8 @@ def _get_kwallet_password(browser_keyring_name, logger):
     try:
         proc = Popen([
             'kwallet-query',
-            '--read-password', '{} Safe Storage'.format(browser_keyring_name),
-            '--folder', '{} Keys'.format(browser_keyring_name),
+            '--read-password', f'{browser_keyring_name} Safe Storage',
+            '--folder', f'{browser_keyring_name} Keys',
             network_wallet
         ], 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):
     if not SECRETSTORAGE_AVAILABLE:
-        logger.error('secretstorage not available {}'.format(SECRETSTORAGE_UNAVAILABLE_REASON))
+        logger.error(f'secretstorage not available {SECRETSTORAGE_UNAVAILABLE_REASON}')
         return b''
     # 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
@@ -827,7 +827,7 @@ def _get_gnome_keyring_password(browser_keyring_name, logger):
     with contextlib.closing(secretstorage.dbus_init()) as con:
         col = secretstorage.get_default_collection(con)
         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()
         else:
             logger.error('failed to read from keyring')
@@ -861,7 +861,7 @@ def _get_mac_keyring_password(browser_keyring_name, logger):
             ['security', 'find-generic-password',
              '-w',  # write password to stdout
              '-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, 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')
         return None
     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)
     try:
         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):
-    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]
 
 
diff --git a/yt_dlp/downloader/__init__.py b/yt_dlp/downloader/__init__.py
index 96d484dee8..f5abfd5df7 100644
--- a/yt_dlp/downloader/__init__.py
+++ b/yt_dlp/downloader/__init__.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from ..compat import compat_str
 from ..utils import (
     determine_protocol,
diff --git a/yt_dlp/downloader/common.py b/yt_dlp/downloader/common.py
index cbfea7a65a..d42539931a 100644
--- a/yt_dlp/downloader/common.py
+++ b/yt_dlp/downloader/common.py
@@ -1,5 +1,3 @@
-from __future__ import division, unicode_literals
-
 import os
 import re
 import time
@@ -25,7 +23,7 @@
 )
 
 
-class FileDownloader(object):
+class FileDownloader:
     """File Downloader class.
 
     File downloader objects are the ones responsible of downloading the
@@ -219,7 +217,7 @@ def inner(self, *args, **kwargs):
                 while True:
                     try:
                         return func(self, *args, **kwargs)
-                    except (IOError, OSError) as err:
+                    except OSError as err:
                         retry = retry + 1
                         if retry > file_access_retries or err.errno not in (errno.EACCES, errno.EINVAL):
                             if not fatal:
@@ -486,4 +484,4 @@ def _debug_cmd(self, args, exe=None):
         if exe is None:
             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)}')
diff --git a/yt_dlp/downloader/dash.py b/yt_dlp/downloader/dash.py
index a845ee7d3d..64eb5e66af 100644
--- a/yt_dlp/downloader/dash.py
+++ b/yt_dlp/downloader/dash.py
@@ -1,4 +1,3 @@
-from __future__ import unicode_literals
 import time
 
 from ..downloader import get_suitable_downloader
@@ -46,7 +45,7 @@ def real_download(self, filename, info_dict):
 
             if real_downloader:
                 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)
                 fd = real_downloader(self.ydl, self.params)
                 return fd.real_download(filename, info_dict)
diff --git a/yt_dlp/downloader/external.py b/yt_dlp/downloader/external.py
index 71af705ea7..b6dd327018 100644
--- a/yt_dlp/downloader/external.py
+++ b/yt_dlp/downloader/external.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import os.path
 import re
 import subprocess
@@ -56,7 +54,7 @@ def real_download(self, filename, info_dict):
             }
             if filename != '-':
                 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)
                 status.update({
                     'downloaded_bytes': fsize,
@@ -157,7 +155,7 @@ def _call_downloader(self, tmpfilename, info_dict):
             fragment_filename = '%s-Frag%d' % (tmpfilename, frag_index)
             try:
                 src, _ = self.sanitize_open(fragment_filename, 'rb')
-            except IOError as err:
+            except OSError as err:
                 if skip_unavailable_fragments and frag_index > 1:
                     self.report_skip_fragment(frag_index, err)
                     continue
@@ -179,7 +177,7 @@ def _make_cmd(self, tmpfilename, info_dict):
         cmd = [self.exe, '--location', '-o', tmpfilename, '--compressed']
         if info_dict.get('http_headers') is not None:
             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._valueless_option('--silent', 'noprogress')
@@ -216,7 +214,7 @@ def _make_cmd(self, tmpfilename, info_dict):
         cmd = [self.exe, '-o', tmpfilename]
         if info_dict.get('http_headers') is not None:
             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 += ['--', info_dict['url']]
         return cmd
@@ -229,7 +227,7 @@ def _make_cmd(self, tmpfilename, info_dict):
         cmd = [self.exe, '-O', tmpfilename, '-nv', '--no-cookies', '--compression=auto']
         if info_dict.get('http_headers') is not None:
             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')
         retry = self._option('--tries', 'retries')
         if len(retry) == 2:
@@ -240,7 +238,7 @@ def _make_cmd(self, tmpfilename, info_dict):
         proxy = self.params.get('proxy')
         if 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._configuration_args()
         cmd += ['--', info_dict['url']]
@@ -271,7 +269,7 @@ def _make_cmd(self, tmpfilename, info_dict):
 
         if info_dict.get('http_headers') is not None:
             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('--interface', 'source_address')
         cmd += self._option('--all-proxy', 'proxy')
@@ -289,10 +287,10 @@ def _make_cmd(self, tmpfilename, info_dict):
         dn = os.path.dirname(tmpfilename)
         if 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]
         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']
 
         if 'fragments' in info_dict:
@@ -320,7 +318,7 @@ def _make_cmd(self, tmpfilename, info_dict):
 
         if info_dict.get('http_headers') is not None:
             for key, val in info_dict['http_headers'].items():
-                cmd += ['%s:%s' % (key, val)]
+                cmd += [f'{key}:{val}']
         return cmd
 
 
@@ -393,7 +391,7 @@ def _call_downloader(self, tmpfilename, info_dict):
             headers = handle_youtubedl_headers(info_dict['http_headers'])
             args += [
                 '-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
         proxy = self.params.get('proxy')
diff --git a/yt_dlp/downloader/f4m.py b/yt_dlp/downloader/f4m.py
index 0008b7c286..4140710751 100644
--- a/yt_dlp/downloader/f4m.py
+++ b/yt_dlp/downloader/f4m.py
@@ -1,5 +1,3 @@
-from __future__ import division, unicode_literals
-
 import io
 import itertools
 import time
diff --git a/yt_dlp/downloader/fc2.py b/yt_dlp/downloader/fc2.py
index 157bcf23eb..d503aac042 100644
--- a/yt_dlp/downloader/fc2.py
+++ b/yt_dlp/downloader/fc2.py
@@ -1,5 +1,3 @@
-from __future__ import division, unicode_literals
-
 import threading
 
 from .common import FileDownloader
diff --git a/yt_dlp/downloader/fragment.py b/yt_dlp/downloader/fragment.py
index c45a8a4767..217b89e3fe 100644
--- a/yt_dlp/downloader/fragment.py
+++ b/yt_dlp/downloader/fragment.py
@@ -1,5 +1,3 @@
-from __future__ import division, unicode_literals
-
 import http.client
 import json
 import math
@@ -172,8 +170,7 @@ def _prepare_frag_download(self, ctx):
                 total_frags_str += ' (not including %d ad)' % ad_frags
         else:
             total_frags_str = 'unknown (live)'
-        self.to_screen(
-            '[%s] Total fragments: %s' % (self.FD_NAME, total_frags_str))
+        self.to_screen(f'[{self.FD_NAME}] Total fragments: {total_frags_str}')
         self.report_destination(ctx['filename'])
         dl = HttpQuietDownloader(
             self.ydl,
@@ -342,8 +339,7 @@ def _prepare_external_frag_download(self, ctx):
                 total_frags_str += ' (not including %d ad)' % ad_frags
         else:
             total_frags_str = 'unknown (live)'
-        self.to_screen(
-            '[%s] Total fragments: %s' % (self.FD_NAME, total_frags_str))
+        self.to_screen(f'[{self.FD_NAME}] Total fragments: {total_frags_str}')
 
         tmpfilename = self.temp_name(ctx['filename'])
 
diff --git a/yt_dlp/downloader/hls.py b/yt_dlp/downloader/hls.py
index e932fd6aea..00695f93fc 100644
--- a/yt_dlp/downloader/hls.py
+++ b/yt_dlp/downloader/hls.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 import io
 import binascii
@@ -102,8 +100,7 @@ def real_download(self, filename, info_dict):
         if real_downloader and not real_downloader.supports_manifest(s):
             real_downloader = None
         if real_downloader:
-            self.to_screen(
-                '[%s] Fragment downloads will be delegated to %s' % (self.FD_NAME, real_downloader.get_basename()))
+            self.to_screen(f'[{self.FD_NAME}] Fragment downloads will be delegated to {real_downloader.get_basename()}')
 
         def is_ad_fragment_start(s):
             return (s.startswith('#ANVATO-SEGMENT-INFO') and 'type=ad' in s
diff --git a/yt_dlp/downloader/http.py b/yt_dlp/downloader/http.py
index a232168fa3..03efbf1cdb 100644
--- a/yt_dlp/downloader/http.py
+++ b/yt_dlp/downloader/http.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import os
 import ssl
 import time
@@ -221,10 +219,12 @@ def download():
                 min_data_len = self.params.get('min_filesize')
                 max_data_len = self.params.get('max_filesize')
                 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
                 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
 
             byte_counter = 0 + ctx.resume_len
@@ -265,7 +265,7 @@ def retry(e):
                         assert ctx.stream is not None
                         ctx.filename = self.undo_temp_name(ctx.tmpfilename)
                         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))
                         return False
 
@@ -277,7 +277,7 @@ def retry(e):
 
                 try:
                     ctx.stream.write(data_block)
-                except (IOError, OSError) as err:
+                except OSError as err:
                     self.to_stderr('\n')
                     self.report_error('unable to write data: %s' % str(err))
                     return False
diff --git a/yt_dlp/downloader/ism.py b/yt_dlp/downloader/ism.py
index 2ba36085ea..ca4ca3a198 100644
--- a/yt_dlp/downloader/ism.py
+++ b/yt_dlp/downloader/ism.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import time
 import binascii
 import io
diff --git a/yt_dlp/downloader/mhtml.py b/yt_dlp/downloader/mhtml.py
index 54e7117925..5a322f1db7 100644
--- a/yt_dlp/downloader/mhtml.py
+++ b/yt_dlp/downloader/mhtml.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import io
 import quopri
 import re
diff --git a/yt_dlp/downloader/niconico.py b/yt_dlp/downloader/niconico.py
index 521dfece31..0e6c177b73 100644
--- a/yt_dlp/downloader/niconico.py
+++ b/yt_dlp/downloader/niconico.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import threading
 
 from .common import FileDownloader
diff --git a/yt_dlp/downloader/rtmp.py b/yt_dlp/downloader/rtmp.py
index 90f1acfd44..12aa04cf3c 100644
--- a/yt_dlp/downloader/rtmp.py
+++ b/yt_dlp/downloader/rtmp.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import os
 import re
 import subprocess
diff --git a/yt_dlp/downloader/rtsp.py b/yt_dlp/downloader/rtsp.py
index 7815d59d97..26dbd9ef75 100644
--- a/yt_dlp/downloader/rtsp.py
+++ b/yt_dlp/downloader/rtsp.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import os
 import subprocess
 
@@ -32,7 +30,7 @@ def real_download(self, filename, info_dict):
         retval = subprocess.call(args)
         if retval == 0:
             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._hook_progress({
                 'downloaded_bytes': fsize,
diff --git a/yt_dlp/downloader/youtube_live_chat.py b/yt_dlp/downloader/youtube_live_chat.py
index cfca686ee4..36c82b03bd 100644
--- a/yt_dlp/downloader/youtube_live_chat.py
+++ b/yt_dlp/downloader/youtube_live_chat.py
@@ -1,5 +1,3 @@
-from __future__ import division, unicode_literals
-
 import json
 import time
 
diff --git a/yt_dlp/extractor/abc.py b/yt_dlp/extractor/abc.py
index 6fe195e82c..03f10ab23d 100644
--- a/yt_dlp/extractor/abc.py
+++ b/yt_dlp/extractor/abc.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import hashlib
 import hmac
 import re
diff --git a/yt_dlp/extractor/abcnews.py b/yt_dlp/extractor/abcnews.py
index 296b8cec1d..a57295b131 100644
--- a/yt_dlp/extractor/abcnews.py
+++ b/yt_dlp/extractor/abcnews.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .amp import AMPIE
 from .common import InfoExtractor
 from ..utils import (
diff --git a/yt_dlp/extractor/abcotvs.py b/yt_dlp/extractor/abcotvs.py
index 5bff466340..44a9f8ca5e 100644
--- a/yt_dlp/extractor/abcotvs.py
+++ b/yt_dlp/extractor/abcotvs.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/academicearth.py b/yt_dlp/extractor/academicearth.py
index 34095501cf..d9691cb5c6 100644
--- a/yt_dlp/extractor/academicearth.py
+++ b/yt_dlp/extractor/academicearth.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/acast.py b/yt_dlp/extractor/acast.py
index 63587c5cff..f2f828f8e7 100644
--- a/yt_dlp/extractor/acast.py
+++ b/yt_dlp/extractor/acast.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/adn.py b/yt_dlp/extractor/adn.py
index fca6e605da..b47345e3c5 100644
--- a/yt_dlp/extractor/adn.py
+++ b/yt_dlp/extractor/adn.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import binascii
 import json
diff --git a/yt_dlp/extractor/adobeconnect.py b/yt_dlp/extractor/adobeconnect.py
index e2e6f93f31..8963b128a5 100644
--- a/yt_dlp/extractor/adobeconnect.py
+++ b/yt_dlp/extractor/adobeconnect.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_parse_qs,
diff --git a/yt_dlp/extractor/adobepass.py b/yt_dlp/extractor/adobepass.py
index 1292484c69..1bdc8587cc 100644
--- a/yt_dlp/extractor/adobepass.py
+++ b/yt_dlp/extractor/adobepass.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 import time
diff --git a/yt_dlp/extractor/adobetv.py b/yt_dlp/extractor/adobetv.py
index 3cfa1ff550..941254243f 100644
--- a/yt_dlp/extractor/adobetv.py
+++ b/yt_dlp/extractor/adobetv.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/adultswim.py b/yt_dlp/extractor/adultswim.py
index c97cfc1611..1368954bc6 100644
--- a/yt_dlp/extractor/adultswim.py
+++ b/yt_dlp/extractor/adultswim.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .turner import TurnerBaseIE
diff --git a/yt_dlp/extractor/aenetworks.py b/yt_dlp/extractor/aenetworks.py
index 8025de5a32..86a10f2dcd 100644
--- a/yt_dlp/extractor/aenetworks.py
+++ b/yt_dlp/extractor/aenetworks.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .theplatform import ThePlatformIE
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/afreecatv.py b/yt_dlp/extractor/afreecatv.py
index 44bfb8bc24..b0fd158f61 100644
--- a/yt_dlp/extractor/afreecatv.py
+++ b/yt_dlp/extractor/afreecatv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/airmozilla.py b/yt_dlp/extractor/airmozilla.py
index 9e38136b4b..669556b98f 100644
--- a/yt_dlp/extractor/airmozilla.py
+++ b/yt_dlp/extractor/airmozilla.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/aliexpress.py b/yt_dlp/extractor/aliexpress.py
index 9722fe9ac3..2e83f2eb6e 100644
--- a/yt_dlp/extractor/aliexpress.py
+++ b/yt_dlp/extractor/aliexpress.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/aljazeera.py b/yt_dlp/extractor/aljazeera.py
index 7bcdb7afba..124bab0d92 100644
--- a/yt_dlp/extractor/aljazeera.py
+++ b/yt_dlp/extractor/aljazeera.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/allocine.py b/yt_dlp/extractor/allocine.py
index 403a277e97..1f881e2a09 100644
--- a/yt_dlp/extractor/allocine.py
+++ b/yt_dlp/extractor/allocine.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/alphaporno.py b/yt_dlp/extractor/alphaporno.py
index 3a6d99f6bf..8d5b472d32 100644
--- a/yt_dlp/extractor/alphaporno.py
+++ b/yt_dlp/extractor/alphaporno.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     parse_iso8601,
diff --git a/yt_dlp/extractor/alsace20tv.py b/yt_dlp/extractor/alsace20tv.py
index 4aae6fe743..d16ab496e9 100644
--- a/yt_dlp/extractor/alsace20tv.py
+++ b/yt_dlp/extractor/alsace20tv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/alura.py b/yt_dlp/extractor/alura.py
index d2e2df2707..b76ccb2a19 100644
--- a/yt_dlp/extractor/alura.py
+++ b/yt_dlp/extractor/alura.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/amara.py b/yt_dlp/extractor/amara.py
index 61d469574a..5018710e03 100644
--- a/yt_dlp/extractor/amara.py
+++ b/yt_dlp/extractor/amara.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .youtube import YoutubeIE
 from .vimeo import VimeoIE
diff --git a/yt_dlp/extractor/amazon.py b/yt_dlp/extractor/amazon.py
index 07b1b18611..de4917adcc 100644
--- a/yt_dlp/extractor/amazon.py
+++ b/yt_dlp/extractor/amazon.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/amcnetworks.py b/yt_dlp/extractor/amcnetworks.py
index e38e215d3f..e04ecf65f0 100644
--- a/yt_dlp/extractor/amcnetworks.py
+++ b/yt_dlp/extractor/amcnetworks.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .theplatform import ThePlatformIE
diff --git a/yt_dlp/extractor/americastestkitchen.py b/yt_dlp/extractor/americastestkitchen.py
index 6e6099a03d..f5747cf1e8 100644
--- a/yt_dlp/extractor/americastestkitchen.py
+++ b/yt_dlp/extractor/americastestkitchen.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/amp.py b/yt_dlp/extractor/amp.py
index 24c684cad7..73b72b0859 100644
--- a/yt_dlp/extractor/amp.py
+++ b/yt_dlp/extractor/amp.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/animelab.py b/yt_dlp/extractor/animelab.py
index 1c2cc47ddd..cd0d77805d 100644
--- a/yt_dlp/extractor/animelab.py
+++ b/yt_dlp/extractor/animelab.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..utils import (
diff --git a/yt_dlp/extractor/animeondemand.py b/yt_dlp/extractor/animeondemand.py
index 2e674d58fc..de49db4ea7 100644
--- a/yt_dlp/extractor/animeondemand.py
+++ b/yt_dlp/extractor/animeondemand.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ant1newsgr.py b/yt_dlp/extractor/ant1newsgr.py
index 1075b461ed..cd0f368569 100644
--- a/yt_dlp/extractor/ant1newsgr.py
+++ b/yt_dlp/extractor/ant1newsgr.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import urllib.parse
 
diff --git a/yt_dlp/extractor/anvato.py b/yt_dlp/extractor/anvato.py
index 0d444fc33e..28fbd606ef 100644
--- a/yt_dlp/extractor/anvato.py
+++ b/yt_dlp/extractor/anvato.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import hashlib
 import json
diff --git a/yt_dlp/extractor/anvato_token_generator/__init__.py b/yt_dlp/extractor/anvato_token_generator/__init__.py
index 6e223db9fc..6530caf530 100644
--- a/yt_dlp/extractor/anvato_token_generator/__init__.py
+++ b/yt_dlp/extractor/anvato_token_generator/__init__.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .nfl import NFLTokenGenerator
 
 __all__ = [
diff --git a/yt_dlp/extractor/anvato_token_generator/common.py b/yt_dlp/extractor/anvato_token_generator/common.py
index b959a903bd..3800b5808e 100644
--- a/yt_dlp/extractor/anvato_token_generator/common.py
+++ b/yt_dlp/extractor/anvato_token_generator/common.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 class TokenGenerator:
     def generate(self, anvack, mcp_id):
         raise NotImplementedError('This method must be implemented by subclasses')
diff --git a/yt_dlp/extractor/anvato_token_generator/nfl.py b/yt_dlp/extractor/anvato_token_generator/nfl.py
index 97a2b245f7..9ee4aa002e 100644
--- a/yt_dlp/extractor/anvato_token_generator/nfl.py
+++ b/yt_dlp/extractor/anvato_token_generator/nfl.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import TokenGenerator
diff --git a/yt_dlp/extractor/aol.py b/yt_dlp/extractor/aol.py
index 4766a2c774..b67db2adca 100644
--- a/yt_dlp/extractor/aol.py
+++ b/yt_dlp/extractor/aol.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .yahoo import YahooIE
diff --git a/yt_dlp/extractor/apa.py b/yt_dlp/extractor/apa.py
index 1736cdf566..847be6edf7 100644
--- a/yt_dlp/extractor/apa.py
+++ b/yt_dlp/extractor/apa.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/aparat.py b/yt_dlp/extractor/aparat.py
index 1057233cf4..cd6cd1c790 100644
--- a/yt_dlp/extractor/aparat.py
+++ b/yt_dlp/extractor/aparat.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     get_element_by_id,
diff --git a/yt_dlp/extractor/appleconnect.py b/yt_dlp/extractor/appleconnect.py
index 494f8330c1..d00b0f9060 100644
--- a/yt_dlp/extractor/appleconnect.py
+++ b/yt_dlp/extractor/appleconnect.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     str_to_int,
diff --git a/yt_dlp/extractor/applepodcasts.py b/yt_dlp/extractor/applepodcasts.py
index 9139ff777a..49bbeab823 100644
--- a/yt_dlp/extractor/applepodcasts.py
+++ b/yt_dlp/extractor/applepodcasts.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/appletrailers.py b/yt_dlp/extractor/appletrailers.py
index 8140e332be..6b63f070d6 100644
--- a/yt_dlp/extractor/appletrailers.py
+++ b/yt_dlp/extractor/appletrailers.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 import json
 
diff --git a/yt_dlp/extractor/archiveorg.py b/yt_dlp/extractor/archiveorg.py
index 2ab3c1bebd..c85d5297d3 100644
--- a/yt_dlp/extractor/archiveorg.py
+++ b/yt_dlp/extractor/archiveorg.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import json
 from .common import InfoExtractor
@@ -479,7 +476,7 @@ def _call_cdx_api(self, item_id, url, filters: list = None, collapse: list = Non
 
     def _extract_yt_initial_variable(self, webpage, regex, video_id, name):
         return self._parse_json(self._search_regex(
-            (r'%s\s*%s' % (regex, self._YT_INITIAL_BOUNDARY_RE),
+            (fr'{regex}\s*{self._YT_INITIAL_BOUNDARY_RE}',
              regex), webpage, name, default='{}'), video_id, fatal=False)
 
     def _extract_webpage_title(self, webpage):
@@ -597,7 +594,7 @@ def _get_capture_dates(self, video_id, url_date):
         response = self._call_cdx_api(
             video_id, f'https://www.youtube.com/watch?v={video_id}',
             filters=['mimetype:text/html'], collapse=['timestamp:6', 'digest'], query={'matchType': 'prefix'}) or []
-        all_captures = sorted([int_or_none(r['timestamp']) for r in response if int_or_none(r['timestamp']) is not None])
+        all_captures = sorted(int_or_none(r['timestamp']) for r in response if int_or_none(r['timestamp']) is not None)
 
         # Prefer the new polymer UI captures as we support extracting more metadata from them
         # WBM captures seem to all switch to this layout ~July 2020
diff --git a/yt_dlp/extractor/arcpublishing.py b/yt_dlp/extractor/arcpublishing.py
index 8880e5c957..2e3f3cc5fb 100644
--- a/yt_dlp/extractor/arcpublishing.py
+++ b/yt_dlp/extractor/arcpublishing.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ard.py b/yt_dlp/extractor/ard.py
index 7ea339b399..f294679eff 100644
--- a/yt_dlp/extractor/ard.py
+++ b/yt_dlp/extractor/ard.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/arkena.py b/yt_dlp/extractor/arkena.py
index 4f4f457c16..9da2bfd5e0 100644
--- a/yt_dlp/extractor/arkena.py
+++ b/yt_dlp/extractor/arkena.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/arnes.py b/yt_dlp/extractor/arnes.py
index 050c252e3f..96b134fa0e 100644
--- a/yt_dlp/extractor/arnes.py
+++ b/yt_dlp/extractor/arnes.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_parse_qs,
diff --git a/yt_dlp/extractor/arte.py b/yt_dlp/extractor/arte.py
index c2f2c1bd3c..443b0d4b9e 100644
--- a/yt_dlp/extractor/arte.py
+++ b/yt_dlp/extractor/arte.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/asiancrush.py b/yt_dlp/extractor/asiancrush.py
index 7f1940fcab..23f310edb3 100644
--- a/yt_dlp/extractor/asiancrush.py
+++ b/yt_dlp/extractor/asiancrush.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/atresplayer.py b/yt_dlp/extractor/atresplayer.py
index 465af4ed34..39d1f1cc56 100644
--- a/yt_dlp/extractor/atresplayer.py
+++ b/yt_dlp/extractor/atresplayer.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_HTTPError
 from ..utils import (
diff --git a/yt_dlp/extractor/atttechchannel.py b/yt_dlp/extractor/atttechchannel.py
index 8f93fb3534..6ff4ec0ad3 100644
--- a/yt_dlp/extractor/atttechchannel.py
+++ b/yt_dlp/extractor/atttechchannel.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import unified_strdate
 
diff --git a/yt_dlp/extractor/atvat.py b/yt_dlp/extractor/atvat.py
index 481a09737a..2311837e91 100644
--- a/yt_dlp/extractor/atvat.py
+++ b/yt_dlp/extractor/atvat.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import datetime
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/audimedia.py b/yt_dlp/extractor/audimedia.py
index 6bd48ef159..c1c4f67d0a 100644
--- a/yt_dlp/extractor/audimedia.py
+++ b/yt_dlp/extractor/audimedia.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/audioboom.py b/yt_dlp/extractor/audioboom.py
index c51837b406..dc19a3874b 100644
--- a/yt_dlp/extractor/audioboom.py
+++ b/yt_dlp/extractor/audioboom.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/audiomack.py b/yt_dlp/extractor/audiomack.py
index 19775cf0f3..5c4160fe46 100644
--- a/yt_dlp/extractor/audiomack.py
+++ b/yt_dlp/extractor/audiomack.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import time
 
diff --git a/yt_dlp/extractor/audius.py b/yt_dlp/extractor/audius.py
index fa64995d50..189d1224fb 100644
--- a/yt_dlp/extractor/audius.py
+++ b/yt_dlp/extractor/audius.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/awaan.py b/yt_dlp/extractor/awaan.py
index f5e559c9f4..d289f6be30 100644
--- a/yt_dlp/extractor/awaan.py
+++ b/yt_dlp/extractor/awaan.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/aws.py b/yt_dlp/extractor/aws.py
index dccfeaf734..c2b22922be 100644
--- a/yt_dlp/extractor/aws.py
+++ b/yt_dlp/extractor/aws.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import datetime
 import hashlib
 import hmac
diff --git a/yt_dlp/extractor/azmedien.py b/yt_dlp/extractor/azmedien.py
index 0168340b93..d1686eed64 100644
--- a/yt_dlp/extractor/azmedien.py
+++ b/yt_dlp/extractor/azmedien.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/baidu.py b/yt_dlp/extractor/baidu.py
index 364fd94591..8786d67e06 100644
--- a/yt_dlp/extractor/baidu.py
+++ b/yt_dlp/extractor/baidu.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import unescapeHTML
 
diff --git a/yt_dlp/extractor/banbye.py b/yt_dlp/extractor/banbye.py
index 3d4d36ec36..92f567c5db 100644
--- a/yt_dlp/extractor/banbye.py
+++ b/yt_dlp/extractor/banbye.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import math
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/bandaichannel.py b/yt_dlp/extractor/bandaichannel.py
index f1bcdef7a3..2e32333761 100644
--- a/yt_dlp/extractor/bandaichannel.py
+++ b/yt_dlp/extractor/bandaichannel.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .brightcove import BrightcoveNewIE
 from ..utils import extract_attributes
 
diff --git a/yt_dlp/extractor/bandcamp.py b/yt_dlp/extractor/bandcamp.py
index 745055e2d5..5863eaeca6 100644
--- a/yt_dlp/extractor/bandcamp.py
+++ b/yt_dlp/extractor/bandcamp.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 import re
 import time
diff --git a/yt_dlp/extractor/bannedvideo.py b/yt_dlp/extractor/bannedvideo.py
index 3db1151f6d..ec9bdd8cad 100644
--- a/yt_dlp/extractor/bannedvideo.py
+++ b/yt_dlp/extractor/bannedvideo.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/bbc.py b/yt_dlp/extractor/bbc.py
index 5bc8d3110c..9cb019a491 100644
--- a/yt_dlp/extractor/bbc.py
+++ b/yt_dlp/extractor/bbc.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import xml.etree.ElementTree
 import functools
 import itertools
diff --git a/yt_dlp/extractor/beatport.py b/yt_dlp/extractor/beatport.py
index e1cf8b4fe7..f71f1f3080 100644
--- a/yt_dlp/extractor/beatport.py
+++ b/yt_dlp/extractor/beatport.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/beeg.py b/yt_dlp/extractor/beeg.py
index 717fff3a68..5957e370ab 100644
--- a/yt_dlp/extractor/beeg.py
+++ b/yt_dlp/extractor/beeg.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..utils import (
diff --git a/yt_dlp/extractor/behindkink.py b/yt_dlp/extractor/behindkink.py
index 2c97f9817d..ca4498150e 100644
--- a/yt_dlp/extractor/behindkink.py
+++ b/yt_dlp/extractor/behindkink.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import url_basename
 
diff --git a/yt_dlp/extractor/bellmedia.py b/yt_dlp/extractor/bellmedia.py
index 904c17ed00..8f9849d9b6 100644
--- a/yt_dlp/extractor/bellmedia.py
+++ b/yt_dlp/extractor/bellmedia.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/bet.py b/yt_dlp/extractor/bet.py
index 2c71442350..6b867d135f 100644
--- a/yt_dlp/extractor/bet.py
+++ b/yt_dlp/extractor/bet.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .mtv import MTVServicesInfoExtractor
 from ..utils import unified_strdate
 
diff --git a/yt_dlp/extractor/bfi.py b/yt_dlp/extractor/bfi.py
index 60c8944b53..76f0516a4d 100644
--- a/yt_dlp/extractor/bfi.py
+++ b/yt_dlp/extractor/bfi.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/bfmtv.py b/yt_dlp/extractor/bfmtv.py
index 501f69d802..48526e38b6 100644
--- a/yt_dlp/extractor/bfmtv.py
+++ b/yt_dlp/extractor/bfmtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/bibeltv.py b/yt_dlp/extractor/bibeltv.py
index 56c2bfee87..fd20aadad4 100644
--- a/yt_dlp/extractor/bibeltv.py
+++ b/yt_dlp/extractor/bibeltv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/bigflix.py b/yt_dlp/extractor/bigflix.py
index 28e3e59f67..6b2797ca00 100644
--- a/yt_dlp/extractor/bigflix.py
+++ b/yt_dlp/extractor/bigflix.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/bigo.py b/yt_dlp/extractor/bigo.py
index ddf76ac55c..f39e15002e 100644
--- a/yt_dlp/extractor/bigo.py
+++ b/yt_dlp/extractor/bigo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import ExtractorError, urlencode_postdata
 
diff --git a/yt_dlp/extractor/bild.py b/yt_dlp/extractor/bild.py
index b8dfbd42b4..f3dea33c46 100644
--- a/yt_dlp/extractor/bild.py
+++ b/yt_dlp/extractor/bild.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/bilibili.py b/yt_dlp/extractor/bilibili.py
index a9574758cc..eb2dcb0244 100644
--- a/yt_dlp/extractor/bilibili.py
+++ b/yt_dlp/extractor/bilibili.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 import base64
 import hashlib
 import itertools
diff --git a/yt_dlp/extractor/biobiochiletv.py b/yt_dlp/extractor/biobiochiletv.py
index dc86c57c5d..180c9656e3 100644
--- a/yt_dlp/extractor/biobiochiletv.py
+++ b/yt_dlp/extractor/biobiochiletv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/biqle.py b/yt_dlp/extractor/biqle.py
index 2b57bade3d..3a42344916 100644
--- a/yt_dlp/extractor/biqle.py
+++ b/yt_dlp/extractor/biqle.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .vk import VKIE
 from ..compat import compat_b64decode
diff --git a/yt_dlp/extractor/bitchute.py b/yt_dlp/extractor/bitchute.py
index dcae6f4cc8..c831092d4c 100644
--- a/yt_dlp/extractor/bitchute.py
+++ b/yt_dlp/extractor/bitchute.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import re
 
diff --git a/yt_dlp/extractor/bitwave.py b/yt_dlp/extractor/bitwave.py
index e6e093f597..bd8eac1f13 100644
--- a/yt_dlp/extractor/bitwave.py
+++ b/yt_dlp/extractor/bitwave.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/blackboardcollaborate.py b/yt_dlp/extractor/blackboardcollaborate.py
index 8ae2941984..8f41c897ad 100644
--- a/yt_dlp/extractor/blackboardcollaborate.py
+++ b/yt_dlp/extractor/blackboardcollaborate.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import parse_iso8601
 
diff --git a/yt_dlp/extractor/bleacherreport.py b/yt_dlp/extractor/bleacherreport.py
index d1bf8e8293..8d8fabe331 100644
--- a/yt_dlp/extractor/bleacherreport.py
+++ b/yt_dlp/extractor/bleacherreport.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .amp import AMPIE
 from ..utils import (
diff --git a/yt_dlp/extractor/blinkx.py b/yt_dlp/extractor/blinkx.py
index d70a3b30ff..80531ccadd 100644
--- a/yt_dlp/extractor/blinkx.py
+++ b/yt_dlp/extractor/blinkx.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/blogger.py b/yt_dlp/extractor/blogger.py
index dba131cb05..d7aa7f94eb 100644
--- a/yt_dlp/extractor/blogger.py
+++ b/yt_dlp/extractor/blogger.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from ..utils import (
diff --git a/yt_dlp/extractor/bloomberg.py b/yt_dlp/extractor/bloomberg.py
index 2fbfad1ba0..c0aaeae02b 100644
--- a/yt_dlp/extractor/bloomberg.py
+++ b/yt_dlp/extractor/bloomberg.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/bokecc.py b/yt_dlp/extractor/bokecc.py
index 6a89d36f49..0c081750e4 100644
--- a/yt_dlp/extractor/bokecc.py
+++ b/yt_dlp/extractor/bokecc.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_parse_qs
 from ..utils import ExtractorError
diff --git a/yt_dlp/extractor/bongacams.py b/yt_dlp/extractor/bongacams.py
index 4e346e7b6e..cbef0fc53a 100644
--- a/yt_dlp/extractor/bongacams.py
+++ b/yt_dlp/extractor/bongacams.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/bostonglobe.py b/yt_dlp/extractor/bostonglobe.py
index 57882fbeea..92f8ea2cb4 100644
--- a/yt_dlp/extractor/bostonglobe.py
+++ b/yt_dlp/extractor/bostonglobe.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/box.py b/yt_dlp/extractor/box.py
index 8214086a6f..5842de88a8 100644
--- a/yt_dlp/extractor/box.py
+++ b/yt_dlp/extractor/box.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/bpb.py b/yt_dlp/extractor/bpb.py
index 98491975c6..388f1f94fb 100644
--- a/yt_dlp/extractor/bpb.py
+++ b/yt_dlp/extractor/bpb.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/br.py b/yt_dlp/extractor/br.py
index 0155827d8f..faac442e89 100644
--- a/yt_dlp/extractor/br.py
+++ b/yt_dlp/extractor/br.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/bravotv.py b/yt_dlp/extractor/bravotv.py
index 139d51c09f..d4895848e0 100644
--- a/yt_dlp/extractor/bravotv.py
+++ b/yt_dlp/extractor/bravotv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .adobepass import AdobePassIE
diff --git a/yt_dlp/extractor/breakcom.py b/yt_dlp/extractor/breakcom.py
index f38789f998..51c8c822fa 100644
--- a/yt_dlp/extractor/breakcom.py
+++ b/yt_dlp/extractor/breakcom.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from .youtube import YoutubeIE
 from ..utils import (
diff --git a/yt_dlp/extractor/breitbart.py b/yt_dlp/extractor/breitbart.py
index e029aa627f..a2b04fccee 100644
--- a/yt_dlp/extractor/breitbart.py
+++ b/yt_dlp/extractor/breitbart.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/brightcove.py b/yt_dlp/extractor/brightcove.py
index 60c853898a..936c34e158 100644
--- a/yt_dlp/extractor/brightcove.py
+++ b/yt_dlp/extractor/brightcove.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import re
 import struct
diff --git a/yt_dlp/extractor/businessinsider.py b/yt_dlp/extractor/businessinsider.py
index 73a57b1e4d..4b3f5e68b8 100644
--- a/yt_dlp/extractor/businessinsider.py
+++ b/yt_dlp/extractor/businessinsider.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .jwplatform import JWPlatformIE
 
diff --git a/yt_dlp/extractor/buzzfeed.py b/yt_dlp/extractor/buzzfeed.py
index ec411091ef..1b4cba63e2 100644
--- a/yt_dlp/extractor/buzzfeed.py
+++ b/yt_dlp/extractor/buzzfeed.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/byutv.py b/yt_dlp/extractor/byutv.py
index f4d5086ed7..eca2e294e7 100644
--- a/yt_dlp/extractor/byutv.py
+++ b/yt_dlp/extractor/byutv.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/c56.py b/yt_dlp/extractor/c56.py
index a853c530cc..1d98ea5983 100644
--- a/yt_dlp/extractor/c56.py
+++ b/yt_dlp/extractor/c56.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import js_to_json
 
diff --git a/yt_dlp/extractor/cableav.py b/yt_dlp/extractor/cableav.py
index 77efdf45af..3200b56771 100644
--- a/yt_dlp/extractor/cableav.py
+++ b/yt_dlp/extractor/cableav.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/callin.py b/yt_dlp/extractor/callin.py
index 1f3b7cfff9..fc5da70283 100644
--- a/yt_dlp/extractor/callin.py
+++ b/yt_dlp/extractor/callin.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from ..utils import (
     traverse_obj,
diff --git a/yt_dlp/extractor/caltrans.py b/yt_dlp/extractor/caltrans.py
index 9ac740f7e9..e52dfb1706 100644
--- a/yt_dlp/extractor/caltrans.py
+++ b/yt_dlp/extractor/caltrans.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/cam4.py b/yt_dlp/extractor/cam4.py
index 2a3931fd07..4256b28e08 100644
--- a/yt_dlp/extractor/cam4.py
+++ b/yt_dlp/extractor/cam4.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/camdemy.py b/yt_dlp/extractor/camdemy.py
index 8f0c6c545c..c7079e4224 100644
--- a/yt_dlp/extractor/camdemy.py
+++ b/yt_dlp/extractor/camdemy.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/cammodels.py b/yt_dlp/extractor/cammodels.py
index 3dc19377b3..32fbffcc2c 100644
--- a/yt_dlp/extractor/cammodels.py
+++ b/yt_dlp/extractor/cammodels.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/camwithher.py b/yt_dlp/extractor/camwithher.py
index bbc5205fde..a0b3749edf 100644
--- a/yt_dlp/extractor/camwithher.py
+++ b/yt_dlp/extractor/camwithher.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/canalalpha.py b/yt_dlp/extractor/canalalpha.py
index 0365cb2f69..f2ec9355f4 100644
--- a/yt_dlp/extractor/canalalpha.py
+++ b/yt_dlp/extractor/canalalpha.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/canalc2.py b/yt_dlp/extractor/canalc2.py
index 407cc80848..c9bb94c402 100644
--- a/yt_dlp/extractor/canalc2.py
+++ b/yt_dlp/extractor/canalc2.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/canalplus.py b/yt_dlp/extractor/canalplus.py
index 211ea267a2..b184398e2d 100644
--- a/yt_dlp/extractor/canalplus.py
+++ b/yt_dlp/extractor/canalplus.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     # ExtractorError,
diff --git a/yt_dlp/extractor/canvas.py b/yt_dlp/extractor/canvas.py
index 8b9903774d..8eff4a57c1 100644
--- a/yt_dlp/extractor/canvas.py
+++ b/yt_dlp/extractor/canvas.py
@@ -1,4 +1,3 @@
-from __future__ import unicode_literals
 import json
 
 
diff --git a/yt_dlp/extractor/carambatv.py b/yt_dlp/extractor/carambatv.py
index 7e5cc90fb5..087ea8aa08 100644
--- a/yt_dlp/extractor/carambatv.py
+++ b/yt_dlp/extractor/carambatv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/cartoonnetwork.py b/yt_dlp/extractor/cartoonnetwork.py
index 48b33617f2..4dd7ac46d4 100644
--- a/yt_dlp/extractor/cartoonnetwork.py
+++ b/yt_dlp/extractor/cartoonnetwork.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .turner import TurnerBaseIE
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/cbc.py b/yt_dlp/extractor/cbc.py
index fba8bf965f..cac3f1e9d0 100644
--- a/yt_dlp/extractor/cbc.py
+++ b/yt_dlp/extractor/cbc.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import json
 import base64
diff --git a/yt_dlp/extractor/cbs.py b/yt_dlp/extractor/cbs.py
index 2af36ea825..e32539c9e7 100644
--- a/yt_dlp/extractor/cbs.py
+++ b/yt_dlp/extractor/cbs.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .theplatform import ThePlatformFeedIE
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/cbsinteractive.py b/yt_dlp/extractor/cbsinteractive.py
index 9d4f754354..7abeecf78a 100644
--- a/yt_dlp/extractor/cbsinteractive.py
+++ b/yt_dlp/extractor/cbsinteractive.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .cbs import CBSIE
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/cbslocal.py b/yt_dlp/extractor/cbslocal.py
index 3b7e1a8b9f..c6495c95fe 100644
--- a/yt_dlp/extractor/cbslocal.py
+++ b/yt_dlp/extractor/cbslocal.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .anvato import AnvatoIE
 from .sendtonews import SendtoNewsIE
 from ..compat import compat_urlparse
diff --git a/yt_dlp/extractor/cbsnews.py b/yt_dlp/extractor/cbsnews.py
index 1285ed65e5..76925b4f9b 100644
--- a/yt_dlp/extractor/cbsnews.py
+++ b/yt_dlp/extractor/cbsnews.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import zlib
 
diff --git a/yt_dlp/extractor/cbssports.py b/yt_dlp/extractor/cbssports.py
index b8a6e59678..56a2551497 100644
--- a/yt_dlp/extractor/cbssports.py
+++ b/yt_dlp/extractor/cbssports.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 # from .cbs import CBSBaseIE
 from .common import InfoExtractor
 from ..utils import (
diff --git a/yt_dlp/extractor/ccc.py b/yt_dlp/extractor/ccc.py
index 36e6dff72c..b11e1f74ed 100644
--- a/yt_dlp/extractor/ccc.py
+++ b/yt_dlp/extractor/ccc.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/ccma.py b/yt_dlp/extractor/ccma.py
index 9dbaabfa08..ca739f8a14 100644
--- a/yt_dlp/extractor/ccma.py
+++ b/yt_dlp/extractor/ccma.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/cctv.py b/yt_dlp/extractor/cctv.py
index 0ed5f327b6..623cbb3420 100644
--- a/yt_dlp/extractor/cctv.py
+++ b/yt_dlp/extractor/cctv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/cda.py b/yt_dlp/extractor/cda.py
index 72c47050ff..9b257bee97 100644
--- a/yt_dlp/extractor/cda.py
+++ b/yt_dlp/extractor/cda.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import codecs
 import re
 import json
diff --git a/yt_dlp/extractor/ceskatelevize.py b/yt_dlp/extractor/ceskatelevize.py
index ddf66b2070..331b350f1d 100644
--- a/yt_dlp/extractor/ceskatelevize.py
+++ b/yt_dlp/extractor/ceskatelevize.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/cgtn.py b/yt_dlp/extractor/cgtn.py
index 89f173887e..aaafa02d1b 100644
--- a/yt_dlp/extractor/cgtn.py
+++ b/yt_dlp/extractor/cgtn.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     try_get,
diff --git a/yt_dlp/extractor/channel9.py b/yt_dlp/extractor/channel9.py
index 90024dbbad..90a1ab2bee 100644
--- a/yt_dlp/extractor/channel9.py
+++ b/yt_dlp/extractor/channel9.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/charlierose.py b/yt_dlp/extractor/charlierose.py
index 42c9af263e..27f8b33e54 100644
--- a/yt_dlp/extractor/charlierose.py
+++ b/yt_dlp/extractor/charlierose.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import remove_end
 
diff --git a/yt_dlp/extractor/chaturbate.py b/yt_dlp/extractor/chaturbate.py
index 8da51f9196..d39210bf74 100644
--- a/yt_dlp/extractor/chaturbate.py
+++ b/yt_dlp/extractor/chaturbate.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/chilloutzone.py b/yt_dlp/extractor/chilloutzone.py
index fd5202b9e4..1a2f77c4eb 100644
--- a/yt_dlp/extractor/chilloutzone.py
+++ b/yt_dlp/extractor/chilloutzone.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/chingari.py b/yt_dlp/extractor/chingari.py
index e6841fb8b2..40613cfa3a 100644
--- a/yt_dlp/extractor/chingari.py
+++ b/yt_dlp/extractor/chingari.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import json
 
diff --git a/yt_dlp/extractor/chirbit.py b/yt_dlp/extractor/chirbit.py
index 8d75cdf199..452711d973 100644
--- a/yt_dlp/extractor/chirbit.py
+++ b/yt_dlp/extractor/chirbit.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/cinchcast.py b/yt_dlp/extractor/cinchcast.py
index b861d54b0a..393df36984 100644
--- a/yt_dlp/extractor/cinchcast.py
+++ b/yt_dlp/extractor/cinchcast.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     unified_strdate,
diff --git a/yt_dlp/extractor/cinemax.py b/yt_dlp/extractor/cinemax.py
index 2c3ff8d4f9..54cab2285e 100644
--- a/yt_dlp/extractor/cinemax.py
+++ b/yt_dlp/extractor/cinemax.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .hbo import HBOBaseIE
 
 
diff --git a/yt_dlp/extractor/ciscolive.py b/yt_dlp/extractor/ciscolive.py
index 349c5eb50d..0668578170 100644
--- a/yt_dlp/extractor/ciscolive.py
+++ b/yt_dlp/extractor/ciscolive.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ciscowebex.py b/yt_dlp/extractor/ciscowebex.py
index 882dae91b5..e1aae9bda6 100644
--- a/yt_dlp/extractor/ciscowebex.py
+++ b/yt_dlp/extractor/ciscowebex.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/cjsw.py b/yt_dlp/extractor/cjsw.py
index 1dea0d7c71..c37a3b8482 100644
--- a/yt_dlp/extractor/cjsw.py
+++ b/yt_dlp/extractor/cjsw.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/cliphunter.py b/yt_dlp/extractor/cliphunter.py
index f2ca7a337d..7e5fd31750 100644
--- a/yt_dlp/extractor/cliphunter.py
+++ b/yt_dlp/extractor/cliphunter.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/clippit.py b/yt_dlp/extractor/clippit.py
index a1a7a774c6..006a713b2a 100644
--- a/yt_dlp/extractor/clippit.py
+++ b/yt_dlp/extractor/clippit.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     parse_iso8601,
diff --git a/yt_dlp/extractor/cliprs.py b/yt_dlp/extractor/cliprs.py
index d55b26d59f..567f77b94e 100644
--- a/yt_dlp/extractor/cliprs.py
+++ b/yt_dlp/extractor/cliprs.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .onet import OnetBaseIE
 
 
diff --git a/yt_dlp/extractor/clipsyndicate.py b/yt_dlp/extractor/clipsyndicate.py
index 6cdb42f5a4..6064443210 100644
--- a/yt_dlp/extractor/clipsyndicate.py
+++ b/yt_dlp/extractor/clipsyndicate.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     find_xpath_attr,
diff --git a/yt_dlp/extractor/closertotruth.py b/yt_dlp/extractor/closertotruth.py
index 517e121e02..e78e26a113 100644
--- a/yt_dlp/extractor/closertotruth.py
+++ b/yt_dlp/extractor/closertotruth.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/cloudflarestream.py b/yt_dlp/extractor/cloudflarestream.py
index 2fdcfbb3af..0333d5def5 100644
--- a/yt_dlp/extractor/cloudflarestream.py
+++ b/yt_dlp/extractor/cloudflarestream.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import re
 
diff --git a/yt_dlp/extractor/cloudy.py b/yt_dlp/extractor/cloudy.py
index 85ca20eccd..848643e262 100644
--- a/yt_dlp/extractor/cloudy.py
+++ b/yt_dlp/extractor/cloudy.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     str_to_int,
diff --git a/yt_dlp/extractor/clubic.py b/yt_dlp/extractor/clubic.py
index 98f9cb5969..ce86212965 100644
--- a/yt_dlp/extractor/clubic.py
+++ b/yt_dlp/extractor/clubic.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/clyp.py b/yt_dlp/extractor/clyp.py
index e6b2ac4d48..c64726ca27 100644
--- a/yt_dlp/extractor/clyp.py
+++ b/yt_dlp/extractor/clyp.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     float_or_none,
diff --git a/yt_dlp/extractor/cmt.py b/yt_dlp/extractor/cmt.py
index a4ddb91609..4eec066dd7 100644
--- a/yt_dlp/extractor/cmt.py
+++ b/yt_dlp/extractor/cmt.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .mtv import MTVIE
 
 # TODO Remove - Reason: Outdated Site
diff --git a/yt_dlp/extractor/cnbc.py b/yt_dlp/extractor/cnbc.py
index da3730cc82..68fd025b7c 100644
--- a/yt_dlp/extractor/cnbc.py
+++ b/yt_dlp/extractor/cnbc.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import smuggle_url
 
diff --git a/yt_dlp/extractor/cnn.py b/yt_dlp/extractor/cnn.py
index af11d95b43..96482eaf58 100644
--- a/yt_dlp/extractor/cnn.py
+++ b/yt_dlp/extractor/cnn.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from .turner import TurnerBaseIE
 from ..utils import url_basename
diff --git a/yt_dlp/extractor/comedycentral.py b/yt_dlp/extractor/comedycentral.py
index 5a12ab5e69..05fc9f2b50 100644
--- a/yt_dlp/extractor/comedycentral.py
+++ b/yt_dlp/extractor/comedycentral.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .mtv import MTVServicesInfoExtractor
 
 
diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py
index 8da21a3dc5..ef22c78765 100644
--- a/yt_dlp/extractor/common.py
+++ b/yt_dlp/extractor/common.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import collections
 import xml.etree.ElementTree
@@ -92,7 +89,7 @@
 )
 
 
-class InfoExtractor(object):
+class InfoExtractor:
     """Information Extractor class.
 
     Information extractors are the classes that, given a URL, extract
@@ -628,7 +625,7 @@ def _initialize_geo_bypass(self, geo_bypass_context):
             if country:
                 self._x_forwarded_for_ip = GeoUtils.random_ipv4(country)
                 self._downloader.write_debug(
-                    'Using fake IP %s (%s) as X-Forwarded-For' % (self._x_forwarded_for_ip, country.upper()))
+                    f'Using fake IP {self._x_forwarded_for_ip} ({country.upper()}) as X-Forwarded-For')
 
     def extract(self, url):
         """Extracts URL information and returns it in list of dicts."""
@@ -741,9 +738,9 @@ def _request_webpage(self, url_or_request, video_id, note=None, errnote=None, fa
             self.report_download_webpage(video_id)
         elif note is not False:
             if video_id is None:
-                self.to_screen('%s' % (note,))
+                self.to_screen(str(note))
             else:
-                self.to_screen('%s: %s' % (video_id, note))
+                self.to_screen(f'{video_id}: {note}')
 
         # Some sites check X-Forwarded-For HTTP header in order to figure out
         # the origin of the client behind proxy. This allows bypassing geo
@@ -779,7 +776,7 @@ def _request_webpage(self, url_or_request, video_id, note=None, errnote=None, fa
             if errnote is None:
                 errnote = 'Unable to download webpage'
 
-            errmsg = '%s: %s' % (errnote, error_to_compat_str(err))
+            errmsg = f'{errnote}: {error_to_compat_str(err)}'
             if fatal:
                 raise ExtractorError(errmsg, cause=err)
             else:
@@ -860,7 +857,7 @@ def _webpage_read_content(self, urlh, url_or_request, video_id, note=None, errno
             dump = base64.b64encode(webpage_bytes).decode('ascii')
             self._downloader.to_screen(dump)
         if self.get_param('write_pages', False):
-            basen = '%s_%s' % (video_id, urlh.geturl())
+            basen = f'{video_id}_{urlh.geturl()}'
             trim_length = self.get_param('trim_file_name') or 240
             if len(basen) > trim_length:
                 h = '___' + hashlib.md5(basen.encode('utf-8')).hexdigest()
@@ -1098,10 +1095,10 @@ def report_warning(self, msg, video_id=None, *args, only_once=False, **kwargs):
 
     def to_screen(self, msg, *args, **kwargs):
         """Print msg to screen, prefixing it with '[ie_name]'"""
-        self._downloader.to_screen('[%s] %s' % (self.IE_NAME, msg), *args, **kwargs)
+        self._downloader.to_screen(f'[{self.IE_NAME}] {msg}', *args, **kwargs)
 
     def write_debug(self, msg, *args, **kwargs):
-        self._downloader.write_debug('[%s] %s' % (self.IE_NAME, msg), *args, **kwargs)
+        self._downloader.write_debug(f'[{self.IE_NAME}] {msg}', *args, **kwargs)
 
     def get_param(self, name, default=None, *args, **kwargs):
         if self._downloader:
@@ -1138,7 +1135,7 @@ def raise_login_required(
             method = 'any' if self.supports_login() else 'cookies'
         if method is not None:
             assert method in self._LOGIN_HINTS, 'Invalid login method'
-            msg = '%s. %s' % (msg, self._LOGIN_HINTS[method])
+            msg = f'{msg}. {self._LOGIN_HINTS[method]}'
         raise ExtractorError(msg, expected=True)
 
     def raise_geo_restricted(
@@ -1257,7 +1254,7 @@ def _get_netrc_login_info(self, netrc_machine=None):
                 else:
                     raise netrc.NetrcParseError(
                         'No authenticators for %s' % netrc_machine)
-            except (IOError, netrc.NetrcParseError) as err:
+            except (OSError, netrc.NetrcParseError) as err:
                 self.report_warning(
                     'parsing .netrc: %s' % error_to_compat_str(err))
 
@@ -3333,7 +3330,7 @@ def _extract_akamai_formats_and_subtitles(self, manifest_url, video_id, hosts={}
                             http_f = f.copy()
                             del http_f['manifest_url']
                             http_url = re.sub(
-                                REPL_REGEX, protocol + r'://%s/\g<1>%s\3' % (http_host, qualities[i]), f['url'])
+                                REPL_REGEX, protocol + fr'://{http_host}/\g<1>{qualities[i]}\3', f['url'])
                             http_f.update({
                                 'format_id': http_f['format_id'].replace('hls-', protocol + '-'),
                                 'url': http_url,
@@ -3354,7 +3351,7 @@ def _extract_wowza_formats(self, url, video_id, m3u8_entry_protocol='m3u8_native
         formats = []
 
         def manifest_url(manifest):
-            m_url = '%s/%s' % (http_base_url, manifest)
+            m_url = f'{http_base_url}/{manifest}'
             if query:
                 m_url += '?%s' % query
             return m_url
@@ -3391,7 +3388,7 @@ def manifest_url(manifest):
             for protocol in ('rtmp', 'rtsp'):
                 if protocol not in skip_protocols:
                     formats.append({
-                        'url': '%s:%s' % (protocol, url_base),
+                        'url': f'{protocol}:{url_base}',
                         'format_id': protocol,
                         'protocol': protocol,
                     })
@@ -3557,7 +3554,7 @@ def _live_title(self, name):
     def _int(self, v, name, fatal=False, **kwargs):
         res = int_or_none(v, **kwargs)
         if res is None:
-            msg = 'Failed to extract %s: Could not parse value %r' % (name, v)
+            msg = f'Failed to extract {name}: Could not parse value {v!r}'
             if fatal:
                 raise ExtractorError(msg)
             else:
@@ -3567,7 +3564,7 @@ def _int(self, v, name, fatal=False, **kwargs):
     def _float(self, v, name, fatal=False, **kwargs):
         res = float_or_none(v, **kwargs)
         if res is None:
-            msg = 'Failed to extract %s: Could not parse value %r' % (name, v)
+            msg = f'Failed to extract {name}: Could not parse value {v!r}'
             if fatal:
                 raise ExtractorError(msg)
             else:
@@ -3685,7 +3682,7 @@ def _get_comments(self, *args, **kwargs):
     def _merge_subtitle_items(subtitle_list1, subtitle_list2):
         """ Merge subtitle items for one language. Items with duplicated URLs/data
         will be dropped. """
-        list1_data = set((item.get('url'), item.get('data')) for item in subtitle_list1)
+        list1_data = {(item.get('url'), item.get('data')) for item in subtitle_list1}
         ret = list(subtitle_list1)
         ret.extend(item for item in subtitle_list2 if (item.get('url'), item.get('data')) not in list1_data)
         return ret
@@ -3798,7 +3795,7 @@ def _real_extract(self, query):
         else:
             n = int(prefix)
             if n <= 0:
-                raise ExtractorError('invalid download number %s for query "%s"' % (n, query))
+                raise ExtractorError(f'invalid download number {n} for query "{query}"')
             elif n > self._MAX_RESULTS:
                 self.report_warning('%s returns max %i results (you requested %i)' % (self._SEARCH_KEY, self._MAX_RESULTS, n))
                 n = self._MAX_RESULTS
diff --git a/yt_dlp/extractor/commonmistakes.py b/yt_dlp/extractor/commonmistakes.py
index e0a9f5956e..62bd51fd7c 100644
--- a/yt_dlp/extractor/commonmistakes.py
+++ b/yt_dlp/extractor/commonmistakes.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import ExtractorError
 
diff --git a/yt_dlp/extractor/commonprotocols.py b/yt_dlp/extractor/commonprotocols.py
index 3708c6ad27..40475f7ecc 100644
--- a/yt_dlp/extractor/commonprotocols.py
+++ b/yt_dlp/extractor/commonprotocols.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import (
     compat_urlparse,
diff --git a/yt_dlp/extractor/condenast.py b/yt_dlp/extractor/condenast.py
index 54e7af8b09..cf6e40cb83 100644
--- a/yt_dlp/extractor/condenast.py
+++ b/yt_dlp/extractor/condenast.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/contv.py b/yt_dlp/extractor/contv.py
index 84b462d40a..50648a5368 100644
--- a/yt_dlp/extractor/contv.py
+++ b/yt_dlp/extractor/contv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     float_or_none,
diff --git a/yt_dlp/extractor/corus.py b/yt_dlp/extractor/corus.py
index 119461375e..7b83c0390d 100644
--- a/yt_dlp/extractor/corus.py
+++ b/yt_dlp/extractor/corus.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .theplatform import ThePlatformFeedIE
 from ..utils import (
     dict_get,
diff --git a/yt_dlp/extractor/coub.py b/yt_dlp/extractor/coub.py
index e90aa1954f..b462acaf01 100644
--- a/yt_dlp/extractor/coub.py
+++ b/yt_dlp/extractor/coub.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/cozytv.py b/yt_dlp/extractor/cozytv.py
index d49f1ca744..5ef5afcc21 100644
--- a/yt_dlp/extractor/cozytv.py
+++ b/yt_dlp/extractor/cozytv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import unified_strdate
 
diff --git a/yt_dlp/extractor/cpac.py b/yt_dlp/extractor/cpac.py
index 22741152c6..e8975e5e2b 100644
--- a/yt_dlp/extractor/cpac.py
+++ b/yt_dlp/extractor/cpac.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/cracked.py b/yt_dlp/extractor/cracked.py
index f77a68eced..c6aabccc68 100644
--- a/yt_dlp/extractor/cracked.py
+++ b/yt_dlp/extractor/cracked.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/crackle.py b/yt_dlp/extractor/crackle.py
index db4962c422..319374f3b8 100644
--- a/yt_dlp/extractor/crackle.py
+++ b/yt_dlp/extractor/crackle.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals, division
-
 import hashlib
 import hmac
 import re
diff --git a/yt_dlp/extractor/craftsy.py b/yt_dlp/extractor/craftsy.py
index ed2f4420ef..307bfb9460 100644
--- a/yt_dlp/extractor/craftsy.py
+++ b/yt_dlp/extractor/craftsy.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .brightcove import BrightcoveNewIE
 from .common import InfoExtractor
 
diff --git a/yt_dlp/extractor/crooksandliars.py b/yt_dlp/extractor/crooksandliars.py
index 7fb782db7c..c831a3ae08 100644
--- a/yt_dlp/extractor/crooksandliars.py
+++ b/yt_dlp/extractor/crooksandliars.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/crowdbunker.py b/yt_dlp/extractor/crowdbunker.py
index 72906afefa..75d90b5c55 100644
--- a/yt_dlp/extractor/crowdbunker.py
+++ b/yt_dlp/extractor/crowdbunker.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/crunchyroll.py b/yt_dlp/extractor/crunchyroll.py
index d7696bbd9c..bb1dbbaad7 100644
--- a/yt_dlp/extractor/crunchyroll.py
+++ b/yt_dlp/extractor/crunchyroll.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import re
 import json
diff --git a/yt_dlp/extractor/cspan.py b/yt_dlp/extractor/cspan.py
index f51159bbe6..cb15236179 100644
--- a/yt_dlp/extractor/cspan.py
+++ b/yt_dlp/extractor/cspan.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ctsnews.py b/yt_dlp/extractor/ctsnews.py
index 679f1d92e9..cec178f034 100644
--- a/yt_dlp/extractor/ctsnews.py
+++ b/yt_dlp/extractor/ctsnews.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import unified_timestamp
 from .youtube import YoutubeIE
diff --git a/yt_dlp/extractor/ctv.py b/yt_dlp/extractor/ctv.py
index 756bcc2bea..f125c1ce99 100644
--- a/yt_dlp/extractor/ctv.py
+++ b/yt_dlp/extractor/ctv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/ctvnews.py b/yt_dlp/extractor/ctvnews.py
index 952f4c747f..ad3f0d8e4d 100644
--- a/yt_dlp/extractor/ctvnews.py
+++ b/yt_dlp/extractor/ctvnews.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/cultureunplugged.py b/yt_dlp/extractor/cultureunplugged.py
index 9002e4cef5..2fb22800f3 100644
--- a/yt_dlp/extractor/cultureunplugged.py
+++ b/yt_dlp/extractor/cultureunplugged.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import time
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/curiositystream.py b/yt_dlp/extractor/curiositystream.py
index b8abcf7a5a..5b76b29ff4 100644
--- a/yt_dlp/extractor/curiositystream.py
+++ b/yt_dlp/extractor/curiositystream.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/cwtv.py b/yt_dlp/extractor/cwtv.py
index 73382431b7..07239f39cf 100644
--- a/yt_dlp/extractor/cwtv.py
+++ b/yt_dlp/extractor/cwtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/cybrary.py b/yt_dlp/extractor/cybrary.py
index c278f0fe0a..7da581828e 100644
--- a/yt_dlp/extractor/cybrary.py
+++ b/yt_dlp/extractor/cybrary.py
@@ -1,5 +1,4 @@
-# coding: utf-8
-from .common import InfoExtractor
+from .common import InfoExtractor
 
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/daftsex.py b/yt_dlp/extractor/daftsex.py
index 6037fd9cad..0fe014f769 100644
--- a/yt_dlp/extractor/daftsex.py
+++ b/yt_dlp/extractor/daftsex.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_b64decode
 from ..utils import (
diff --git a/yt_dlp/extractor/dailymail.py b/yt_dlp/extractor/dailymail.py
index 67b88fd562..5451dbf000 100644
--- a/yt_dlp/extractor/dailymail.py
+++ b/yt_dlp/extractor/dailymail.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/dailymotion.py b/yt_dlp/extractor/dailymotion.py
index 9cb56185bc..3b090d5e02 100644
--- a/yt_dlp/extractor/dailymotion.py
+++ b/yt_dlp/extractor/dailymotion.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import json
 import re
diff --git a/yt_dlp/extractor/damtomo.py b/yt_dlp/extractor/damtomo.py
index 456cd35a44..962d9741bf 100644
--- a/yt_dlp/extractor/damtomo.py
+++ b/yt_dlp/extractor/damtomo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/daum.py b/yt_dlp/extractor/daum.py
index 4362e92cbf..a1f197b0bc 100644
--- a/yt_dlp/extractor/daum.py
+++ b/yt_dlp/extractor/daum.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/dbtv.py b/yt_dlp/extractor/dbtv.py
index 8e73176a67..2beccd8b51 100644
--- a/yt_dlp/extractor/dbtv.py
+++ b/yt_dlp/extractor/dbtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/dctp.py b/yt_dlp/extractor/dctp.py
index e700f8d865..24bb6aca25 100644
--- a/yt_dlp/extractor/dctp.py
+++ b/yt_dlp/extractor/dctp.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/deezer.py b/yt_dlp/extractor/deezer.py
index 7ba02e552e..bee1c7501c 100644
--- a/yt_dlp/extractor/deezer.py
+++ b/yt_dlp/extractor/deezer.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/defense.py b/yt_dlp/extractor/defense.py
index 9fe144e143..7d73ea862e 100644
--- a/yt_dlp/extractor/defense.py
+++ b/yt_dlp/extractor/defense.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/democracynow.py b/yt_dlp/extractor/democracynow.py
index 5c9c0ecdc0..af327e6c6b 100644
--- a/yt_dlp/extractor/democracynow.py
+++ b/yt_dlp/extractor/democracynow.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import os.path
 
diff --git a/yt_dlp/extractor/dfb.py b/yt_dlp/extractor/dfb.py
index 97f70fc7b0..5aca729889 100644
--- a/yt_dlp/extractor/dfb.py
+++ b/yt_dlp/extractor/dfb.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import unified_strdate
 
diff --git a/yt_dlp/extractor/dhm.py b/yt_dlp/extractor/dhm.py
index aee72a6ed1..3d42fc2b0c 100644
--- a/yt_dlp/extractor/dhm.py
+++ b/yt_dlp/extractor/dhm.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import parse_duration
 
diff --git a/yt_dlp/extractor/digg.py b/yt_dlp/extractor/digg.py
index 913c1750f1..86e8a6facb 100644
--- a/yt_dlp/extractor/digg.py
+++ b/yt_dlp/extractor/digg.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import js_to_json
 
diff --git a/yt_dlp/extractor/digitalconcerthall.py b/yt_dlp/extractor/digitalconcerthall.py
index 8398ae30e6..c891ad0a63 100644
--- a/yt_dlp/extractor/digitalconcerthall.py
+++ b/yt_dlp/extractor/digitalconcerthall.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..utils import (
diff --git a/yt_dlp/extractor/digiteka.py b/yt_dlp/extractor/digiteka.py
index d63204778c..5d244cb08a 100644
--- a/yt_dlp/extractor/digiteka.py
+++ b/yt_dlp/extractor/digiteka.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/discovery.py b/yt_dlp/extractor/discovery.py
index fd3ad75c78..fd3fc8fb0f 100644
--- a/yt_dlp/extractor/discovery.py
+++ b/yt_dlp/extractor/discovery.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import random
 import string
 
diff --git a/yt_dlp/extractor/discoverygo.py b/yt_dlp/extractor/discoverygo.py
index 9e7b14a7d5..7b4278c882 100644
--- a/yt_dlp/extractor/discoverygo.py
+++ b/yt_dlp/extractor/discoverygo.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/discoveryvr.py b/yt_dlp/extractor/discoveryvr.py
index cb63c26495..a021d986e6 100644
--- a/yt_dlp/extractor/discoveryvr.py
+++ b/yt_dlp/extractor/discoveryvr.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import parse_duration
 
diff --git a/yt_dlp/extractor/disney.py b/yt_dlp/extractor/disney.py
index 0ad7b1f462..f9af59a571 100644
--- a/yt_dlp/extractor/disney.py
+++ b/yt_dlp/extractor/disney.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/dispeak.py b/yt_dlp/extractor/dispeak.py
index 3d651f3abc..d4f3324e7c 100644
--- a/yt_dlp/extractor/dispeak.py
+++ b/yt_dlp/extractor/dispeak.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/dlive.py b/yt_dlp/extractor/dlive.py
index 7410eb6c87..31b4a568f2 100644
--- a/yt_dlp/extractor/dlive.py
+++ b/yt_dlp/extractor/dlive.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/doodstream.py b/yt_dlp/extractor/doodstream.py
index f692127c2f..f1001c778c 100644
--- a/yt_dlp/extractor/doodstream.py
+++ b/yt_dlp/extractor/doodstream.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import string
 import random
 import time
diff --git a/yt_dlp/extractor/dotsub.py b/yt_dlp/extractor/dotsub.py
index 148605c0bd..079f837500 100644
--- a/yt_dlp/extractor/dotsub.py
+++ b/yt_dlp/extractor/dotsub.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     float_or_none,
diff --git a/yt_dlp/extractor/douyutv.py b/yt_dlp/extractor/douyutv.py
index 26a8d645cd..477f4687cd 100644
--- a/yt_dlp/extractor/douyutv.py
+++ b/yt_dlp/extractor/douyutv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import time
 import hashlib
 import re
diff --git a/yt_dlp/extractor/dplay.py b/yt_dlp/extractor/dplay.py
index a25f27c3a2..54f95a44af 100644
--- a/yt_dlp/extractor/dplay.py
+++ b/yt_dlp/extractor/dplay.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import uuid
 
diff --git a/yt_dlp/extractor/drbonanza.py b/yt_dlp/extractor/drbonanza.py
index ea0f06d3da..dca8c89d04 100644
--- a/yt_dlp/extractor/drbonanza.py
+++ b/yt_dlp/extractor/drbonanza.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     js_to_json,
diff --git a/yt_dlp/extractor/dreisat.py b/yt_dlp/extractor/dreisat.py
index 5a07c18f49..80a724607c 100644
--- a/yt_dlp/extractor/dreisat.py
+++ b/yt_dlp/extractor/dreisat.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .zdf import ZDFIE
 
 
diff --git a/yt_dlp/extractor/drooble.py b/yt_dlp/extractor/drooble.py
index 058425095f..106e5c457a 100644
--- a/yt_dlp/extractor/drooble.py
+++ b/yt_dlp/extractor/drooble.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/dropbox.py b/yt_dlp/extractor/dropbox.py
index 2559657ada..6ac0c713a6 100644
--- a/yt_dlp/extractor/dropbox.py
+++ b/yt_dlp/extractor/dropbox.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import os.path
 import re
 
diff --git a/yt_dlp/extractor/dropout.py b/yt_dlp/extractor/dropout.py
index 2fa61950c2..475825eb81 100644
--- a/yt_dlp/extractor/dropout.py
+++ b/yt_dlp/extractor/dropout.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from .vimeo import VHXEmbedIE
 from ..utils import (
diff --git a/yt_dlp/extractor/drtuber.py b/yt_dlp/extractor/drtuber.py
index 540b86a169..3149e319f0 100644
--- a/yt_dlp/extractor/drtuber.py
+++ b/yt_dlp/extractor/drtuber.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/drtv.py b/yt_dlp/extractor/drtv.py
index 37e4d5b262..843e930720 100644
--- a/yt_dlp/extractor/drtv.py
+++ b/yt_dlp/extractor/drtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import binascii
 import hashlib
 import re
diff --git a/yt_dlp/extractor/dtube.py b/yt_dlp/extractor/dtube.py
index ad247b7ddd..25a98f625b 100644
--- a/yt_dlp/extractor/dtube.py
+++ b/yt_dlp/extractor/dtube.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 from socket import timeout
 
diff --git a/yt_dlp/extractor/duboku.py b/yt_dlp/extractor/duboku.py
index a87597873e..24403842d3 100644
--- a/yt_dlp/extractor/duboku.py
+++ b/yt_dlp/extractor/duboku.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/dumpert.py b/yt_dlp/extractor/dumpert.py
index d9d9afdecb..dc61115ff7 100644
--- a/yt_dlp/extractor/dumpert.py
+++ b/yt_dlp/extractor/dumpert.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/dvtv.py b/yt_dlp/extractor/dvtv.py
index 08663cffb8..61d469f11c 100644
--- a/yt_dlp/extractor/dvtv.py
+++ b/yt_dlp/extractor/dvtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/dw.py b/yt_dlp/extractor/dw.py
index 6eaee07b47..ee2365ddd0 100644
--- a/yt_dlp/extractor/dw.py
+++ b/yt_dlp/extractor/dw.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/eagleplatform.py b/yt_dlp/extractor/eagleplatform.py
index f86731a0c1..e2ecd4b7cf 100644
--- a/yt_dlp/extractor/eagleplatform.py
+++ b/yt_dlp/extractor/eagleplatform.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ebaumsworld.py b/yt_dlp/extractor/ebaumsworld.py
index c97682cd36..0854d03443 100644
--- a/yt_dlp/extractor/ebaumsworld.py
+++ b/yt_dlp/extractor/ebaumsworld.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/echomsk.py b/yt_dlp/extractor/echomsk.py
index 6b7cc652fe..850eabbff0 100644
--- a/yt_dlp/extractor/echomsk.py
+++ b/yt_dlp/extractor/echomsk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/egghead.py b/yt_dlp/extractor/egghead.py
index b6b86768c2..d5c954961f 100644
--- a/yt_dlp/extractor/egghead.py
+++ b/yt_dlp/extractor/egghead.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/ehow.py b/yt_dlp/extractor/ehow.py
index b1cd4f5d4e..74469ce36f 100644
--- a/yt_dlp/extractor/ehow.py
+++ b/yt_dlp/extractor/ehow.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urllib_parse_unquote
 
diff --git a/yt_dlp/extractor/eighttracks.py b/yt_dlp/extractor/eighttracks.py
index 9a44f89f3f..3dd9ab1b31 100644
--- a/yt_dlp/extractor/eighttracks.py
+++ b/yt_dlp/extractor/eighttracks.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import random
 
diff --git a/yt_dlp/extractor/einthusan.py b/yt_dlp/extractor/einthusan.py
index 7af279a536..37be68c613 100644
--- a/yt_dlp/extractor/einthusan.py
+++ b/yt_dlp/extractor/einthusan.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/eitb.py b/yt_dlp/extractor/eitb.py
index ee5ead18b0..01a47f6fde 100644
--- a/yt_dlp/extractor/eitb.py
+++ b/yt_dlp/extractor/eitb.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     float_or_none,
diff --git a/yt_dlp/extractor/ellentube.py b/yt_dlp/extractor/ellentube.py
index d451bc0483..bcd458cdf4 100644
--- a/yt_dlp/extractor/ellentube.py
+++ b/yt_dlp/extractor/ellentube.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/elonet.py b/yt_dlp/extractor/elonet.py
index 9c6aea28e8..f99e12250e 100644
--- a/yt_dlp/extractor/elonet.py
+++ b/yt_dlp/extractor/elonet.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import determine_ext
 
diff --git a/yt_dlp/extractor/elpais.py b/yt_dlp/extractor/elpais.py
index b89f6db62f..7c6c880757 100644
--- a/yt_dlp/extractor/elpais.py
+++ b/yt_dlp/extractor/elpais.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import strip_jsonp, unified_strdate
 
diff --git a/yt_dlp/extractor/embedly.py b/yt_dlp/extractor/embedly.py
index a5820b21e0..a8d1f3c55c 100644
--- a/yt_dlp/extractor/embedly.py
+++ b/yt_dlp/extractor/embedly.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urllib_parse_unquote
 
diff --git a/yt_dlp/extractor/engadget.py b/yt_dlp/extractor/engadget.py
index 733bf322fd..e7c5d7bf16 100644
--- a/yt_dlp/extractor/engadget.py
+++ b/yt_dlp/extractor/engadget.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/epicon.py b/yt_dlp/extractor/epicon.py
index cd19325bc7..89424785ec 100644
--- a/yt_dlp/extractor/epicon.py
+++ b/yt_dlp/extractor/epicon.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/eporner.py b/yt_dlp/extractor/eporner.py
index 25a0d97990..6bc70c5c61 100644
--- a/yt_dlp/extractor/eporner.py
+++ b/yt_dlp/extractor/eporner.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     encode_base_n,
diff --git a/yt_dlp/extractor/eroprofile.py b/yt_dlp/extractor/eroprofile.py
index 5d5e7f2442..2b61f3be7d 100644
--- a/yt_dlp/extractor/eroprofile.py
+++ b/yt_dlp/extractor/eroprofile.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ertgr.py b/yt_dlp/extractor/ertgr.py
index 19ce23f017..507f0a5c11 100644
--- a/yt_dlp/extractor/ertgr.py
+++ b/yt_dlp/extractor/ertgr.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/escapist.py b/yt_dlp/extractor/escapist.py
index 4cd815ebc4..5d9c46f72d 100644
--- a/yt_dlp/extractor/escapist.py
+++ b/yt_dlp/extractor/escapist.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/espn.py b/yt_dlp/extractor/espn.py
index dc50f3b8b5..8fad70e6b3 100644
--- a/yt_dlp/extractor/espn.py
+++ b/yt_dlp/extractor/espn.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/esri.py b/yt_dlp/extractor/esri.py
index e9dcaeb1dd..1736788db2 100644
--- a/yt_dlp/extractor/esri.py
+++ b/yt_dlp/extractor/esri.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/europa.py b/yt_dlp/extractor/europa.py
index 60ab2ce133..ea20b4d4d4 100644
--- a/yt_dlp/extractor/europa.py
+++ b/yt_dlp/extractor/europa.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/europeantour.py b/yt_dlp/extractor/europeantour.py
index e28f067be0..1995a745d0 100644
--- a/yt_dlp/extractor/europeantour.py
+++ b/yt_dlp/extractor/europeantour.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/euscreen.py b/yt_dlp/extractor/euscreen.py
index 2759e7436f..4435f08e0d 100644
--- a/yt_dlp/extractor/euscreen.py
+++ b/yt_dlp/extractor/euscreen.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..utils import (
diff --git a/yt_dlp/extractor/everyonesmixtape.py b/yt_dlp/extractor/everyonesmixtape.py
index 80cb032be8..d26ff8ad3c 100644
--- a/yt_dlp/extractor/everyonesmixtape.py
+++ b/yt_dlp/extractor/everyonesmixtape.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/expotv.py b/yt_dlp/extractor/expotv.py
index 95a8977821..92eaf4248a 100644
--- a/yt_dlp/extractor/expotv.py
+++ b/yt_dlp/extractor/expotv.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/expressen.py b/yt_dlp/extractor/expressen.py
index dc8b855d23..a1b8e9bc9f 100644
--- a/yt_dlp/extractor/expressen.py
+++ b/yt_dlp/extractor/expressen.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/extractors.py b/yt_dlp/extractor/extractors.py
index 0cb6863048..cd3934a70d 100644
--- a/yt_dlp/extractor/extractors.py
+++ b/yt_dlp/extractor/extractors.py
@@ -1,6 +1,4 @@
 # flake8: noqa
-from __future__ import unicode_literals
-
 from .abc import (
     ABCIE,
     ABCIViewIE,
diff --git a/yt_dlp/extractor/extremetube.py b/yt_dlp/extractor/extremetube.py
index acd4090fa3..99520b6a0c 100644
--- a/yt_dlp/extractor/extremetube.py
+++ b/yt_dlp/extractor/extremetube.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from ..utils import str_to_int
 from .keezmovies import KeezMoviesIE
 
diff --git a/yt_dlp/extractor/eyedotv.py b/yt_dlp/extractor/eyedotv.py
index f62ddebaee..d8b068e9c5 100644
--- a/yt_dlp/extractor/eyedotv.py
+++ b/yt_dlp/extractor/eyedotv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     xpath_text,
diff --git a/yt_dlp/extractor/facebook.py b/yt_dlp/extractor/facebook.py
index 5e0e2facf3..2e69dce0f2 100644
--- a/yt_dlp/extractor/facebook.py
+++ b/yt_dlp/extractor/facebook.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/fancode.py b/yt_dlp/extractor/fancode.py
index 7ea16c61d2..9716e581a9 100644
--- a/yt_dlp/extractor/fancode.py
+++ b/yt_dlp/extractor/fancode.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..compat import compat_str
diff --git a/yt_dlp/extractor/faz.py b/yt_dlp/extractor/faz.py
index 312ee2aeed..cc12fda2b9 100644
--- a/yt_dlp/extractor/faz.py
+++ b/yt_dlp/extractor/faz.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/fc2.py b/yt_dlp/extractor/fc2.py
index 54a83aa16a..a4c9793bbf 100644
--- a/yt_dlp/extractor/fc2.py
+++ b/yt_dlp/extractor/fc2.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/fczenit.py b/yt_dlp/extractor/fczenit.py
index 8db7c59638..df40888e1b 100644
--- a/yt_dlp/extractor/fczenit.py
+++ b/yt_dlp/extractor/fczenit.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/filmmodu.py b/yt_dlp/extractor/filmmodu.py
index 2746876d53..d741311925 100644
--- a/yt_dlp/extractor/filmmodu.py
+++ b/yt_dlp/extractor/filmmodu.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/filmon.py b/yt_dlp/extractor/filmon.py
index 7b43ecc0f9..7040231bee 100644
--- a/yt_dlp/extractor/filmon.py
+++ b/yt_dlp/extractor/filmon.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/filmweb.py b/yt_dlp/extractor/filmweb.py
index 5e323b4f8f..cfea1f2fb6 100644
--- a/yt_dlp/extractor/filmweb.py
+++ b/yt_dlp/extractor/filmweb.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/firsttv.py b/yt_dlp/extractor/firsttv.py
index ccad173b79..99c27e0c32 100644
--- a/yt_dlp/extractor/firsttv.py
+++ b/yt_dlp/extractor/firsttv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/fivetv.py b/yt_dlp/extractor/fivetv.py
index d6bebd19bd..448c332b3d 100644
--- a/yt_dlp/extractor/fivetv.py
+++ b/yt_dlp/extractor/fivetv.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/flickr.py b/yt_dlp/extractor/flickr.py
index 2ed6c2bdc6..552ecd43a0 100644
--- a/yt_dlp/extractor/flickr.py
+++ b/yt_dlp/extractor/flickr.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/folketinget.py b/yt_dlp/extractor/folketinget.py
index b3df93f28f..0e69fa32f3 100644
--- a/yt_dlp/extractor/folketinget.py
+++ b/yt_dlp/extractor/folketinget.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_parse_qs
 from ..utils import (
diff --git a/yt_dlp/extractor/footyroom.py b/yt_dlp/extractor/footyroom.py
index 118325b6d5..4a1316b50c 100644
--- a/yt_dlp/extractor/footyroom.py
+++ b/yt_dlp/extractor/footyroom.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .streamable import StreamableIE
 
diff --git a/yt_dlp/extractor/formula1.py b/yt_dlp/extractor/formula1.py
index 67662e6de1..0a8ef850ef 100644
--- a/yt_dlp/extractor/formula1.py
+++ b/yt_dlp/extractor/formula1.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/fourtube.py b/yt_dlp/extractor/fourtube.py
index d4d955b6b5..c6af100f37 100644
--- a/yt_dlp/extractor/fourtube.py
+++ b/yt_dlp/extractor/fourtube.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/fox.py b/yt_dlp/extractor/fox.py
index 4c52b9ac61..5996e86bb7 100644
--- a/yt_dlp/extractor/fox.py
+++ b/yt_dlp/extractor/fox.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import uuid
 
diff --git a/yt_dlp/extractor/fox9.py b/yt_dlp/extractor/fox9.py
index 91f8f7b8a1..dfbafa7ddf 100644
--- a/yt_dlp/extractor/fox9.py
+++ b/yt_dlp/extractor/fox9.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/foxgay.py b/yt_dlp/extractor/foxgay.py
index 1c53e0642b..4abc2cfd02 100644
--- a/yt_dlp/extractor/foxgay.py
+++ b/yt_dlp/extractor/foxgay.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/foxnews.py b/yt_dlp/extractor/foxnews.py
index 18fa0a5efb..cee4d6b496 100644
--- a/yt_dlp/extractor/foxnews.py
+++ b/yt_dlp/extractor/foxnews.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .amp import AMPIE
diff --git a/yt_dlp/extractor/foxsports.py b/yt_dlp/extractor/foxsports.py
index 2b2cb6c6f6..f9d7fe52ae 100644
--- a/yt_dlp/extractor/foxsports.py
+++ b/yt_dlp/extractor/foxsports.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/fptplay.py b/yt_dlp/extractor/fptplay.py
index c23fe6c533..1872d8a1ca 100644
--- a/yt_dlp/extractor/fptplay.py
+++ b/yt_dlp/extractor/fptplay.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import time
 import urllib.parse
diff --git a/yt_dlp/extractor/franceculture.py b/yt_dlp/extractor/franceculture.py
index 9dc28d801c..6bd9912f33 100644
--- a/yt_dlp/extractor/franceculture.py
+++ b/yt_dlp/extractor/franceculture.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 from .common import InfoExtractor
 from ..utils import (
diff --git a/yt_dlp/extractor/franceinter.py b/yt_dlp/extractor/franceinter.py
index ae822a50e3..779249b843 100644
--- a/yt_dlp/extractor/franceinter.py
+++ b/yt_dlp/extractor/franceinter.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import month_by_name
 
diff --git a/yt_dlp/extractor/francetv.py b/yt_dlp/extractor/francetv.py
index 347a766d8f..5902eaca07 100644
--- a/yt_dlp/extractor/francetv.py
+++ b/yt_dlp/extractor/francetv.py
@@ -1,8 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/freesound.py b/yt_dlp/extractor/freesound.py
index 138b6bc58c..9724dbdf0f 100644
--- a/yt_dlp/extractor/freesound.py
+++ b/yt_dlp/extractor/freesound.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/freespeech.py b/yt_dlp/extractor/freespeech.py
index ea9c3e317c..aea551379b 100644
--- a/yt_dlp/extractor/freespeech.py
+++ b/yt_dlp/extractor/freespeech.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .youtube import YoutubeIE
 
diff --git a/yt_dlp/extractor/frontendmasters.py b/yt_dlp/extractor/frontendmasters.py
index fc67a8437f..e0529b7ba7 100644
--- a/yt_dlp/extractor/frontendmasters.py
+++ b/yt_dlp/extractor/frontendmasters.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/fujitv.py b/yt_dlp/extractor/fujitv.py
index 4fdfe12abb..15d75a972b 100644
--- a/yt_dlp/extractor/fujitv.py
+++ b/yt_dlp/extractor/fujitv.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
 from ..utils import HEADRequest
 from .common import InfoExtractor
 
diff --git a/yt_dlp/extractor/funimation.py b/yt_dlp/extractor/funimation.py
index 6aa9bc9ce0..1e3309605a 100644
--- a/yt_dlp/extractor/funimation.py
+++ b/yt_dlp/extractor/funimation.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 import re
 import string
diff --git a/yt_dlp/extractor/funk.py b/yt_dlp/extractor/funk.py
index 2c5cfe8648..539d719c5b 100644
--- a/yt_dlp/extractor/funk.py
+++ b/yt_dlp/extractor/funk.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from .nexx import NexxIE
 from ..utils import (
diff --git a/yt_dlp/extractor/fusion.py b/yt_dlp/extractor/fusion.py
index a3f44b812f..46bda49ea8 100644
--- a/yt_dlp/extractor/fusion.py
+++ b/yt_dlp/extractor/fusion.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/fxnetworks.py b/yt_dlp/extractor/fxnetworks.py
index 00e67426b9..370b0a597b 100644
--- a/yt_dlp/extractor/fxnetworks.py
+++ b/yt_dlp/extractor/fxnetworks.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .adobepass import AdobePassIE
 from ..utils import (
     extract_attributes,
diff --git a/yt_dlp/extractor/gab.py b/yt_dlp/extractor/gab.py
index 9ba0b1ca19..7ed81f7613 100644
--- a/yt_dlp/extractor/gab.py
+++ b/yt_dlp/extractor/gab.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/gaia.py b/yt_dlp/extractor/gaia.py
index 5b0195c63c..4ace0544a9 100644
--- a/yt_dlp/extractor/gaia.py
+++ b/yt_dlp/extractor/gaia.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/gameinformer.py b/yt_dlp/extractor/gameinformer.py
index f1b96c172e..2664edb816 100644
--- a/yt_dlp/extractor/gameinformer.py
+++ b/yt_dlp/extractor/gameinformer.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .brightcove import BrightcoveNewIE
 from .common import InfoExtractor
 from ..utils import (
diff --git a/yt_dlp/extractor/gamejolt.py b/yt_dlp/extractor/gamejolt.py
index a13e528f52..440b832fcb 100644
--- a/yt_dlp/extractor/gamejolt.py
+++ b/yt_dlp/extractor/gamejolt.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 import itertools
 import json
 import math
diff --git a/yt_dlp/extractor/gamespot.py b/yt_dlp/extractor/gamespot.py
index 7a1beae3cf..e1d3173771 100644
--- a/yt_dlp/extractor/gamespot.py
+++ b/yt_dlp/extractor/gamespot.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .once import OnceIE
 from ..compat import compat_urllib_parse_unquote
 
diff --git a/yt_dlp/extractor/gamestar.py b/yt_dlp/extractor/gamestar.py
index e882fa6719..e9966f5327 100644
--- a/yt_dlp/extractor/gamestar.py
+++ b/yt_dlp/extractor/gamestar.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/gaskrank.py b/yt_dlp/extractor/gaskrank.py
index 03acd2a731..76ddcc40e6 100644
--- a/yt_dlp/extractor/gaskrank.py
+++ b/yt_dlp/extractor/gaskrank.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 from .common import InfoExtractor
 from ..utils import (
diff --git a/yt_dlp/extractor/gazeta.py b/yt_dlp/extractor/gazeta.py
index 367187080e..c6868a6722 100644
--- a/yt_dlp/extractor/gazeta.py
+++ b/yt_dlp/extractor/gazeta.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/gdcvault.py b/yt_dlp/extractor/gdcvault.py
index c3ad6b4cea..2878bbd88c 100644
--- a/yt_dlp/extractor/gdcvault.py
+++ b/yt_dlp/extractor/gdcvault.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/gedidigital.py b/yt_dlp/extractor/gedidigital.py
index ec386c2187..c878daff82 100644
--- a/yt_dlp/extractor/gedidigital.py
+++ b/yt_dlp/extractor/gedidigital.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py
index fd620217ed..f44f19a549 100644
--- a/yt_dlp/extractor/generic.py
+++ b/yt_dlp/extractor/generic.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import os
 import re
 import xml.etree.ElementTree
@@ -2628,7 +2624,7 @@ def _extract_camtasia(self, url, video_id, webpage):
 
             entries.append({
                 'id': os.path.splitext(url_n.text.rpartition('/')[2])[0],
-                'title': '%s - %s' % (title, n.tag),
+                'title': f'{title} - {n.tag}',
                 'url': compat_urlparse.urljoin(url, url_n.text),
                 'duration': float_or_none(n.find('./duration').text),
             })
@@ -2650,7 +2646,7 @@ def _kvs_getrealurl(self, video_url, license_code):
 
         for o in range(len(newmagic) - 1, -1, -1):
             new = ''
-            l = (o + sum([int(n) for n in license[o:]])) % 32
+            l = (o + sum(int(n) for n in license[o:])) % 32
 
             for i in range(0, len(newmagic)):
                 if i == o:
@@ -3772,7 +3768,7 @@ def _real_extract(self, url):
             else:
                 for num, entry in enumerate(entries, start=1):
                     entry.update({
-                        'id': '%s-%s' % (video_id, num),
+                        'id': f'{video_id}-{num}',
                         'title': '%s (%d)' % (video_title, num),
                     })
             for entry in entries:
diff --git a/yt_dlp/extractor/gettr.py b/yt_dlp/extractor/gettr.py
index 327a4d0b88..9bd6200b67 100644
--- a/yt_dlp/extractor/gettr.py
+++ b/yt_dlp/extractor/gettr.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     bool_or_none,
diff --git a/yt_dlp/extractor/gfycat.py b/yt_dlp/extractor/gfycat.py
index 2ad03e2b25..7373c574ff 100644
--- a/yt_dlp/extractor/gfycat.py
+++ b/yt_dlp/extractor/gfycat.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/giantbomb.py b/yt_dlp/extractor/giantbomb.py
index 1920923fc1..5d6b208aad 100644
--- a/yt_dlp/extractor/giantbomb.py
+++ b/yt_dlp/extractor/giantbomb.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/giga.py b/yt_dlp/extractor/giga.py
index 5a9992a278..9e835a6da6 100644
--- a/yt_dlp/extractor/giga.py
+++ b/yt_dlp/extractor/giga.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/gigya.py b/yt_dlp/extractor/gigya.py
index 412178492f..c5bc86bb4a 100644
--- a/yt_dlp/extractor/gigya.py
+++ b/yt_dlp/extractor/gigya.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..utils import (
diff --git a/yt_dlp/extractor/glide.py b/yt_dlp/extractor/glide.py
index 12af859be3..2bffb26dc2 100644
--- a/yt_dlp/extractor/glide.py
+++ b/yt_dlp/extractor/glide.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/globo.py b/yt_dlp/extractor/globo.py
index f6aaae1e9e..8915ebf484 100644
--- a/yt_dlp/extractor/globo.py
+++ b/yt_dlp/extractor/globo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import hashlib
 import json
diff --git a/yt_dlp/extractor/glomex.py b/yt_dlp/extractor/glomex.py
index d9ef4338fc..85ffa4c052 100644
--- a/yt_dlp/extractor/glomex.py
+++ b/yt_dlp/extractor/glomex.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import urllib.parse
 
diff --git a/yt_dlp/extractor/go.py b/yt_dlp/extractor/go.py
index f92e16600e..07d13d1c33 100644
--- a/yt_dlp/extractor/go.py
+++ b/yt_dlp/extractor/go.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .adobepass import AdobePassIE
diff --git a/yt_dlp/extractor/godtube.py b/yt_dlp/extractor/godtube.py
index 96e68b4d20..697540155a 100644
--- a/yt_dlp/extractor/godtube.py
+++ b/yt_dlp/extractor/godtube.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/gofile.py b/yt_dlp/extractor/gofile.py
index 858bac52c3..b491b46a55 100644
--- a/yt_dlp/extractor/gofile.py
+++ b/yt_dlp/extractor/gofile.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/golem.py b/yt_dlp/extractor/golem.py
index 47a068e742..8416b5aa47 100644
--- a/yt_dlp/extractor/golem.py
+++ b/yt_dlp/extractor/golem.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/googledrive.py b/yt_dlp/extractor/googledrive.py
index 7b5bf280ff..c0905f86ae 100644
--- a/yt_dlp/extractor/googledrive.py
+++ b/yt_dlp/extractor/googledrive.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/googlepodcasts.py b/yt_dlp/extractor/googlepodcasts.py
index 25631e2134..8b2351ba88 100644
--- a/yt_dlp/extractor/googlepodcasts.py
+++ b/yt_dlp/extractor/googlepodcasts.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/googlesearch.py b/yt_dlp/extractor/googlesearch.py
index 4b8b1bcbb8..67ca0e5e0f 100644
--- a/yt_dlp/extractor/googlesearch.py
+++ b/yt_dlp/extractor/googlesearch.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import itertools
 import re
 
diff --git a/yt_dlp/extractor/gopro.py b/yt_dlp/extractor/gopro.py
index 10cc1aec1d..14d6b21879 100644
--- a/yt_dlp/extractor/gopro.py
+++ b/yt_dlp/extractor/gopro.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/goshgay.py b/yt_dlp/extractor/goshgay.py
index 377981d3e4..9a1f32b7e3 100644
--- a/yt_dlp/extractor/goshgay.py
+++ b/yt_dlp/extractor/goshgay.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_parse_qs,
diff --git a/yt_dlp/extractor/gotostage.py b/yt_dlp/extractor/gotostage.py
index 6aa96106a6..112293bef5 100644
--- a/yt_dlp/extractor/gotostage.py
+++ b/yt_dlp/extractor/gotostage.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/gputechconf.py b/yt_dlp/extractor/gputechconf.py
index 73dc62c494..2d13bf4915 100644
--- a/yt_dlp/extractor/gputechconf.py
+++ b/yt_dlp/extractor/gputechconf.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/gronkh.py b/yt_dlp/extractor/gronkh.py
index c9f1dd2566..52bbf3bc73 100644
--- a/yt_dlp/extractor/gronkh.py
+++ b/yt_dlp/extractor/gronkh.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import unified_strdate
 
diff --git a/yt_dlp/extractor/groupon.py b/yt_dlp/extractor/groupon.py
index a6da909310..362d3ff831 100644
--- a/yt_dlp/extractor/groupon.py
+++ b/yt_dlp/extractor/groupon.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/hbo.py b/yt_dlp/extractor/hbo.py
index 68df748f56..f546286651 100644
--- a/yt_dlp/extractor/hbo.py
+++ b/yt_dlp/extractor/hbo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/hearthisat.py b/yt_dlp/extractor/hearthisat.py
index a3d6a055fe..9aa1325afd 100644
--- a/yt_dlp/extractor/hearthisat.py
+++ b/yt_dlp/extractor/hearthisat.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/heise.py b/yt_dlp/extractor/heise.py
index cbe564a3cf..84e5d3023a 100644
--- a/yt_dlp/extractor/heise.py
+++ b/yt_dlp/extractor/heise.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .kaltura import KalturaIE
 from .youtube import YoutubeIE
diff --git a/yt_dlp/extractor/hellporno.py b/yt_dlp/extractor/hellporno.py
index 92d32cdcc8..fd0327228f 100644
--- a/yt_dlp/extractor/hellporno.py
+++ b/yt_dlp/extractor/hellporno.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/helsinki.py b/yt_dlp/extractor/helsinki.py
index 575fb332a0..b7c8260553 100644
--- a/yt_dlp/extractor/helsinki.py
+++ b/yt_dlp/extractor/helsinki.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import js_to_json
 
diff --git a/yt_dlp/extractor/hentaistigma.py b/yt_dlp/extractor/hentaistigma.py
index 86a93de4d6..ca5ffc2aea 100644
--- a/yt_dlp/extractor/hentaistigma.py
+++ b/yt_dlp/extractor/hentaistigma.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/hgtv.py b/yt_dlp/extractor/hgtv.py
index a4f3325650..c40017db18 100644
--- a/yt_dlp/extractor/hgtv.py
+++ b/yt_dlp/extractor/hgtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/hidive.py b/yt_dlp/extractor/hidive.py
index 46d7d62abf..a6a71d6307 100644
--- a/yt_dlp/extractor/hidive.py
+++ b/yt_dlp/extractor/hidive.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/historicfilms.py b/yt_dlp/extractor/historicfilms.py
index 56343e98fb..c428feeded 100644
--- a/yt_dlp/extractor/historicfilms.py
+++ b/yt_dlp/extractor/historicfilms.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import parse_duration
 
diff --git a/yt_dlp/extractor/hitbox.py b/yt_dlp/extractor/hitbox.py
index 0470d0a99c..a7e4424b6d 100644
--- a/yt_dlp/extractor/hitbox.py
+++ b/yt_dlp/extractor/hitbox.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/hitrecord.py b/yt_dlp/extractor/hitrecord.py
index fd5dc29357..902af44fab 100644
--- a/yt_dlp/extractor/hitrecord.py
+++ b/yt_dlp/extractor/hitrecord.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/hketv.py b/yt_dlp/extractor/hketv.py
index 1f3502b902..4c616d1ddc 100644
--- a/yt_dlp/extractor/hketv.py
+++ b/yt_dlp/extractor/hketv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/hotnewhiphop.py b/yt_dlp/extractor/hotnewhiphop.py
index 4703e1894f..f8570cb861 100644
--- a/yt_dlp/extractor/hotnewhiphop.py
+++ b/yt_dlp/extractor/hotnewhiphop.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_b64decode
 from ..utils import (
diff --git a/yt_dlp/extractor/hotstar.py b/yt_dlp/extractor/hotstar.py
index a0ce1f10a1..d82e1aead7 100644
--- a/yt_dlp/extractor/hotstar.py
+++ b/yt_dlp/extractor/hotstar.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import hmac
 import re
diff --git a/yt_dlp/extractor/howcast.py b/yt_dlp/extractor/howcast.py
index 7e36b85ad5..59cf80f1a4 100644
--- a/yt_dlp/extractor/howcast.py
+++ b/yt_dlp/extractor/howcast.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import parse_iso8601
 
diff --git a/yt_dlp/extractor/howstuffworks.py b/yt_dlp/extractor/howstuffworks.py
index cf90ab3c9d..c49c0899e0 100644
--- a/yt_dlp/extractor/howstuffworks.py
+++ b/yt_dlp/extractor/howstuffworks.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     find_xpath_attr,
diff --git a/yt_dlp/extractor/hrfensehen.py b/yt_dlp/extractor/hrfensehen.py
index e39ded2543..6f7ed9b4bc 100644
--- a/yt_dlp/extractor/hrfensehen.py
+++ b/yt_dlp/extractor/hrfensehen.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/hrti.py b/yt_dlp/extractor/hrti.py
index 36d6007736..773ae0c9a7 100644
--- a/yt_dlp/extractor/hrti.py
+++ b/yt_dlp/extractor/hrti.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/hse.py b/yt_dlp/extractor/hse.py
index 9144ff8dcc..9faf46a5d4 100644
--- a/yt_dlp/extractor/hse.py
+++ b/yt_dlp/extractor/hse.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/huajiao.py b/yt_dlp/extractor/huajiao.py
index 4ca275dda1..c498fa330c 100644
--- a/yt_dlp/extractor/huajiao.py
+++ b/yt_dlp/extractor/huajiao.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/huffpost.py b/yt_dlp/extractor/huffpost.py
index 54385bafa2..7286dbcd71 100644
--- a/yt_dlp/extractor/huffpost.py
+++ b/yt_dlp/extractor/huffpost.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/hungama.py b/yt_dlp/extractor/hungama.py
index 821b16e5dc..938a242962 100644
--- a/yt_dlp/extractor/hungama.py
+++ b/yt_dlp/extractor/hungama.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/huya.py b/yt_dlp/extractor/huya.py
index 4e96f22faa..9dd5e41b3e 100644
--- a/yt_dlp/extractor/huya.py
+++ b/yt_dlp/extractor/huya.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import random
 
diff --git a/yt_dlp/extractor/hypem.py b/yt_dlp/extractor/hypem.py
index 9ca28d632e..54db7b3eb0 100644
--- a/yt_dlp/extractor/hypem.py
+++ b/yt_dlp/extractor/hypem.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/ichinanalive.py b/yt_dlp/extractor/ichinanalive.py
index cb39f821c6..ffff36cc1f 100644
--- a/yt_dlp/extractor/ichinanalive.py
+++ b/yt_dlp/extractor/ichinanalive.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import ExtractorError, str_or_none, traverse_obj, unified_strdate
 from ..compat import compat_str
diff --git a/yt_dlp/extractor/ign.py b/yt_dlp/extractor/ign.py
index c826eb3bab..bfb1e9d649 100644
--- a/yt_dlp/extractor/ign.py
+++ b/yt_dlp/extractor/ign.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/iheart.py b/yt_dlp/extractor/iheart.py
index b54c05eeb0..2c6a5b6a1d 100644
--- a/yt_dlp/extractor/iheart.py
+++ b/yt_dlp/extractor/iheart.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/imdb.py b/yt_dlp/extractor/imdb.py
index 96cee2e2fc..74cab7dc1d 100644
--- a/yt_dlp/extractor/imdb.py
+++ b/yt_dlp/extractor/imdb.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import base64
 import json
 import re
diff --git a/yt_dlp/extractor/imggaming.py b/yt_dlp/extractor/imggaming.py
index ce7b21ab27..5b8bfda96f 100644
--- a/yt_dlp/extractor/imggaming.py
+++ b/yt_dlp/extractor/imggaming.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/imgur.py b/yt_dlp/extractor/imgur.py
index dfa4737522..a3bb476154 100644
--- a/yt_dlp/extractor/imgur.py
+++ b/yt_dlp/extractor/imgur.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ina.py b/yt_dlp/extractor/ina.py
index b3b2683cbb..56038f1ca4 100644
--- a/yt_dlp/extractor/ina.py
+++ b/yt_dlp/extractor/ina.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/inc.py b/yt_dlp/extractor/inc.py
index d5b258a0fc..9b3fe9ac14 100644
--- a/yt_dlp/extractor/inc.py
+++ b/yt_dlp/extractor/inc.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .kaltura import KalturaIE
 
diff --git a/yt_dlp/extractor/indavideo.py b/yt_dlp/extractor/indavideo.py
index 4c16243ec1..fb041a1821 100644
--- a/yt_dlp/extractor/indavideo.py
+++ b/yt_dlp/extractor/indavideo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/infoq.py b/yt_dlp/extractor/infoq.py
index 347cc51544..abf7d36ef0 100644
--- a/yt_dlp/extractor/infoq.py
+++ b/yt_dlp/extractor/infoq.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 from ..compat import (
     compat_b64decode,
     compat_urllib_parse_unquote,
diff --git a/yt_dlp/extractor/instagram.py b/yt_dlp/extractor/instagram.py
index 970f2c8abf..05000e2fb7 100644
--- a/yt_dlp/extractor/instagram.py
+++ b/yt_dlp/extractor/instagram.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 import itertools
 import hashlib
 import json
diff --git a/yt_dlp/extractor/internazionale.py b/yt_dlp/extractor/internazionale.py
index 45e2af6905..c8f70785f1 100644
--- a/yt_dlp/extractor/internazionale.py
+++ b/yt_dlp/extractor/internazionale.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import unified_timestamp
 
diff --git a/yt_dlp/extractor/internetvideoarchive.py b/yt_dlp/extractor/internetvideoarchive.py
index 880918cd79..6a8e30d73d 100644
--- a/yt_dlp/extractor/internetvideoarchive.py
+++ b/yt_dlp/extractor/internetvideoarchive.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/iprima.py b/yt_dlp/extractor/iprima.py
index 1a20384539..5e0b523dcb 100644
--- a/yt_dlp/extractor/iprima.py
+++ b/yt_dlp/extractor/iprima.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import time
 
diff --git a/yt_dlp/extractor/iqiyi.py b/yt_dlp/extractor/iqiyi.py
index 14877d4055..b755aab078 100644
--- a/yt_dlp/extractor/iqiyi.py
+++ b/yt_dlp/extractor/iqiyi.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import itertools
 import re
diff --git a/yt_dlp/extractor/itprotv.py b/yt_dlp/extractor/itprotv.py
index 64cb4e69af..4ac12603ae 100644
--- a/yt_dlp/extractor/itprotv.py
+++ b/yt_dlp/extractor/itprotv.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/itv.py b/yt_dlp/extractor/itv.py
index f1591403f0..26d77a4695 100644
--- a/yt_dlp/extractor/itv.py
+++ b/yt_dlp/extractor/itv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ivi.py b/yt_dlp/extractor/ivi.py
index 5f8a046e08..6997469438 100644
--- a/yt_dlp/extractor/ivi.py
+++ b/yt_dlp/extractor/ivi.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/ivideon.py b/yt_dlp/extractor/ivideon.py
index 44b2208468..538a961b70 100644
--- a/yt_dlp/extractor/ivideon.py
+++ b/yt_dlp/extractor/ivideon.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import (
     compat_urllib_parse_urlencode,
diff --git a/yt_dlp/extractor/iwara.py b/yt_dlp/extractor/iwara.py
index c0e01e3522..974b4be7d8 100644
--- a/yt_dlp/extractor/iwara.py
+++ b/yt_dlp/extractor/iwara.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/izlesene.py b/yt_dlp/extractor/izlesene.py
index f8fca6c8f4..6520ecf6d1 100644
--- a/yt_dlp/extractor/izlesene.py
+++ b/yt_dlp/extractor/izlesene.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/jable.py b/yt_dlp/extractor/jable.py
index b294aee704..6840654cc3 100644
--- a/yt_dlp/extractor/jable.py
+++ b/yt_dlp/extractor/jable.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/jamendo.py b/yt_dlp/extractor/jamendo.py
index 755d9703bd..5dc2c25e6a 100644
--- a/yt_dlp/extractor/jamendo.py
+++ b/yt_dlp/extractor/jamendo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import random
 
diff --git a/yt_dlp/extractor/jeuxvideo.py b/yt_dlp/extractor/jeuxvideo.py
index 77c0f520ca..56ea15cf95 100644
--- a/yt_dlp/extractor/jeuxvideo.py
+++ b/yt_dlp/extractor/jeuxvideo.py
@@ -1,8 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/joj.py b/yt_dlp/extractor/joj.py
index 7350f537c6..a01411be10 100644
--- a/yt_dlp/extractor/joj.py
+++ b/yt_dlp/extractor/joj.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/jove.py b/yt_dlp/extractor/jove.py
index 4b7dfc5264..245fe73d4a 100644
--- a/yt_dlp/extractor/jove.py
+++ b/yt_dlp/extractor/jove.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/jwplatform.py b/yt_dlp/extractor/jwplatform.py
index 5aa508bf98..8dbbb29260 100644
--- a/yt_dlp/extractor/jwplatform.py
+++ b/yt_dlp/extractor/jwplatform.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/kakao.py b/yt_dlp/extractor/kakao.py
index 483ab71286..8ad1d9efd8 100644
--- a/yt_dlp/extractor/kakao.py
+++ b/yt_dlp/extractor/kakao.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_HTTPError
 from ..utils import (
diff --git a/yt_dlp/extractor/kaltura.py b/yt_dlp/extractor/kaltura.py
index f6dfc9caae..f9b9c5c78c 100644
--- a/yt_dlp/extractor/kaltura.py
+++ b/yt_dlp/extractor/kaltura.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import base64
 
diff --git a/yt_dlp/extractor/kanalplay.py b/yt_dlp/extractor/kanalplay.py
index 5e24f7e216..ef74014c0c 100644
--- a/yt_dlp/extractor/kanalplay.py
+++ b/yt_dlp/extractor/kanalplay.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/karaoketv.py b/yt_dlp/extractor/karaoketv.py
index bfccf89b0f..381dc00ad7 100644
--- a/yt_dlp/extractor/karaoketv.py
+++ b/yt_dlp/extractor/karaoketv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/karrierevideos.py b/yt_dlp/extractor/karrierevideos.py
index 7b291e0a05..28d4841aa3 100644
--- a/yt_dlp/extractor/karrierevideos.py
+++ b/yt_dlp/extractor/karrierevideos.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urlparse
 from ..utils import (
diff --git a/yt_dlp/extractor/keezmovies.py b/yt_dlp/extractor/keezmovies.py
index 06dbcbb402..79f9c7fa78 100644
--- a/yt_dlp/extractor/keezmovies.py
+++ b/yt_dlp/extractor/keezmovies.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/kelbyone.py b/yt_dlp/extractor/kelbyone.py
index 20c26cf482..dea056c127 100644
--- a/yt_dlp/extractor/kelbyone.py
+++ b/yt_dlp/extractor/kelbyone.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/ketnet.py b/yt_dlp/extractor/ketnet.py
index e0599d02fa..ab6276727a 100644
--- a/yt_dlp/extractor/ketnet.py
+++ b/yt_dlp/extractor/ketnet.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .canvas import CanvasIE
 from .common import InfoExtractor
 from ..compat import compat_urllib_parse_unquote
diff --git a/yt_dlp/extractor/khanacademy.py b/yt_dlp/extractor/khanacademy.py
index 87e520378b..83cfeadba7 100644
--- a/yt_dlp/extractor/khanacademy.py
+++ b/yt_dlp/extractor/khanacademy.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/kickstarter.py b/yt_dlp/extractor/kickstarter.py
index d4da8f4846..c0d851d961 100644
--- a/yt_dlp/extractor/kickstarter.py
+++ b/yt_dlp/extractor/kickstarter.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import smuggle_url
 
diff --git a/yt_dlp/extractor/kinja.py b/yt_dlp/extractor/kinja.py
index 1be8b48091..c00abfbc11 100644
--- a/yt_dlp/extractor/kinja.py
+++ b/yt_dlp/extractor/kinja.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/kinopoisk.py b/yt_dlp/extractor/kinopoisk.py
index cdbb642e23..84a2489a31 100644
--- a/yt_dlp/extractor/kinopoisk.py
+++ b/yt_dlp/extractor/kinopoisk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     dict_get,
diff --git a/yt_dlp/extractor/konserthusetplay.py b/yt_dlp/extractor/konserthusetplay.py
index dd42bb2f27..1e177c3637 100644
--- a/yt_dlp/extractor/konserthusetplay.py
+++ b/yt_dlp/extractor/konserthusetplay.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/koo.py b/yt_dlp/extractor/koo.py
index 088db1cb01..892d355bad 100644
--- a/yt_dlp/extractor/koo.py
+++ b/yt_dlp/extractor/koo.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/krasview.py b/yt_dlp/extractor/krasview.py
index d27d052ff0..4323aa4292 100644
--- a/yt_dlp/extractor/krasview.py
+++ b/yt_dlp/extractor/krasview.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ku6.py b/yt_dlp/extractor/ku6.py
index a574408e55..31b4ea0c60 100644
--- a/yt_dlp/extractor/ku6.py
+++ b/yt_dlp/extractor/ku6.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/kusi.py b/yt_dlp/extractor/kusi.py
index 707fe18213..f1221ef1be 100644
--- a/yt_dlp/extractor/kusi.py
+++ b/yt_dlp/extractor/kusi.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/kuwo.py b/yt_dlp/extractor/kuwo.py
index 460a4252f4..0c9518e661 100644
--- a/yt_dlp/extractor/kuwo.py
+++ b/yt_dlp/extractor/kuwo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/la7.py b/yt_dlp/extractor/la7.py
index de985e4508..5d52decdba 100644
--- a/yt_dlp/extractor/la7.py
+++ b/yt_dlp/extractor/la7.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/laola1tv.py b/yt_dlp/extractor/laola1tv.py
index b5d27c2f07..4014a9256f 100644
--- a/yt_dlp/extractor/laola1tv.py
+++ b/yt_dlp/extractor/laola1tv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/lastfm.py b/yt_dlp/extractor/lastfm.py
index 5215717e8d..7ba666d064 100644
--- a/yt_dlp/extractor/lastfm.py
+++ b/yt_dlp/extractor/lastfm.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/lbry.py b/yt_dlp/extractor/lbry.py
index 5d5457c532..953ce2e184 100644
--- a/yt_dlp/extractor/lbry.py
+++ b/yt_dlp/extractor/lbry.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import json
 
diff --git a/yt_dlp/extractor/lci.py b/yt_dlp/extractor/lci.py
index 920872f5c4..81cf88b6c7 100644
--- a/yt_dlp/extractor/lci.py
+++ b/yt_dlp/extractor/lci.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/lcp.py b/yt_dlp/extractor/lcp.py
index ade27a99e0..87543d56f8 100644
--- a/yt_dlp/extractor/lcp.py
+++ b/yt_dlp/extractor/lcp.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .arkena import ArkenaIE
 
diff --git a/yt_dlp/extractor/lecture2go.py b/yt_dlp/extractor/lecture2go.py
index 81b5d41be4..bee4e7587b 100644
--- a/yt_dlp/extractor/lecture2go.py
+++ b/yt_dlp/extractor/lecture2go.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/lecturio.py b/yt_dlp/extractor/lecturio.py
index 0ee1eeb4d3..c3d0cb193b 100644
--- a/yt_dlp/extractor/lecturio.py
+++ b/yt_dlp/extractor/lecturio.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/leeco.py b/yt_dlp/extractor/leeco.py
index d5e11423ca..258e396cbd 100644
--- a/yt_dlp/extractor/leeco.py
+++ b/yt_dlp/extractor/leeco.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import datetime
 import hashlib
 import re
diff --git a/yt_dlp/extractor/lego.py b/yt_dlp/extractor/lego.py
index 901f43bcf3..7d0238a1f1 100644
--- a/yt_dlp/extractor/lego.py
+++ b/yt_dlp/extractor/lego.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import uuid
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/lemonde.py b/yt_dlp/extractor/lemonde.py
index 3306892e8d..c916791af5 100644
--- a/yt_dlp/extractor/lemonde.py
+++ b/yt_dlp/extractor/lemonde.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/lenta.py b/yt_dlp/extractor/lenta.py
index 2ebd4e5778..10aac984e4 100644
--- a/yt_dlp/extractor/lenta.py
+++ b/yt_dlp/extractor/lenta.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/libraryofcongress.py b/yt_dlp/extractor/libraryofcongress.py
index 03f2051444..afe3c98a11 100644
--- a/yt_dlp/extractor/libraryofcongress.py
+++ b/yt_dlp/extractor/libraryofcongress.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/libsyn.py b/yt_dlp/extractor/libsyn.py
index d1fcda4ef8..8245a34817 100644
--- a/yt_dlp/extractor/libsyn.py
+++ b/yt_dlp/extractor/libsyn.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/lifenews.py b/yt_dlp/extractor/lifenews.py
index 49a0a59890..8c7d2064d3 100644
--- a/yt_dlp/extractor/lifenews.py
+++ b/yt_dlp/extractor/lifenews.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/limelight.py b/yt_dlp/extractor/limelight.py
index b20681ad11..25667fc076 100644
--- a/yt_dlp/extractor/limelight.py
+++ b/yt_dlp/extractor/limelight.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/line.py b/yt_dlp/extractor/line.py
index 987c434300..63b6c002ab 100644
--- a/yt_dlp/extractor/line.py
+++ b/yt_dlp/extractor/line.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/linkedin.py b/yt_dlp/extractor/linkedin.py
index 0f57bfa06f..27f1080b44 100644
--- a/yt_dlp/extractor/linkedin.py
+++ b/yt_dlp/extractor/linkedin.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from itertools import zip_longest
 import re
 
diff --git a/yt_dlp/extractor/linuxacademy.py b/yt_dlp/extractor/linuxacademy.py
index 6aff88e13f..bf22855a98 100644
--- a/yt_dlp/extractor/linuxacademy.py
+++ b/yt_dlp/extractor/linuxacademy.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 import random
 
diff --git a/yt_dlp/extractor/litv.py b/yt_dlp/extractor/litv.py
index 16b475a441..31826ac99e 100644
--- a/yt_dlp/extractor/litv.py
+++ b/yt_dlp/extractor/litv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/livejournal.py b/yt_dlp/extractor/livejournal.py
index 3a9f4553f4..96bd8b2335 100644
--- a/yt_dlp/extractor/livejournal.py
+++ b/yt_dlp/extractor/livejournal.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import int_or_none
diff --git a/yt_dlp/extractor/livestream.py b/yt_dlp/extractor/livestream.py
index 45bf26d26c..4b90c22c56 100644
--- a/yt_dlp/extractor/livestream.py
+++ b/yt_dlp/extractor/livestream.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 import itertools
 
diff --git a/yt_dlp/extractor/lnkgo.py b/yt_dlp/extractor/lnkgo.py
index bd2dffac0c..3bb52777f6 100644
--- a/yt_dlp/extractor/lnkgo.py
+++ b/yt_dlp/extractor/lnkgo.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/localnews8.py b/yt_dlp/extractor/localnews8.py
index c3e9d10fae..6f3f02c705 100644
--- a/yt_dlp/extractor/localnews8.py
+++ b/yt_dlp/extractor/localnews8.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/lovehomeporn.py b/yt_dlp/extractor/lovehomeporn.py
index ca4b5f3755..ba5a13acd8 100644
--- a/yt_dlp/extractor/lovehomeporn.py
+++ b/yt_dlp/extractor/lovehomeporn.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .nuevo import NuevoBaseIE
 
 
diff --git a/yt_dlp/extractor/lrt.py b/yt_dlp/extractor/lrt.py
index 4024aef73a..53076b839f 100644
--- a/yt_dlp/extractor/lrt.py
+++ b/yt_dlp/extractor/lrt.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/lynda.py b/yt_dlp/extractor/lynda.py
index ce304743fb..1ae7f9d4fe 100644
--- a/yt_dlp/extractor/lynda.py
+++ b/yt_dlp/extractor/lynda.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/m6.py b/yt_dlp/extractor/m6.py
index 9806875e8d..9dcc601642 100644
--- a/yt_dlp/extractor/m6.py
+++ b/yt_dlp/extractor/m6.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/magentamusik360.py b/yt_dlp/extractor/magentamusik360.py
index 5c274902f9..5d0cb3bfb5 100644
--- a/yt_dlp/extractor/magentamusik360.py
+++ b/yt_dlp/extractor/magentamusik360.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/mailru.py b/yt_dlp/extractor/mailru.py
index 5d9f80bb31..5f30d0eaa8 100644
--- a/yt_dlp/extractor/mailru.py
+++ b/yt_dlp/extractor/mailru.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import json
 import re
diff --git a/yt_dlp/extractor/mainstreaming.py b/yt_dlp/extractor/mainstreaming.py
index 0f349a7a38..c144c75928 100644
--- a/yt_dlp/extractor/mainstreaming.py
+++ b/yt_dlp/extractor/mainstreaming.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/malltv.py b/yt_dlp/extractor/malltv.py
index fadfd93387..bfd6008b3a 100644
--- a/yt_dlp/extractor/malltv.py
+++ b/yt_dlp/extractor/malltv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/mangomolo.py b/yt_dlp/extractor/mangomolo.py
index 68ce138b3e..a392e9b542 100644
--- a/yt_dlp/extractor/mangomolo.py
+++ b/yt_dlp/extractor/mangomolo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_b64decode,
diff --git a/yt_dlp/extractor/manoto.py b/yt_dlp/extractor/manoto.py
index d12aa5f600..dc8653f5d5 100644
--- a/yt_dlp/extractor/manoto.py
+++ b/yt_dlp/extractor/manoto.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/manyvids.py b/yt_dlp/extractor/manyvids.py
index bd24f88535..1f537d2673 100644
--- a/yt_dlp/extractor/manyvids.py
+++ b/yt_dlp/extractor/manyvids.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/maoritv.py b/yt_dlp/extractor/maoritv.py
index 0d23fec75e..67780eafcc 100644
--- a/yt_dlp/extractor/maoritv.py
+++ b/yt_dlp/extractor/maoritv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/markiza.py b/yt_dlp/extractor/markiza.py
index def960a0c5..53ed79158f 100644
--- a/yt_dlp/extractor/markiza.py
+++ b/yt_dlp/extractor/markiza.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/massengeschmacktv.py b/yt_dlp/extractor/massengeschmacktv.py
index b381d31b48..4508e4391a 100644
--- a/yt_dlp/extractor/massengeschmacktv.py
+++ b/yt_dlp/extractor/massengeschmacktv.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/matchtv.py b/yt_dlp/extractor/matchtv.py
index e003b8d259..94ae20b26f 100644
--- a/yt_dlp/extractor/matchtv.py
+++ b/yt_dlp/extractor/matchtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mdr.py b/yt_dlp/extractor/mdr.py
index 3ca174c2b9..b44cf809ad 100644
--- a/yt_dlp/extractor/mdr.py
+++ b/yt_dlp/extractor/mdr.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urlparse
 from ..utils import (
diff --git a/yt_dlp/extractor/medaltv.py b/yt_dlp/extractor/medaltv.py
index 59cc30736c..527b50cb02 100644
--- a/yt_dlp/extractor/medaltv.py
+++ b/yt_dlp/extractor/medaltv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mediaite.py b/yt_dlp/extractor/mediaite.py
index b670f0d615..0f9079b112 100644
--- a/yt_dlp/extractor/mediaite.py
+++ b/yt_dlp/extractor/mediaite.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/mediaklikk.py b/yt_dlp/extractor/mediaklikk.py
index 18ff3befae..f9a449377e 100644
--- a/yt_dlp/extractor/mediaklikk.py
+++ b/yt_dlp/extractor/mediaklikk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from ..utils import (
     unified_strdate
 )
diff --git a/yt_dlp/extractor/medialaan.py b/yt_dlp/extractor/medialaan.py
index 788acf7fb2..297f8c4b25 100644
--- a/yt_dlp/extractor/medialaan.py
+++ b/yt_dlp/extractor/medialaan.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mediaset.py b/yt_dlp/extractor/mediaset.py
index d6b456c5d5..60c454ddad 100644
--- a/yt_dlp/extractor/mediaset.py
+++ b/yt_dlp/extractor/mediaset.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/mediasite.py b/yt_dlp/extractor/mediasite.py
index fbf9223b21..30464bad0e 100644
--- a/yt_dlp/extractor/mediasite.py
+++ b/yt_dlp/extractor/mediasite.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import json
 
diff --git a/yt_dlp/extractor/medici.py b/yt_dlp/extractor/medici.py
index cd910238e8..328ccd2c9b 100644
--- a/yt_dlp/extractor/medici.py
+++ b/yt_dlp/extractor/medici.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     unified_strdate,
diff --git a/yt_dlp/extractor/megaphone.py b/yt_dlp/extractor/megaphone.py
index 5bafa6cf44..0c150ef45c 100644
--- a/yt_dlp/extractor/megaphone.py
+++ b/yt_dlp/extractor/megaphone.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/megatvcom.py b/yt_dlp/extractor/megatvcom.py
index 0d6793acdb..ec481d016c 100644
--- a/yt_dlp/extractor/megatvcom.py
+++ b/yt_dlp/extractor/megatvcom.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/meipai.py b/yt_dlp/extractor/meipai.py
index 2445b8b398..95b6dfe52e 100644
--- a/yt_dlp/extractor/meipai.py
+++ b/yt_dlp/extractor/meipai.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/melonvod.py b/yt_dlp/extractor/melonvod.py
index bd8cf13ab4..0cbc961c42 100644
--- a/yt_dlp/extractor/melonvod.py
+++ b/yt_dlp/extractor/melonvod.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/meta.py b/yt_dlp/extractor/meta.py
index cdb46e163b..7c11e6017e 100644
--- a/yt_dlp/extractor/meta.py
+++ b/yt_dlp/extractor/meta.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .pladform import PladformIE
 from ..utils import (
diff --git a/yt_dlp/extractor/metacafe.py b/yt_dlp/extractor/metacafe.py
index 7b2d4a0031..31fec86d28 100644
--- a/yt_dlp/extractor/metacafe.py
+++ b/yt_dlp/extractor/metacafe.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/metacritic.py b/yt_dlp/extractor/metacritic.py
index 1424288e74..543bdffadd 100644
--- a/yt_dlp/extractor/metacritic.py
+++ b/yt_dlp/extractor/metacritic.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mgoon.py b/yt_dlp/extractor/mgoon.py
index 184c311bec..c41c513844 100644
--- a/yt_dlp/extractor/mgoon.py
+++ b/yt_dlp/extractor/mgoon.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/mgtv.py b/yt_dlp/extractor/mgtv.py
index 4ac70ea575..96f3fb9825 100644
--- a/yt_dlp/extractor/mgtv.py
+++ b/yt_dlp/extractor/mgtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import time
 import uuid
diff --git a/yt_dlp/extractor/miaopai.py b/yt_dlp/extractor/miaopai.py
index cf0610bdf4..329ce36582 100644
--- a/yt_dlp/extractor/miaopai.py
+++ b/yt_dlp/extractor/miaopai.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/microsoftstream.py b/yt_dlp/extractor/microsoftstream.py
index 4d5a9df1ff..2dde82a752 100644
--- a/yt_dlp/extractor/microsoftstream.py
+++ b/yt_dlp/extractor/microsoftstream.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from base64 import b64decode
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/microsoftvirtualacademy.py b/yt_dlp/extractor/microsoftvirtualacademy.py
index 9255a79641..f15f00ee57 100644
--- a/yt_dlp/extractor/microsoftvirtualacademy.py
+++ b/yt_dlp/extractor/microsoftvirtualacademy.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mildom.py b/yt_dlp/extractor/mildom.py
index 4de8e9ef4d..c7a61dfa0a 100644
--- a/yt_dlp/extractor/mildom.py
+++ b/yt_dlp/extractor/mildom.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import json
 import uuid
diff --git a/yt_dlp/extractor/minds.py b/yt_dlp/extractor/minds.py
index 9da07207ba..393d20604b 100644
--- a/yt_dlp/extractor/minds.py
+++ b/yt_dlp/extractor/minds.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/ministrygrid.py b/yt_dlp/extractor/ministrygrid.py
index 8ad9239c50..053c6726c3 100644
--- a/yt_dlp/extractor/ministrygrid.py
+++ b/yt_dlp/extractor/ministrygrid.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/minoto.py b/yt_dlp/extractor/minoto.py
index 603ce940ba..e799cd3bcc 100644
--- a/yt_dlp/extractor/minoto.py
+++ b/yt_dlp/extractor/minoto.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/miomio.py b/yt_dlp/extractor/miomio.py
index 40f72d66f2..a0a041ea54 100644
--- a/yt_dlp/extractor/miomio.py
+++ b/yt_dlp/extractor/miomio.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mirrativ.py b/yt_dlp/extractor/mirrativ.py
index 2111de615a..8192f2b467 100644
--- a/yt_dlp/extractor/mirrativ.py
+++ b/yt_dlp/extractor/mirrativ.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/mit.py b/yt_dlp/extractor/mit.py
index 60e4569785..38cc0c2741 100644
--- a/yt_dlp/extractor/mit.py
+++ b/yt_dlp/extractor/mit.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 import json
 
diff --git a/yt_dlp/extractor/mitele.py b/yt_dlp/extractor/mitele.py
index b5937233b9..12b2b2432d 100644
--- a/yt_dlp/extractor/mitele.py
+++ b/yt_dlp/extractor/mitele.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .telecinco import TelecincoIE
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/mixch.py b/yt_dlp/extractor/mixch.py
index 31f450dfa0..3f430a7176 100644
--- a/yt_dlp/extractor/mixch.py
+++ b/yt_dlp/extractor/mixch.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/mixcloud.py b/yt_dlp/extractor/mixcloud.py
index b19e59b1a5..796f268f43 100644
--- a/yt_dlp/extractor/mixcloud.py
+++ b/yt_dlp/extractor/mixcloud.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mlb.py b/yt_dlp/extractor/mlb.py
index b69301d977..5fb97083a0 100644
--- a/yt_dlp/extractor/mlb.py
+++ b/yt_dlp/extractor/mlb.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mlssoccer.py b/yt_dlp/extractor/mlssoccer.py
index 1d6d4b8040..9383f13581 100644
--- a/yt_dlp/extractor/mlssoccer.py
+++ b/yt_dlp/extractor/mlssoccer.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/mnet.py b/yt_dlp/extractor/mnet.py
index 0e26ca1b30..65e3d476a9 100644
--- a/yt_dlp/extractor/mnet.py
+++ b/yt_dlp/extractor/mnet.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/moevideo.py b/yt_dlp/extractor/moevideo.py
index a3f1b38663..fda08cae91 100644
--- a/yt_dlp/extractor/moevideo.py
+++ b/yt_dlp/extractor/moevideo.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/mofosex.py b/yt_dlp/extractor/mofosex.py
index 5234cac026..66a098c976 100644
--- a/yt_dlp/extractor/mofosex.py
+++ b/yt_dlp/extractor/mofosex.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mojvideo.py b/yt_dlp/extractor/mojvideo.py
index 16d94052bd..d47ad07421 100644
--- a/yt_dlp/extractor/mojvideo.py
+++ b/yt_dlp/extractor/mojvideo.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/morningstar.py b/yt_dlp/extractor/morningstar.py
index 71a22a614c..e9fcfe3e20 100644
--- a/yt_dlp/extractor/morningstar.py
+++ b/yt_dlp/extractor/morningstar.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/motherless.py b/yt_dlp/extractor/motherless.py
index 111c7c5442..9e53a8a97d 100644
--- a/yt_dlp/extractor/motherless.py
+++ b/yt_dlp/extractor/motherless.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import datetime
 import re
 
diff --git a/yt_dlp/extractor/motorsport.py b/yt_dlp/extractor/motorsport.py
index c9d1ab64dc..b292aeb9a1 100644
--- a/yt_dlp/extractor/motorsport.py
+++ b/yt_dlp/extractor/motorsport.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_urlparse,
diff --git a/yt_dlp/extractor/movieclips.py b/yt_dlp/extractor/movieclips.py
index 5453da1acf..4777f440e0 100644
--- a/yt_dlp/extractor/movieclips.py
+++ b/yt_dlp/extractor/movieclips.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     smuggle_url,
diff --git a/yt_dlp/extractor/moviepilot.py b/yt_dlp/extractor/moviepilot.py
index 4605d34815..ca541567a4 100644
--- a/yt_dlp/extractor/moviepilot.py
+++ b/yt_dlp/extractor/moviepilot.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .dailymotion import DailymotionIE
 from .common import InfoExtractor
 from ..utils import (
diff --git a/yt_dlp/extractor/moviezine.py b/yt_dlp/extractor/moviezine.py
index 730da4bd70..5757322d66 100644
--- a/yt_dlp/extractor/moviezine.py
+++ b/yt_dlp/extractor/moviezine.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/movingimage.py b/yt_dlp/extractor/movingimage.py
index 4f62d628a2..cdd8ba4dce 100644
--- a/yt_dlp/extractor/movingimage.py
+++ b/yt_dlp/extractor/movingimage.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     unescapeHTML,
diff --git a/yt_dlp/extractor/msn.py b/yt_dlp/extractor/msn.py
index f34e2102c2..6f4935e513 100644
--- a/yt_dlp/extractor/msn.py
+++ b/yt_dlp/extractor/msn.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/mtv.py b/yt_dlp/extractor/mtv.py
index cff314e272..3ef851e0bb 100644
--- a/yt_dlp/extractor/mtv.py
+++ b/yt_dlp/extractor/mtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/muenchentv.py b/yt_dlp/extractor/muenchentv.py
index a53929e1b4..b9681d1bd7 100644
--- a/yt_dlp/extractor/muenchentv.py
+++ b/yt_dlp/extractor/muenchentv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/murrtube.py b/yt_dlp/extractor/murrtube.py
index 1eb5de6606..508d512479 100644
--- a/yt_dlp/extractor/murrtube.py
+++ b/yt_dlp/extractor/murrtube.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import json
 
diff --git a/yt_dlp/extractor/musescore.py b/yt_dlp/extractor/musescore.py
index 09fadf8d90..289ae57335 100644
--- a/yt_dlp/extractor/musescore.py
+++ b/yt_dlp/extractor/musescore.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/musicdex.py b/yt_dlp/extractor/musicdex.py
index 05f722091b..4d8e74f6b4 100644
--- a/yt_dlp/extractor/musicdex.py
+++ b/yt_dlp/extractor/musicdex.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     date_from_str,
diff --git a/yt_dlp/extractor/mwave.py b/yt_dlp/extractor/mwave.py
index a67276596f..0cbb167362 100644
--- a/yt_dlp/extractor/mwave.py
+++ b/yt_dlp/extractor/mwave.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/mxplayer.py b/yt_dlp/extractor/mxplayer.py
index 3c2afd838d..cdc340a80f 100644
--- a/yt_dlp/extractor/mxplayer.py
+++ b/yt_dlp/extractor/mxplayer.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import try_get
diff --git a/yt_dlp/extractor/mychannels.py b/yt_dlp/extractor/mychannels.py
index d820d4eb8f..8a70c1f7b4 100644
--- a/yt_dlp/extractor/mychannels.py
+++ b/yt_dlp/extractor/mychannels.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/myspace.py b/yt_dlp/extractor/myspace.py
index 4227d42481..63d36c30a7 100644
--- a/yt_dlp/extractor/myspace.py
+++ b/yt_dlp/extractor/myspace.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/myspass.py b/yt_dlp/extractor/myspass.py
index 1775d5f0be..28ac982d66 100644
--- a/yt_dlp/extractor/myspass.py
+++ b/yt_dlp/extractor/myspass.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/myvi.py b/yt_dlp/extractor/myvi.py
index 75d2863655..b31cf4493a 100644
--- a/yt_dlp/extractor/myvi.py
+++ b/yt_dlp/extractor/myvi.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/myvideoge.py b/yt_dlp/extractor/myvideoge.py
index 0a1d7d0cbc..513d4cb773 100644
--- a/yt_dlp/extractor/myvideoge.py
+++ b/yt_dlp/extractor/myvideoge.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import js_to_json
 
diff --git a/yt_dlp/extractor/myvidster.py b/yt_dlp/extractor/myvidster.py
index 2117d302d6..c91f294bf0 100644
--- a/yt_dlp/extractor/myvidster.py
+++ b/yt_dlp/extractor/myvidster.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/n1.py b/yt_dlp/extractor/n1.py
index fdb7f32dbe..cc0ff533e7 100644
--- a/yt_dlp/extractor/n1.py
+++ b/yt_dlp/extractor/n1.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nate.py b/yt_dlp/extractor/nate.py
index 072faf6ea3..c83b2acbd8 100644
--- a/yt_dlp/extractor/nate.py
+++ b/yt_dlp/extractor/nate.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nationalgeographic.py b/yt_dlp/extractor/nationalgeographic.py
index ee12e2b47f..f22317d561 100644
--- a/yt_dlp/extractor/nationalgeographic.py
+++ b/yt_dlp/extractor/nationalgeographic.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .fox import FOXIE
 from ..utils import (
diff --git a/yt_dlp/extractor/naver.py b/yt_dlp/extractor/naver.py
index a6821ba86d..a230d9cdd5 100644
--- a/yt_dlp/extractor/naver.py
+++ b/yt_dlp/extractor/naver.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nba.py b/yt_dlp/extractor/nba.py
index 359cc52b73..e95c1b795c 100644
--- a/yt_dlp/extractor/nba.py
+++ b/yt_dlp/extractor/nba.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/nbc.py b/yt_dlp/extractor/nbc.py
index 109403440a..8aab80a0f7 100644
--- a/yt_dlp/extractor/nbc.py
+++ b/yt_dlp/extractor/nbc.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import base64
 import json
 import re
diff --git a/yt_dlp/extractor/ndr.py b/yt_dlp/extractor/ndr.py
index 1917254b8d..de0142ccf7 100644
--- a/yt_dlp/extractor/ndr.py
+++ b/yt_dlp/extractor/ndr.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/ndtv.py b/yt_dlp/extractor/ndtv.py
index bc3eb91606..fbb033169f 100644
--- a/yt_dlp/extractor/ndtv.py
+++ b/yt_dlp/extractor/ndtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_urllib_parse_unquote_plus
diff --git a/yt_dlp/extractor/nebula.py b/yt_dlp/extractor/nebula.py
index 77f253519e..eccf740aad 100644
--- a/yt_dlp/extractor/nebula.py
+++ b/yt_dlp/extractor/nebula.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import json
 import time
diff --git a/yt_dlp/extractor/nerdcubed.py b/yt_dlp/extractor/nerdcubed.py
index 9feccc6723..7c801b5d38 100644
--- a/yt_dlp/extractor/nerdcubed.py
+++ b/yt_dlp/extractor/nerdcubed.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import datetime
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/neteasemusic.py b/yt_dlp/extractor/neteasemusic.py
index 57b4774b6b..4def7e76bc 100644
--- a/yt_dlp/extractor/neteasemusic.py
+++ b/yt_dlp/extractor/neteasemusic.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from hashlib import md5
 from base64 import b64encode
 from datetime import datetime
diff --git a/yt_dlp/extractor/netzkino.py b/yt_dlp/extractor/netzkino.py
index 4ad0d8e96c..49b29b67cc 100644
--- a/yt_dlp/extractor/netzkino.py
+++ b/yt_dlp/extractor/netzkino.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/newgrounds.py b/yt_dlp/extractor/newgrounds.py
index 6525a6d8a3..ba24720e32 100644
--- a/yt_dlp/extractor/newgrounds.py
+++ b/yt_dlp/extractor/newgrounds.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/newstube.py b/yt_dlp/extractor/newstube.py
index 479141ae03..20db460573 100644
--- a/yt_dlp/extractor/newstube.py
+++ b/yt_dlp/extractor/newstube.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import hashlib
 
diff --git a/yt_dlp/extractor/newsy.py b/yt_dlp/extractor/newsy.py
index cf31641004..9fde6c0790 100644
--- a/yt_dlp/extractor/newsy.py
+++ b/yt_dlp/extractor/newsy.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     js_to_json,
diff --git a/yt_dlp/extractor/nextmedia.py b/yt_dlp/extractor/nextmedia.py
index 7bd1290bf0..1f83089fc9 100644
--- a/yt_dlp/extractor/nextmedia.py
+++ b/yt_dlp/extractor/nextmedia.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urlparse
 from ..utils import (
diff --git a/yt_dlp/extractor/nexx.py b/yt_dlp/extractor/nexx.py
index a521bb6e49..01376be3da 100644
--- a/yt_dlp/extractor/nexx.py
+++ b/yt_dlp/extractor/nexx.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import random
 import re
diff --git a/yt_dlp/extractor/nfb.py b/yt_dlp/extractor/nfb.py
index a12e503de2..79c6aaf0cb 100644
--- a/yt_dlp/extractor/nfb.py
+++ b/yt_dlp/extractor/nfb.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/nfhsnetwork.py b/yt_dlp/extractor/nfhsnetwork.py
index 802f6caf06..e6f98b036a 100644
--- a/yt_dlp/extractor/nfhsnetwork.py
+++ b/yt_dlp/extractor/nfhsnetwork.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/nfl.py b/yt_dlp/extractor/nfl.py
index 821276a31b..e5810b3464 100644
--- a/yt_dlp/extractor/nfl.py
+++ b/yt_dlp/extractor/nfl.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nhk.py b/yt_dlp/extractor/nhk.py
index 3b8efc3e60..cf2ec7b793 100644
--- a/yt_dlp/extractor/nhk.py
+++ b/yt_dlp/extractor/nhk.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nhl.py b/yt_dlp/extractor/nhl.py
index d3a5e17e94..884f9e2aed 100644
--- a/yt_dlp/extractor/nhl.py
+++ b/yt_dlp/extractor/nhl.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/nick.py b/yt_dlp/extractor/nick.py
index ba7da76026..2a228d8de2 100644
--- a/yt_dlp/extractor/nick.py
+++ b/yt_dlp/extractor/nick.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .mtv import MTVServicesInfoExtractor
 from ..utils import update_url_query
 
diff --git a/yt_dlp/extractor/niconico.py b/yt_dlp/extractor/niconico.py
index 4eb6ed070a..e60556a4d2 100644
--- a/yt_dlp/extractor/niconico.py
+++ b/yt_dlp/extractor/niconico.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import datetime
 import functools
 import itertools
diff --git a/yt_dlp/extractor/ninecninemedia.py b/yt_dlp/extractor/ninecninemedia.py
index 781842721b..462caf4663 100644
--- a/yt_dlp/extractor/ninecninemedia.py
+++ b/yt_dlp/extractor/ninecninemedia.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     float_or_none,
diff --git a/yt_dlp/extractor/ninegag.py b/yt_dlp/extractor/ninegag.py
index 14390823bc..00ca95ea2e 100644
--- a/yt_dlp/extractor/ninegag.py
+++ b/yt_dlp/extractor/ninegag.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/ninenow.py b/yt_dlp/extractor/ninenow.py
index 6043674ba1..b970f8ccb5 100644
--- a/yt_dlp/extractor/ninenow.py
+++ b/yt_dlp/extractor/ninenow.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/nintendo.py b/yt_dlp/extractor/nintendo.py
index ff8f70ba66..ed839af25d 100644
--- a/yt_dlp/extractor/nintendo.py
+++ b/yt_dlp/extractor/nintendo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nitter.py b/yt_dlp/extractor/nitter.py
index 8bb709cd7e..251bf444fa 100644
--- a/yt_dlp/extractor/nitter.py
+++ b/yt_dlp/extractor/nitter.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urlparse
 from ..utils import (
diff --git a/yt_dlp/extractor/njpwworld.py b/yt_dlp/extractor/njpwworld.py
index 68c8c8e522..e761cf257c 100644
--- a/yt_dlp/extractor/njpwworld.py
+++ b/yt_dlp/extractor/njpwworld.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nobelprize.py b/yt_dlp/extractor/nobelprize.py
index 4dfdb09d62..35b64530f8 100644
--- a/yt_dlp/extractor/nobelprize.py
+++ b/yt_dlp/extractor/nobelprize.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     js_to_json,
diff --git a/yt_dlp/extractor/noco.py b/yt_dlp/extractor/noco.py
index 28af909d52..583d399cc7 100644
--- a/yt_dlp/extractor/noco.py
+++ b/yt_dlp/extractor/noco.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import time
 import hashlib
diff --git a/yt_dlp/extractor/nonktube.py b/yt_dlp/extractor/nonktube.py
index ca1424e06a..f191be33b7 100644
--- a/yt_dlp/extractor/nonktube.py
+++ b/yt_dlp/extractor/nonktube.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .nuevo import NuevoBaseIE
 
 
diff --git a/yt_dlp/extractor/noodlemagazine.py b/yt_dlp/extractor/noodlemagazine.py
index 2f170bbfe2..3e04da67e8 100644
--- a/yt_dlp/extractor/noodlemagazine.py
+++ b/yt_dlp/extractor/noodlemagazine.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/noovo.py b/yt_dlp/extractor/noovo.py
index b40770d07a..acbb74c6eb 100644
--- a/yt_dlp/extractor/noovo.py
+++ b/yt_dlp/extractor/noovo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .brightcove import BrightcoveNewIE
 from .common import InfoExtractor
 from ..compat import compat_str
diff --git a/yt_dlp/extractor/normalboots.py b/yt_dlp/extractor/normalboots.py
index 61fe571dfe..07babcd2c5 100644
--- a/yt_dlp/extractor/normalboots.py
+++ b/yt_dlp/extractor/normalboots.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .jwplatform import JWPlatformIE
 
diff --git a/yt_dlp/extractor/nosvideo.py b/yt_dlp/extractor/nosvideo.py
index 53c500c351..b6d3ea40c1 100644
--- a/yt_dlp/extractor/nosvideo.py
+++ b/yt_dlp/extractor/nosvideo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nova.py b/yt_dlp/extractor/nova.py
index 00a64f88d1..6875d26ba5 100644
--- a/yt_dlp/extractor/nova.py
+++ b/yt_dlp/extractor/nova.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/novaplay.py b/yt_dlp/extractor/novaplay.py
index bfb2c87511..4f1a846518 100644
--- a/yt_dlp/extractor/novaplay.py
+++ b/yt_dlp/extractor/novaplay.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from ..utils import int_or_none, parse_duration, parse_iso8601
 
diff --git a/yt_dlp/extractor/nowness.py b/yt_dlp/extractor/nowness.py
index b2c715f413..fc9043bceb 100644
--- a/yt_dlp/extractor/nowness.py
+++ b/yt_dlp/extractor/nowness.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .brightcove import (
     BrightcoveLegacyIE,
     BrightcoveNewIE,
diff --git a/yt_dlp/extractor/noz.py b/yt_dlp/extractor/noz.py
index bdc2efcd7b..22cb08e8a2 100644
--- a/yt_dlp/extractor/noz.py
+++ b/yt_dlp/extractor/noz.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_urllib_parse_unquote,
diff --git a/yt_dlp/extractor/npo.py b/yt_dlp/extractor/npo.py
index a8aaef6f16..0b5f32c2e8 100644
--- a/yt_dlp/extractor/npo.py
+++ b/yt_dlp/extractor/npo.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/npr.py b/yt_dlp/extractor/npr.py
index 49f062d7ab..6d93f154c0 100644
--- a/yt_dlp/extractor/npr.py
+++ b/yt_dlp/extractor/npr.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/nrk.py b/yt_dlp/extractor/nrk.py
index 0cf26d5981..553c551329 100644
--- a/yt_dlp/extractor/nrk.py
+++ b/yt_dlp/extractor/nrk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import random
 import re
diff --git a/yt_dlp/extractor/nrl.py b/yt_dlp/extractor/nrl.py
index 0bd5086ae2..798d03417b 100644
--- a/yt_dlp/extractor/nrl.py
+++ b/yt_dlp/extractor/nrl.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/ntvcojp.py b/yt_dlp/extractor/ntvcojp.py
index c9af91188b..422ec6eb02 100644
--- a/yt_dlp/extractor/ntvcojp.py
+++ b/yt_dlp/extractor/ntvcojp.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/ntvde.py b/yt_dlp/extractor/ntvde.py
index 035582ee82..d252ced866 100644
--- a/yt_dlp/extractor/ntvde.py
+++ b/yt_dlp/extractor/ntvde.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ntvru.py b/yt_dlp/extractor/ntvru.py
index c47d1dfa4d..c8df110e80 100644
--- a/yt_dlp/extractor/ntvru.py
+++ b/yt_dlp/extractor/ntvru.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/nuevo.py b/yt_dlp/extractor/nuevo.py
index be1e09d375..ec54041f12 100644
--- a/yt_dlp/extractor/nuevo.py
+++ b/yt_dlp/extractor/nuevo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..utils import (
diff --git a/yt_dlp/extractor/nuvid.py b/yt_dlp/extractor/nuvid.py
index 84fb97d6a3..fafcc8f4b3 100644
--- a/yt_dlp/extractor/nuvid.py
+++ b/yt_dlp/extractor/nuvid.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/nytimes.py b/yt_dlp/extractor/nytimes.py
index 99964737d8..f388688c4c 100644
--- a/yt_dlp/extractor/nytimes.py
+++ b/yt_dlp/extractor/nytimes.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hmac
 import hashlib
 import base64
diff --git a/yt_dlp/extractor/nzherald.py b/yt_dlp/extractor/nzherald.py
index e5601b4953..7c9efd9226 100644
--- a/yt_dlp/extractor/nzherald.py
+++ b/yt_dlp/extractor/nzherald.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .brightcove import BrightcoveNewIE
 from .common import InfoExtractor
 
diff --git a/yt_dlp/extractor/nzz.py b/yt_dlp/extractor/nzz.py
index 61ee77adbd..ac3b73156e 100644
--- a/yt_dlp/extractor/nzz.py
+++ b/yt_dlp/extractor/nzz.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/odatv.py b/yt_dlp/extractor/odatv.py
index 314527f985..24ab939421 100644
--- a/yt_dlp/extractor/odatv.py
+++ b/yt_dlp/extractor/odatv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/odnoklassniki.py b/yt_dlp/extractor/odnoklassniki.py
index 293f1aa603..36a7f5f4e7 100644
--- a/yt_dlp/extractor/odnoklassniki.py
+++ b/yt_dlp/extractor/odnoklassniki.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/oktoberfesttv.py b/yt_dlp/extractor/oktoberfesttv.py
index 276567436b..e0ac8563a7 100644
--- a/yt_dlp/extractor/oktoberfesttv.py
+++ b/yt_dlp/extractor/oktoberfesttv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/olympics.py b/yt_dlp/extractor/olympics.py
index 784f282c7b..85f17a2f42 100644
--- a/yt_dlp/extractor/olympics.py
+++ b/yt_dlp/extractor/olympics.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/on24.py b/yt_dlp/extractor/on24.py
index d4d824430f..779becc700 100644
--- a/yt_dlp/extractor/on24.py
+++ b/yt_dlp/extractor/on24.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/once.py b/yt_dlp/extractor/once.py
index 3e44b78290..460b82d02f 100644
--- a/yt_dlp/extractor/once.py
+++ b/yt_dlp/extractor/once.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ondemandkorea.py b/yt_dlp/extractor/ondemandkorea.py
index e933ea2cc8..84687ef473 100644
--- a/yt_dlp/extractor/ondemandkorea.py
+++ b/yt_dlp/extractor/ondemandkorea.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/onefootball.py b/yt_dlp/extractor/onefootball.py
index 826faadd2e..41815bef1f 100644
--- a/yt_dlp/extractor/onefootball.py
+++ b/yt_dlp/extractor/onefootball.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/onet.py b/yt_dlp/extractor/onet.py
index 95177a2131..ea46d7def6 100644
--- a/yt_dlp/extractor/onet.py
+++ b/yt_dlp/extractor/onet.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/onionstudios.py b/yt_dlp/extractor/onionstudios.py
index cf5c39e66b..9776b4d975 100644
--- a/yt_dlp/extractor/onionstudios.py
+++ b/yt_dlp/extractor/onionstudios.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ooyala.py b/yt_dlp/extractor/ooyala.py
index 20cfa0a870..77017f08b9 100644
--- a/yt_dlp/extractor/ooyala.py
+++ b/yt_dlp/extractor/ooyala.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import base64
 import re
 
diff --git a/yt_dlp/extractor/opencast.py b/yt_dlp/extractor/opencast.py
index cf8d917176..c640224dd6 100644
--- a/yt_dlp/extractor/opencast.py
+++ b/yt_dlp/extractor/opencast.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/openload.py b/yt_dlp/extractor/openload.py
index c19d04900f..41ef2e892b 100644
--- a/yt_dlp/extractor/openload.py
+++ b/yt_dlp/extractor/openload.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import os
 import subprocess
@@ -50,7 +47,7 @@ def cookie_jar_to_list(cookie_jar):
     return [cookie_to_dict(cookie) for cookie in cookie_jar]
 
 
-class PhantomJSwrapper(object):
+class PhantomJSwrapper:
     """PhantomJS wrapper class
 
     This class is experimental.
@@ -136,7 +133,7 @@ def __del__(self):
         for name in self._TMP_FILE_NAMES:
             try:
                 os.remove(self._TMP_FILES[name].name)
-            except (IOError, OSError, KeyError):
+            except (OSError, KeyError):
                 pass
 
     def _save_cookies(self, url):
@@ -217,9 +214,9 @@ def get(self, url, html=None, video_id=None, note=None, note2='Executing JS on w
             f.write(self._TEMPLATE.format(**replaces).encode('utf-8'))
 
         if video_id is None:
-            self.extractor.to_screen('%s' % (note2,))
+            self.extractor.to_screen(f'{note2}')
         else:
-            self.extractor.to_screen('%s: %s' % (video_id, note2))
+            self.extractor.to_screen(f'{video_id}: {note2}')
 
         p = Popen(
             [self.exe, '--ssl-protocol=any', self._TMP_FILES['script'].name],
diff --git a/yt_dlp/extractor/openrec.py b/yt_dlp/extractor/openrec.py
index 5eb1cdbad5..7546c12fb4 100644
--- a/yt_dlp/extractor/openrec.py
+++ b/yt_dlp/extractor/openrec.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/ora.py b/yt_dlp/extractor/ora.py
index 422d0b3304..09b1214227 100644
--- a/yt_dlp/extractor/ora.py
+++ b/yt_dlp/extractor/ora.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 from .common import InfoExtractor
 from ..compat import compat_urlparse
diff --git a/yt_dlp/extractor/orf.py b/yt_dlp/extractor/orf.py
index 0628977a02..56309ffcbb 100644
--- a/yt_dlp/extractor/orf.py
+++ b/yt_dlp/extractor/orf.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/outsidetv.py b/yt_dlp/extractor/outsidetv.py
index c5333b08cb..b1fcbd6a77 100644
--- a/yt_dlp/extractor/outsidetv.py
+++ b/yt_dlp/extractor/outsidetv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/packtpub.py b/yt_dlp/extractor/packtpub.py
index 62c52cd6e4..51778d8a20 100644
--- a/yt_dlp/extractor/packtpub.py
+++ b/yt_dlp/extractor/packtpub.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/palcomp3.py b/yt_dlp/extractor/palcomp3.py
index d0a62fb17e..4b0801c1a0 100644
--- a/yt_dlp/extractor/palcomp3.py
+++ b/yt_dlp/extractor/palcomp3.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/pandoratv.py b/yt_dlp/extractor/pandoratv.py
index 623005338b..3747f31d2c 100644
--- a/yt_dlp/extractor/pandoratv.py
+++ b/yt_dlp/extractor/pandoratv.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/paramountplus.py b/yt_dlp/extractor/paramountplus.py
index 94a9319ea0..7987d77c6e 100644
--- a/yt_dlp/extractor/paramountplus.py
+++ b/yt_dlp/extractor/paramountplus.py
@@ -1,4 +1,3 @@
-from __future__ import unicode_literals
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/parliamentliveuk.py b/yt_dlp/extractor/parliamentliveuk.py
index 974d65482f..38cb031645 100644
--- a/yt_dlp/extractor/parliamentliveuk.py
+++ b/yt_dlp/extractor/parliamentliveuk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import uuid
 
diff --git a/yt_dlp/extractor/parlview.py b/yt_dlp/extractor/parlview.py
index c85eaa7dcc..f31ae576cd 100644
--- a/yt_dlp/extractor/parlview.py
+++ b/yt_dlp/extractor/parlview.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/patreon.py b/yt_dlp/extractor/patreon.py
index 963a0d6fb9..cce9843d41 100644
--- a/yt_dlp/extractor/patreon.py
+++ b/yt_dlp/extractor/patreon.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pbs.py b/yt_dlp/extractor/pbs.py
index e48a2b8e08..4e6674e85e 100644
--- a/yt_dlp/extractor/pbs.py
+++ b/yt_dlp/extractor/pbs.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pearvideo.py b/yt_dlp/extractor/pearvideo.py
index 1d777221cc..d552e09666 100644
--- a/yt_dlp/extractor/pearvideo.py
+++ b/yt_dlp/extractor/pearvideo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/peekvids.py b/yt_dlp/extractor/peekvids.py
index 4bf68559a1..f1c4469d65 100644
--- a/yt_dlp/extractor/peekvids.py
+++ b/yt_dlp/extractor/peekvids.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/peertube.py b/yt_dlp/extractor/peertube.py
index 9d6b821784..0d3bc18a84 100644
--- a/yt_dlp/extractor/peertube.py
+++ b/yt_dlp/extractor/peertube.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/peertv.py b/yt_dlp/extractor/peertv.py
index 002d33a880..821abe496e 100644
--- a/yt_dlp/extractor/peertv.py
+++ b/yt_dlp/extractor/peertv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import js_to_json
 
diff --git a/yt_dlp/extractor/peloton.py b/yt_dlp/extractor/peloton.py
index 7d832253fe..8e50ffc7f6 100644
--- a/yt_dlp/extractor/peloton.py
+++ b/yt_dlp/extractor/peloton.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/people.py b/yt_dlp/extractor/people.py
index 6ca95715ee..c5143c3edd 100644
--- a/yt_dlp/extractor/people.py
+++ b/yt_dlp/extractor/people.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/performgroup.py b/yt_dlp/extractor/performgroup.py
index c00d393754..824495f40d 100644
--- a/yt_dlp/extractor/performgroup.py
+++ b/yt_dlp/extractor/performgroup.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/periscope.py b/yt_dlp/extractor/periscope.py
index 1a292b8ac4..fc8591a2ce 100644
--- a/yt_dlp/extractor/periscope.py
+++ b/yt_dlp/extractor/periscope.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/philharmoniedeparis.py b/yt_dlp/extractor/philharmoniedeparis.py
index 9f4899c09c..22164caaac 100644
--- a/yt_dlp/extractor/philharmoniedeparis.py
+++ b/yt_dlp/extractor/philharmoniedeparis.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/phoenix.py b/yt_dlp/extractor/phoenix.py
index e3ea014436..5fa133afea 100644
--- a/yt_dlp/extractor/phoenix.py
+++ b/yt_dlp/extractor/phoenix.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .youtube import YoutubeIE
diff --git a/yt_dlp/extractor/photobucket.py b/yt_dlp/extractor/photobucket.py
index 53aebe2d92..71e9a4805b 100644
--- a/yt_dlp/extractor/photobucket.py
+++ b/yt_dlp/extractor/photobucket.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/piapro.py b/yt_dlp/extractor/piapro.py
index ae160623b8..d8d9c78010 100644
--- a/yt_dlp/extractor/piapro.py
+++ b/yt_dlp/extractor/piapro.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urlparse
 from ..utils import (
diff --git a/yt_dlp/extractor/picarto.py b/yt_dlp/extractor/picarto.py
index adf21fda87..54999a832c 100644
--- a/yt_dlp/extractor/picarto.py
+++ b/yt_dlp/extractor/picarto.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/piksel.py b/yt_dlp/extractor/piksel.py
index 84c3de2f0e..14a5408598 100644
--- a/yt_dlp/extractor/piksel.py
+++ b/yt_dlp/extractor/piksel.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pinkbike.py b/yt_dlp/extractor/pinkbike.py
index 9f3501f777..313b5cce0d 100644
--- a/yt_dlp/extractor/pinkbike.py
+++ b/yt_dlp/extractor/pinkbike.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pinterest.py b/yt_dlp/extractor/pinterest.py
index 80e9cd00ee..171f9e4eb0 100644
--- a/yt_dlp/extractor/pinterest.py
+++ b/yt_dlp/extractor/pinterest.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pixivsketch.py b/yt_dlp/extractor/pixivsketch.py
index f0ad0b24a1..bfdb8b24e8 100644
--- a/yt_dlp/extractor/pixivsketch.py
+++ b/yt_dlp/extractor/pixivsketch.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/pladform.py b/yt_dlp/extractor/pladform.py
index 99ade85ec8..301f5c8387 100644
--- a/yt_dlp/extractor/pladform.py
+++ b/yt_dlp/extractor/pladform.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/planetmarathi.py b/yt_dlp/extractor/planetmarathi.py
index 07ac15b540..03b9d6aaae 100644
--- a/yt_dlp/extractor/planetmarathi.py
+++ b/yt_dlp/extractor/planetmarathi.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     try_get,
diff --git a/yt_dlp/extractor/platzi.py b/yt_dlp/extractor/platzi.py
index 17f52e7f41..29d3210ace 100644
--- a/yt_dlp/extractor/platzi.py
+++ b/yt_dlp/extractor/platzi.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_b64decode,
diff --git a/yt_dlp/extractor/playfm.py b/yt_dlp/extractor/playfm.py
index 4298cbe308..e895ba480c 100644
--- a/yt_dlp/extractor/playfm.py
+++ b/yt_dlp/extractor/playfm.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/playplustv.py b/yt_dlp/extractor/playplustv.py
index cad2c3a0f4..05dbaf0661 100644
--- a/yt_dlp/extractor/playplustv.py
+++ b/yt_dlp/extractor/playplustv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/plays.py b/yt_dlp/extractor/plays.py
index ddfc6f1486..700dfe4077 100644
--- a/yt_dlp/extractor/plays.py
+++ b/yt_dlp/extractor/plays.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/playstuff.py b/yt_dlp/extractor/playstuff.py
index 5a329957f5..b424ba1872 100644
--- a/yt_dlp/extractor/playstuff.py
+++ b/yt_dlp/extractor/playstuff.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/playtvak.py b/yt_dlp/extractor/playtvak.py
index 30c8a599e7..f7e5ddbe77 100644
--- a/yt_dlp/extractor/playtvak.py
+++ b/yt_dlp/extractor/playtvak.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_urlparse,
diff --git a/yt_dlp/extractor/playvid.py b/yt_dlp/extractor/playvid.py
index e1c406b6c2..5ffefc934d 100644
--- a/yt_dlp/extractor/playvid.py
+++ b/yt_dlp/extractor/playvid.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/playwire.py b/yt_dlp/extractor/playwire.py
index 9c9e597b5a..ab7f71493f 100644
--- a/yt_dlp/extractor/playwire.py
+++ b/yt_dlp/extractor/playwire.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     dict_get,
diff --git a/yt_dlp/extractor/pluralsight.py b/yt_dlp/extractor/pluralsight.py
index 2a5e0e4887..b50152ad8b 100644
--- a/yt_dlp/extractor/pluralsight.py
+++ b/yt_dlp/extractor/pluralsight.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import collections
 import json
 import os
diff --git a/yt_dlp/extractor/plutotv.py b/yt_dlp/extractor/plutotv.py
index 26aff1af5d..6e8f46fa32 100644
--- a/yt_dlp/extractor/plutotv.py
+++ b/yt_dlp/extractor/plutotv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import uuid
 
diff --git a/yt_dlp/extractor/podomatic.py b/yt_dlp/extractor/podomatic.py
index 673a3ab949..985bfae9dd 100644
--- a/yt_dlp/extractor/podomatic.py
+++ b/yt_dlp/extractor/podomatic.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pokemon.py b/yt_dlp/extractor/pokemon.py
index b411390e2d..eef0d02ca9 100644
--- a/yt_dlp/extractor/pokemon.py
+++ b/yt_dlp/extractor/pokemon.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pokergo.py b/yt_dlp/extractor/pokergo.py
index c9e2fed12b..5c7baadf24 100644
--- a/yt_dlp/extractor/pokergo.py
+++ b/yt_dlp/extractor/pokergo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/polsatgo.py b/yt_dlp/extractor/polsatgo.py
index 1e3f46c07c..e44d951e6e 100644
--- a/yt_dlp/extractor/polsatgo.py
+++ b/yt_dlp/extractor/polsatgo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from uuid import uuid4
 import json
 
diff --git a/yt_dlp/extractor/polskieradio.py b/yt_dlp/extractor/polskieradio.py
index b2b3eb29cf..514753b64d 100644
--- a/yt_dlp/extractor/polskieradio.py
+++ b/yt_dlp/extractor/polskieradio.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import json
 import math
diff --git a/yt_dlp/extractor/popcorntimes.py b/yt_dlp/extractor/popcorntimes.py
index 5f9d0e720b..ed741a07be 100644
--- a/yt_dlp/extractor/popcorntimes.py
+++ b/yt_dlp/extractor/popcorntimes.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import (
     compat_b64decode,
diff --git a/yt_dlp/extractor/popcorntv.py b/yt_dlp/extractor/popcorntv.py
index 66d2e50940..77984626f1 100644
--- a/yt_dlp/extractor/popcorntv.py
+++ b/yt_dlp/extractor/popcorntv.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     extract_attributes,
diff --git a/yt_dlp/extractor/porn91.py b/yt_dlp/extractor/porn91.py
index 20eac647a8..af4a0dc9c7 100644
--- a/yt_dlp/extractor/porn91.py
+++ b/yt_dlp/extractor/porn91.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/porncom.py b/yt_dlp/extractor/porncom.py
index 83df22141b..2ebd3fa096 100644
--- a/yt_dlp/extractor/porncom.py
+++ b/yt_dlp/extractor/porncom.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pornez.py b/yt_dlp/extractor/pornez.py
index 713dc00805..df0e44a699 100644
--- a/yt_dlp/extractor/pornez.py
+++ b/yt_dlp/extractor/pornez.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/pornflip.py b/yt_dlp/extractor/pornflip.py
index accf45269b..26536bc656 100644
--- a/yt_dlp/extractor/pornflip.py
+++ b/yt_dlp/extractor/pornflip.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/pornhd.py b/yt_dlp/extractor/pornhd.py
index 9dbd72f1d2..06a44ddd14 100644
--- a/yt_dlp/extractor/pornhd.py
+++ b/yt_dlp/extractor/pornhd.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/pornhub.py b/yt_dlp/extractor/pornhub.py
index 17c8c91007..d296ccacb9 100644
--- a/yt_dlp/extractor/pornhub.py
+++ b/yt_dlp/extractor/pornhub.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import itertools
 import math
diff --git a/yt_dlp/extractor/pornotube.py b/yt_dlp/extractor/pornotube.py
index 1b5b9a320d..e0960f4c6f 100644
--- a/yt_dlp/extractor/pornotube.py
+++ b/yt_dlp/extractor/pornotube.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/pornovoisines.py b/yt_dlp/extractor/pornovoisines.py
index 18459fc94e..96d2da7c75 100644
--- a/yt_dlp/extractor/pornovoisines.py
+++ b/yt_dlp/extractor/pornovoisines.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/pornoxo.py b/yt_dlp/extractor/pornoxo.py
index 489dc2b259..5104d8a49b 100644
--- a/yt_dlp/extractor/pornoxo.py
+++ b/yt_dlp/extractor/pornoxo.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     str_to_int,
diff --git a/yt_dlp/extractor/presstv.py b/yt_dlp/extractor/presstv.py
index bfb2eb71e3..26ce74a590 100644
--- a/yt_dlp/extractor/presstv.py
+++ b/yt_dlp/extractor/presstv.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import remove_start
 
diff --git a/yt_dlp/extractor/projectveritas.py b/yt_dlp/extractor/projectveritas.py
index 9e9867ba5d..e4aa4bd35c 100644
--- a/yt_dlp/extractor/projectveritas.py
+++ b/yt_dlp/extractor/projectveritas.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/prosiebensat1.py b/yt_dlp/extractor/prosiebensat1.py
index e89bbfd279..cb5ada1b9a 100644
--- a/yt_dlp/extractor/prosiebensat1.py
+++ b/yt_dlp/extractor/prosiebensat1.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from hashlib import sha1
diff --git a/yt_dlp/extractor/prx.py b/yt_dlp/extractor/prx.py
index 80561b80a2..5bb1832702 100644
--- a/yt_dlp/extractor/prx.py
+++ b/yt_dlp/extractor/prx.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 from .common import InfoExtractor, SearchInfoExtractor
 from ..utils import (
diff --git a/yt_dlp/extractor/puhutv.py b/yt_dlp/extractor/puhutv.py
index ca71665e0f..a5dac1dff5 100644
--- a/yt_dlp/extractor/puhutv.py
+++ b/yt_dlp/extractor/puhutv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_HTTPError,
diff --git a/yt_dlp/extractor/puls4.py b/yt_dlp/extractor/puls4.py
index 80091b85f8..3c13d1f564 100644
--- a/yt_dlp/extractor/puls4.py
+++ b/yt_dlp/extractor/puls4.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .prosiebensat1 import ProSiebenSat1BaseIE
 from ..utils import (
     unified_strdate,
diff --git a/yt_dlp/extractor/pyvideo.py b/yt_dlp/extractor/pyvideo.py
index 869619723d..7b25166b22 100644
--- a/yt_dlp/extractor/pyvideo.py
+++ b/yt_dlp/extractor/pyvideo.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/qqmusic.py b/yt_dlp/extractor/qqmusic.py
index 0106d166ff..fa2454df45 100644
--- a/yt_dlp/extractor/qqmusic.py
+++ b/yt_dlp/extractor/qqmusic.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 import re
 import time
diff --git a/yt_dlp/extractor/r7.py b/yt_dlp/extractor/r7.py
index e2202d6036..b459efceb5 100644
--- a/yt_dlp/extractor/r7.py
+++ b/yt_dlp/extractor/r7.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/radiko.py b/yt_dlp/extractor/radiko.py
index 1e60de1539..a0f5ebdd08 100644
--- a/yt_dlp/extractor/radiko.py
+++ b/yt_dlp/extractor/radiko.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import base64
 import calendar
diff --git a/yt_dlp/extractor/radiobremen.py b/yt_dlp/extractor/radiobremen.py
index 2c35f98451..99ba050d0f 100644
--- a/yt_dlp/extractor/radiobremen.py
+++ b/yt_dlp/extractor/radiobremen.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/radiocanada.py b/yt_dlp/extractor/radiocanada.py
index 4b4445c307..dd6f899a48 100644
--- a/yt_dlp/extractor/radiocanada.py
+++ b/yt_dlp/extractor/radiocanada.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_HTTPError
 from ..utils import (
diff --git a/yt_dlp/extractor/radiode.py b/yt_dlp/extractor/radiode.py
index 0382873637..befb0b72b4 100644
--- a/yt_dlp/extractor/radiode.py
+++ b/yt_dlp/extractor/radiode.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/radiofrance.py b/yt_dlp/extractor/radiofrance.py
index 082238bbc8..8fef54dabf 100644
--- a/yt_dlp/extractor/radiofrance.py
+++ b/yt_dlp/extractor/radiofrance.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/radiojavan.py b/yt_dlp/extractor/radiojavan.py
index 3f74f0c01f..6a61188991 100644
--- a/yt_dlp/extractor/radiojavan.py
+++ b/yt_dlp/extractor/radiojavan.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/radiokapital.py b/yt_dlp/extractor/radiokapital.py
index 2e93e034f7..8f9737ac31 100644
--- a/yt_dlp/extractor/radiokapital.py
+++ b/yt_dlp/extractor/radiokapital.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/radiozet.py b/yt_dlp/extractor/radiozet.py
index 2e1ff36c2f..67520172e8 100644
--- a/yt_dlp/extractor/radiozet.py
+++ b/yt_dlp/extractor/radiozet.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from ..utils import (
     traverse_obj,
diff --git a/yt_dlp/extractor/rai.py b/yt_dlp/extractor/rai.py
index 7c72d60c62..31199e32e4 100644
--- a/yt_dlp/extractor/rai.py
+++ b/yt_dlp/extractor/rai.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/raywenderlich.py b/yt_dlp/extractor/raywenderlich.py
index f04d51f7b9..e0e3c3eadf 100644
--- a/yt_dlp/extractor/raywenderlich.py
+++ b/yt_dlp/extractor/raywenderlich.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/rbmaradio.py b/yt_dlp/extractor/rbmaradio.py
index 9642fbbe1e..86c63dbb7f 100644
--- a/yt_dlp/extractor/rbmaradio.py
+++ b/yt_dlp/extractor/rbmaradio.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/rcs.py b/yt_dlp/extractor/rcs.py
index ace611bc92..abbc167c0f 100644
--- a/yt_dlp/extractor/rcs.py
+++ b/yt_dlp/extractor/rcs.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/rcti.py b/yt_dlp/extractor/rcti.py
index ac42e58d9c..0cfecbc9a8 100644
--- a/yt_dlp/extractor/rcti.py
+++ b/yt_dlp/extractor/rcti.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import random
 import time
diff --git a/yt_dlp/extractor/rds.py b/yt_dlp/extractor/rds.py
index 0c497856ef..9a2e0d9851 100644
--- a/yt_dlp/extractor/rds.py
+++ b/yt_dlp/extractor/rds.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/redbulltv.py b/yt_dlp/extractor/redbulltv.py
index 756a3666b7..2f0e41c5b8 100644
--- a/yt_dlp/extractor/redbulltv.py
+++ b/yt_dlp/extractor/redbulltv.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_HTTPError
 from ..utils import (
diff --git a/yt_dlp/extractor/redgifs.py b/yt_dlp/extractor/redgifs.py
index 55196b768f..e3712a1d6b 100644
--- a/yt_dlp/extractor/redgifs.py
+++ b/yt_dlp/extractor/redgifs.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 import functools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/redtube.py b/yt_dlp/extractor/redtube.py
index 7fee54fee4..ab7c505dab 100644
--- a/yt_dlp/extractor/redtube.py
+++ b/yt_dlp/extractor/redtube.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/regiotv.py b/yt_dlp/extractor/regiotv.py
index e250a52f06..6114841fb2 100644
--- a/yt_dlp/extractor/regiotv.py
+++ b/yt_dlp/extractor/regiotv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..utils import (
diff --git a/yt_dlp/extractor/rentv.py b/yt_dlp/extractor/rentv.py
index 7c8909d953..ab47ee5525 100644
--- a/yt_dlp/extractor/rentv.py
+++ b/yt_dlp/extractor/rentv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/restudy.py b/yt_dlp/extractor/restudy.py
index d47fb45ca5..cd3c20d7ae 100644
--- a/yt_dlp/extractor/restudy.py
+++ b/yt_dlp/extractor/restudy.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/reuters.py b/yt_dlp/extractor/reuters.py
index 9dc482d216..1428b7cc95 100644
--- a/yt_dlp/extractor/reuters.py
+++ b/yt_dlp/extractor/reuters.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/reverbnation.py b/yt_dlp/extractor/reverbnation.py
index 4cb99c244c..06b6c3c2f6 100644
--- a/yt_dlp/extractor/reverbnation.py
+++ b/yt_dlp/extractor/reverbnation.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     qualities,
diff --git a/yt_dlp/extractor/rice.py b/yt_dlp/extractor/rice.py
index cf2bb1b51f..9ca47f3d43 100644
--- a/yt_dlp/extractor/rice.py
+++ b/yt_dlp/extractor/rice.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/rmcdecouverte.py b/yt_dlp/extractor/rmcdecouverte.py
index 8bfce34169..8d29b302bb 100644
--- a/yt_dlp/extractor/rmcdecouverte.py
+++ b/yt_dlp/extractor/rmcdecouverte.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from .brightcove import BrightcoveLegacyIE
 from ..compat import (
diff --git a/yt_dlp/extractor/rockstargames.py b/yt_dlp/extractor/rockstargames.py
index cd6904bc93..5f1db0f057 100644
--- a/yt_dlp/extractor/rockstargames.py
+++ b/yt_dlp/extractor/rockstargames.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/rokfin.py b/yt_dlp/extractor/rokfin.py
index 0fd65db4b2..d7e8ba6207 100644
--- a/yt_dlp/extractor/rokfin.py
+++ b/yt_dlp/extractor/rokfin.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 import itertools
 from datetime import datetime
 
diff --git a/yt_dlp/extractor/roosterteeth.py b/yt_dlp/extractor/roosterteeth.py
index a55dd4f8b9..011dadfaa2 100644
--- a/yt_dlp/extractor/roosterteeth.py
+++ b/yt_dlp/extractor/roosterteeth.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from ..compat import compat_HTTPError
 from ..utils import (
diff --git a/yt_dlp/extractor/rottentomatoes.py b/yt_dlp/extractor/rottentomatoes.py
index 14c8e82369..f133c851be 100644
--- a/yt_dlp/extractor/rottentomatoes.py
+++ b/yt_dlp/extractor/rottentomatoes.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .internetvideoarchive import InternetVideoArchiveIE
 
diff --git a/yt_dlp/extractor/rozhlas.py b/yt_dlp/extractor/rozhlas.py
index fccf69401d..a8189676f8 100644
--- a/yt_dlp/extractor/rozhlas.py
+++ b/yt_dlp/extractor/rozhlas.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/rtbf.py b/yt_dlp/extractor/rtbf.py
index 4b61fdb17e..a300a24824 100644
--- a/yt_dlp/extractor/rtbf.py
+++ b/yt_dlp/extractor/rtbf.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/rte.py b/yt_dlp/extractor/rte.py
index 1fbc72915e..93faf1b324 100644
--- a/yt_dlp/extractor/rte.py
+++ b/yt_dlp/extractor/rte.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/rtl2.py b/yt_dlp/extractor/rtl2.py
index e291714745..afa0d33cf5 100644
--- a/yt_dlp/extractor/rtl2.py
+++ b/yt_dlp/extractor/rtl2.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/rtlnl.py b/yt_dlp/extractor/rtlnl.py
index 9eaa06f25d..ed89554ab0 100644
--- a/yt_dlp/extractor/rtlnl.py
+++ b/yt_dlp/extractor/rtlnl.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/rtnews.py b/yt_dlp/extractor/rtnews.py
index 68b6044b68..6be9945f70 100644
--- a/yt_dlp/extractor/rtnews.py
+++ b/yt_dlp/extractor/rtnews.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/rtp.py b/yt_dlp/extractor/rtp.py
index c165ade788..5928a207ae 100644
--- a/yt_dlp/extractor/rtp.py
+++ b/yt_dlp/extractor/rtp.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import js_to_json
 import re
diff --git a/yt_dlp/extractor/rtrfm.py b/yt_dlp/extractor/rtrfm.py
index 93d51e8ed7..7381d82026 100644
--- a/yt_dlp/extractor/rtrfm.py
+++ b/yt_dlp/extractor/rtrfm.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/rts.py b/yt_dlp/extractor/rts.py
index 865a730243..e5ba1a26bd 100644
--- a/yt_dlp/extractor/rts.py
+++ b/yt_dlp/extractor/rts.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .srgssr import SRGSSRIE
diff --git a/yt_dlp/extractor/rtve.py b/yt_dlp/extractor/rtve.py
index 7a1dc6f326..e5837e8c87 100644
--- a/yt_dlp/extractor/rtve.py
+++ b/yt_dlp/extractor/rtve.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import io
 import sys
diff --git a/yt_dlp/extractor/rtvnh.py b/yt_dlp/extractor/rtvnh.py
index 6a00f70072..58af3dda2c 100644
--- a/yt_dlp/extractor/rtvnh.py
+++ b/yt_dlp/extractor/rtvnh.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import ExtractorError
 
diff --git a/yt_dlp/extractor/rtvs.py b/yt_dlp/extractor/rtvs.py
index 3ea0f1883c..fb06efa4b9 100644
--- a/yt_dlp/extractor/rtvs.py
+++ b/yt_dlp/extractor/rtvs.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ruhd.py b/yt_dlp/extractor/ruhd.py
index 3c8053a261..abaa3f9ea9 100644
--- a/yt_dlp/extractor/ruhd.py
+++ b/yt_dlp/extractor/ruhd.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/rule34video.py b/yt_dlp/extractor/rule34video.py
index a602a9f335..bb113d822d 100644
--- a/yt_dlp/extractor/rule34video.py
+++ b/yt_dlp/extractor/rule34video.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
 import re
 
 from ..utils import parse_duration
diff --git a/yt_dlp/extractor/rumble.py b/yt_dlp/extractor/rumble.py
index a0d5f88d97..50c383d793 100644
--- a/yt_dlp/extractor/rumble.py
+++ b/yt_dlp/extractor/rumble.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import re
 
diff --git a/yt_dlp/extractor/rutube.py b/yt_dlp/extractor/rutube.py
index 2f753b41f2..ecfcea9393 100644
--- a/yt_dlp/extractor/rutube.py
+++ b/yt_dlp/extractor/rutube.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import itertools
 
diff --git a/yt_dlp/extractor/rutv.py b/yt_dlp/extractor/rutv.py
index 0ea8253fa9..adf78ddb09 100644
--- a/yt_dlp/extractor/rutv.py
+++ b/yt_dlp/extractor/rutv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ruutu.py b/yt_dlp/extractor/ruutu.py
index 5a30e33606..f5dadf2786 100644
--- a/yt_dlp/extractor/ruutu.py
+++ b/yt_dlp/extractor/ruutu.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/ruv.py b/yt_dlp/extractor/ruv.py
index d806ed068d..12499d6ca8 100644
--- a/yt_dlp/extractor/ruv.py
+++ b/yt_dlp/extractor/ruv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/safari.py b/yt_dlp/extractor/safari.py
index 7b4571daa7..450a661e9f 100644
--- a/yt_dlp/extractor/safari.py
+++ b/yt_dlp/extractor/safari.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/saitosan.py b/yt_dlp/extractor/saitosan.py
index 621335ca06..d2f60e92ff 100644
--- a/yt_dlp/extractor/saitosan.py
+++ b/yt_dlp/extractor/saitosan.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import ExtractorError, try_get
 
diff --git a/yt_dlp/extractor/samplefocus.py b/yt_dlp/extractor/samplefocus.py
index 806c3c3542..e9f5c227b7 100644
--- a/yt_dlp/extractor/samplefocus.py
+++ b/yt_dlp/extractor/samplefocus.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/sapo.py b/yt_dlp/extractor/sapo.py
index df202a3a40..9a601a01c3 100644
--- a/yt_dlp/extractor/sapo.py
+++ b/yt_dlp/extractor/sapo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/savefrom.py b/yt_dlp/extractor/savefrom.py
index 98efdc2a4f..9c9e74b6dd 100644
--- a/yt_dlp/extractor/savefrom.py
+++ b/yt_dlp/extractor/savefrom.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import os.path
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/sbs.py b/yt_dlp/extractor/sbs.py
index 4090f6385d..711524406b 100644
--- a/yt_dlp/extractor/sbs.py
+++ b/yt_dlp/extractor/sbs.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     smuggle_url,
diff --git a/yt_dlp/extractor/screencast.py b/yt_dlp/extractor/screencast.py
index 69a0d01f39..e3dbaab690 100644
--- a/yt_dlp/extractor/screencast.py
+++ b/yt_dlp/extractor/screencast.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_parse_qs,
diff --git a/yt_dlp/extractor/screencastomatic.py b/yt_dlp/extractor/screencastomatic.py
index 0afdc17158..f2f281f479 100644
--- a/yt_dlp/extractor/screencastomatic.py
+++ b/yt_dlp/extractor/screencastomatic.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     get_element_by_class,
diff --git a/yt_dlp/extractor/scrippsnetworks.py b/yt_dlp/extractor/scrippsnetworks.py
index 84918b67f4..c3cee6e4aa 100644
--- a/yt_dlp/extractor/scrippsnetworks.py
+++ b/yt_dlp/extractor/scrippsnetworks.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import hashlib
 
diff --git a/yt_dlp/extractor/scte.py b/yt_dlp/extractor/scte.py
index 7215cf5d1c..d839ffcde8 100644
--- a/yt_dlp/extractor/scte.py
+++ b/yt_dlp/extractor/scte.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/seeker.py b/yt_dlp/extractor/seeker.py
index e5c18c7a55..65eb16a09d 100644
--- a/yt_dlp/extractor/seeker.py
+++ b/yt_dlp/extractor/seeker.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/senategov.py b/yt_dlp/extractor/senategov.py
index b295184a19..bced143288 100644
--- a/yt_dlp/extractor/senategov.py
+++ b/yt_dlp/extractor/senategov.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/sendtonews.py b/yt_dlp/extractor/sendtonews.py
index 858547b54f..cf4b93d454 100644
--- a/yt_dlp/extractor/sendtonews.py
+++ b/yt_dlp/extractor/sendtonews.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/servus.py b/yt_dlp/extractor/servus.py
index 1610ddc2cd..ac030ea41b 100644
--- a/yt_dlp/extractor/servus.py
+++ b/yt_dlp/extractor/servus.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/sevenplus.py b/yt_dlp/extractor/sevenplus.py
index 9867961f07..8e95bc230d 100644
--- a/yt_dlp/extractor/sevenplus.py
+++ b/yt_dlp/extractor/sevenplus.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/sexu.py b/yt_dlp/extractor/sexu.py
index 3df51520b0..000f7e166a 100644
--- a/yt_dlp/extractor/sexu.py
+++ b/yt_dlp/extractor/sexu.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/seznamzpravy.py b/yt_dlp/extractor/seznamzpravy.py
index eef4975cba..891bfcfee6 100644
--- a/yt_dlp/extractor/seznamzpravy.py
+++ b/yt_dlp/extractor/seznamzpravy.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/shahid.py b/yt_dlp/extractor/shahid.py
index ab45d9ce4f..53ca86b73e 100644
--- a/yt_dlp/extractor/shahid.py
+++ b/yt_dlp/extractor/shahid.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import math
 import re
diff --git a/yt_dlp/extractor/shared.py b/yt_dlp/extractor/shared.py
index 93ab2a1676..5bc097b0d8 100644
--- a/yt_dlp/extractor/shared.py
+++ b/yt_dlp/extractor/shared.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_b64decode,
diff --git a/yt_dlp/extractor/shemaroome.py b/yt_dlp/extractor/shemaroome.py
index 45c12915a3..c0780abe2e 100644
--- a/yt_dlp/extractor/shemaroome.py
+++ b/yt_dlp/extractor/shemaroome.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..aes import aes_cbc_decrypt, unpad_pkcs7
 from ..compat import (
diff --git a/yt_dlp/extractor/showroomlive.py b/yt_dlp/extractor/showroomlive.py
index 1aada69ac3..cd681a0351 100644
--- a/yt_dlp/extractor/showroomlive.py
+++ b/yt_dlp/extractor/showroomlive.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/simplecast.py b/yt_dlp/extractor/simplecast.py
index 857e9414fa..ecbb6123b8 100644
--- a/yt_dlp/extractor/simplecast.py
+++ b/yt_dlp/extractor/simplecast.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/sina.py b/yt_dlp/extractor/sina.py
index b62b0c3e5b..d30d57d858 100644
--- a/yt_dlp/extractor/sina.py
+++ b/yt_dlp/extractor/sina.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     HEADRequest,
diff --git a/yt_dlp/extractor/sixplay.py b/yt_dlp/extractor/sixplay.py
index fd747f59b5..b7b7d7d7fd 100644
--- a/yt_dlp/extractor/sixplay.py
+++ b/yt_dlp/extractor/sixplay.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/skeb.py b/yt_dlp/extractor/skeb.py
index 81aecb3112..e02f8cef0e 100644
--- a/yt_dlp/extractor/skeb.py
+++ b/yt_dlp/extractor/skeb.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import ExtractorError, determine_ext, parse_qs, traverse_obj
 
diff --git a/yt_dlp/extractor/sky.py b/yt_dlp/extractor/sky.py
index ad1e62d88f..0a8b6cc769 100644
--- a/yt_dlp/extractor/sky.py
+++ b/yt_dlp/extractor/sky.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/skyit.py b/yt_dlp/extractor/skyit.py
index ddb43c075e..438fb60e3e 100644
--- a/yt_dlp/extractor/skyit.py
+++ b/yt_dlp/extractor/skyit.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_parse_qs,
diff --git a/yt_dlp/extractor/skylinewebcams.py b/yt_dlp/extractor/skylinewebcams.py
index 47bbb7632e..4292bb2ae5 100644
--- a/yt_dlp/extractor/skylinewebcams.py
+++ b/yt_dlp/extractor/skylinewebcams.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/skynewsarabia.py b/yt_dlp/extractor/skynewsarabia.py
index fffc9aa227..6264b04bb3 100644
--- a/yt_dlp/extractor/skynewsarabia.py
+++ b/yt_dlp/extractor/skynewsarabia.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/skynewsau.py b/yt_dlp/extractor/skynewsau.py
index 8e079ee312..43a9c82cf1 100644
--- a/yt_dlp/extractor/skynewsau.py
+++ b/yt_dlp/extractor/skynewsau.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     try_get,
diff --git a/yt_dlp/extractor/slideshare.py b/yt_dlp/extractor/slideshare.py
index 9b3ad0ad49..ab9dad0ec6 100644
--- a/yt_dlp/extractor/slideshare.py
+++ b/yt_dlp/extractor/slideshare.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/slideslive.py b/yt_dlp/extractor/slideslive.py
index df60846473..72ca560579 100644
--- a/yt_dlp/extractor/slideslive.py
+++ b/yt_dlp/extractor/slideslive.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     bool_or_none,
diff --git a/yt_dlp/extractor/slutload.py b/yt_dlp/extractor/slutload.py
index 661f9e59d0..8e6e89c9aa 100644
--- a/yt_dlp/extractor/slutload.py
+++ b/yt_dlp/extractor/slutload.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/snotr.py b/yt_dlp/extractor/snotr.py
index 0bb5482554..6889f1929d 100644
--- a/yt_dlp/extractor/snotr.py
+++ b/yt_dlp/extractor/snotr.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/sohu.py b/yt_dlp/extractor/sohu.py
index 3bff5c595e..c3a1359558 100644
--- a/yt_dlp/extractor/sohu.py
+++ b/yt_dlp/extractor/sohu.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/sonyliv.py b/yt_dlp/extractor/sonyliv.py
index 5b6849fc90..771f890cc9 100644
--- a/yt_dlp/extractor/sonyliv.py
+++ b/yt_dlp/extractor/sonyliv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import datetime
 import math
 import random
diff --git a/yt_dlp/extractor/soundcloud.py b/yt_dlp/extractor/soundcloud.py
index 749e6dda39..6dfa50c602 100644
--- a/yt_dlp/extractor/soundcloud.py
+++ b/yt_dlp/extractor/soundcloud.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import re
 import json
diff --git a/yt_dlp/extractor/soundgasm.py b/yt_dlp/extractor/soundgasm.py
index d608eb7a76..9e59c7c0e5 100644
--- a/yt_dlp/extractor/soundgasm.py
+++ b/yt_dlp/extractor/soundgasm.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/southpark.py b/yt_dlp/extractor/southpark.py
index 942a52dcf5..855f1d6d3a 100644
--- a/yt_dlp/extractor/southpark.py
+++ b/yt_dlp/extractor/southpark.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .mtv import MTVServicesInfoExtractor
 
 
diff --git a/yt_dlp/extractor/sovietscloset.py b/yt_dlp/extractor/sovietscloset.py
index 4bc2263f0c..fc5a492a63 100644
--- a/yt_dlp/extractor/sovietscloset.py
+++ b/yt_dlp/extractor/sovietscloset.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     try_get,
diff --git a/yt_dlp/extractor/spankbang.py b/yt_dlp/extractor/spankbang.py
index dd849ae13e..1aa8eaba1d 100644
--- a/yt_dlp/extractor/spankbang.py
+++ b/yt_dlp/extractor/spankbang.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/spankwire.py b/yt_dlp/extractor/spankwire.py
index e97c1d23e1..603f17e9da 100644
--- a/yt_dlp/extractor/spankwire.py
+++ b/yt_dlp/extractor/spankwire.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/spiegel.py b/yt_dlp/extractor/spiegel.py
index 58f2ed3533..3701e295a9 100644
--- a/yt_dlp/extractor/spiegel.py
+++ b/yt_dlp/extractor/spiegel.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .jwplatform import JWPlatformIE
 
diff --git a/yt_dlp/extractor/spiegeltv.py b/yt_dlp/extractor/spiegeltv.py
index 6ccf4c3423..69942334e4 100644
--- a/yt_dlp/extractor/spiegeltv.py
+++ b/yt_dlp/extractor/spiegeltv.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .nexx import NexxIE
 
diff --git a/yt_dlp/extractor/spike.py b/yt_dlp/extractor/spike.py
index 5805f3d445..5c1c78d8fc 100644
--- a/yt_dlp/extractor/spike.py
+++ b/yt_dlp/extractor/spike.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .mtv import MTVServicesInfoExtractor
 
 
diff --git a/yt_dlp/extractor/sport5.py b/yt_dlp/extractor/sport5.py
index 35c57d62a7..f4ac98b6e0 100644
--- a/yt_dlp/extractor/sport5.py
+++ b/yt_dlp/extractor/sport5.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import ExtractorError
 
diff --git a/yt_dlp/extractor/sportbox.py b/yt_dlp/extractor/sportbox.py
index b9017fd2ab..1041cc7d18 100644
--- a/yt_dlp/extractor/sportbox.py
+++ b/yt_dlp/extractor/sportbox.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/sportdeutschland.py b/yt_dlp/extractor/sportdeutschland.py
index 15b488ab7f..75074b3100 100644
--- a/yt_dlp/extractor/sportdeutschland.py
+++ b/yt_dlp/extractor/sportdeutschland.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/spotify.py b/yt_dlp/extractor/spotify.py
index 826f98cffc..3b8dea8f49 100644
--- a/yt_dlp/extractor/spotify.py
+++ b/yt_dlp/extractor/spotify.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/spreaker.py b/yt_dlp/extractor/spreaker.py
index 6c7e40ae4d..36a9bd2915 100644
--- a/yt_dlp/extractor/spreaker.py
+++ b/yt_dlp/extractor/spreaker.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/springboardplatform.py b/yt_dlp/extractor/springboardplatform.py
index 49ac1f559c..8e156bf1a1 100644
--- a/yt_dlp/extractor/springboardplatform.py
+++ b/yt_dlp/extractor/springboardplatform.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/sprout.py b/yt_dlp/extractor/sprout.py
index e243732f24..444a6c270f 100644
--- a/yt_dlp/extractor/sprout.py
+++ b/yt_dlp/extractor/sprout.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .adobepass import AdobePassIE
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/srgssr.py b/yt_dlp/extractor/srgssr.py
index f9919816d4..6dd3129851 100644
--- a/yt_dlp/extractor/srgssr.py
+++ b/yt_dlp/extractor/srgssr.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/srmediathek.py b/yt_dlp/extractor/srmediathek.py
index 359dadaa3c..3cc39870f9 100644
--- a/yt_dlp/extractor/srmediathek.py
+++ b/yt_dlp/extractor/srmediathek.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .ard import ARDMediathekBaseIE
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/stanfordoc.py b/yt_dlp/extractor/stanfordoc.py
index 0003075aca..be0f4afc12 100644
--- a/yt_dlp/extractor/stanfordoc.py
+++ b/yt_dlp/extractor/stanfordoc.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/startv.py b/yt_dlp/extractor/startv.py
index 411320ede8..bb6e8f1ea5 100644
--- a/yt_dlp/extractor/startv.py
+++ b/yt_dlp/extractor/startv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/steam.py b/yt_dlp/extractor/steam.py
index 4ed0fb592a..ab22fdbc67 100644
--- a/yt_dlp/extractor/steam.py
+++ b/yt_dlp/extractor/steam.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/stitcher.py b/yt_dlp/extractor/stitcher.py
index 8227825070..2fd200f87a 100644
--- a/yt_dlp/extractor/stitcher.py
+++ b/yt_dlp/extractor/stitcher.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/storyfire.py b/yt_dlp/extractor/storyfire.py
index e18a59a49c..7161902201 100644
--- a/yt_dlp/extractor/storyfire.py
+++ b/yt_dlp/extractor/storyfire.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/streamable.py b/yt_dlp/extractor/streamable.py
index 808129649c..a2935b04bb 100644
--- a/yt_dlp/extractor/streamable.py
+++ b/yt_dlp/extractor/streamable.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/streamanity.py b/yt_dlp/extractor/streamanity.py
index 2e2d5eedf9..f8c37c0dd5 100644
--- a/yt_dlp/extractor/streamanity.py
+++ b/yt_dlp/extractor/streamanity.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/streamcloud.py b/yt_dlp/extractor/streamcloud.py
index b97bb43741..7289809210 100644
--- a/yt_dlp/extractor/streamcloud.py
+++ b/yt_dlp/extractor/streamcloud.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/streamcz.py b/yt_dlp/extractor/streamcz.py
index 4cb9923e2c..85fc3a3c32 100644
--- a/yt_dlp/extractor/streamcz.py
+++ b/yt_dlp/extractor/streamcz.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/streamff.py b/yt_dlp/extractor/streamff.py
index 6b190bb3b8..93c42942c3 100644
--- a/yt_dlp/extractor/streamff.py
+++ b/yt_dlp/extractor/streamff.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 from ..utils import int_or_none, parse_iso8601
 
diff --git a/yt_dlp/extractor/streetvoice.py b/yt_dlp/extractor/streetvoice.py
index f21681ae78..a32c8bc378 100644
--- a/yt_dlp/extractor/streetvoice.py
+++ b/yt_dlp/extractor/streetvoice.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/stretchinternet.py b/yt_dlp/extractor/stretchinternet.py
index ec08eae551..e438dee111 100644
--- a/yt_dlp/extractor/stretchinternet.py
+++ b/yt_dlp/extractor/stretchinternet.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/stripchat.py b/yt_dlp/extractor/stripchat.py
index 0d4a0ce4c0..a7c7b06496 100644
--- a/yt_dlp/extractor/stripchat.py
+++ b/yt_dlp/extractor/stripchat.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/stv.py b/yt_dlp/extractor/stv.py
index ba5661d747..618dc4329a 100644
--- a/yt_dlp/extractor/stv.py
+++ b/yt_dlp/extractor/stv.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     compat_str,
diff --git a/yt_dlp/extractor/sunporno.py b/yt_dlp/extractor/sunporno.py
index 59b77bf92f..19498701c6 100644
--- a/yt_dlp/extractor/sunporno.py
+++ b/yt_dlp/extractor/sunporno.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/sverigesradio.py b/yt_dlp/extractor/sverigesradio.py
index aa0691f0df..4a4b5cf7ef 100644
--- a/yt_dlp/extractor/sverigesradio.py
+++ b/yt_dlp/extractor/sverigesradio.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/svt.py b/yt_dlp/extractor/svt.py
index 8ca62e370c..e0c436b67a 100644
--- a/yt_dlp/extractor/svt.py
+++ b/yt_dlp/extractor/svt.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/swrmediathek.py b/yt_dlp/extractor/swrmediathek.py
index 0f615979e1..deebdd1a4a 100644
--- a/yt_dlp/extractor/swrmediathek.py
+++ b/yt_dlp/extractor/swrmediathek.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/syfy.py b/yt_dlp/extractor/syfy.py
index def7e5a2c7..c79d27a0de 100644
--- a/yt_dlp/extractor/syfy.py
+++ b/yt_dlp/extractor/syfy.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .adobepass import AdobePassIE
 from ..utils import (
     update_url_query,
diff --git a/yt_dlp/extractor/sztvhu.py b/yt_dlp/extractor/sztvhu.py
index cfad331464..1cbc2a3cf5 100644
--- a/yt_dlp/extractor/sztvhu.py
+++ b/yt_dlp/extractor/sztvhu.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/tagesschau.py b/yt_dlp/extractor/tagesschau.py
index 6e03d0a7d1..9b9513f075 100644
--- a/yt_dlp/extractor/tagesschau.py
+++ b/yt_dlp/extractor/tagesschau.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tass.py b/yt_dlp/extractor/tass.py
index 6d336da788..d20dacfc1f 100644
--- a/yt_dlp/extractor/tass.py
+++ b/yt_dlp/extractor/tass.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tastytrade.py b/yt_dlp/extractor/tastytrade.py
index 7fe96bd5fc..bb26926e88 100644
--- a/yt_dlp/extractor/tastytrade.py
+++ b/yt_dlp/extractor/tastytrade.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .ooyala import OoyalaIE
 
diff --git a/yt_dlp/extractor/tbs.py b/yt_dlp/extractor/tbs.py
index c7d62ff4e4..808c6c73d3 100644
--- a/yt_dlp/extractor/tbs.py
+++ b/yt_dlp/extractor/tbs.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .turner import TurnerBaseIE
diff --git a/yt_dlp/extractor/tdslifeway.py b/yt_dlp/extractor/tdslifeway.py
index 101c6ee31a..3623a68c8c 100644
--- a/yt_dlp/extractor/tdslifeway.py
+++ b/yt_dlp/extractor/tdslifeway.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/teachable.py b/yt_dlp/extractor/teachable.py
index 232eaa5216..e480d76101 100644
--- a/yt_dlp/extractor/teachable.py
+++ b/yt_dlp/extractor/teachable.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/teachertube.py b/yt_dlp/extractor/teachertube.py
index e22f0114cf..2bf836abd7 100644
--- a/yt_dlp/extractor/teachertube.py
+++ b/yt_dlp/extractor/teachertube.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/teachingchannel.py b/yt_dlp/extractor/teachingchannel.py
index 624cdb3adc..275f6d1f92 100644
--- a/yt_dlp/extractor/teachingchannel.py
+++ b/yt_dlp/extractor/teachingchannel.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/teamcoco.py b/yt_dlp/extractor/teamcoco.py
index 5793b711f6..840702ed9e 100644
--- a/yt_dlp/extractor/teamcoco.py
+++ b/yt_dlp/extractor/teamcoco.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .turner import TurnerBaseIE
diff --git a/yt_dlp/extractor/teamtreehouse.py b/yt_dlp/extractor/teamtreehouse.py
index 64522ec4cc..dd802db5b7 100644
--- a/yt_dlp/extractor/teamtreehouse.py
+++ b/yt_dlp/extractor/teamtreehouse.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/techtalks.py b/yt_dlp/extractor/techtalks.py
index 78f07319b6..d37de360b8 100644
--- a/yt_dlp/extractor/techtalks.py
+++ b/yt_dlp/extractor/techtalks.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tele13.py b/yt_dlp/extractor/tele13.py
index f8a27550e3..8e35bc85fe 100644
--- a/yt_dlp/extractor/tele13.py
+++ b/yt_dlp/extractor/tele13.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .youtube import YoutubeIE
 from ..utils import (
diff --git a/yt_dlp/extractor/tele5.py b/yt_dlp/extractor/tele5.py
index c7beee1535..58d343b449 100644
--- a/yt_dlp/extractor/tele5.py
+++ b/yt_dlp/extractor/tele5.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .dplay import DPlayIE
 from ..compat import compat_urlparse
 from ..utils import (
diff --git a/yt_dlp/extractor/telebruxelles.py b/yt_dlp/extractor/telebruxelles.py
index 9e8c89bd63..8d87b6ec1f 100644
--- a/yt_dlp/extractor/telebruxelles.py
+++ b/yt_dlp/extractor/telebruxelles.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/telecinco.py b/yt_dlp/extractor/telecinco.py
index eecd6a5c9b..a9c0755f48 100644
--- a/yt_dlp/extractor/telecinco.py
+++ b/yt_dlp/extractor/telecinco.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/telegraaf.py b/yt_dlp/extractor/telegraaf.py
index 2dc0205373..bc9a8d6084 100644
--- a/yt_dlp/extractor/telegraaf.py
+++ b/yt_dlp/extractor/telegraaf.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/telemb.py b/yt_dlp/extractor/telemb.py
index ac2d603b6b..7e444c0d09 100644
--- a/yt_dlp/extractor/telemb.py
+++ b/yt_dlp/extractor/telemb.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/telemundo.py b/yt_dlp/extractor/telemundo.py
index ebcecf55f8..64954b8f1b 100644
--- a/yt_dlp/extractor/telemundo.py
+++ b/yt_dlp/extractor/telemundo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     try_get,
diff --git a/yt_dlp/extractor/telequebec.py b/yt_dlp/extractor/telequebec.py
index 4bef2fe764..e89137269a 100644
--- a/yt_dlp/extractor/telequebec.py
+++ b/yt_dlp/extractor/telequebec.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/teletask.py b/yt_dlp/extractor/teletask.py
index b9e2ef8cab..a73dd68fba 100644
--- a/yt_dlp/extractor/teletask.py
+++ b/yt_dlp/extractor/teletask.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/telewebion.py b/yt_dlp/extractor/telewebion.py
index 1207b1a1b8..550549f056 100644
--- a/yt_dlp/extractor/telewebion.py
+++ b/yt_dlp/extractor/telewebion.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/tennistv.py b/yt_dlp/extractor/tennistv.py
index 58fdecebee..80acaf1906 100644
--- a/yt_dlp/extractor/tennistv.py
+++ b/yt_dlp/extractor/tennistv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tenplay.py b/yt_dlp/extractor/tenplay.py
index 5c7b54531c..fc47814473 100644
--- a/yt_dlp/extractor/tenplay.py
+++ b/yt_dlp/extractor/tenplay.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from datetime import datetime
 import base64
 
diff --git a/yt_dlp/extractor/testurl.py b/yt_dlp/extractor/testurl.py
index 8bc512a9c1..140fa4a963 100644
--- a/yt_dlp/extractor/testurl.py
+++ b/yt_dlp/extractor/testurl.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tf1.py b/yt_dlp/extractor/tf1.py
index 44785bc657..4cf0322b35 100644
--- a/yt_dlp/extractor/tf1.py
+++ b/yt_dlp/extractor/tf1.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tfo.py b/yt_dlp/extractor/tfo.py
index 0631cb7aba..a24789cb37 100644
--- a/yt_dlp/extractor/tfo.py
+++ b/yt_dlp/extractor/tfo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/theintercept.py b/yt_dlp/extractor/theintercept.py
index f23b587137..a991a4dfd0 100644
--- a/yt_dlp/extractor/theintercept.py
+++ b/yt_dlp/extractor/theintercept.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/theplatform.py b/yt_dlp/extractor/theplatform.py
index c2729f12d7..bf7efc0134 100644
--- a/yt_dlp/extractor/theplatform.py
+++ b/yt_dlp/extractor/theplatform.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import time
 import hmac
diff --git a/yt_dlp/extractor/thestar.py b/yt_dlp/extractor/thestar.py
index c3f1188947..293c34c06e 100644
--- a/yt_dlp/extractor/thestar.py
+++ b/yt_dlp/extractor/thestar.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/thesun.py b/yt_dlp/extractor/thesun.py
index 15d4a69327..ba58482836 100644
--- a/yt_dlp/extractor/thesun.py
+++ b/yt_dlp/extractor/thesun.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/theta.py b/yt_dlp/extractor/theta.py
index 8b6d70a9f6..3ec6b97118 100644
--- a/yt_dlp/extractor/theta.py
+++ b/yt_dlp/extractor/theta.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import try_get
 
diff --git a/yt_dlp/extractor/theweatherchannel.py b/yt_dlp/extractor/theweatherchannel.py
index 9e506c9e02..9e94cd1ea1 100644
--- a/yt_dlp/extractor/theweatherchannel.py
+++ b/yt_dlp/extractor/theweatherchannel.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .theplatform import ThePlatformIE
diff --git a/yt_dlp/extractor/thisamericanlife.py b/yt_dlp/extractor/thisamericanlife.py
index 91e45f2c3d..9a3d79840a 100644
--- a/yt_dlp/extractor/thisamericanlife.py
+++ b/yt_dlp/extractor/thisamericanlife.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/thisav.py b/yt_dlp/extractor/thisav.py
index 6bb00b3aba..b1cd57d1f1 100644
--- a/yt_dlp/extractor/thisav.py
+++ b/yt_dlp/extractor/thisav.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import remove_end
 
diff --git a/yt_dlp/extractor/thisoldhouse.py b/yt_dlp/extractor/thisoldhouse.py
index 8a1d173116..55b6413ae6 100644
--- a/yt_dlp/extractor/thisoldhouse.py
+++ b/yt_dlp/extractor/thisoldhouse.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import HEADRequest
 
diff --git a/yt_dlp/extractor/threeqsdn.py b/yt_dlp/extractor/threeqsdn.py
index 00a51dccda..1c0baf5ed4 100644
--- a/yt_dlp/extractor/threeqsdn.py
+++ b/yt_dlp/extractor/threeqsdn.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/threespeak.py b/yt_dlp/extractor/threespeak.py
index fe6a9554a9..ce28a37c07 100644
--- a/yt_dlp/extractor/threespeak.py
+++ b/yt_dlp/extractor/threespeak.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tiktok.py b/yt_dlp/extractor/tiktok.py
index 987b0c43b5..4ba9935820 100644
--- a/yt_dlp/extractor/tiktok.py
+++ b/yt_dlp/extractor/tiktok.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import random
 import string
diff --git a/yt_dlp/extractor/tinypic.py b/yt_dlp/extractor/tinypic.py
index 39056e52e6..216208cbdc 100644
--- a/yt_dlp/extractor/tinypic.py
+++ b/yt_dlp/extractor/tinypic.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tmz.py b/yt_dlp/extractor/tmz.py
index aee2273b82..a8c91f617c 100644
--- a/yt_dlp/extractor/tmz.py
+++ b/yt_dlp/extractor/tmz.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tnaflix.py b/yt_dlp/extractor/tnaflix.py
index d7617f7084..6b766f3cc6 100644
--- a/yt_dlp/extractor/tnaflix.py
+++ b/yt_dlp/extractor/tnaflix.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/toggle.py b/yt_dlp/extractor/toggle.py
index eb873495fc..51a51d84b9 100644
--- a/yt_dlp/extractor/toggle.py
+++ b/yt_dlp/extractor/toggle.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/tokentube.py b/yt_dlp/extractor/tokentube.py
index 579623fed4..a30cabb3ce 100644
--- a/yt_dlp/extractor/tokentube.py
+++ b/yt_dlp/extractor/tokentube.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import re
 
diff --git a/yt_dlp/extractor/tonline.py b/yt_dlp/extractor/tonline.py
index 9b6a40db51..7202826636 100644
--- a/yt_dlp/extractor/tonline.py
+++ b/yt_dlp/extractor/tonline.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import int_or_none, join_nonempty
 
diff --git a/yt_dlp/extractor/toongoggles.py b/yt_dlp/extractor/toongoggles.py
index df13d64c0b..1b8fc3acdb 100644
--- a/yt_dlp/extractor/toongoggles.py
+++ b/yt_dlp/extractor/toongoggles.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/toutv.py b/yt_dlp/extractor/toutv.py
index 1d5da10400..349c0bded9 100644
--- a/yt_dlp/extractor/toutv.py
+++ b/yt_dlp/extractor/toutv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .radiocanada import RadioCanadaIE
diff --git a/yt_dlp/extractor/toypics.py b/yt_dlp/extractor/toypics.py
index f705a06c95..bc73361861 100644
--- a/yt_dlp/extractor/toypics.py
+++ b/yt_dlp/extractor/toypics.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 import re
 
diff --git a/yt_dlp/extractor/traileraddict.py b/yt_dlp/extractor/traileraddict.py
index 514f4793e6..5c4a138c47 100644
--- a/yt_dlp/extractor/traileraddict.py
+++ b/yt_dlp/extractor/traileraddict.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/trilulilu.py b/yt_dlp/extractor/trilulilu.py
index a800449e94..fb97be7373 100644
--- a/yt_dlp/extractor/trilulilu.py
+++ b/yt_dlp/extractor/trilulilu.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/trovo.py b/yt_dlp/extractor/trovo.py
index 65ea13ddb2..3487f3acce 100644
--- a/yt_dlp/extractor/trovo.py
+++ b/yt_dlp/extractor/trovo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import json
 
diff --git a/yt_dlp/extractor/trueid.py b/yt_dlp/extractor/trueid.py
index fc98303abd..696343627b 100644
--- a/yt_dlp/extractor/trueid.py
+++ b/yt_dlp/extractor/trueid.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_HTTPError
 from ..utils import (
diff --git a/yt_dlp/extractor/trunews.py b/yt_dlp/extractor/trunews.py
index cca5b5cebd..d5ce86ece6 100644
--- a/yt_dlp/extractor/trunews.py
+++ b/yt_dlp/extractor/trunews.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/trutv.py b/yt_dlp/extractor/trutv.py
index c09ff897c1..ea0f2f40e0 100644
--- a/yt_dlp/extractor/trutv.py
+++ b/yt_dlp/extractor/trutv.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .turner import TurnerBaseIE
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/tube8.py b/yt_dlp/extractor/tube8.py
index db93b01825..32e80d9d2a 100644
--- a/yt_dlp/extractor/tube8.py
+++ b/yt_dlp/extractor/tube8.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from ..utils import (
diff --git a/yt_dlp/extractor/tubitv.py b/yt_dlp/extractor/tubitv.py
index 31feb9a701..9c8e1ac879 100644
--- a/yt_dlp/extractor/tubitv.py
+++ b/yt_dlp/extractor/tubitv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tudou.py b/yt_dlp/extractor/tudou.py
index 7421378a8c..69774ee384 100644
--- a/yt_dlp/extractor/tudou.py
+++ b/yt_dlp/extractor/tudou.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/tumblr.py b/yt_dlp/extractor/tumblr.py
index 8086f613df..5d66151002 100644
--- a/yt_dlp/extractor/tumblr.py
+++ b/yt_dlp/extractor/tumblr.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/tunein.py b/yt_dlp/extractor/tunein.py
index 7e51de89ed..e3d3f2a96b 100644
--- a/yt_dlp/extractor/tunein.py
+++ b/yt_dlp/extractor/tunein.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tunepk.py b/yt_dlp/extractor/tunepk.py
index 9d42651ce0..2973d15ec5 100644
--- a/yt_dlp/extractor/tunepk.py
+++ b/yt_dlp/extractor/tunepk.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/turbo.py b/yt_dlp/extractor/turbo.py
index f6bbf2529e..e3f8941c44 100644
--- a/yt_dlp/extractor/turbo.py
+++ b/yt_dlp/extractor/turbo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/turner.py b/yt_dlp/extractor/turner.py
index 519dc323cd..568b6de495 100644
--- a/yt_dlp/extractor/turner.py
+++ b/yt_dlp/extractor/turner.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .adobepass import AdobePassIE
diff --git a/yt_dlp/extractor/tv2.py b/yt_dlp/extractor/tv2.py
index 977da30fee..391baa6c5e 100644
--- a/yt_dlp/extractor/tv2.py
+++ b/yt_dlp/extractor/tv2.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tv2dk.py b/yt_dlp/extractor/tv2dk.py
index ec5cbdf035..0af2863126 100644
--- a/yt_dlp/extractor/tv2dk.py
+++ b/yt_dlp/extractor/tv2dk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/tv2hu.py b/yt_dlp/extractor/tv2hu.py
index f2104358bb..6ac07716ba 100644
--- a/yt_dlp/extractor/tv2hu.py
+++ b/yt_dlp/extractor/tv2hu.py
@@ -1,6 +1,4 @@
 # encoding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     traverse_obj,
diff --git a/yt_dlp/extractor/tv4.py b/yt_dlp/extractor/tv4.py
index 4043e63662..e8cdd5c8cb 100644
--- a/yt_dlp/extractor/tv4.py
+++ b/yt_dlp/extractor/tv4.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tv5mondeplus.py b/yt_dlp/extractor/tv5mondeplus.py
index a0832d28f4..d449cdc042 100644
--- a/yt_dlp/extractor/tv5mondeplus.py
+++ b/yt_dlp/extractor/tv5mondeplus.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/tv5unis.py b/yt_dlp/extractor/tv5unis.py
index 398b85db56..978255b177 100644
--- a/yt_dlp/extractor/tv5unis.py
+++ b/yt_dlp/extractor/tv5unis.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/tva.py b/yt_dlp/extractor/tva.py
index 52a4ddf32f..9afe233284 100644
--- a/yt_dlp/extractor/tva.py
+++ b/yt_dlp/extractor/tva.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     float_or_none,
diff --git a/yt_dlp/extractor/tvanouvelles.py b/yt_dlp/extractor/tvanouvelles.py
index 1086176a2e..b9f5e110eb 100644
--- a/yt_dlp/extractor/tvanouvelles.py
+++ b/yt_dlp/extractor/tvanouvelles.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tvc.py b/yt_dlp/extractor/tvc.py
index 008f64cc2e..4ccc8f5227 100644
--- a/yt_dlp/extractor/tvc.py
+++ b/yt_dlp/extractor/tvc.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tver.py b/yt_dlp/extractor/tver.py
index f23af1f142..19236f8e82 100644
--- a/yt_dlp/extractor/tver.py
+++ b/yt_dlp/extractor/tver.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/tvigle.py b/yt_dlp/extractor/tvigle.py
index aa25ba0dc1..cc1d35dc23 100644
--- a/yt_dlp/extractor/tvigle.py
+++ b/yt_dlp/extractor/tvigle.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/tvland.py b/yt_dlp/extractor/tvland.py
index 9ebf57f740..481d5eb19e 100644
--- a/yt_dlp/extractor/tvland.py
+++ b/yt_dlp/extractor/tvland.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .mtv import MTVServicesInfoExtractor
 
 # TODO: Remove - Reason not used anymore - Service moved to youtube
diff --git a/yt_dlp/extractor/tvn24.py b/yt_dlp/extractor/tvn24.py
index de0fb50631..22b6058231 100644
--- a/yt_dlp/extractor/tvn24.py
+++ b/yt_dlp/extractor/tvn24.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/tvnet.py b/yt_dlp/extractor/tvnet.py
index aa1e9d9234..5820bb4a7b 100644
--- a/yt_dlp/extractor/tvnet.py
+++ b/yt_dlp/extractor/tvnet.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tvnoe.py b/yt_dlp/extractor/tvnoe.py
index 26a5aeae43..712fbb2754 100644
--- a/yt_dlp/extractor/tvnoe.py
+++ b/yt_dlp/extractor/tvnoe.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/tvnow.py b/yt_dlp/extractor/tvnow.py
index b31818477e..4aa558d839 100644
--- a/yt_dlp/extractor/tvnow.py
+++ b/yt_dlp/extractor/tvnow.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tvopengr.py b/yt_dlp/extractor/tvopengr.py
index a11cdc6b08..aded261f36 100644
--- a/yt_dlp/extractor/tvopengr.py
+++ b/yt_dlp/extractor/tvopengr.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tvp.py b/yt_dlp/extractor/tvp.py
index 48e2c6e764..69168f6558 100644
--- a/yt_dlp/extractor/tvp.py
+++ b/yt_dlp/extractor/tvp.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import random
 import re
diff --git a/yt_dlp/extractor/tvplay.py b/yt_dlp/extractor/tvplay.py
index b5dbc55262..f815b51379 100644
--- a/yt_dlp/extractor/tvplay.py
+++ b/yt_dlp/extractor/tvplay.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/tvplayer.py b/yt_dlp/extractor/tvplayer.py
index 5970596b21..31d70b6b83 100644
--- a/yt_dlp/extractor/tvplayer.py
+++ b/yt_dlp/extractor/tvplayer.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_HTTPError,
diff --git a/yt_dlp/extractor/tweakers.py b/yt_dlp/extractor/tweakers.py
index 2b10d9bcae..6d1f92bbb4 100644
--- a/yt_dlp/extractor/tweakers.py
+++ b/yt_dlp/extractor/tweakers.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/twentyfourvideo.py b/yt_dlp/extractor/twentyfourvideo.py
index ae19e11e1e..baeb85d473 100644
--- a/yt_dlp/extractor/twentyfourvideo.py
+++ b/yt_dlp/extractor/twentyfourvideo.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     parse_iso8601,
diff --git a/yt_dlp/extractor/twentymin.py b/yt_dlp/extractor/twentymin.py
index a42977f397..616c3c36ed 100644
--- a/yt_dlp/extractor/twentymin.py
+++ b/yt_dlp/extractor/twentymin.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/twentythreevideo.py b/yt_dlp/extractor/twentythreevideo.py
index e8cf5a1e96..290c3761e2 100644
--- a/yt_dlp/extractor/twentythreevideo.py
+++ b/yt_dlp/extractor/twentythreevideo.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/twitcasting.py b/yt_dlp/extractor/twitcasting.py
index 7f3fa07352..3d6a122655 100644
--- a/yt_dlp/extractor/twitcasting.py
+++ b/yt_dlp/extractor/twitcasting.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import re
 
diff --git a/yt_dlp/extractor/twitch.py b/yt_dlp/extractor/twitch.py
index 10de74c8e4..834350d12a 100644
--- a/yt_dlp/extractor/twitch.py
+++ b/yt_dlp/extractor/twitch.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import collections
 import itertools
 import json
diff --git a/yt_dlp/extractor/twitter.py b/yt_dlp/extractor/twitter.py
index 8ccc38e242..af67503330 100644
--- a/yt_dlp/extractor/twitter.py
+++ b/yt_dlp/extractor/twitter.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/udemy.py b/yt_dlp/extractor/udemy.py
index 77485247fd..d35cd0d431 100644
--- a/yt_dlp/extractor/udemy.py
+++ b/yt_dlp/extractor/udemy.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/udn.py b/yt_dlp/extractor/udn.py
index 2c8e5c7b41..4fa74b9e84 100644
--- a/yt_dlp/extractor/udn.py
+++ b/yt_dlp/extractor/udn.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/ufctv.py b/yt_dlp/extractor/ufctv.py
index 3d74ba0714..2c1c5e0ff1 100644
--- a/yt_dlp/extractor/ufctv.py
+++ b/yt_dlp/extractor/ufctv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .imggaming import ImgGamingBaseIE
 
 
diff --git a/yt_dlp/extractor/ukcolumn.py b/yt_dlp/extractor/ukcolumn.py
index d2626f0d3b..aade79f20e 100644
--- a/yt_dlp/extractor/ukcolumn.py
+++ b/yt_dlp/extractor/ukcolumn.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from ..utils import (
     unescapeHTML,
     urljoin,
diff --git a/yt_dlp/extractor/uktvplay.py b/yt_dlp/extractor/uktvplay.py
index f28fd514db..abea07ab56 100644
--- a/yt_dlp/extractor/uktvplay.py
+++ b/yt_dlp/extractor/uktvplay.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/umg.py b/yt_dlp/extractor/umg.py
index c1b65d1897..e6ed656b92 100644
--- a/yt_dlp/extractor/umg.py
+++ b/yt_dlp/extractor/umg.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/unistra.py b/yt_dlp/extractor/unistra.py
index 685d74f358..083c87209e 100644
--- a/yt_dlp/extractor/unistra.py
+++ b/yt_dlp/extractor/unistra.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/unity.py b/yt_dlp/extractor/unity.py
index 73daacf29f..d1b0ecbf38 100644
--- a/yt_dlp/extractor/unity.py
+++ b/yt_dlp/extractor/unity.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .youtube import YoutubeIE
 
diff --git a/yt_dlp/extractor/uol.py b/yt_dlp/extractor/uol.py
index 1baee0b10c..e3d9127d8e 100644
--- a/yt_dlp/extractor/uol.py
+++ b/yt_dlp/extractor/uol.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_str,
diff --git a/yt_dlp/extractor/uplynk.py b/yt_dlp/extractor/uplynk.py
index 9adb96943e..04c96f388c 100644
--- a/yt_dlp/extractor/uplynk.py
+++ b/yt_dlp/extractor/uplynk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/urort.py b/yt_dlp/extractor/urort.py
index 020425fc7b..296799d386 100644
--- a/yt_dlp/extractor/urort.py
+++ b/yt_dlp/extractor/urort.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import (
     compat_urllib_parse,
diff --git a/yt_dlp/extractor/urplay.py b/yt_dlp/extractor/urplay.py
index eb2ab26e1f..30bd3dcbf3 100644
--- a/yt_dlp/extractor/urplay.py
+++ b/yt_dlp/extractor/urplay.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     dict_get,
diff --git a/yt_dlp/extractor/usanetwork.py b/yt_dlp/extractor/usanetwork.py
index d953e460b8..d6b58a51c4 100644
--- a/yt_dlp/extractor/usanetwork.py
+++ b/yt_dlp/extractor/usanetwork.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .nbc import NBCIE
 
 
diff --git a/yt_dlp/extractor/usatoday.py b/yt_dlp/extractor/usatoday.py
index b2103448df..3243f3e3bd 100644
--- a/yt_dlp/extractor/usatoday.py
+++ b/yt_dlp/extractor/usatoday.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/ustream.py b/yt_dlp/extractor/ustream.py
index 4a7a8f8798..fff21667aa 100644
--- a/yt_dlp/extractor/ustream.py
+++ b/yt_dlp/extractor/ustream.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import random
 import re
 
diff --git a/yt_dlp/extractor/ustudio.py b/yt_dlp/extractor/ustudio.py
index 92509d1bf1..fd5dad0fc0 100644
--- a/yt_dlp/extractor/ustudio.py
+++ b/yt_dlp/extractor/ustudio.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/utreon.py b/yt_dlp/extractor/utreon.py
index 4986635f24..1213ae1bf5 100644
--- a/yt_dlp/extractor/utreon.py
+++ b/yt_dlp/extractor/utreon.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     dict_get,
diff --git a/yt_dlp/extractor/varzesh3.py b/yt_dlp/extractor/varzesh3.py
index 32655b96de..2c13cbdc0b 100644
--- a/yt_dlp/extractor/varzesh3.py
+++ b/yt_dlp/extractor/varzesh3.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/vbox7.py b/yt_dlp/extractor/vbox7.py
index 8152acefd0..76c844cb87 100644
--- a/yt_dlp/extractor/vbox7.py
+++ b/yt_dlp/extractor/vbox7.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/veehd.py b/yt_dlp/extractor/veehd.py
index a6dc3c8d89..5ecd88726a 100644
--- a/yt_dlp/extractor/veehd.py
+++ b/yt_dlp/extractor/veehd.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 import json
 
diff --git a/yt_dlp/extractor/veo.py b/yt_dlp/extractor/veo.py
index d87bb5b47a..25d462a7d0 100644
--- a/yt_dlp/extractor/veo.py
+++ b/yt_dlp/extractor/veo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 from ..utils import (
diff --git a/yt_dlp/extractor/veoh.py b/yt_dlp/extractor/veoh.py
index d9afb5617b..70280ae850 100644
--- a/yt_dlp/extractor/veoh.py
+++ b/yt_dlp/extractor/veoh.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/vesti.py b/yt_dlp/extractor/vesti.py
index 002047dbf6..e9731a9415 100644
--- a/yt_dlp/extractor/vesti.py
+++ b/yt_dlp/extractor/vesti.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vevo.py b/yt_dlp/extractor/vevo.py
index 8a0f29259c..bc01875110 100644
--- a/yt_dlp/extractor/vevo.py
+++ b/yt_dlp/extractor/vevo.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 import json
 
diff --git a/yt_dlp/extractor/vgtv.py b/yt_dlp/extractor/vgtv.py
index 9d6090b08e..6564b7b0bd 100644
--- a/yt_dlp/extractor/vgtv.py
+++ b/yt_dlp/extractor/vgtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vh1.py b/yt_dlp/extractor/vh1.py
index 862c5c7dcd..41b8a46075 100644
--- a/yt_dlp/extractor/vh1.py
+++ b/yt_dlp/extractor/vh1.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .mtv import MTVServicesInfoExtractor
 
 # TODO Remove - Reason: Outdated Site
diff --git a/yt_dlp/extractor/vice.py b/yt_dlp/extractor/vice.py
index c8c30559e7..abb4a6fa0b 100644
--- a/yt_dlp/extractor/vice.py
+++ b/yt_dlp/extractor/vice.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import functools
 import hashlib
 import json
diff --git a/yt_dlp/extractor/vidbit.py b/yt_dlp/extractor/vidbit.py
index 91f45b7cc7..2813032db0 100644
--- a/yt_dlp/extractor/vidbit.py
+++ b/yt_dlp/extractor/vidbit.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urlparse
 from ..utils import (
diff --git a/yt_dlp/extractor/viddler.py b/yt_dlp/extractor/viddler.py
index ecc48246f4..f491b67efd 100644
--- a/yt_dlp/extractor/viddler.py
+++ b/yt_dlp/extractor/viddler.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     float_or_none,
diff --git a/yt_dlp/extractor/videa.py b/yt_dlp/extractor/videa.py
index 90d7050921..251eb78feb 100644
--- a/yt_dlp/extractor/videa.py
+++ b/yt_dlp/extractor/videa.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 import re
 import string
diff --git a/yt_dlp/extractor/videocampus_sachsen.py b/yt_dlp/extractor/videocampus_sachsen.py
index 96e98573f3..fe9e061ae2 100644
--- a/yt_dlp/extractor/videocampus_sachsen.py
+++ b/yt_dlp/extractor/videocampus_sachsen.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/videodetective.py b/yt_dlp/extractor/videodetective.py
index fe70db713e..7928a41c21 100644
--- a/yt_dlp/extractor/videodetective.py
+++ b/yt_dlp/extractor/videodetective.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .internetvideoarchive import InternetVideoArchiveIE
 
diff --git a/yt_dlp/extractor/videofyme.py b/yt_dlp/extractor/videofyme.py
index cd3f50a63b..1d1c8f7b7c 100644
--- a/yt_dlp/extractor/videofyme.py
+++ b/yt_dlp/extractor/videofyme.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/videomore.py b/yt_dlp/extractor/videomore.py
index 17ef3b1b9e..09d12d192e 100644
--- a/yt_dlp/extractor/videomore.py
+++ b/yt_dlp/extractor/videomore.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/videopress.py b/yt_dlp/extractor/videopress.py
index 6376ff0961..3c5e27a9dc 100644
--- a/yt_dlp/extractor/videopress.py
+++ b/yt_dlp/extractor/videopress.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vidio.py b/yt_dlp/extractor/vidio.py
index 6bfb8d4429..599996bf95 100644
--- a/yt_dlp/extractor/vidio.py
+++ b/yt_dlp/extractor/vidio.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
diff --git a/yt_dlp/extractor/vidlii.py b/yt_dlp/extractor/vidlii.py
index a63919ff24..b9845affd7 100644
--- a/yt_dlp/extractor/vidlii.py
+++ b/yt_dlp/extractor/vidlii.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vidzi.py b/yt_dlp/extractor/vidzi.py
index 42ea4952c3..efa9be116e 100644
--- a/yt_dlp/extractor/vidzi.py
+++ b/yt_dlp/extractor/vidzi.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vier.py b/yt_dlp/extractor/vier.py
index 94aa350e78..eab894ab63 100644
--- a/yt_dlp/extractor/vier.py
+++ b/yt_dlp/extractor/vier.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import itertools
 
diff --git a/yt_dlp/extractor/viewlift.py b/yt_dlp/extractor/viewlift.py
index 4627f66fdf..d081a2f125 100644
--- a/yt_dlp/extractor/viewlift.py
+++ b/yt_dlp/extractor/viewlift.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import json
 import re
 
diff --git a/yt_dlp/extractor/viidea.py b/yt_dlp/extractor/viidea.py
index 0da06818b5..157ce4d8f9 100644
--- a/yt_dlp/extractor/viidea.py
+++ b/yt_dlp/extractor/viidea.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/viki.py b/yt_dlp/extractor/viki.py
index 8a930798d0..a922b195c9 100644
--- a/yt_dlp/extractor/viki.py
+++ b/yt_dlp/extractor/viki.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
 import hashlib
 import hmac
 import json
diff --git a/yt_dlp/extractor/vimeo.py b/yt_dlp/extractor/vimeo.py
index a00b387f3e..b2c9293738 100644
--- a/yt_dlp/extractor/vimeo.py
+++ b/yt_dlp/extractor/vimeo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import functools
 import re
diff --git a/yt_dlp/extractor/vimm.py b/yt_dlp/extractor/vimm.py
index 060b92ba60..3522b8e332 100644
--- a/yt_dlp/extractor/vimm.py
+++ b/yt_dlp/extractor/vimm.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/vimple.py b/yt_dlp/extractor/vimple.py
index c74b437668..a8b16dd290 100644
--- a/yt_dlp/extractor/vimple.py
+++ b/yt_dlp/extractor/vimple.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import int_or_none
 
diff --git a/yt_dlp/extractor/vine.py b/yt_dlp/extractor/vine.py
index e59b1037b0..bbf43a83fc 100644
--- a/yt_dlp/extractor/vine.py
+++ b/yt_dlp/extractor/vine.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/viqeo.py b/yt_dlp/extractor/viqeo.py
index be7dfa814f..d214223e9a 100644
--- a/yt_dlp/extractor/viqeo.py
+++ b/yt_dlp/extractor/viqeo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/viu.py b/yt_dlp/extractor/viu.py
index ba627ca5b7..63b6fd3a12 100644
--- a/yt_dlp/extractor/viu.py
+++ b/yt_dlp/extractor/viu.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import json
 import uuid
diff --git a/yt_dlp/extractor/vk.py b/yt_dlp/extractor/vk.py
index cbc315961e..402508aa34 100644
--- a/yt_dlp/extractor/vk.py
+++ b/yt_dlp/extractor/vk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import collections
 import re
 
diff --git a/yt_dlp/extractor/vlive.py b/yt_dlp/extractor/vlive.py
index ae35c976c2..c608014170 100644
--- a/yt_dlp/extractor/vlive.py
+++ b/yt_dlp/extractor/vlive.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import json
 
diff --git a/yt_dlp/extractor/vodlocker.py b/yt_dlp/extractor/vodlocker.py
index 02c9617d29..1c7236ed31 100644
--- a/yt_dlp/extractor/vodlocker.py
+++ b/yt_dlp/extractor/vodlocker.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/vodpl.py b/yt_dlp/extractor/vodpl.py
index 9e919708ed..8af1572d07 100644
--- a/yt_dlp/extractor/vodpl.py
+++ b/yt_dlp/extractor/vodpl.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .onet import OnetBaseIE
 
 
diff --git a/yt_dlp/extractor/vodplatform.py b/yt_dlp/extractor/vodplatform.py
index 74d2257e7c..2b45dcd866 100644
--- a/yt_dlp/extractor/vodplatform.py
+++ b/yt_dlp/extractor/vodplatform.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import unescapeHTML
 
diff --git a/yt_dlp/extractor/voicerepublic.py b/yt_dlp/extractor/voicerepublic.py
index a52e40afa2..e8cbd0e32c 100644
--- a/yt_dlp/extractor/voicerepublic.py
+++ b/yt_dlp/extractor/voicerepublic.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/voicy.py b/yt_dlp/extractor/voicy.py
index 37c7d5685f..e4570a03ae 100644
--- a/yt_dlp/extractor/voicy.py
+++ b/yt_dlp/extractor/voicy.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/voot.py b/yt_dlp/extractor/voot.py
index a9b66b95c2..7ac38a813a 100644
--- a/yt_dlp/extractor/voot.py
+++ b/yt_dlp/extractor/voot.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/voxmedia.py b/yt_dlp/extractor/voxmedia.py
index 6612081258..a7bf298aaf 100644
--- a/yt_dlp/extractor/voxmedia.py
+++ b/yt_dlp/extractor/voxmedia.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from .once import OnceIE
 from ..compat import compat_urllib_parse_unquote
diff --git a/yt_dlp/extractor/vrak.py b/yt_dlp/extractor/vrak.py
index daa247cce4..198c0a2942 100644
--- a/yt_dlp/extractor/vrak.py
+++ b/yt_dlp/extractor/vrak.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vrt.py b/yt_dlp/extractor/vrt.py
index 10dc94abcb..26f48bf67f 100644
--- a/yt_dlp/extractor/vrt.py
+++ b/yt_dlp/extractor/vrt.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     extract_attributes,
diff --git a/yt_dlp/extractor/vrv.py b/yt_dlp/extractor/vrv.py
index 00e1006c45..35662753ed 100644
--- a/yt_dlp/extractor/vrv.py
+++ b/yt_dlp/extractor/vrv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import json
 import hashlib
diff --git a/yt_dlp/extractor/vshare.py b/yt_dlp/extractor/vshare.py
index b4874ac390..8ef75d30e3 100644
--- a/yt_dlp/extractor/vshare.py
+++ b/yt_dlp/extractor/vshare.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vtm.py b/yt_dlp/extractor/vtm.py
index 093f1aa699..6381fd311f 100644
--- a/yt_dlp/extractor/vtm.py
+++ b/yt_dlp/extractor/vtm.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/vuclip.py b/yt_dlp/extractor/vuclip.py
index 55e087bdb4..0e562983d0 100644
--- a/yt_dlp/extractor/vuclip.py
+++ b/yt_dlp/extractor/vuclip.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vupload.py b/yt_dlp/extractor/vupload.py
index b561f63f73..23ea70c77e 100644
--- a/yt_dlp/extractor/vupload.py
+++ b/yt_dlp/extractor/vupload.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/vvvvid.py b/yt_dlp/extractor/vvvvid.py
index 3faa90fbd6..ccc44d08a3 100644
--- a/yt_dlp/extractor/vvvvid.py
+++ b/yt_dlp/extractor/vvvvid.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/vyborymos.py b/yt_dlp/extractor/vyborymos.py
index 4d93666c54..3865187951 100644
--- a/yt_dlp/extractor/vyborymos.py
+++ b/yt_dlp/extractor/vyborymos.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 
diff --git a/yt_dlp/extractor/vzaar.py b/yt_dlp/extractor/vzaar.py
index 54f88bba82..7ce0ba9f56 100644
--- a/yt_dlp/extractor/vzaar.py
+++ b/yt_dlp/extractor/vzaar.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/wakanim.py b/yt_dlp/extractor/wakanim.py
index a70a71961a..155008f8cb 100644
--- a/yt_dlp/extractor/wakanim.py
+++ b/yt_dlp/extractor/wakanim.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from urllib.parse import unquote
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/walla.py b/yt_dlp/extractor/walla.py
index 00f081bcaa..6b954c5cc2 100644
--- a/yt_dlp/extractor/walla.py
+++ b/yt_dlp/extractor/walla.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/wasdtv.py b/yt_dlp/extractor/wasdtv.py
index 38c10dc621..bf1ad65b23 100644
--- a/yt_dlp/extractor/wasdtv.py
+++ b/yt_dlp/extractor/wasdtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/washingtonpost.py b/yt_dlp/extractor/washingtonpost.py
index 9d6ae2870c..7274eaa396 100644
--- a/yt_dlp/extractor/washingtonpost.py
+++ b/yt_dlp/extractor/washingtonpost.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/wat.py b/yt_dlp/extractor/wat.py
index 9ff4523db6..2ad664890a 100644
--- a/yt_dlp/extractor/wat.py
+++ b/yt_dlp/extractor/wat.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/watchbox.py b/yt_dlp/extractor/watchbox.py
index d19d80102c..e41148d4a6 100644
--- a/yt_dlp/extractor/watchbox.py
+++ b/yt_dlp/extractor/watchbox.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/watchindianporn.py b/yt_dlp/extractor/watchindianporn.py
index a86819173f..3ded2d1d48 100644
--- a/yt_dlp/extractor/watchindianporn.py
+++ b/yt_dlp/extractor/watchindianporn.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/wdr.py b/yt_dlp/extractor/wdr.py
index ef58a66c3b..d0ad69477d 100644
--- a/yt_dlp/extractor/wdr.py
+++ b/yt_dlp/extractor/wdr.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/webcaster.py b/yt_dlp/extractor/webcaster.py
index a858e992ca..374fe35cd3 100644
--- a/yt_dlp/extractor/webcaster.py
+++ b/yt_dlp/extractor/webcaster.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/webofstories.py b/yt_dlp/extractor/webofstories.py
index f2b8d19b43..fde9300b0f 100644
--- a/yt_dlp/extractor/webofstories.py
+++ b/yt_dlp/extractor/webofstories.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/weibo.py b/yt_dlp/extractor/weibo.py
index dafa2af3be..d5a52ce20e 100644
--- a/yt_dlp/extractor/weibo.py
+++ b/yt_dlp/extractor/weibo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 import json
diff --git a/yt_dlp/extractor/weiqitv.py b/yt_dlp/extractor/weiqitv.py
index 7e0befd392..c9ff641542 100644
--- a/yt_dlp/extractor/weiqitv.py
+++ b/yt_dlp/extractor/weiqitv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/whowatch.py b/yt_dlp/extractor/whowatch.py
index e4b610d00d..21574471c4 100644
--- a/yt_dlp/extractor/whowatch.py
+++ b/yt_dlp/extractor/whowatch.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/willow.py b/yt_dlp/extractor/willow.py
index 4d3d62f955..6c71e9a04c 100644
--- a/yt_dlp/extractor/willow.py
+++ b/yt_dlp/extractor/willow.py
@@ -1,4 +1,3 @@
-# coding: utf-8
 from ..utils import ExtractorError
 from .common import InfoExtractor
 
diff --git a/yt_dlp/extractor/wimtv.py b/yt_dlp/extractor/wimtv.py
index ea953bf776..6e7ec3436f 100644
--- a/yt_dlp/extractor/wimtv.py
+++ b/yt_dlp/extractor/wimtv.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/wistia.py b/yt_dlp/extractor/wistia.py
index a170966c36..8f0e7949b2 100644
--- a/yt_dlp/extractor/wistia.py
+++ b/yt_dlp/extractor/wistia.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/worldstarhiphop.py b/yt_dlp/extractor/worldstarhiphop.py
index 82587b4ce9..c6948a1eb0 100644
--- a/yt_dlp/extractor/worldstarhiphop.py
+++ b/yt_dlp/extractor/worldstarhiphop.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 
 
diff --git a/yt_dlp/extractor/wppilot.py b/yt_dlp/extractor/wppilot.py
index 3003a0f108..6349e5326b 100644
--- a/yt_dlp/extractor/wppilot.py
+++ b/yt_dlp/extractor/wppilot.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 from .common import InfoExtractor
 from ..utils import (
     try_get,
diff --git a/yt_dlp/extractor/wsj.py b/yt_dlp/extractor/wsj.py
index 67236f377d..8be3645e35 100644
--- a/yt_dlp/extractor/wsj.py
+++ b/yt_dlp/extractor/wsj.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/wwe.py b/yt_dlp/extractor/wwe.py
index bebc77bb54..9bbd477c33 100644
--- a/yt_dlp/extractor/wwe.py
+++ b/yt_dlp/extractor/wwe.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/xbef.py b/yt_dlp/extractor/xbef.py
index 4c41e98b27..ac69528a3a 100644
--- a/yt_dlp/extractor/xbef.py
+++ b/yt_dlp/extractor/xbef.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urllib_parse_unquote
 
diff --git a/yt_dlp/extractor/xboxclips.py b/yt_dlp/extractor/xboxclips.py
index 9bac982f84..235b567d99 100644
--- a/yt_dlp/extractor/xboxclips.py
+++ b/yt_dlp/extractor/xboxclips.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/xfileshare.py b/yt_dlp/extractor/xfileshare.py
index cd97c77dc6..28b6ecb6ea 100644
--- a/yt_dlp/extractor/xfileshare.py
+++ b/yt_dlp/extractor/xfileshare.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/xhamster.py b/yt_dlp/extractor/xhamster.py
index 9d4ed47d41..ff15d37076 100644
--- a/yt_dlp/extractor/xhamster.py
+++ b/yt_dlp/extractor/xhamster.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import itertools
 import re
 
diff --git a/yt_dlp/extractor/xiami.py b/yt_dlp/extractor/xiami.py
index 769aab3316..71b2956a8e 100644
--- a/yt_dlp/extractor/xiami.py
+++ b/yt_dlp/extractor/xiami.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_urllib_parse_unquote
 from ..utils import int_or_none
diff --git a/yt_dlp/extractor/ximalaya.py b/yt_dlp/extractor/ximalaya.py
index 802d1bb1b4..c3447fba08 100644
--- a/yt_dlp/extractor/ximalaya.py
+++ b/yt_dlp/extractor/ximalaya.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import itertools
 import re
 
diff --git a/yt_dlp/extractor/xinpianchang.py b/yt_dlp/extractor/xinpianchang.py
index 9832d23985..96e23bb8d0 100644
--- a/yt_dlp/extractor/xinpianchang.py
+++ b/yt_dlp/extractor/xinpianchang.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     int_or_none,
diff --git a/yt_dlp/extractor/xminus.py b/yt_dlp/extractor/xminus.py
index 36e5ead1e6..5f113810fd 100644
--- a/yt_dlp/extractor/xminus.py
+++ b/yt_dlp/extractor/xminus.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import time
 
diff --git a/yt_dlp/extractor/xnxx.py b/yt_dlp/extractor/xnxx.py
index 27f9916277..14beb13475 100644
--- a/yt_dlp/extractor/xnxx.py
+++ b/yt_dlp/extractor/xnxx.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/xstream.py b/yt_dlp/extractor/xstream.py
index 792843df58..42bffb071f 100644
--- a/yt_dlp/extractor/xstream.py
+++ b/yt_dlp/extractor/xstream.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/xtube.py b/yt_dlp/extractor/xtube.py
index abd319188d..93a6a3f335 100644
--- a/yt_dlp/extractor/xtube.py
+++ b/yt_dlp/extractor/xtube.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import itertools
 import re
 
diff --git a/yt_dlp/extractor/xuite.py b/yt_dlp/extractor/xuite.py
index 0276c0dbb2..52423a3279 100644
--- a/yt_dlp/extractor/xuite.py
+++ b/yt_dlp/extractor/xuite.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/xvideos.py b/yt_dlp/extractor/xvideos.py
index d5261b6ab4..50b9394961 100644
--- a/yt_dlp/extractor/xvideos.py
+++ b/yt_dlp/extractor/xvideos.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/xxxymovies.py b/yt_dlp/extractor/xxxymovies.py
index 0d536015cc..e3e3a9fe63 100644
--- a/yt_dlp/extractor/xxxymovies.py
+++ b/yt_dlp/extractor/xxxymovies.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     parse_duration,
diff --git a/yt_dlp/extractor/yahoo.py b/yt_dlp/extractor/yahoo.py
index 20504de2c0..3fe6192bf6 100644
--- a/yt_dlp/extractor/yahoo.py
+++ b/yt_dlp/extractor/yahoo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import itertools
 import re
diff --git a/yt_dlp/extractor/yandexdisk.py b/yt_dlp/extractor/yandexdisk.py
index c15f3a4f32..d87a7f9be9 100644
--- a/yt_dlp/extractor/yandexdisk.py
+++ b/yt_dlp/extractor/yandexdisk.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/yandexmusic.py b/yt_dlp/extractor/yandexmusic.py
index a3558cc126..8ea416a1d8 100644
--- a/yt_dlp/extractor/yandexmusic.py
+++ b/yt_dlp/extractor/yandexmusic.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import itertools
 
diff --git a/yt_dlp/extractor/yandexvideo.py b/yt_dlp/extractor/yandexvideo.py
index 7d3966bf1a..37ff514b3a 100644
--- a/yt_dlp/extractor/yandexvideo.py
+++ b/yt_dlp/extractor/yandexvideo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 import re
 
diff --git a/yt_dlp/extractor/yapfiles.py b/yt_dlp/extractor/yapfiles.py
index cfb368de94..8fabdf81c9 100644
--- a/yt_dlp/extractor/yapfiles.py
+++ b/yt_dlp/extractor/yapfiles.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/yesjapan.py b/yt_dlp/extractor/yesjapan.py
index 681338c96a..b45fa8f144 100644
--- a/yt_dlp/extractor/yesjapan.py
+++ b/yt_dlp/extractor/yesjapan.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import (
     HEADRequest,
diff --git a/yt_dlp/extractor/yinyuetai.py b/yt_dlp/extractor/yinyuetai.py
index 1fd8d35c63..b28c393808 100644
--- a/yt_dlp/extractor/yinyuetai.py
+++ b/yt_dlp/extractor/yinyuetai.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import ExtractorError
 
diff --git a/yt_dlp/extractor/ynet.py b/yt_dlp/extractor/ynet.py
index c4ae4d88eb..4447859479 100644
--- a/yt_dlp/extractor/ynet.py
+++ b/yt_dlp/extractor/ynet.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 import json
 
diff --git a/yt_dlp/extractor/youjizz.py b/yt_dlp/extractor/youjizz.py
index 111623ffe6..cd12be500b 100644
--- a/yt_dlp/extractor/youjizz.py
+++ b/yt_dlp/extractor/youjizz.py
@@ -1,6 +1,3 @@
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
diff --git a/yt_dlp/extractor/youku.py b/yt_dlp/extractor/youku.py
index b505799153..45856fbbea 100644
--- a/yt_dlp/extractor/youku.py
+++ b/yt_dlp/extractor/youku.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import random
 import re
 import string
diff --git a/yt_dlp/extractor/younow.py b/yt_dlp/extractor/younow.py
index 583aea38d9..76d89f3cec 100644
--- a/yt_dlp/extractor/younow.py
+++ b/yt_dlp/extractor/younow.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import itertools
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/youporn.py b/yt_dlp/extractor/youporn.py
index 5feb568e72..5aea82295a 100644
--- a/yt_dlp/extractor/youporn.py
+++ b/yt_dlp/extractor/youporn.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/yourporn.py b/yt_dlp/extractor/yourporn.py
index 98347491ee..38f42a991c 100644
--- a/yt_dlp/extractor/yourporn.py
+++ b/yt_dlp/extractor/yourporn.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
diff --git a/yt_dlp/extractor/yourupload.py b/yt_dlp/extractor/yourupload.py
index 9fa7728389..def63293aa 100644
--- a/yt_dlp/extractor/yourupload.py
+++ b/yt_dlp/extractor/yourupload.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import urljoin
 
diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py
index f284487b8a..21c6143bd3 100644
--- a/yt_dlp/extractor/youtube.py
+++ b/yt_dlp/extractor/youtube.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import calendar
 import copy
 import datetime
@@ -452,7 +448,7 @@ def _generate_sapisidhash_header(self, origin='https://www.youtube.com'):
             return None
         # SAPISIDHASH algorithm from https://stackoverflow.com/a/32065323
         sapisidhash = hashlib.sha1(
-            f'{time_now} {self._SAPISID} {origin}'.encode('utf-8')).hexdigest()
+            f'{time_now} {self._SAPISID} {origin}'.encode()).hexdigest()
         return f'SAPISIDHASH {time_now}_{sapisidhash}'
 
     def _call_api(self, ep, query, video_id, fatal=True, headers=None,
@@ -466,14 +462,14 @@ def _call_api(self, ep, query, video_id, fatal=True, headers=None,
         if headers:
             real_headers.update(headers)
         return self._download_json(
-            'https://%s/youtubei/v1/%s' % (api_hostname or self._get_innertube_host(default_client), ep),
+            f'https://{api_hostname or self._get_innertube_host(default_client)}/youtubei/v1/{ep}',
             video_id=video_id, fatal=fatal, note=note, errnote=errnote,
             data=json.dumps(data).encode('utf8'), headers=real_headers,
             query={'key': api_key or self._extract_api_key(), 'prettyPrint': 'false'})
 
     def extract_yt_initial_data(self, item_id, webpage, fatal=True):
         data = self._search_regex(
-            (r'%s\s*%s' % (self._YT_INITIAL_DATA_RE, self._YT_INITIAL_BOUNDARY_RE),
+            (fr'{self._YT_INITIAL_DATA_RE}\s*{self._YT_INITIAL_BOUNDARY_RE}',
              self._YT_INITIAL_DATA_RE), webpage, 'yt initial data', fatal=fatal)
         if data:
             return self._parse_json(data, item_id, fatal=fatal)
@@ -657,7 +653,7 @@ def _report_alerts(self, alerts, expected=True, fatal=True, only_once=False):
                 warnings.append([alert_type, alert_message])
 
         for alert_type, alert_message in (warnings + errors[:-1]):
-            self.report_warning('YouTube said: %s - %s' % (alert_type, alert_message), only_once=only_once)
+            self.report_warning(f'YouTube said: {alert_type} - {alert_message}', only_once=only_once)
         if errors:
             raise ExtractorError('YouTube said: %s' % errors[-1][1], expected=expected)
 
@@ -2214,10 +2210,10 @@ def suitable(cls, url):
         qs = parse_qs(url)
         if qs.get('list', [None])[0]:
             return False
-        return super(YoutubeIE, cls).suitable(url)
+        return super().suitable(url)
 
     def __init__(self, *args, **kwargs):
-        super(YoutubeIE, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self._code_cache = {}
         self._player_cache = {}
 
@@ -2413,8 +2409,7 @@ def _extract_signature_function(self, video_id, player_url, example_sig):
         player_id = self._extract_player_info(player_url)
 
         # Read from filesystem cache
-        func_id = 'js_%s_%s' % (
-            player_id, self._signature_cache_id(example_sig))
+        func_id = f'js_{player_id}_{self._signature_cache_id(example_sig)}'
         assert os.path.basename(func_id) == func_id
 
         cache_spec = self._downloader.cache.load('youtube-sigfuncs', func_id)
@@ -2441,7 +2436,7 @@ def _genslice(start, end, step):
                 starts = '' if start == 0 else str(start)
                 ends = (':%d' % (end + step)) if end + step >= 0 else ':'
                 steps = '' if step == 1 else (':%d' % step)
-                return 's[%s%s%s]' % (starts, ends, steps)
+                return f's[{starts}{ends}{steps}]'
 
             step = None
             # Quelch pyflakes warnings - start will be set when step is set
@@ -2603,7 +2598,7 @@ def _mark_watched(self, video_id, player_responses):
         # cpn generation algorithm is reverse engineered from base.js.
         # In fact it works even with dummy cpn.
         CPN_ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_'
-        cpn = ''.join((CPN_ALPHABET[random.randint(0, 256) & 63] for _ in range(0, 16)))
+        cpn = ''.join(CPN_ALPHABET[random.randint(0, 256) & 63] for _ in range(0, 16))
 
         qs.update({
             'ver': ['2'],
@@ -2714,7 +2709,7 @@ def _extract_chapters(self, chapter_list, chapter_time, chapter_title, duration)
 
     def _extract_yt_initial_variable(self, webpage, regex, video_id, name):
         return self._parse_json(self._search_regex(
-            (r'%s\s*%s' % (regex, self._YT_INITIAL_BOUNDARY_RE),
+            (fr'{regex}\s*{self._YT_INITIAL_BOUNDARY_RE}',
              regex), webpage, name, default='{}'), video_id, fatal=False)
 
     def _extract_comment(self, comment_renderer, parent=None):
@@ -2812,8 +2807,8 @@ def extract_thread(contents):
                     comment_entries_iter = self._comment_entries(
                         comment_replies_renderer, ytcfg, video_id,
                         parent=comment.get('id'), tracker=tracker)
-                    for reply_comment in itertools.islice(comment_entries_iter, min(max_replies_per_thread, max(0, max_replies - tracker['total_reply_comments']))):
-                        yield reply_comment
+                    yield from itertools.islice(comment_entries_iter, min(
+                        max_replies_per_thread, max(0, max_replies - tracker['total_reply_comments'])))
 
         # Keeps track of counts across recursive calls
         if not tracker:
@@ -2955,7 +2950,7 @@ def _get_requested_clients(self, url, smuggled_data):
         requested_clients = []
         default = ['android', 'web']
         allowed_clients = sorted(
-            [client for client in INNERTUBE_CLIENTS.keys() if client[:1] != '_'],
+            (client for client in INNERTUBE_CLIENTS.keys() if client[:1] != '_'),
             key=lambda client: INNERTUBE_CLIENTS[client]['priority'], reverse=True)
         for client in self._configuration_arg('player_client'):
             if client in allowed_clients:
@@ -3865,8 +3860,7 @@ def _shelf_entries_from_content(self, shelf_renderer):
             # TODO: add support for nested playlists so each shelf is processed
             # as separate playlist
             # TODO: this includes only first N items
-            for entry in self._grid_entries(renderer):
-                yield entry
+            yield from self._grid_entries(renderer)
         renderer = content.get('horizontalListRenderer')
         if renderer:
             # TODO
@@ -3886,8 +3880,7 @@ def _shelf_entries(self, shelf_renderer, skip_channels=False):
             title = self._get_text(shelf_renderer, 'title')
             yield self.url_result(shelf_url, video_title=title)
         # Shelf may not contain shelf URL, fallback to extraction from content
-        for entry in self._shelf_entries_from_content(shelf_renderer):
-            yield entry
+        yield from self._shelf_entries_from_content(shelf_renderer)
 
     def _playlist_entries(self, video_list_renderer):
         for content in video_list_renderer['contents']:
@@ -3965,8 +3958,7 @@ def _post_thread_continuation_entries(self, post_thread_continuation):
             renderer = content.get('backstagePostThreadRenderer')
             if not isinstance(renderer, dict):
                 continue
-            for entry in self._post_thread_entries(renderer):
-                yield entry
+            yield from self._post_thread_entries(renderer)
 
     r''' # unused
     def _rich_grid_entries(self, contents):
@@ -4036,8 +4028,7 @@ def _entries(self, tab, item_id, ytcfg, account_syncid, visitor_data):
         parent_renderer = (
             try_get(tab_content, lambda x: x['sectionListRenderer'], dict)
             or try_get(tab_content, lambda x: x['richGridRenderer'], dict) or {})
-        for entry in extract_entries(parent_renderer):
-            yield entry
+        yield from extract_entries(parent_renderer)
         continuation = continuation_list[0]
 
         for page_num in itertools.count(1):
@@ -4046,7 +4037,7 @@ def _entries(self, tab, item_id, ytcfg, account_syncid, visitor_data):
             headers = self.generate_api_headers(
                 ytcfg=ytcfg, account_syncid=account_syncid, visitor_data=visitor_data)
             response = self._extract_response(
-                item_id='%s page %s' % (item_id, page_num),
+                item_id=f'{item_id} page {page_num}',
                 query=continuation, headers=headers, ytcfg=ytcfg,
                 check_get_keys=('continuationContents', 'onResponseReceivedActions', 'onResponseReceivedEndpoints'))
 
@@ -4070,8 +4061,7 @@ def _entries(self, tab, item_id, ytcfg, account_syncid, visitor_data):
                     continue
                 continuation_renderer = value
                 continuation_list = [None]
-                for entry in known_continuation_renderers[key](continuation_renderer):
-                    yield entry
+                yield from known_continuation_renderers[key](continuation_renderer)
                 continuation = continuation_list[0] or self._extract_continuation(continuation_renderer)
                 break
             if continuation_renderer:
@@ -4097,8 +4087,7 @@ def _entries(self, tab, item_id, ytcfg, account_syncid, visitor_data):
                     continue
                 video_items_renderer = {known_renderers[key][1]: continuation_items}
                 continuation_list = [None]
-                for entry in known_renderers[key][0](video_items_renderer):
-                    yield entry
+                yield from known_renderers[key][0](video_items_renderer)
                 continuation = continuation_list[0] or self._extract_continuation(video_items_renderer)
                 break
             if video_items_renderer:
@@ -4470,7 +4459,7 @@ def _search_results(self, query, params=NO_DEFAULT, default_client='web'):
             ('continuationContents', ),
         )
         display_id = f'query "{query}"'
-        check_get_keys = tuple(set(keys[0] for keys in content_keys))
+        check_get_keys = tuple({keys[0] for keys in content_keys})
         ytcfg = self._download_ytcfg(default_client, display_id) if not self.skip_webpage else {}
         self._report_playlist_authcheck(ytcfg, fatal=False)
 
@@ -5180,8 +5169,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
 
     @classmethod
     def suitable(cls, url):
-        return False if YoutubeIE.suitable(url) else super(
-            YoutubeTabIE, cls).suitable(url)
+        return False if YoutubeIE.suitable(url) else super().suitable(url)
 
     _URL_RE = re.compile(rf'(?P<pre>{_VALID_URL})(?(not_channel)|(?P<tab>/\w+))?(?P<post>.*)$')
 
@@ -5228,7 +5216,7 @@ def get_mobj(url):
 
         # Handle both video/playlist URLs
         qs = parse_qs(url)
-        video_id, playlist_id = [qs.get(key, [None])[0] for key in ('v', 'list')]
+        video_id, playlist_id = (qs.get(key, [None])[0] for key in ('v', 'list'))
 
         if not video_id and mobj['not_channel'].startswith('watch'):
             if not playlist_id:
@@ -5414,7 +5402,7 @@ def suitable(cls, url):
         qs = parse_qs(url)
         if qs.get('v', [None])[0]:
             return False
-        return super(YoutubePlaylistIE, cls).suitable(url)
+        return super().suitable(url)
 
     def _real_extract(self, url):
         playlist_id = self._match_id(url)
@@ -5883,5 +5871,5 @@ class YoutubeTruncatedIDIE(InfoExtractor):
     def _real_extract(self, url):
         video_id = self._match_id(url)
         raise ExtractorError(
-            'Incomplete YouTube ID %s. URL %s looks truncated.' % (video_id, url),
+            f'Incomplete YouTube ID {video_id}. URL {url} looks truncated.',
             expected=True)
diff --git a/yt_dlp/extractor/zapiks.py b/yt_dlp/extractor/zapiks.py
index 161b011ab6..a1546fd88f 100644
--- a/yt_dlp/extractor/zapiks.py
+++ b/yt_dlp/extractor/zapiks.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/zattoo.py b/yt_dlp/extractor/zattoo.py
index 8614ca23de..16f827a7e1 100644
--- a/yt_dlp/extractor/zattoo.py
+++ b/yt_dlp/extractor/zattoo.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 from uuid import uuid4
 
diff --git a/yt_dlp/extractor/zdf.py b/yt_dlp/extractor/zdf.py
index 5f4d26622f..a388ff562b 100644
--- a/yt_dlp/extractor/zdf.py
+++ b/yt_dlp/extractor/zdf.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/extractor/zee5.py b/yt_dlp/extractor/zee5.py
index 9e411d83ff..9ff36052ea 100644
--- a/yt_dlp/extractor/zee5.py
+++ b/yt_dlp/extractor/zee5.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import json
 
 from .common import InfoExtractor
@@ -96,14 +93,14 @@ class Zee5IE(InfoExtractor):
     def _perform_login(self, username, password):
         if len(username) == 10 and username.isdigit() and self._USER_TOKEN is None:
             self.report_login()
-            otp_request_json = self._download_json('https://b2bapi.zee5.com/device/sendotp_v1.php?phoneno=91{}'.format(username),
+            otp_request_json = self._download_json(f'https://b2bapi.zee5.com/device/sendotp_v1.php?phoneno=91{username}',
                                                    None, note='Sending OTP')
             if otp_request_json['code'] == 0:
                 self.to_screen(otp_request_json['message'])
             else:
                 raise ExtractorError(otp_request_json['message'], expected=True)
             otp_code = self._get_tfa_info('OTP')
-            otp_verify_json = self._download_json('https://b2bapi.zee5.com/device/verifyotp_v1.php?phoneno=91{}&otp={}&guest_token={}&platform=web'.format(username, otp_code, self._DEVICE_ID),
+            otp_verify_json = self._download_json(f'https://b2bapi.zee5.com/device/verifyotp_v1.php?phoneno=91{username}&otp={otp_code}&guest_token={self._DEVICE_ID}&platform=web',
                                                   None, note='Verifying OTP', fatal=False)
             if not otp_verify_json:
                 raise ExtractorError('Unable to verify OTP.', expected=True)
@@ -227,13 +224,13 @@ def _entries(self, show_id):
             'X-Access-Token': access_token_request['token'],
             'Referer': 'https://www.zee5.com/',
         }
-        show_url = 'https://gwapi.zee5.com/content/tvshow/{}?translation=en&country=IN'.format(show_id)
+        show_url = f'https://gwapi.zee5.com/content/tvshow/{show_id}?translation=en&country=IN'
 
         page_num = 0
         show_json = self._download_json(show_url, video_id=show_id, headers=headers)
         for season in show_json.get('seasons') or []:
             season_id = try_get(season, lambda x: x['id'], compat_str)
-            next_url = 'https://gwapi.zee5.com/content/tvshow/?season_id={}&type=episode&translation=en&country=IN&on_air=false&asset_subtype=tvshow&page=1&limit=100'.format(season_id)
+            next_url = f'https://gwapi.zee5.com/content/tvshow/?season_id={season_id}&type=episode&translation=en&country=IN&on_air=false&asset_subtype=tvshow&page=1&limit=100'
             while next_url:
                 page_num += 1
                 episodes_json = self._download_json(
diff --git a/yt_dlp/extractor/zhihu.py b/yt_dlp/extractor/zhihu.py
index 278a9438e8..70eb3ccd1b 100644
--- a/yt_dlp/extractor/zhihu.py
+++ b/yt_dlp/extractor/zhihu.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from .common import InfoExtractor
 from ..utils import format_field, float_or_none, int_or_none
 
diff --git a/yt_dlp/extractor/zingmp3.py b/yt_dlp/extractor/zingmp3.py
index 419bf30d85..42a8ac0561 100644
--- a/yt_dlp/extractor/zingmp3.py
+++ b/yt_dlp/extractor/zingmp3.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import hashlib
 import hmac
 import urllib.parse
diff --git a/yt_dlp/extractor/zoom.py b/yt_dlp/extractor/zoom.py
index c005488399..a455f8c04a 100644
--- a/yt_dlp/extractor/zoom.py
+++ b/yt_dlp/extractor/zoom.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
-
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
diff --git a/yt_dlp/extractor/zype.py b/yt_dlp/extractor/zype.py
index 7663cb36b0..6f2fbb9e9d 100644
--- a/yt_dlp/extractor/zype.py
+++ b/yt_dlp/extractor/zype.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from .common import InfoExtractor
diff --git a/yt_dlp/jsinterp.py b/yt_dlp/jsinterp.py
index 350b44dd07..3695a282d2 100644
--- a/yt_dlp/jsinterp.py
+++ b/yt_dlp/jsinterp.py
@@ -71,7 +71,7 @@ def __repr__(self):
         return f'LocalNameSpace{self.stack}'
 
 
-class JSInterpreter(object):
+class JSInterpreter:
     def __init__(self, code, objects=None):
         if objects is None:
             objects = {}
@@ -232,7 +232,7 @@ def interpret_expression(self, expr, local_vars, allow_recursion):
             for default in (False, True):
                 matched = False
                 for item in items:
-                    case, stmt = [i.strip() for i in self._separate(item, ':', 1)]
+                    case, stmt = (i.strip() for i in self._separate(item, ':', 1))
                     if default:
                         matched = matched or case == 'default'
                     elif not matched:
@@ -268,10 +268,10 @@ def interpret_expression(self, expr, local_vars, allow_recursion):
             expr = expr[:start] + json.dumps(ret) + expr[end:]
 
         for op, opfunc in _ASSIGN_OPERATORS:
-            m = re.match(r'''(?x)
-                (?P<out>%s)(?:\[(?P<index>[^\]]+?)\])?
-                \s*%s
-                (?P<expr>.*)$''' % (_NAME_RE, re.escape(op)), expr)
+            m = re.match(rf'''(?x)
+                (?P<out>{_NAME_RE})(?:\[(?P<index>[^\]]+?)\])?
+                \s*{re.escape(op)}
+                (?P<expr>.*)$''', expr)
             if not m:
                 continue
             right_val = self.interpret_expression(m.group('expr'), local_vars, allow_recursion)
@@ -451,9 +451,9 @@ def eval_method():
         m = re.match(r'^(?P<func>%s)\((?P<args>[a-zA-Z0-9_$,]*)\)$' % _NAME_RE, expr)
         if m:
             fname = m.group('func')
-            argvals = tuple([
+            argvals = tuple(
                 int(v) if v.isdigit() else local_vars[v]
-                for v in self._separate(m.group('args'))])
+                for v in self._separate(m.group('args')))
             if fname in local_vars:
                 return local_vars[fname](argvals)
             elif fname not in self._functions:
diff --git a/yt_dlp/options.py b/yt_dlp/options.py
index 8839b44d4b..c434e32b95 100644
--- a/yt_dlp/options.py
+++ b/yt_dlp/options.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import os.path
 import optparse
 import re
@@ -124,7 +122,7 @@ def _match_long_opt(self, opt):
         try:
             return super()._match_long_opt(opt)
         except optparse.AmbiguousOptionError as e:
-            if len(set(self._long_opt[p] for p in e.possibilities)) == 1:
+            if len({self._long_opt[p] for p in e.possibilities}) == 1:
                 return e.possibilities[0]
             raise
 
@@ -189,9 +187,9 @@ def _dict_from_options_callback(
         out_dict = dict(getattr(parser.values, option.dest))
         multiple_args = not isinstance(value, str)
         if multiple_keys:
-            allowed_keys = r'(%s)(,(%s))*' % (allowed_keys, allowed_keys)
+            allowed_keys = fr'({allowed_keys})(,({allowed_keys}))*'
         mobj = re.match(
-            r'(?i)(?P<keys>%s)%s(?P<val>.*)$' % (allowed_keys, delimiter),
+            fr'(?i)(?P<keys>{allowed_keys}){delimiter}(?P<val>.*)$',
             value[0] if multiple_args else value)
         if mobj is not None:
             keys, val = mobj.group('keys').split(','), mobj.group('val')
@@ -201,7 +199,7 @@ def _dict_from_options_callback(
             keys, val = [default_key], value
         else:
             raise optparse.OptionValueError(
-                'wrong %s formatting; it should be %s, not "%s"' % (opt_str, option.metavar, value))
+                f'wrong {opt_str} formatting; it should be {option.metavar}, not "{value}"')
         try:
             keys = map(process_key, keys) if process_key else keys
             val = process(val) if process else val
diff --git a/yt_dlp/postprocessor/common.py b/yt_dlp/postprocessor/common.py
index 8420ee8641..3f55b24f2c 100644
--- a/yt_dlp/postprocessor/common.py
+++ b/yt_dlp/postprocessor/common.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import functools
 import itertools
 import json
@@ -73,7 +71,7 @@ def pp_key(cls):
     def to_screen(self, text, prefix=True, *args, **kwargs):
         tag = '[%s] ' % self.PP_NAME if prefix else ''
         if self._downloader:
-            return self._downloader.to_screen('%s%s' % (tag, text), *args, **kwargs)
+            return self._downloader.to_screen(f'{tag}{text}', *args, **kwargs)
 
     def report_warning(self, text, *args, **kwargs):
         if self._downloader:
diff --git a/yt_dlp/postprocessor/embedthumbnail.py b/yt_dlp/postprocessor/embedthumbnail.py
index 057007f2e9..2fca977846 100644
--- a/yt_dlp/postprocessor/embedthumbnail.py
+++ b/yt_dlp/postprocessor/embedthumbnail.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import base64
 import imghdr
 import os
@@ -61,7 +58,7 @@ def guess():
         return int(mobj.group('w')), int(mobj.group('h'))
 
     def _report_run(self, exe, filename):
-        self.to_screen('%s: Adding thumbnail to "%s"' % (exe, filename))
+        self.to_screen(f'{exe}: Adding thumbnail to "{filename}"')
 
     @PostProcessor._restrict_to(images=False)
     def run(self, info):
diff --git a/yt_dlp/postprocessor/exec.py b/yt_dlp/postprocessor/exec.py
index 63f4d23f26..6621889d5c 100644
--- a/yt_dlp/postprocessor/exec.py
+++ b/yt_dlp/postprocessor/exec.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import subprocess
 
 from .common import PostProcessor
diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py
index 78c6f91074..3175c8d10b 100644
--- a/yt_dlp/postprocessor/ffmpeg.py
+++ b/yt_dlp/postprocessor/ffmpeg.py
@@ -1,7 +1,4 @@
-from __future__ import unicode_literals
-
 import collections
-import io
 import itertools
 import os
 import subprocess
@@ -73,11 +70,9 @@ def check_version(self):
             raise FFmpegPostProcessorError('ffmpeg not found. Please install or provide the path using --ffmpeg-location')
 
         required_version = '10-0' if self.basename == 'avconv' else '1.0'
-        if is_outdated_version(
-                self._versions[self.basename], required_version):
-            warning = 'Your copy of %s is outdated, update %s to version %s or newer if you encounter any errors.' % (
-                self.basename, self.basename, required_version)
-            self.report_warning(warning)
+        if is_outdated_version(self._versions[self.basename], required_version):
+            self.report_warning(f'Your copy of {self.basename} is outdated, update {self.basename} '
+                                f'to version {required_version} or newer if you encounter any errors')
 
     @staticmethod
     def get_versions_and_features(downloader=None):
@@ -147,8 +142,8 @@ def get_ffmpeg_version(path, prog):
                 if basename in ('ffmpeg', 'ffprobe'):
                     prefer_ffmpeg = True
 
-            self._paths = dict(
-                (p, os.path.join(dirname, p)) for p in programs)
+            self._paths = {
+                p: os.path.join(dirname, p) for p in programs}
             if basename:
                 self._paths[basename] = location
 
@@ -211,13 +206,13 @@ def get_audio_codec(self, path):
                     encodeFilename(self.executable, True),
                     encodeArgument('-i')]
             cmd.append(encodeFilename(self._ffmpeg_filename_argument(path), True))
-            self.write_debug('%s command line: %s' % (self.basename, shell_quote(cmd)))
+            self.write_debug(f'{self.basename} command line: {shell_quote(cmd)}')
             handle = Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
             stdout_data, stderr_data = handle.communicate_or_kill()
             expected_ret = 0 if self.probe_available else 1
             if handle.wait() != expected_ret:
                 return None
-        except (IOError, OSError):
+        except OSError:
             return None
         output = (stdout_data if self.probe_available else stderr_data).decode('ascii', 'ignore')
         if self.probe_available:
@@ -539,7 +534,7 @@ class FFmpegVideoConvertorPP(FFmpegPostProcessor):
     _ACTION = 'converting'
 
     def __init__(self, downloader=None, preferedformat=None):
-        super(FFmpegVideoConvertorPP, self).__init__(downloader)
+        super().__init__(downloader)
         self._preferedformats = preferedformat.lower().split('/')
 
     def _target_ext(self, source_ext):
@@ -585,7 +580,7 @@ def _options(target_ext):
 
 class FFmpegEmbedSubtitlePP(FFmpegPostProcessor):
     def __init__(self, downloader=None, already_have_subtitle=False):
-        super(FFmpegEmbedSubtitlePP, self).__init__(downloader)
+        super().__init__(downloader)
         self._already_have_subtitle = already_have_subtitle
 
     @PostProcessor._restrict_to(images=False)
@@ -713,7 +708,7 @@ def run(self, info):
 
     @staticmethod
     def _get_chapter_opts(chapters, metadata_filename):
-        with io.open(metadata_filename, 'wt', encoding='utf-8') as f:
+        with open(metadata_filename, 'wt', encoding='utf-8') as f:
             def ffmpeg_escape(text):
                 return re.sub(r'([\\=;#\n])', r'\\\1', text)
 
@@ -899,7 +894,7 @@ class FFmpegFixupTimestampPP(FFmpegFixupPostProcessor):
 
     def __init__(self, downloader=None, trim=0.001):
         # "trim" should be used when the video contains unintended packets
-        super(FFmpegFixupTimestampPP, self).__init__(downloader)
+        super().__init__(downloader)
         assert isinstance(trim, (int, float))
         self.trim = str(trim)
 
@@ -937,7 +932,7 @@ class FFmpegSubtitlesConvertorPP(FFmpegPostProcessor):
     SUPPORTED_EXTS = ('srt', 'vtt', 'ass', 'lrc')
 
     def __init__(self, downloader=None, format=None):
-        super(FFmpegSubtitlesConvertorPP, self).__init__(downloader)
+        super().__init__(downloader)
         self.format = format
 
     def run(self, info):
@@ -979,7 +974,7 @@ def run(self, info):
                 with open(dfxp_file, 'rb') as f:
                     srt_data = dfxp2srt(f.read())
 
-                with io.open(srt_file, 'wt', encoding='utf-8') as f:
+                with open(srt_file, 'wt', encoding='utf-8') as f:
                     f.write(srt_data)
                 old_file = srt_file
 
@@ -996,7 +991,7 @@ def run(self, info):
 
             self.run_ffmpeg(old_file, new_file, ['-f', new_format])
 
-            with io.open(new_file, 'rt', encoding='utf-8') as f:
+            with open(new_file, encoding='utf-8') as f:
                 subs[lang] = {
                     'ext': new_ext,
                     'data': f.read(),
@@ -1059,7 +1054,7 @@ class FFmpegThumbnailsConvertorPP(FFmpegPostProcessor):
     SUPPORTED_EXTS = ('jpg', 'png', 'webp')
 
     def __init__(self, downloader=None, format=None):
-        super(FFmpegThumbnailsConvertorPP, self).__init__(downloader)
+        super().__init__(downloader)
         self.format = format
 
     @staticmethod
@@ -1090,7 +1085,7 @@ def _options(target_ext):
     def convert_thumbnail(self, thumbnail_filename, target_ext):
         thumbnail_conv_filename = replace_extension(thumbnail_filename, target_ext)
 
-        self.to_screen('Converting thumbnail "%s" to %s' % (thumbnail_filename, target_ext))
+        self.to_screen(f'Converting thumbnail "{thumbnail_filename}" to {target_ext}')
         self.real_run_ffmpeg(
             [(thumbnail_filename, ['-f', 'image2', '-pattern_type', 'none'])],
             [(thumbnail_conv_filename.replace('%', '%%'), self._options(target_ext))])
diff --git a/yt_dlp/postprocessor/movefilesafterdownload.py b/yt_dlp/postprocessor/movefilesafterdownload.py
index 1064a8cb8d..bc3d15ca45 100644
--- a/yt_dlp/postprocessor/movefilesafterdownload.py
+++ b/yt_dlp/postprocessor/movefilesafterdownload.py
@@ -1,4 +1,3 @@
-from __future__ import unicode_literals
 import os
 import shutil
 
@@ -47,7 +46,7 @@ def run(self, info):
                         % (oldfile, newfile))
                     continue
             make_dir(newfile, PostProcessingError)
-            self.to_screen('Moving file "%s" to "%s"' % (oldfile, newfile))
+            self.to_screen(f'Moving file "{oldfile}" to "{newfile}"')
             shutil.move(oldfile, newfile)  # os.rename cannot move between volumes
 
         info['filepath'] = finalpath
diff --git a/yt_dlp/postprocessor/sponskrub.py b/yt_dlp/postprocessor/sponskrub.py
index 59cf0e0c3e..38089de086 100644
--- a/yt_dlp/postprocessor/sponskrub.py
+++ b/yt_dlp/postprocessor/sponskrub.py
@@ -1,4 +1,3 @@
-from __future__ import unicode_literals
 import os
 import shlex
 import subprocess
diff --git a/yt_dlp/postprocessor/xattrpp.py b/yt_dlp/postprocessor/xattrpp.py
index 93acd6d133..5ad8509e7b 100644
--- a/yt_dlp/postprocessor/xattrpp.py
+++ b/yt_dlp/postprocessor/xattrpp.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from .common import PostProcessor
 from ..compat import compat_os_name
 from ..utils import (
diff --git a/yt_dlp/socks.py b/yt_dlp/socks.py
index 5d4adbe72d..ffa960e03c 100644
--- a/yt_dlp/socks.py
+++ b/yt_dlp/socks.py
@@ -1,8 +1,5 @@
 # Public Domain SOCKS proxy protocol implementation
 # Adapted from https://gist.github.com/bluec0re/cafd3764412967417fd3
-
-from __future__ import unicode_literals
-
 # References:
 # SOCKS4 protocol http://www.openssh.com/txt/socks4.protocol
 # SOCKS4A protocol http://www.openssh.com/txt/socks4a.protocol
@@ -33,7 +30,7 @@
 SOCKS5_USER_AUTH_SUCCESS = 0x00
 
 
-class Socks4Command(object):
+class Socks4Command:
     CMD_CONNECT = 0x01
     CMD_BIND = 0x02
 
@@ -42,14 +39,14 @@ class Socks5Command(Socks4Command):
     CMD_UDP_ASSOCIATE = 0x03
 
 
-class Socks5Auth(object):
+class Socks5Auth:
     AUTH_NONE = 0x00
     AUTH_GSSAPI = 0x01
     AUTH_USER_PASS = 0x02
     AUTH_NO_ACCEPTABLE = 0xFF  # For server response
 
 
-class Socks5AddressType(object):
+class Socks5AddressType:
     ATYP_IPV4 = 0x01
     ATYP_DOMAINNAME = 0x03
     ATYP_IPV6 = 0x04
@@ -61,14 +58,14 @@ class ProxyError(socket.error):
     def __init__(self, code=None, msg=None):
         if code is not None and msg is None:
             msg = self.CODES.get(code) or 'unknown error'
-        super(ProxyError, self).__init__(code, msg)
+        super().__init__(code, msg)
 
 
 class InvalidVersionError(ProxyError):
     def __init__(self, expected_version, got_version):
-        msg = ('Invalid response version from server. Expected {0:02x} got '
-               '{1:02x}'.format(expected_version, got_version))
-        super(InvalidVersionError, self).__init__(0, msg)
+        msg = ('Invalid response version from server. Expected {:02x} got '
+               '{:02x}'.format(expected_version, got_version))
+        super().__init__(0, msg)
 
 
 class Socks4Error(ProxyError):
@@ -98,7 +95,7 @@ class Socks5Error(ProxyError):
     }
 
 
-class ProxyType(object):
+class ProxyType:
     SOCKS4 = 0
     SOCKS4A = 1
     SOCKS5 = 2
@@ -111,7 +108,7 @@ class ProxyType(object):
 class sockssocket(socket.socket):
     def __init__(self, *args, **kwargs):
         self._proxy = None
-        super(sockssocket, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def setproxy(self, proxytype, addr, port, rdns=True, username=None, password=None):
         assert proxytype in (ProxyType.SOCKS4, ProxyType.SOCKS4A, ProxyType.SOCKS5)
@@ -123,13 +120,13 @@ def recvall(self, cnt):
         while len(data) < cnt:
             cur = self.recv(cnt - len(data))
             if not cur:
-                raise EOFError('{0} bytes missing'.format(cnt - len(data)))
+                raise EOFError(f'{cnt - len(data)} bytes missing')
             data += cur
         return data
 
     def _recv_bytes(self, cnt):
         data = self.recvall(cnt)
-        return compat_struct_unpack('!{0}B'.format(cnt), data)
+        return compat_struct_unpack(f'!{cnt}B', data)
 
     @staticmethod
     def _len_and_data(data):
@@ -143,7 +140,7 @@ def _check_response_version(self, expected_version, got_version):
     def _resolve_address(self, destaddr, default, use_remote_dns):
         try:
             return socket.inet_aton(destaddr)
-        except socket.error:
+        except OSError:
             if use_remote_dns and self._proxy.remote_dns:
                 return default
             else:
@@ -185,7 +182,7 @@ def _socks5_auth(self):
             auth_methods.append(Socks5Auth.AUTH_USER_PASS)
 
         packet += compat_struct_pack('!B', len(auth_methods))
-        packet += compat_struct_pack('!{0}B'.format(len(auth_methods)), *auth_methods)
+        packet += compat_struct_pack(f'!{len(auth_methods)}B', *auth_methods)
 
         self.sendall(packet)
 
diff --git a/yt_dlp/update.py b/yt_dlp/update.py
index f6ac207a1c..7db260e96f 100644
--- a/yt_dlp/update.py
+++ b/yt_dlp/update.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import hashlib
 import json
 import os
@@ -111,11 +109,11 @@ def version_tuple(version_str):
     }
 
     def get_bin_info(bin_or_exe, version):
-        label = version_labels['%s_%s' % (bin_or_exe, version)]
+        label = version_labels[f'{bin_or_exe}_{version}']
         return next((i for i in version_info['assets'] if i['name'] == 'yt-dlp%s' % label), {})
 
     def get_sha256sum(bin_or_exe, version):
-        filename = 'yt-dlp%s' % version_labels['%s_%s' % (bin_or_exe, version)]
+        filename = 'yt-dlp%s' % version_labels[f'{bin_or_exe}_{version}']
         urlh = next(
             (i for i in version_info['assets'] if i['name'] in ('SHA2-256SUMS')),
             {}).get('browser_download_url')
@@ -136,7 +134,7 @@ def get_sha256sum(bin_or_exe, version):
         try:
             if os.path.exists(filename + '.old'):
                 os.remove(filename + '.old')
-        except (IOError, OSError):
+        except OSError:
             return report_unable('remove the old version')
 
         try:
@@ -147,13 +145,13 @@ def get_sha256sum(bin_or_exe, version):
             urlh = ydl._opener.open(url)
             newcontent = urlh.read()
             urlh.close()
-        except (IOError, OSError):
+        except OSError:
             return report_network_error('download latest version')
 
         try:
             with open(filename + '.new', 'wb') as outf:
                 outf.write(newcontent)
-        except (IOError, OSError):
+        except OSError:
             return report_permission_error(f'{filename}.new')
 
         expected_sum = get_sha256sum(variant, arch)
@@ -168,11 +166,11 @@ def get_sha256sum(bin_or_exe, version):
 
         try:
             os.rename(filename, filename + '.old')
-        except (IOError, OSError):
+        except OSError:
             return report_unable('move current version')
         try:
             os.rename(filename + '.new', filename)
-        except (IOError, OSError):
+        except OSError:
             report_unable('overwrite current version')
             os.rename(filename + '.old', filename)
             return
@@ -195,7 +193,7 @@ def get_sha256sum(bin_or_exe, version):
             urlh = ydl._opener.open(url)
             newcontent = urlh.read()
             urlh.close()
-        except (IOError, OSError):
+        except OSError:
             return report_network_error('download the latest version')
 
         expected_sum = get_sha256sum(variant, pack_type)
@@ -207,7 +205,7 @@ def get_sha256sum(bin_or_exe, version):
         try:
             with open(filename, 'wb') as outf:
                 outf.write(newcontent)
-        except (IOError, OSError):
+        except OSError:
             return report_unable('overwrite current version')
 
         ydl.to_screen('Updated yt-dlp to version %s; Restart yt-dlp to use the new version' % version_id)
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 3f70b1f603..91e1a9870e 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -1,8 +1,4 @@
 #!/usr/bin/env python3
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import asyncio
 import atexit
 import base64
@@ -311,7 +307,7 @@ def write_json_file(obj, fn):
 def find_xpath_attr(node, xpath, key, val=None):
     """ Find the xpath xpath[@key=val] """
     assert re.match(r'^[a-zA-Z_-]+$', key)
-    expr = xpath + ('[@%s]' % key if val is None else "[@%s='%s']" % (key, val))
+    expr = xpath + ('[@%s]' % key if val is None else f"[@{key}='{val}']")
     return node.find(expr)
 
 # On python2.6 the xml.etree.ElementTree.Element methods don't support
@@ -374,7 +370,7 @@ def xpath_attr(node, xpath, key, name=None, fatal=False, default=NO_DEFAULT):
         if default is not NO_DEFAULT:
             return default
         elif fatal:
-            name = '%s[@%s]' % (xpath, key) if name is None else name
+            name = f'{xpath}[@{key}]' if name is None else name
             raise ExtractorError('Could not find XML attribute %s' % name)
         else:
             return None
@@ -443,15 +439,15 @@ def get_elements_text_and_html_by_attribute(attribute, value, html, escape_value
     attribute in the passed HTML document
     """
 
-    value_quote_optional = '' if re.match(r'''[\s"'`=<>]''', value) else '?'
+    quote = '' if re.match(r'''[\s"'`=<>]''', value) else '?'
 
     value = re.escape(value) if escape_value else value
 
-    partial_element_re = r'''(?x)
+    partial_element_re = rf'''(?x)
         <(?P<tag>[a-zA-Z0-9:._-]+)
          (?:\s(?:[^>"']|"[^"]*"|'[^']*')*)?
-         \s%(attribute)s\s*=\s*(?P<_q>['"]%(vqo)s)(?-x:%(value)s)(?P=_q)
-        ''' % {'attribute': re.escape(attribute), 'value': value, 'vqo': value_quote_optional}
+         \s{re.escape(attribute)}\s*=\s*(?P<_q>['"]{quote})(?-x:{value})(?P=_q)
+        '''
 
     for m in re.finditer(partial_element_re, html):
         content, whole = get_element_text_and_html_by_tag(m.group('tag'), html[m.start():])
@@ -644,7 +640,7 @@ def sanitize_open(filename, open_mode):
             except LockingUnsupportedError:
                 stream = open(filename, open_mode)
             return (stream, filename)
-        except (IOError, OSError) as err:
+        except OSError as err:
             if attempt or err.errno in (errno.EACCES,):
                 raise
             old_filename, filename = filename, sanitize_path(filename)
@@ -853,7 +849,7 @@ class Popen(subprocess.Popen):
         _startupinfo = None
 
     def __init__(self, *args, **kwargs):
-        super(Popen, self).__init__(*args, **kwargs, startupinfo=self._startupinfo)
+        super().__init__(*args, **kwargs, startupinfo=self._startupinfo)
 
     def communicate_or_kill(self, *args, **kwargs):
         return process_communicate_or_kill(self, *args, **kwargs)
@@ -1013,7 +1009,7 @@ def __init__(self, msg, tb=None, expected=False, cause=None, video_id=None, ie=N
         self.ie = ie
         self.exc_info = sys.exc_info()  # preserve original exception
 
-        super(ExtractorError, self).__init__(''.join((
+        super().__init__(''.join((
             format_field(ie, template='[%s] '),
             format_field(video_id, template='%s: '),
             msg,
@@ -1029,7 +1025,7 @@ def format_traceback(self):
 
 class UnsupportedError(ExtractorError):
     def __init__(self, url):
-        super(UnsupportedError, self).__init__(
+        super().__init__(
             'Unsupported URL: %s' % url, expected=True)
         self.url = url
 
@@ -1048,7 +1044,7 @@ class GeoRestrictedError(ExtractorError):
 
     def __init__(self, msg, countries=None, **kwargs):
         kwargs['expected'] = True
-        super(GeoRestrictedError, self).__init__(msg, **kwargs)
+        super().__init__(msg, **kwargs)
         self.countries = countries
 
 
@@ -1062,7 +1058,7 @@ class DownloadError(YoutubeDLError):
 
     def __init__(self, msg, exc_info=None):
         """ exc_info, if given, is the original exception that caused the trouble (as returned by sys.exc_info()). """
-        super(DownloadError, self).__init__(msg)
+        super().__init__(msg)
         self.exc_info = exc_info
 
 
@@ -1156,9 +1152,7 @@ class ContentTooShortError(YoutubeDLError):
     """
 
     def __init__(self, downloaded, expected):
-        super(ContentTooShortError, self).__init__(
-            'Downloaded {0} bytes, expected {1} bytes'.format(downloaded, expected)
-        )
+        super().__init__(f'Downloaded {downloaded} bytes, expected {expected} bytes')
         # Both in bytes
         self.downloaded = downloaded
         self.expected = expected
@@ -1166,7 +1160,7 @@ def __init__(self, downloaded, expected):
 
 class XAttrMetadataError(YoutubeDLError):
     def __init__(self, code=None, msg='Unknown error'):
-        super(XAttrMetadataError, self).__init__(msg)
+        super().__init__(msg)
         self.code = code
         self.msg = msg
 
@@ -1202,7 +1196,7 @@ def _create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_a
             ip_addrs = [addr for addr in addrs if addr[0] == af]
             if addrs and not ip_addrs:
                 ip_version = 'v4' if af == socket.AF_INET else 'v6'
-                raise socket.error(
+                raise OSError(
                     "No remote IP%s addresses available for connect, can't use '%s' as source address"
                     % (ip_version, source_address[0]))
             for res in ip_addrs:
@@ -1216,14 +1210,14 @@ def _create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_a
                     sock.connect(sa)
                     err = None  # Explicitly break reference cycle
                     return sock
-                except socket.error as _:
+                except OSError as _:
                     err = _
                     if sock is not None:
                         sock.close()
             if err is not None:
                 raise err
             else:
-                raise socket.error('getaddrinfo returns an empty list')
+                raise OSError('getaddrinfo returns an empty list')
         if hasattr(hc, '_create_connection'):
             hc._create_connection = _create_connection
         hc.source_address = (source_address, 0)
@@ -1235,7 +1229,7 @@ def handle_youtubedl_headers(headers):
     filtered_headers = headers
 
     if 'Youtubedl-no-compression' in filtered_headers:
-        filtered_headers = dict((k, v) for k, v in filtered_headers.items() if k.lower() != 'accept-encoding')
+        filtered_headers = {k: v for k, v in filtered_headers.items() if k.lower() != 'accept-encoding'}
         del filtered_headers['Youtubedl-no-compression']
 
     return filtered_headers
@@ -1327,14 +1321,14 @@ def http_response(self, req, resp):
             gz = gzip.GzipFile(fileobj=io.BytesIO(content), mode='rb')
             try:
                 uncompressed = io.BytesIO(gz.read())
-            except IOError as original_ioerror:
+            except OSError as original_ioerror:
                 # There may be junk add the end of the file
                 # See http://stackoverflow.com/q/4928560/35070 for details
                 for i in range(1, 1024):
                     try:
                         gz = gzip.GzipFile(fileobj=io.BytesIO(content[:-i]), mode='rb')
                         uncompressed = io.BytesIO(gz.read())
-                    except IOError:
+                    except OSError:
                         continue
                     break
                 else:
@@ -1474,7 +1468,7 @@ def save(self, filename=None, ignore_discard=False, ignore_expires=False):
             if cookie.expires is None:
                 cookie.expires = 0
 
-        with io.open(filename, 'w', encoding='utf-8') as f:
+        with open(filename, 'w', encoding='utf-8') as f:
             f.write(self._HEADER)
             now = time.time()
             for cookie in self:
@@ -1530,7 +1524,7 @@ def prepare_line(line):
             return line
 
         cf = io.StringIO()
-        with io.open(filename, encoding='utf-8') as f:
+        with open(filename, encoding='utf-8') as f:
             for line in f:
                 try:
                     cf.write(prepare_line(line))
@@ -1612,8 +1606,7 @@ def redirect_request(self, req, fp, code, msg, headers, newurl):
 
         CONTENT_HEADERS = ("content-length", "content-type")
         # NB: don't use dict comprehension for python 2.6 compatibility
-        newheaders = dict((k, v) for k, v in req.headers.items()
-                          if k.lower() not in CONTENT_HEADERS)
+        newheaders = {k: v for k, v in req.headers.items() if k.lower() not in CONTENT_HEADERS}
         return compat_urllib_request.Request(
             newurl, headers=newheaders, origin_req_host=req.origin_req_host,
             unverifiable=True)
@@ -1657,7 +1650,7 @@ def parse_iso8601(date_str, delimiter='T', timezone=None):
         timezone, date_str = extract_timezone(date_str)
 
     try:
-        date_format = '%Y-%m-%d{0}%H:%M:%S'.format(delimiter)
+        date_format = f'%Y-%m-%d{delimiter}%H:%M:%S'
         dt = datetime.datetime.strptime(date_str, date_format) - timezone
         return calendar.timegm(dt.timetuple())
     except ValueError:
@@ -1839,7 +1832,7 @@ def hyphenate_date(date_str):
         return date_str
 
 
-class DateRange(object):
+class DateRange:
     """Represents a time interval between two dates"""
 
     def __init__(self, start=None, end=None):
@@ -1867,7 +1860,7 @@ def __contains__(self, date):
         return self.start <= date <= self.end
 
     def __str__(self):
-        return '%s - %s' % (self.start.isoformat(), self.end.isoformat())
+        return f'{self.start.isoformat()} - {self.end.isoformat()}'
 
 
 def platform_name():
@@ -2012,7 +2005,7 @@ def _unlock_file(f):
             raise LockingUnsupportedError()
 
 
-class locked_file(object):
+class locked_file:
     locked = False
 
     def __init__(self, filename, mode, block=True, encoding=None):
@@ -2039,7 +2032,7 @@ def __enter__(self):
         try:
             _lock_file(self.f, exclusive, self.block)
             self.locked = True
-        except IOError:
+        except OSError:
             self.f.close()
             raise
         if 'w' in self.mode:
@@ -2510,14 +2503,14 @@ def parse_duration(s):
 def prepend_extension(filename, ext, expected_real_ext=None):
     name, real_ext = os.path.splitext(filename)
     return (
-        '{0}.{1}{2}'.format(name, ext, real_ext)
+        f'{name}.{ext}{real_ext}'
         if not expected_real_ext or real_ext[1:] == expected_real_ext
-        else '{0}.{1}'.format(filename, ext))
+        else f'{filename}.{ext}')
 
 
 def replace_extension(filename, ext, expected_real_ext=None):
     name, real_ext = os.path.splitext(filename)
-    return '{0}.{1}'.format(
+    return '{}.{}'.format(
         name if not expected_real_ext or real_ext[1:] == expected_real_ext else filename,
         ext)
 
@@ -2700,6 +2693,7 @@ def __getitem__(self, idx):
 
 class OnDemandPagedList(PagedList):
     """Download pages until a page with less than maximum results"""
+
     def _getslice(self, start, end):
         for pagenum in itertools.count(start // self._pagesize):
             firstid = pagenum * self._pagesize
@@ -2740,6 +2734,7 @@ def _getslice(self, start, end):
 
 class InAdvancePagedList(PagedList):
     """PagedList with total number of pages known in advance"""
+
     def __init__(self, pagefunc, pagecount, pagesize):
         PagedList.__init__(self, pagefunc, pagesize, True)
         self._pagecount = pagecount
@@ -2994,10 +2989,10 @@ def strip_jsonp(code):
 def js_to_json(code, vars={}):
     # vars is a dict of var, val pairs to substitute
     COMMENT_RE = r'/\*(?:(?!\*/).)*?\*/|//[^\n]*\n'
-    SKIP_RE = r'\s*(?:{comment})?\s*'.format(comment=COMMENT_RE)
+    SKIP_RE = fr'\s*(?:{COMMENT_RE})?\s*'
     INTEGER_TABLE = (
-        (r'(?s)^(0[xX][0-9a-fA-F]+){skip}:?$'.format(skip=SKIP_RE), 16),
-        (r'(?s)^(0+[0-7]+){skip}:?$'.format(skip=SKIP_RE), 8),
+        (fr'(?s)^(0[xX][0-9a-fA-F]+){SKIP_RE}:?$', 16),
+        (fr'(?s)^(0+[0-7]+){SKIP_RE}:?$', 8),
     )
 
     def fix_kv(m):
@@ -3518,7 +3513,7 @@ def dfxp2srt(dfxp_data):
     styles = {}
     default_style = {}
 
-    class TTMLPElementParser(object):
+    class TTMLPElementParser:
         _out = ''
         _unclosed_elements = []
         _applied_styles = []
@@ -3703,7 +3698,7 @@ def _configuration_args(main_key, argdict, exe, keys=None, default=[], use_compa
     return cli_configuration_args(argdict, keys, default, use_compat)
 
 
-class ISO639Utils(object):
+class ISO639Utils:
     # See http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt
     _lang_map = {
         'aa': 'aar',
@@ -3908,7 +3903,7 @@ def long2short(cls, code):
                 return short_name
 
 
-class ISO3166Utils(object):
+class ISO3166Utils:
     # From http://data.okfn.org/data/core/country-list
     _country_map = {
         'AF': 'Afghanistan',
@@ -4168,7 +4163,7 @@ def short2full(cls, code):
         return cls._country_map.get(code.upper())
 
 
-class GeoUtils(object):
+class GeoUtils:
     # Major IPv4 address blocks per country
     _country_ip_map = {
         'AD': '46.172.224.0/19',
@@ -4605,7 +4600,7 @@ def decode_png(png_data):
     header = png_data[8:]
 
     if png_data[:8] != b'\x89PNG\x0d\x0a\x1a\x0a' or header[4:8] != b'IHDR':
-        raise IOError('Not a valid PNG file.')
+        raise OSError('Not a valid PNG file.')
 
     int_map = {1: '>B', 2: '>H', 4: '>I'}
     unpack_integer = lambda x: compat_struct_unpack(int_map[len(x)], x)[0]
@@ -4642,7 +4637,7 @@ def decode_png(png_data):
             idat += chunk['data']
 
     if not idat:
-        raise IOError('Unable to read PNG data.')
+        raise OSError('Unable to read PNG data.')
 
     decompressed_data = bytearray(zlib.decompress(idat))
 
@@ -4730,7 +4725,7 @@ def write_xattr(path, key, value):
 
         try:
             setxattr(path, key, value)
-        except EnvironmentError as e:
+        except OSError as e:
             raise XAttrMetadataError(e.errno, e.strerror)
 
     except ImportError:
@@ -4744,7 +4739,7 @@ def write_xattr(path, key, value):
             try:
                 with open(ads_fn, 'wb') as f:
                     f.write(value)
-            except EnvironmentError as e:
+            except OSError as e:
                 raise XAttrMetadataError(e.errno, e.strerror)
         else:
             user_has_setfattr = check_executable('setfattr', ['--version'])
@@ -4767,7 +4762,7 @@ def write_xattr(path, key, value):
                 try:
                     p = Popen(
                         cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
-                except EnvironmentError as e:
+                except OSError as e:
                     raise XAttrMetadataError(e.errno, e.strerror)
                 stdout, stderr = p.communicate_or_kill()
                 stderr = stderr.decode('utf-8', 'replace')
@@ -4923,7 +4918,7 @@ def make_dir(path, to_screen=None):
         if dn and not os.path.exists(dn):
             os.makedirs(dn)
         return True
-    except (OSError, IOError) as err:
+    except OSError as err:
         if callable(to_screen) is not None:
             to_screen('unable to create directory ' + error_to_compat_str(err))
         return False
@@ -5155,7 +5150,7 @@ def scale_thumbnails_to_max_format_width(formats, thumbnails, url_width_re):
     """
     _keys = ('width', 'height')
     max_dimensions = max(
-        [tuple(format.get(k) or 0 for k in _keys) for format in formats],
+        (tuple(format.get(k) or 0 for k in _keys) for format in formats),
         default=(0, 0))
     if not max_dimensions[0]:
         return thumbnails
@@ -5220,7 +5215,7 @@ def __str__(self):
     def read_file(filename, default=[]):
         try:
             optionf = open(filename)
-        except IOError:
+        except OSError:
             return default  # silently skip if file is not present
         try:
             # FIXME: https://github.com/ytdl-org/youtube-dl/commit/dfe5fa49aed02cf36ba9f743b11b0903554b5e56
@@ -5232,7 +5227,7 @@ def read_file(filename, default=[]):
 
     @staticmethod
     def hide_login_info(opts):
-        PRIVATE_OPTS = set(['-p', '--password', '-u', '--username', '--video-password', '--ap-password', '--ap-username'])
+        PRIVATE_OPTS = {'-p', '--password', '-u', '--username', '--video-password', '--ap-password', '--ap-username'}
         eqre = re.compile('^(?P<key>' + ('|'.join(re.escape(po) for po in PRIVATE_OPTS)) + ')=.+$')
 
         def _scrub_eq(o):
diff --git a/yt_dlp/webvtt.py b/yt_dlp/webvtt.py
index c78078f17d..e0d7f67436 100644
--- a/yt_dlp/webvtt.py
+++ b/yt_dlp/webvtt.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals, print_function, division
-
 """
 A partial parser for WebVTT segments. Interprets enough of the WebVTT stream
 to be able to assemble a single stand-alone subtitle file, suitably adjusting
@@ -20,7 +17,7 @@
 )
 
 
-class _MatchParser(object):
+class _MatchParser:
     """
     An object that maintains the current parsing position and allows
     conveniently advancing it as syntax elements are successfully parsed.
@@ -69,7 +66,7 @@ class _MatchChildParser(_MatchParser):
     """
 
     def __init__(self, parent):
-        super(_MatchChildParser, self).__init__(parent._data)
+        super().__init__(parent._data)
         self.__parent = parent
         self._pos = parent._pos
 
@@ -83,7 +80,7 @@ def commit(self):
 
 class ParseError(Exception):
     def __init__(self, parser):
-        super(ParseError, self).__init__("Parse error at position %u (near %r)" % (
+        super().__init__("Parse error at position %u (near %r)" % (
             parser._pos, parser._data[parser._pos:parser._pos + 20]
         ))
 
@@ -126,7 +123,7 @@ def _format_ts(ts):
     return '%02u:%02u:%02u.%03u' % timetuple_from_msec(int((ts + 45) // 90))
 
 
-class Block(object):
+class Block:
     """
     An abstract WebVTT block.
     """
diff --git a/ytdlp_plugins/extractor/sample.py b/ytdlp_plugins/extractor/sample.py
index d99b7ca331..82c0af459c 100644
--- a/ytdlp_plugins/extractor/sample.py
+++ b/ytdlp_plugins/extractor/sample.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 # âš  Don't use relative imports
 from yt_dlp.extractor.common import InfoExtractor
 
diff --git a/ytdlp_plugins/postprocessor/sample.py b/ytdlp_plugins/postprocessor/sample.py
index 6ba49266e0..4563e1c116 100644
--- a/ytdlp_plugins/postprocessor/sample.py
+++ b/ytdlp_plugins/postprocessor/sample.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 # âš  Don't use relative imports
 from yt_dlp.postprocessor.common import PostProcessor
 
-- 
GitLab


From f82711587cee043cb2496fe180b5cc0e07c06eda Mon Sep 17 00:00:00 2001
From: pukkandan <pukkandan.ytdlp@gmail.com>
Date: Tue, 12 Apr 2022 04:02:57 +0530
Subject: [PATCH 6/9] [cleanup] Sort imports

Using https://github.com/PyCQA/isort

    isort -m VERTICAL_HANGING_INDENT --py 36 -l 80 --rr -n --tc .
---
 .gitignore                                    |   1 +
 devscripts/bash-completion.py                 |   2 +-
 devscripts/check-porn.py                      |   5 +-
 devscripts/fish-completion.py                 |   2 +-
 devscripts/generate_aes_testdata.py           |   6 +-
 devscripts/make_lazy_extractors.py            |   4 +-
 devscripts/make_readme.py                     |   2 +-
 devscripts/make_supportedsites.py             |   1 -
 devscripts/update-formulae.py                 |   1 -
 devscripts/update-version.py                  |   5 +-
 devscripts/zsh-completion.py                  |   2 +-
 pyinst.py                                     |  12 +-
 setup.py                                      |   6 +-
 test/helper.py                                |  13 +-
 test/test_InfoExtractor.py                    |  14 +-
 test/test_YoutubeDL.py                        |  17 +-
 test/test_YoutubeDLCookieJar.py               |   1 +
 test/test_aes.py                              |  16 +-
 test/test_age_restriction.py                  |   3 +-
 test/test_all_urls.py                         |   9 +-
 test/test_cache.py                            |   5 +-
 test/test_compat.py                           |   5 +-
 test/test_cookies.py                          |   4 +-
 test/test_download.py                         |  15 +-
 test/test_downloader_http.py                  |   4 +-
 test/test_execution.py                        |   6 +-
 test/test_http.py                             |   6 +-
 test/test_iqiyi_sdk_interpreter.py            |   2 +
 test/test_jsinterp.py                         |   1 +
 test/test_netrc.py                            |   1 +
 test/test_overwrites.py                       |   4 +-
 test/test_post_hooks.py                       |   4 +-
 test/test_postprocessors.py                   |   2 +-
 test/test_socks.py                            |  12 +-
 test/test_subtitles.py                        |  28 +--
 test/test_update.py.disabled                  |   2 +
 test/test_utils.py                            |  95 ++++----
 test/test_verbose_output.py                   |   6 +-
 test/test_write_annotations.py.disabled       |   8 +-
 test/test_youtube_lists.py                    |   6 +-
 test/test_youtube_misc.py                     |   1 +
 test/test_youtube_signature.py                |   5 +-
 yt_dlp/YoutubeDL.py                           | 124 +++++-----
 yt_dlp/__init__.py                            |  42 ++--
 yt_dlp/aes.py                                 |  12 +-
 yt_dlp/cache.py                               |   5 +-
 yt_dlp/cookies.py                             |  12 +-
 yt_dlp/downloader/__init__.py                 |  14 +-
 yt_dlp/downloader/common.py                   |  18 +-
 yt_dlp/downloader/dash.py                     |   3 +-
 yt_dlp/downloader/external.py                 |  17 +-
 yt_dlp/downloader/f4m.py                      |  11 +-
 yt_dlp/downloader/fragment.py                 |   8 +-
 yt_dlp/downloader/hls.py                      |  20 +-
 yt_dlp/downloader/http.py                     |  13 +-
 yt_dlp/downloader/ism.py                      |   7 +-
 yt_dlp/downloader/mhtml.py                    |   7 +-
 yt_dlp/downloader/rtmp.py                     |   4 +-
 yt_dlp/downloader/rtsp.py                     |   5 +-
 yt_dlp/downloader/websocket.py                |   2 +-
 yt_dlp/downloader/youtube_live_chat.py        |   7 +-
 yt_dlp/extractor/abematv.py                   |  28 +--
 yt_dlp/extractor/common.py                    |  23 +-
 yt_dlp/extractor/commonprotocols.py           |   4 +-
 yt_dlp/extractor/generic.py                   | 215 +++++++++---------
 yt_dlp/extractor/mtv.py                       |   4 +-
 yt_dlp/extractor/noz.py                       |   4 +-
 yt_dlp/extractor/openload.py                  |   8 +-
 yt_dlp/extractor/youtube.py                   |   7 +-
 yt_dlp/jsinterp.py                            |   7 +-
 yt_dlp/minicurses.py                          |   2 +-
 yt_dlp/options.py                             |  29 +--
 yt_dlp/postprocessor/__init__.py              |  15 +-
 yt_dlp/postprocessor/common.py                |   2 +-
 yt_dlp/postprocessor/embedthumbnail.py        |  13 +-
 yt_dlp/postprocessor/exec.py                  |   6 +-
 yt_dlp/postprocessor/ffmpeg.py                |  16 +-
 yt_dlp/postprocessor/modify_chapters.py       |  12 +-
 .../postprocessor/movefilesafterdownload.py   |   2 +-
 yt_dlp/postprocessor/sponskrub.py             |   6 +-
 yt_dlp/postprocessor/sponsorblock.py          |   2 +-
 yt_dlp/postprocessor/xattrpp.py               |   4 +-
 yt_dlp/socks.py                               |   6 +-
 yt_dlp/update.py                              |   3 +-
 yt_dlp/utils.py                               |  22 +-
 yt_dlp/webvtt.py                              |   8 +-
 86 files changed, 504 insertions(+), 619 deletions(-)

diff --git a/.gitignore b/.gitignore
index c815538e82..92f9029e3e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,6 +82,7 @@ updates_key.pem
 *.egg-info
 .tox
 *.class
+*.isorted
 
 # Generated
 AUTHORS
diff --git a/devscripts/bash-completion.py b/devscripts/bash-completion.py
index 23a9a5781d..73d698c39b 100755
--- a/devscripts/bash-completion.py
+++ b/devscripts/bash-completion.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 import os
-from os.path import dirname as dirn
 import sys
+from os.path import dirname as dirn
 
 sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
 import yt_dlp
diff --git a/devscripts/check-porn.py b/devscripts/check-porn.py
index 6188f68ec7..08f663e4ba 100644
--- a/devscripts/check-porn.py
+++ b/devscripts/check-porn.py
@@ -10,11 +10,12 @@
 # Allow direct execution
 import os
 import sys
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from test.helper import gettestcases
-from yt_dlp.utils import compat_urllib_parse_urlparse
-from yt_dlp.utils import compat_urllib_request
+
+from yt_dlp.utils import compat_urllib_parse_urlparse, compat_urllib_request
 
 if len(sys.argv) > 1:
     METHOD = 'LIST'
diff --git a/devscripts/fish-completion.py b/devscripts/fish-completion.py
index d958a5d6bc..c318b69e41 100755
--- a/devscripts/fish-completion.py
+++ b/devscripts/fish-completion.py
@@ -1,8 +1,8 @@
 #!/usr/bin/env python3
 import optparse
 import os
-from os.path import dirname as dirn
 import sys
+from os.path import dirname as dirn
 
 sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
 import yt_dlp
diff --git a/devscripts/generate_aes_testdata.py b/devscripts/generate_aes_testdata.py
index 308c74a204..c7d83f1a75 100644
--- a/devscripts/generate_aes_testdata.py
+++ b/devscripts/generate_aes_testdata.py
@@ -1,13 +1,13 @@
 #!/usr/bin/env python3
 import codecs
-import subprocess
-
 import os
+import subprocess
 import sys
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
-from yt_dlp.utils import intlist_to_bytes
 from yt_dlp.aes import aes_encrypt, key_expansion
+from yt_dlp.utils import intlist_to_bytes
 
 secret_msg = b'Secret message goes here'
 
diff --git a/devscripts/make_lazy_extractors.py b/devscripts/make_lazy_extractors.py
index 24e8cfa5b8..6d5f96cf0e 100644
--- a/devscripts/make_lazy_extractors.py
+++ b/devscripts/make_lazy_extractors.py
@@ -1,8 +1,8 @@
 #!/usr/bin/env python3
-from inspect import getsource
 import os
-from os.path import dirname as dirn
 import sys
+from inspect import getsource
+from os.path import dirname as dirn
 
 sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
 
diff --git a/devscripts/make_readme.py b/devscripts/make_readme.py
index 5d85bcc63a..1719ac8e43 100755
--- a/devscripts/make_readme.py
+++ b/devscripts/make_readme.py
@@ -2,8 +2,8 @@
 
 # yt-dlp --help | make_readme.py
 # This must be run in a console of correct width
-import sys
 import re
+import sys
 
 README_FILE = 'README.md'
 helptext = sys.stdin.read()
diff --git a/devscripts/make_supportedsites.py b/devscripts/make_supportedsites.py
index 26d25704ea..0a0d08f56f 100644
--- a/devscripts/make_supportedsites.py
+++ b/devscripts/make_supportedsites.py
@@ -3,7 +3,6 @@
 import os
 import sys
 
-
 # Import yt_dlp
 ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
 sys.path.insert(0, ROOT_DIR)
diff --git a/devscripts/update-formulae.py b/devscripts/update-formulae.py
index 3a0bef52e5..6424f5d9bc 100644
--- a/devscripts/update-formulae.py
+++ b/devscripts/update-formulae.py
@@ -8,7 +8,6 @@
 
 from yt_dlp.compat import compat_urllib_request
 
-
 # usage: python3 ./devscripts/update-formulae.py <path-to-formulae-rb> <version>
 # version can be either 0-aligned (yt-dlp version) or normalized (PyPl version)
 
diff --git a/devscripts/update-version.py b/devscripts/update-version.py
index 233cdaa76a..991cfb2aff 100644
--- a/devscripts/update-version.py
+++ b/devscripts/update-version.py
@@ -1,8 +1,7 @@
 #!/usr/bin/env python3
-from datetime import datetime
-import sys
 import subprocess
-
+import sys
+from datetime import datetime
 
 with open('yt_dlp/version.py') as f:
     exec(compile(f.read(), 'yt_dlp/version.py', 'exec'))
diff --git a/devscripts/zsh-completion.py b/devscripts/zsh-completion.py
index 677fe7373d..2d5ac2a45d 100755
--- a/devscripts/zsh-completion.py
+++ b/devscripts/zsh-completion.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 import os
-from os.path import dirname as dirn
 import sys
+from os.path import dirname as dirn
 
 sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
 import yt_dlp
diff --git a/pyinst.py b/pyinst.py
index 1f72bd4be5..9e8128e09d 100644
--- a/pyinst.py
+++ b/pyinst.py
@@ -2,14 +2,20 @@
 import os
 import platform
 import sys
-from PyInstaller.utils.hooks import collect_submodules
 
+from PyInstaller.utils.hooks import collect_submodules
 
 OS_NAME = platform.system()
 if OS_NAME == 'Windows':
     from PyInstaller.utils.win32.versioninfo import (
-        VarStruct, VarFileInfo, StringStruct, StringTable,
-        StringFileInfo, FixedFileInfo, VSVersionInfo, SetVersion,
+        FixedFileInfo,
+        SetVersion,
+        StringFileInfo,
+        StringStruct,
+        StringTable,
+        VarFileInfo,
+        VarStruct,
+        VSVersionInfo,
     )
 elif OS_NAME == 'Darwin':
     pass
diff --git a/setup.py b/setup.py
index 9eab7f1d7d..45f4d6b49e 100644
--- a/setup.py
+++ b/setup.py
@@ -1,13 +1,13 @@
 #!/usr/bin/env python3
 import os.path
-import warnings
 import sys
+import warnings
 
 try:
-    from setuptools import setup, Command, find_packages
+    from setuptools import Command, find_packages, setup
     setuptools_available = True
 except ImportError:
-    from distutils.core import setup, Command
+    from distutils.core import Command, setup
     setuptools_available = False
 from distutils.spawn import spawn
 
diff --git a/test/helper.py b/test/helper.py
index d940e327cf..81e53ed74c 100644
--- a/test/helper.py
+++ b/test/helper.py
@@ -3,21 +3,14 @@
 import json
 import os.path
 import re
-import types
 import ssl
 import sys
+import types
 
 import yt_dlp.extractor
 from yt_dlp import YoutubeDL
-from yt_dlp.compat import (
-    compat_os_name,
-    compat_str,
-)
-from yt_dlp.utils import (
-    preferredencoding,
-    write_string,
-)
-
+from yt_dlp.compat import compat_os_name, compat_str
+from yt_dlp.utils import preferredencoding, write_string
 
 if 'pytest' in sys.modules:
     import pytest
diff --git a/test/test_InfoExtractor.py b/test/test_InfoExtractor.py
index 4fd21bed4b..173b629201 100644
--- a/test/test_InfoExtractor.py
+++ b/test/test_InfoExtractor.py
@@ -3,15 +3,21 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
+import threading
 from test.helper import FakeYDL, expect_dict, expect_value, http_server_port
+
 from yt_dlp.compat import compat_etree_fromstring, compat_http_server
-from yt_dlp.extractor.common import InfoExtractor
 from yt_dlp.extractor import YoutubeIE, get_info_extractor
-from yt_dlp.utils import encode_data_uri, strip_jsonp, ExtractorError, RegexNotFoundError
-import threading
-
+from yt_dlp.extractor.common import InfoExtractor
+from yt_dlp.utils import (
+    ExtractorError,
+    RegexNotFoundError,
+    encode_data_uri,
+    strip_jsonp,
+)
 
 TEAPOT_RESPONSE_STATUS = 418
 TEAPOT_RESPONSE_BODY = "<h1>418 I'm a teapot</h1>"
diff --git a/test/test_YoutubeDL.py b/test/test_YoutubeDL.py
index 480c7539c8..051a203acd 100644
--- a/test/test_YoutubeDL.py
+++ b/test/test_YoutubeDL.py
@@ -3,18 +3,29 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 import copy
 import json
-
 from test.helper import FakeYDL, assertRegexpMatches
+
 from yt_dlp import YoutubeDL
-from yt_dlp.compat import compat_os_name, compat_setenv, compat_str, compat_urllib_error
+from yt_dlp.compat import (
+    compat_os_name,
+    compat_setenv,
+    compat_str,
+    compat_urllib_error,
+)
 from yt_dlp.extractor import YoutubeIE
 from yt_dlp.extractor.common import InfoExtractor
 from yt_dlp.postprocessor.common import PostProcessor
-from yt_dlp.utils import ExtractorError, int_or_none, match_filter_func, LazyList
+from yt_dlp.utils import (
+    ExtractorError,
+    LazyList,
+    int_or_none,
+    match_filter_func,
+)
 
 TEST_URL = 'http://localhost/sample.mp4'
 
diff --git a/test/test_YoutubeDLCookieJar.py b/test/test_YoutubeDLCookieJar.py
index 1e5bedcaed..13a4569b24 100644
--- a/test/test_YoutubeDLCookieJar.py
+++ b/test/test_YoutubeDLCookieJar.py
@@ -4,6 +4,7 @@
 import sys
 import tempfile
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from yt_dlp.utils import YoutubeDLCookieJar
diff --git a/test/test_aes.py b/test/test_aes.py
index 34584a04f5..1c1238c8b5 100644
--- a/test/test_aes.py
+++ b/test/test_aes.py
@@ -3,26 +3,28 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
+import base64
+
 from yt_dlp.aes import (
-    aes_decrypt,
-    aes_encrypt,
-    aes_ecb_encrypt,
-    aes_ecb_decrypt,
+    BLOCK_SIZE_BYTES,
     aes_cbc_decrypt,
     aes_cbc_decrypt_bytes,
     aes_cbc_encrypt,
     aes_ctr_decrypt,
     aes_ctr_encrypt,
+    aes_decrypt,
+    aes_decrypt_text,
+    aes_ecb_decrypt,
+    aes_ecb_encrypt,
+    aes_encrypt,
     aes_gcm_decrypt_and_verify,
     aes_gcm_decrypt_and_verify_bytes,
-    aes_decrypt_text,
-    BLOCK_SIZE_BYTES,
 )
 from yt_dlp.compat import compat_pycrypto_AES
 from yt_dlp.utils import bytes_to_intlist, intlist_to_bytes
-import base64
 
 # the encrypted data can be generate with 'devscripts/generate_aes_testdata.py'
 
diff --git a/test/test_age_restriction.py b/test/test_age_restriction.py
index 50d16a7297..e1012f69bb 100644
--- a/test/test_age_restriction.py
+++ b/test/test_age_restriction.py
@@ -3,9 +3,10 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
-from test.helper import try_rm, is_download_test
+from test.helper import is_download_test, try_rm
 
 from yt_dlp import YoutubeDL
 
diff --git a/test/test_all_urls.py b/test/test_all_urls.py
index d70da8cae5..b6019554e5 100644
--- a/test/test_all_urls.py
+++ b/test/test_all_urls.py
@@ -1,19 +1,16 @@
 #!/usr/bin/env python3
 # Allow direct execution
+import collections
 import os
 import sys
 import unittest
-import collections
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
 from test.helper import gettestcases
 
-from yt_dlp.extractor import (
-    FacebookIE,
-    gen_extractors,
-    YoutubeIE,
-)
+from yt_dlp.extractor import FacebookIE, YoutubeIE, gen_extractors
 
 
 class TestAllURLsMatching(unittest.TestCase):
diff --git a/test/test_cache.py b/test/test_cache.py
index 4e4641ebad..14e54ba204 100644
--- a/test/test_cache.py
+++ b/test/test_cache.py
@@ -1,14 +1,15 @@
 #!/usr/bin/env python3
-import shutil
-
 # Allow direct execution
 import os
+import shutil
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
 from test.helper import FakeYDL
+
 from yt_dlp.cache import Cache
 
 
diff --git a/test/test_compat.py b/test/test_compat.py
index 31524c5abb..20dab9573f 100644
--- a/test/test_compat.py
+++ b/test/test_compat.py
@@ -3,14 +3,15 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
 from yt_dlp.compat import (
-    compat_getenv,
-    compat_setenv,
     compat_etree_fromstring,
     compat_expanduser,
+    compat_getenv,
+    compat_setenv,
     compat_str,
     compat_struct_unpack,
     compat_urllib_parse_unquote,
diff --git a/test/test_cookies.py b/test/test_cookies.py
index 842ebcb99b..5bfaec3678 100644
--- a/test/test_cookies.py
+++ b/test/test_cookies.py
@@ -6,10 +6,10 @@
     LinuxChromeCookieDecryptor,
     MacChromeCookieDecryptor,
     WindowsChromeCookieDecryptor,
-    parse_safari_cookies,
-    pbkdf2_sha1,
     _get_linux_desktop_environment,
     _LinuxDesktopEnvironment,
+    parse_safari_cookies,
+    pbkdf2_sha1,
 )
 
 
diff --git a/test/test_download.py b/test/test_download.py
index 3c6b55d984..9a83bee2f5 100755
--- a/test/test_download.py
+++ b/test/test_download.py
@@ -1,8 +1,12 @@
 #!/usr/bin/env python3
 # Allow direct execution
+import hashlib
+import json
 import os
+import socket
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from test.helper import (
@@ -16,24 +20,19 @@
     try_rm,
 )
 
-
-import hashlib
-import json
-import socket
-
 import yt_dlp.YoutubeDL
 from yt_dlp.compat import (
     compat_http_client,
-    compat_urllib_error,
     compat_HTTPError,
+    compat_urllib_error,
 )
+from yt_dlp.extractor import get_info_extractor
 from yt_dlp.utils import (
     DownloadError,
     ExtractorError,
-    format_bytes,
     UnavailableVideoError,
+    format_bytes,
 )
-from yt_dlp.extractor import get_info_extractor
 
 RETRIES = 3
 
diff --git a/test/test_downloader_http.py b/test/test_downloader_http.py
index c511909c72..c33308064f 100644
--- a/test/test_downloader_http.py
+++ b/test/test_downloader_http.py
@@ -4,14 +4,16 @@
 import re
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
+import threading
 from test.helper import http_server_port, try_rm
+
 from yt_dlp import YoutubeDL
 from yt_dlp.compat import compat_http_server
 from yt_dlp.downloader.http import HttpFD
 from yt_dlp.utils import encodeFilename
-import threading
 
 TEST_DIR = os.path.dirname(os.path.abspath(__file__))
 
diff --git a/test/test_execution.py b/test/test_execution.py
index 623f081655..6a3e9944bf 100644
--- a/test/test_execution.py
+++ b/test/test_execution.py
@@ -1,9 +1,9 @@
 #!/usr/bin/env python3
-import unittest
-
-import sys
 import os
 import subprocess
+import sys
+import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from yt_dlp.utils import encodeArgument
diff --git a/test/test_http.py b/test/test_http.py
index 2106220eb2..029996ca93 100644
--- a/test/test_http.py
+++ b/test/test_http.py
@@ -3,13 +3,15 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
+import ssl
+import threading
 from test.helper import http_server_port
+
 from yt_dlp import YoutubeDL
 from yt_dlp.compat import compat_http_server, compat_urllib_request
-import ssl
-import threading
 
 TEST_DIR = os.path.dirname(os.path.abspath(__file__))
 
diff --git a/test/test_iqiyi_sdk_interpreter.py b/test/test_iqiyi_sdk_interpreter.py
index 57a7ed3a8a..4b82b71874 100644
--- a/test/test_iqiyi_sdk_interpreter.py
+++ b/test/test_iqiyi_sdk_interpreter.py
@@ -3,9 +3,11 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from test.helper import FakeYDL, is_download_test
+
 from yt_dlp.extractor import IqiyiIE
 
 
diff --git a/test/test_jsinterp.py b/test/test_jsinterp.py
index 10a465cf95..872c58c8fa 100644
--- a/test/test_jsinterp.py
+++ b/test/test_jsinterp.py
@@ -3,6 +3,7 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from yt_dlp.jsinterp import JSInterpreter
diff --git a/test/test_netrc.py b/test/test_netrc.py
index adc3a0ed1e..f7a0b33d26 100644
--- a/test/test_netrc.py
+++ b/test/test_netrc.py
@@ -1,6 +1,7 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
diff --git a/test/test_overwrites.py b/test/test_overwrites.py
index 8e0548db5b..39741b65c5 100644
--- a/test/test_overwrites.py
+++ b/test/test_overwrites.py
@@ -1,14 +1,14 @@
 #!/usr/bin/env python3
 import os
-from os.path import join
 import subprocess
 import sys
 import unittest
+from os.path import join
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from test.helper import is_download_test, try_rm
 
-
 root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 download_file = join(root_dir, 'test.webm')
 
diff --git a/test/test_post_hooks.py b/test/test_post_hooks.py
index 020203f2fa..e84a08f295 100644
--- a/test/test_post_hooks.py
+++ b/test/test_post_hooks.py
@@ -2,9 +2,11 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
-from test.helper import get_params, try_rm, is_download_test
+from test.helper import get_params, is_download_test, try_rm
+
 import yt_dlp.YoutubeDL
 from yt_dlp.utils import DownloadError
 
diff --git a/test/test_postprocessors.py b/test/test_postprocessors.py
index e5893f7d2e..9d8a4dcc50 100644
--- a/test/test_postprocessors.py
+++ b/test/test_postprocessors.py
@@ -13,7 +13,7 @@
     FFmpegThumbnailsConvertorPP,
     MetadataFromFieldPP,
     MetadataParserPP,
-    ModifyChaptersPP
+    ModifyChaptersPP,
 )
 
 
diff --git a/test/test_socks.py b/test/test_socks.py
index 02723b4698..546f0d73dc 100644
--- a/test/test_socks.py
+++ b/test/test_socks.py
@@ -3,20 +3,14 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 import random
 import subprocess
+from test.helper import FakeYDL, get_params, is_download_test
 
-from test.helper import (
-    FakeYDL,
-    get_params,
-    is_download_test,
-)
-from yt_dlp.compat import (
-    compat_str,
-    compat_urllib_request,
-)
+from yt_dlp.compat import compat_str, compat_urllib_request
 
 
 @is_download_test
diff --git a/test/test_subtitles.py b/test/test_subtitles.py
index 0be1842da9..362b67ceff 100644
--- a/test/test_subtitles.py
+++ b/test/test_subtitles.py
@@ -3,29 +3,29 @@
 import os
 import sys
 import unittest
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
-from test.helper import FakeYDL, md5, is_download_test
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
+from test.helper import FakeYDL, is_download_test, md5
 
 from yt_dlp.extractor import (
-    YoutubeIE,
-    DailymotionIE,
-    TedTalkIE,
-    VimeoIE,
-    WallaIE,
-    CeskaTelevizeIE,
-    LyndaIE,
     NPOIE,
+    NRKTVIE,
     PBSIE,
+    CeskaTelevizeIE,
     ComedyCentralIE,
-    NRKTVIE,
+    DailymotionIE,
+    DemocracynowIE,
+    LyndaIE,
     RaiPlayIE,
-    VikiIE,
-    ThePlatformIE,
-    ThePlatformFeedIE,
     RTVEALaCartaIE,
-    DemocracynowIE,
+    TedTalkIE,
+    ThePlatformFeedIE,
+    ThePlatformIE,
+    VikiIE,
+    VimeoIE,
+    WallaIE,
+    YoutubeIE,
 )
 
 
diff --git a/test/test_update.py.disabled b/test/test_update.py.disabled
index 5f0794ae27..389b8ffe5f 100644
--- a/test/test_update.py.disabled
+++ b/test/test_update.py.disabled
@@ -3,10 +3,12 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
 import json
+
 from yt_dlp.update import rsa_verify
 
 
diff --git a/test/test_utils.py b/test/test_utils.py
index e0c862807e..7909dc61c0 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -3,6 +3,7 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
@@ -12,75 +13,95 @@
 import json
 import xml.etree.ElementTree
 
+from yt_dlp.compat import (
+    compat_chr,
+    compat_etree_fromstring,
+    compat_getenv,
+    compat_HTMLParseError,
+    compat_os_name,
+    compat_setenv,
+)
 from yt_dlp.utils import (
+    Config,
+    DateRange,
+    ExtractorError,
+    InAdvancePagedList,
+    LazyList,
+    OnDemandPagedList,
     age_restricted,
     args_to_str,
-    encode_base_n,
+    base_url,
     caesar,
     clean_html,
     clean_podcast_url,
-    Config,
+    cli_bool_option,
+    cli_option,
+    cli_valueless_option,
     date_from_str,
     datetime_from_str,
-    DateRange,
     detect_exe_version,
     determine_ext,
+    dfxp2srt,
     dict_get,
+    encode_base_n,
     encode_compat_str,
     encodeFilename,
     escape_rfc3986,
     escape_url,
+    expand_path,
     extract_attributes,
-    ExtractorError,
     find_xpath_attr,
     fix_xml_ampersands,
-    format_bytes,
     float_or_none,
-    get_element_by_class,
+    format_bytes,
     get_element_by_attribute,
-    get_elements_by_class,
-    get_elements_by_attribute,
-    get_element_html_by_class,
+    get_element_by_class,
     get_element_html_by_attribute,
-    get_elements_html_by_class,
+    get_element_html_by_class,
+    get_element_text_and_html_by_tag,
+    get_elements_by_attribute,
+    get_elements_by_class,
     get_elements_html_by_attribute,
+    get_elements_html_by_class,
     get_elements_text_and_html_by_attribute,
-    get_element_text_and_html_by_tag,
-    InAdvancePagedList,
     int_or_none,
     intlist_to_bytes,
+    iri_to_uri,
     is_html,
     js_to_json,
     limit_length,
     locked_file,
+    lowercase_escape,
+    match_str,
     merge_dicts,
     mimetype2ext,
     month_by_name,
     multipart_encode,
     ohdave_rsa_encrypt,
-    OnDemandPagedList,
     orderedSet,
     parse_age_limit,
+    parse_bitrate,
+    parse_codecs,
+    parse_count,
+    parse_dfxp_time_expr,
     parse_duration,
     parse_filesize,
-    parse_count,
     parse_iso8601,
-    parse_resolution,
-    parse_bitrate,
     parse_qs,
+    parse_resolution,
     pkcs1pad,
+    prepend_extension,
     read_batch_urls,
+    remove_end,
+    remove_quotes,
+    remove_start,
+    render_table,
+    replace_extension,
+    rot47,
     sanitize_filename,
     sanitize_path,
     sanitize_url,
     sanitized_Request,
-    expand_path,
-    prepend_extension,
-    replace_extension,
-    remove_start,
-    remove_end,
-    remove_quotes,
-    rot47,
     shell_quote,
     smuggle_url,
     str_to_int,
@@ -92,38 +113,18 @@
     unified_strdate,
     unified_timestamp,
     unsmuggle_url,
+    update_url_query,
     uppercase_escape,
-    lowercase_escape,
     url_basename,
     url_or_none,
-    base_url,
-    urljoin,
     urlencode_postdata,
+    urljoin,
     urshift,
-    update_url_query,
     version_tuple,
-    xpath_with_ns,
+    xpath_attr,
     xpath_element,
     xpath_text,
-    xpath_attr,
-    render_table,
-    match_str,
-    parse_dfxp_time_expr,
-    dfxp2srt,
-    cli_option,
-    cli_valueless_option,
-    cli_bool_option,
-    parse_codecs,
-    iri_to_uri,
-    LazyList,
-)
-from yt_dlp.compat import (
-    compat_chr,
-    compat_etree_fromstring,
-    compat_getenv,
-    compat_HTMLParseError,
-    compat_os_name,
-    compat_setenv,
+    xpath_with_ns,
 )
 
 
diff --git a/test/test_verbose_output.py b/test/test_verbose_output.py
index 17aeafbc06..1213a97266 100644
--- a/test/test_verbose_output.py
+++ b/test/test_verbose_output.py
@@ -1,9 +1,9 @@
 #!/usr/bin/env python3
-import unittest
-
-import sys
 import os
 import subprocess
+import sys
+import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 rootDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
diff --git a/test/test_write_annotations.py.disabled b/test/test_write_annotations.py.disabled
index 4173fd09d1..bf13efe2c3 100644
--- a/test/test_write_annotations.py.disabled
+++ b/test/test_write_annotations.py.disabled
@@ -3,17 +3,15 @@
 import os
 import sys
 import unittest
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-
-from test.helper import get_params, try_rm, is_download_test
 
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 import io
-
 import xml.etree.ElementTree
+from test.helper import get_params, is_download_test, try_rm
 
-import yt_dlp.YoutubeDL
 import yt_dlp.extractor
+import yt_dlp.YoutubeDL
 
 
 class YoutubeDL(yt_dlp.YoutubeDL):
diff --git a/test/test_youtube_lists.py b/test/test_youtube_lists.py
index 8691abb67a..66611e236e 100644
--- a/test/test_youtube_lists.py
+++ b/test/test_youtube_lists.py
@@ -3,14 +3,12 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from test.helper import FakeYDL, is_download_test
 
-from yt_dlp.extractor import (
-    YoutubeIE,
-    YoutubeTabIE,
-)
+from yt_dlp.extractor import YoutubeIE, YoutubeTabIE
 
 
 @is_download_test
diff --git a/test/test_youtube_misc.py b/test/test_youtube_misc.py
index 70d6d99491..36f8be6890 100644
--- a/test/test_youtube_misc.py
+++ b/test/test_youtube_misc.py
@@ -3,6 +3,7 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
diff --git a/test/test_youtube_signature.py b/test/test_youtube_signature.py
index d751d53961..ca23c910d5 100644
--- a/test/test_youtube_signature.py
+++ b/test/test_youtube_signature.py
@@ -3,16 +3,17 @@
 import os
 import sys
 import unittest
+
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 import re
 import string
 import urllib.request
-
 from test.helper import FakeYDL, is_download_test
+
+from yt_dlp.compat import compat_str
 from yt_dlp.extractor import YoutubeIE
 from yt_dlp.jsinterp import JSInterpreter
-from yt_dlp.compat import compat_str
 
 _SIG_TESTS = [
     (
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py
index 56f0346dcc..a8bb7f45c3 100644
--- a/yt_dlp/YoutubeDL.py
+++ b/yt_dlp/YoutubeDL.py
@@ -12,6 +12,7 @@
 import operator
 import os
 import platform
+import random
 import re
 import shutil
 import subprocess
@@ -20,13 +21,12 @@
 import time
 import tokenize
 import traceback
-import random
 import unicodedata
 import urllib.request
-
 from enum import Enum
 from string import ascii_letters
 
+from .cache import Cache
 from .compat import (
     compat_brotli,
     compat_get_terminal_size,
@@ -39,74 +39,100 @@
     windows_enable_vt_mode,
 )
 from .cookies import load_cookies
+from .downloader import FFmpegFD, get_suitable_downloader, shorten_protocol_name
+from .downloader.rtmp import rtmpdump_version
+from .extractor import _LAZY_LOADER
+from .extractor import _PLUGIN_CLASSES as plugin_extractors
+from .extractor import gen_extractor_classes, get_info_extractor
+from .extractor.openload import PhantomJSwrapper
+from .minicurses import format_text
+from .postprocessor import _PLUGIN_CLASSES as plugin_postprocessors
+from .postprocessor import (
+    EmbedThumbnailPP,
+    FFmpegFixupDuplicateMoovPP,
+    FFmpegFixupDurationPP,
+    FFmpegFixupM3u8PP,
+    FFmpegFixupM4aPP,
+    FFmpegFixupStretchedPP,
+    FFmpegFixupTimestampPP,
+    FFmpegMergerPP,
+    FFmpegPostProcessor,
+    MoveFilesAfterDownloadPP,
+    get_postprocessor,
+)
+from .update import detect_variant
 from .utils import (
+    DEFAULT_OUTTMPL,
+    LINK_TEMPLATES,
+    NO_DEFAULT,
+    OUTTMPL_TYPES,
+    POSTPROCESS_WHEN,
+    STR_FORMAT_RE_TMPL,
+    STR_FORMAT_TYPES,
+    ContentTooShortError,
+    DateRange,
+    DownloadCancelled,
+    DownloadError,
+    EntryNotInPlaylist,
+    ExistingVideoReached,
+    ExtractorError,
+    GeoRestrictedError,
+    HEADRequest,
+    InAdvancePagedList,
+    ISO3166Utils,
+    LazyList,
+    MaxDownloadsReached,
+    PagedList,
+    PerRequestProxyHandler,
+    Popen,
+    PostProcessingError,
+    ReExtractInfo,
+    RejectedVideoReached,
+    SameFileError,
+    UnavailableVideoError,
+    YoutubeDLCookieProcessor,
+    YoutubeDLHandler,
+    YoutubeDLRedirectHandler,
     age_restricted,
     args_to_str,
-    ContentTooShortError,
     date_from_str,
-    DateRange,
-    DEFAULT_OUTTMPL,
     determine_ext,
     determine_protocol,
-    DownloadCancelled,
-    DownloadError,
     encode_compat_str,
     encodeFilename,
-    EntryNotInPlaylist,
     error_to_compat_str,
-    ExistingVideoReached,
     expand_path,
-    ExtractorError,
     filter_dict,
     float_or_none,
     format_bytes,
-    format_field,
     format_decimal_suffix,
+    format_field,
     formatSeconds,
-    GeoRestrictedError,
     get_domain,
     has_certifi,
-    HEADRequest,
-    InAdvancePagedList,
     int_or_none,
     iri_to_uri,
-    ISO3166Utils,
     join_nonempty,
-    LazyList,
-    LINK_TEMPLATES,
     locked_file,
     make_dir,
     make_HTTPS_handler,
-    MaxDownloadsReached,
     merge_headers,
     network_exceptions,
-    NO_DEFAULT,
     number_of_digits,
     orderedSet,
-    OUTTMPL_TYPES,
-    PagedList,
     parse_filesize,
-    PerRequestProxyHandler,
     platform_name,
-    Popen,
-    POSTPROCESS_WHEN,
-    PostProcessingError,
     preferredencoding,
     prepend_extension,
-    ReExtractInfo,
     register_socks_protocols,
-    RejectedVideoReached,
     remove_terminal_sequences,
     render_table,
     replace_extension,
-    SameFileError,
     sanitize_filename,
     sanitize_path,
     sanitize_url,
     sanitized_Request,
     std_headers,
-    STR_FORMAT_RE_TMPL,
-    STR_FORMAT_TYPES,
     str_or_none,
     strftime_or_none,
     subtitles_filename,
@@ -115,47 +141,13 @@
     to_high_limit_path,
     traverse_obj,
     try_get,
-    UnavailableVideoError,
     url_basename,
     variadic,
     version_tuple,
     write_json_file,
     write_string,
-    YoutubeDLCookieProcessor,
-    YoutubeDLHandler,
-    YoutubeDLRedirectHandler,
-)
-from .cache import Cache
-from .minicurses import format_text
-from .extractor import (
-    gen_extractor_classes,
-    get_info_extractor,
-    _LAZY_LOADER,
-    _PLUGIN_CLASSES as plugin_extractors
-)
-from .extractor.openload import PhantomJSwrapper
-from .downloader import (
-    FFmpegFD,
-    get_suitable_downloader,
-    shorten_protocol_name
-)
-from .downloader.rtmp import rtmpdump_version
-from .postprocessor import (
-    get_postprocessor,
-    EmbedThumbnailPP,
-    FFmpegFixupDuplicateMoovPP,
-    FFmpegFixupDurationPP,
-    FFmpegFixupM3u8PP,
-    FFmpegFixupM4aPP,
-    FFmpegFixupStretchedPP,
-    FFmpegFixupTimestampPP,
-    FFmpegMergerPP,
-    FFmpegPostProcessor,
-    MoveFilesAfterDownloadPP,
-    _PLUGIN_CLASSES as plugin_postprocessors
 )
-from .update import detect_variant
-from .version import __version__, RELEASE_GIT_HEAD
+from .version import RELEASE_GIT_HEAD, __version__
 
 if compat_os_name == 'nt':
     import ctypes
@@ -3666,9 +3658,9 @@ def python_implementation():
         ) or 'none'
         write_debug('exe versions: %s' % exe_str)
 
+        from .cookies import SECRETSTORAGE_AVAILABLE, SQLITE_AVAILABLE
         from .downloader.websocket import has_websockets
         from .postprocessor.embedthumbnail import has_mutagen
-        from .cookies import SQLITE_AVAILABLE, SECRETSTORAGE_AVAILABLE
 
         lib_str = join_nonempty(
             compat_brotli and compat_brotli.__name__,
diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py
index 91bf5c4cea..f339e4cd1c 100644
--- a/yt_dlp/__init__.py
+++ b/yt_dlp/__init__.py
@@ -9,48 +9,44 @@
 import re
 import sys
 
+from .compat import compat_getpass, compat_os_name, compat_shlex_quote
+from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
+from .downloader import FileDownloader
+from .extractor import gen_extractors, list_extractors
+from .extractor.adobepass import MSO_INFO
+from .extractor.common import InfoExtractor
 from .options import parseOpts
-from .compat import (
-    compat_getpass,
-    compat_os_name,
-    compat_shlex_quote,
+from .postprocessor import (
+    FFmpegExtractAudioPP,
+    FFmpegSubtitlesConvertorPP,
+    FFmpegThumbnailsConvertorPP,
+    FFmpegVideoConvertorPP,
+    FFmpegVideoRemuxerPP,
+    MetadataFromFieldPP,
+    MetadataParserPP,
 )
-from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
+from .update import run_update
 from .utils import (
+    NO_DEFAULT,
     DateRange,
-    decodeOption,
     DownloadCancelled,
     DownloadError,
+    GeoUtils,
+    SameFileError,
+    decodeOption,
     expand_path,
     float_or_none,
-    GeoUtils,
     int_or_none,
     match_filter_func,
-    NO_DEFAULT,
     parse_duration,
     preferredencoding,
     read_batch_urls,
     render_table,
-    SameFileError,
     setproctitle,
     std_headers,
     traverse_obj,
     write_string,
 )
-from .update import run_update
-from .downloader import FileDownloader
-from .extractor import gen_extractors, list_extractors
-from .extractor.common import InfoExtractor
-from .extractor.adobepass import MSO_INFO
-from .postprocessor import (
-    FFmpegExtractAudioPP,
-    FFmpegSubtitlesConvertorPP,
-    FFmpegThumbnailsConvertorPP,
-    FFmpegVideoConvertorPP,
-    FFmpegVideoRemuxerPP,
-    MetadataFromFieldPP,
-    MetadataParserPP,
-)
 from .YoutubeDL import YoutubeDL
 
 
diff --git a/yt_dlp/aes.py b/yt_dlp/aes.py
index e5d73f7406..01818df61c 100644
--- a/yt_dlp/aes.py
+++ b/yt_dlp/aes.py
@@ -1,15 +1,7 @@
 from math import ceil
 
-from .compat import (
-    compat_b64decode,
-    compat_ord,
-    compat_pycrypto_AES,
-)
-from .utils import (
-    bytes_to_intlist,
-    intlist_to_bytes,
-)
-
+from .compat import compat_b64decode, compat_ord, compat_pycrypto_AES
+from .utils import bytes_to_intlist, intlist_to_bytes
 
 if compat_pycrypto_AES:
     def aes_cbc_decrypt_bytes(data, key, iv):
diff --git a/yt_dlp/cache.py b/yt_dlp/cache.py
index f93ef85e72..0cac3ee888 100644
--- a/yt_dlp/cache.py
+++ b/yt_dlp/cache.py
@@ -6,10 +6,7 @@
 import traceback
 
 from .compat import compat_getenv
-from .utils import (
-    expand_path,
-    write_json_file,
-)
+from .utils import expand_path, write_json_file
 
 
 class Cache:
diff --git a/yt_dlp/cookies.py b/yt_dlp/cookies.py
index 1d92fd8ce9..6ff9f6f2d2 100644
--- a/yt_dlp/cookies.py
+++ b/yt_dlp/cookies.py
@@ -16,17 +16,9 @@
     aes_gcm_decrypt_and_verify_bytes,
     unpad_pkcs7,
 )
-from .compat import (
-    compat_b64decode,
-    compat_cookiejar_Cookie,
-)
+from .compat import compat_b64decode, compat_cookiejar_Cookie
 from .minicurses import MultilinePrinter, QuietMultilinePrinter
-from .utils import (
-    error_to_str,
-    expand_path,
-    Popen,
-    YoutubeDLCookieJar,
-)
+from .utils import Popen, YoutubeDLCookieJar, error_to_str, expand_path
 
 try:
     import sqlite3
diff --git a/yt_dlp/downloader/__init__.py b/yt_dlp/downloader/__init__.py
index f5abfd5df7..5aba303dd5 100644
--- a/yt_dlp/downloader/__init__.py
+++ b/yt_dlp/downloader/__init__.py
@@ -1,8 +1,5 @@
 from ..compat import compat_str
-from ..utils import (
-    determine_protocol,
-    NO_DEFAULT
-)
+from ..utils import NO_DEFAULT, determine_protocol
 
 
 def get_suitable_downloader(info_dict, params={}, default=NO_DEFAULT, protocol=None, to_stdout=False):
@@ -27,21 +24,18 @@ def get_suitable_downloader(info_dict, params={}, default=NO_DEFAULT, protocol=N
 # Some of these require get_suitable_downloader
 from .common import FileDownloader
 from .dash import DashSegmentsFD
+from .external import FFmpegFD, get_external_downloader
 from .f4m import F4mFD
 from .fc2 import FC2LiveFD
 from .hls import HlsFD
 from .http import HttpFD
-from .rtmp import RtmpFD
-from .rtsp import RtspFD
 from .ism import IsmFD
 from .mhtml import MhtmlFD
 from .niconico import NiconicoDmcFD
+from .rtmp import RtmpFD
+from .rtsp import RtspFD
 from .websocket import WebSocketFragmentFD
 from .youtube_live_chat import YoutubeLiveChatFD
-from .external import (
-    get_external_downloader,
-    FFmpegFD,
-)
 
 PROTOCOL_MAP = {
     'rtmp': RtmpFD,
diff --git a/yt_dlp/downloader/common.py b/yt_dlp/downloader/common.py
index d42539931a..3033926ae1 100644
--- a/yt_dlp/downloader/common.py
+++ b/yt_dlp/downloader/common.py
@@ -1,26 +1,26 @@
+import errno
 import os
+import random
 import re
 import time
-import random
-import errno
 
+from ..minicurses import (
+    BreaklineStatusPrinter,
+    MultilineLogger,
+    MultilinePrinter,
+    QuietMultilinePrinter,
+)
 from ..utils import (
+    LockingUnsupportedError,
     decodeArgument,
     encodeFilename,
     error_to_compat_str,
     format_bytes,
-    LockingUnsupportedError,
     sanitize_open,
     shell_quote,
     timeconvert,
     timetuple_from_msec,
 )
-from ..minicurses import (
-    MultilineLogger,
-    MultilinePrinter,
-    QuietMultilinePrinter,
-    BreaklineStatusPrinter
-)
 
 
 class FileDownloader:
diff --git a/yt_dlp/downloader/dash.py b/yt_dlp/downloader/dash.py
index 64eb5e66af..e6efae4852 100644
--- a/yt_dlp/downloader/dash.py
+++ b/yt_dlp/downloader/dash.py
@@ -1,8 +1,7 @@
 import time
 
-from ..downloader import get_suitable_downloader
 from .fragment import FragmentFD
-
+from ..downloader import get_suitable_downloader
 from ..utils import urljoin
 
 
diff --git a/yt_dlp/downloader/external.py b/yt_dlp/downloader/external.py
index b6dd327018..6c5616c602 100644
--- a/yt_dlp/downloader/external.py
+++ b/yt_dlp/downloader/external.py
@@ -5,23 +5,20 @@
 import time
 
 from .fragment import FragmentFD
-from ..compat import (
-    compat_setenv,
-    compat_str,
-)
-from ..postprocessor.ffmpeg import FFmpegPostProcessor, EXT_TO_OUT_FORMATS
+from ..compat import compat_setenv, compat_str
+from ..postprocessor.ffmpeg import EXT_TO_OUT_FORMATS, FFmpegPostProcessor
 from ..utils import (
+    Popen,
+    _configuration_args,
+    check_executable,
     classproperty,
+    cli_bool_option,
     cli_option,
     cli_valueless_option,
-    cli_bool_option,
-    _configuration_args,
     determine_ext,
-    encodeFilename,
     encodeArgument,
+    encodeFilename,
     handle_youtubedl_headers,
-    check_executable,
-    Popen,
     remove_end,
 )
 
diff --git a/yt_dlp/downloader/f4m.py b/yt_dlp/downloader/f4m.py
index 4140710751..12ecec0082 100644
--- a/yt_dlp/downloader/f4m.py
+++ b/yt_dlp/downloader/f4m.py
@@ -6,16 +6,13 @@
 from ..compat import (
     compat_b64decode,
     compat_etree_fromstring,
-    compat_urlparse,
-    compat_urllib_error,
-    compat_urllib_parse_urlparse,
     compat_struct_pack,
     compat_struct_unpack,
+    compat_urllib_error,
+    compat_urllib_parse_urlparse,
+    compat_urlparse,
 )
-from ..utils import (
-    fix_xml_ampersands,
-    xpath_text,
-)
+from ..utils import fix_xml_ampersands, xpath_text
 
 
 class DataTruncatedError(Exception):
diff --git a/yt_dlp/downloader/fragment.py b/yt_dlp/downloader/fragment.py
index 217b89e3fe..a2a2fe950c 100644
--- a/yt_dlp/downloader/fragment.py
+++ b/yt_dlp/downloader/fragment.py
@@ -13,15 +13,11 @@
 from .common import FileDownloader
 from .http import HttpFD
 from ..aes import aes_cbc_decrypt_bytes, unpad_pkcs7
-from ..compat import (
-    compat_os_name,
-    compat_urllib_error,
-    compat_struct_pack,
-)
+from ..compat import compat_os_name, compat_struct_pack, compat_urllib_error
 from ..utils import (
     DownloadError,
-    error_to_compat_str,
     encodeFilename,
+    error_to_compat_str,
     sanitized_Request,
     traverse_obj,
 )
diff --git a/yt_dlp/downloader/hls.py b/yt_dlp/downloader/hls.py
index 00695f93fc..2d65f48ae6 100644
--- a/yt_dlp/downloader/hls.py
+++ b/yt_dlp/downloader/hls.py
@@ -1,21 +1,13 @@
-import re
-import io
 import binascii
+import io
+import re
 
-from ..downloader import get_suitable_downloader
-from .fragment import FragmentFD
 from .external import FFmpegFD
-
-from ..compat import (
-    compat_pycrypto_AES,
-    compat_urlparse,
-)
-from ..utils import (
-    parse_m3u8_attributes,
-    update_url_query,
-    bug_reports_message,
-)
+from .fragment import FragmentFD
 from .. import webvtt
+from ..compat import compat_pycrypto_AES, compat_urlparse
+from ..downloader import get_suitable_downloader
+from ..utils import bug_reports_message, parse_m3u8_attributes, update_url_query
 
 
 class HlsFD(FragmentFD):
diff --git a/yt_dlp/downloader/http.py b/yt_dlp/downloader/http.py
index 03efbf1cdb..d590dbfbd7 100644
--- a/yt_dlp/downloader/http.py
+++ b/yt_dlp/downloader/http.py
@@ -1,24 +1,21 @@
 import os
+import random
 import ssl
 import time
-import random
 
 from .common import FileDownloader
-from ..compat import (
-    compat_urllib_error,
-    compat_http_client
-)
+from ..compat import compat_http_client, compat_urllib_error
 from ..utils import (
     ContentTooShortError,
+    ThrottledDownload,
+    XAttrMetadataError,
+    XAttrUnavailableError,
     encodeFilename,
     int_or_none,
     parse_http_range,
     sanitized_Request,
-    ThrottledDownload,
     try_call,
     write_xattr,
-    XAttrMetadataError,
-    XAttrUnavailableError,
 )
 
 RESPONSE_READ_EXCEPTIONS = (TimeoutError, ConnectionError, ssl.SSLError, compat_http_client.HTTPException)
diff --git a/yt_dlp/downloader/ism.py b/yt_dlp/downloader/ism.py
index ca4ca3a198..82ed51e889 100644
--- a/yt_dlp/downloader/ism.py
+++ b/yt_dlp/downloader/ism.py
@@ -1,13 +1,10 @@
-import time
 import binascii
 import io
 import struct
+import time
 
 from .fragment import FragmentFD
-from ..compat import (
-    compat_urllib_error,
-)
-
+from ..compat import compat_urllib_error
 
 u8 = struct.Struct('>B')
 u88 = struct.Struct('>Bx')
diff --git a/yt_dlp/downloader/mhtml.py b/yt_dlp/downloader/mhtml.py
index 5a322f1db7..7bc3ab049b 100644
--- a/yt_dlp/downloader/mhtml.py
+++ b/yt_dlp/downloader/mhtml.py
@@ -4,12 +4,7 @@
 import uuid
 
 from .fragment import FragmentFD
-from ..utils import (
-    escapeHTML,
-    formatSeconds,
-    srt_subtitles_timecode,
-    urljoin,
-)
+from ..utils import escapeHTML, formatSeconds, srt_subtitles_timecode, urljoin
 from ..version import __version__ as YT_DLP_VERSION
 
 
diff --git a/yt_dlp/downloader/rtmp.py b/yt_dlp/downloader/rtmp.py
index 12aa04cf3c..3464eeef93 100644
--- a/yt_dlp/downloader/rtmp.py
+++ b/yt_dlp/downloader/rtmp.py
@@ -6,11 +6,11 @@
 from .common import FileDownloader
 from ..compat import compat_str
 from ..utils import (
+    Popen,
     check_executable,
-    encodeFilename,
     encodeArgument,
+    encodeFilename,
     get_exe_version,
-    Popen,
 )
 
 
diff --git a/yt_dlp/downloader/rtsp.py b/yt_dlp/downloader/rtsp.py
index 26dbd9ef75..e89269fed9 100644
--- a/yt_dlp/downloader/rtsp.py
+++ b/yt_dlp/downloader/rtsp.py
@@ -2,10 +2,7 @@
 import subprocess
 
 from .common import FileDownloader
-from ..utils import (
-    check_executable,
-    encodeFilename,
-)
+from ..utils import check_executable, encodeFilename
 
 
 class RtspFD(FileDownloader):
diff --git a/yt_dlp/downloader/websocket.py b/yt_dlp/downloader/websocket.py
index daac348842..96d1138469 100644
--- a/yt_dlp/downloader/websocket.py
+++ b/yt_dlp/downloader/websocket.py
@@ -1,6 +1,6 @@
+import asyncio
 import os
 import signal
-import asyncio
 import threading
 
 try:
diff --git a/yt_dlp/downloader/youtube_live_chat.py b/yt_dlp/downloader/youtube_live_chat.py
index 36c82b03bd..7f06dfb487 100644
--- a/yt_dlp/downloader/youtube_live_chat.py
+++ b/yt_dlp/downloader/youtube_live_chat.py
@@ -3,13 +3,8 @@
 
 from .fragment import FragmentFD
 from ..compat import compat_urllib_error
-from ..utils import (
-    try_get,
-    dict_get,
-    int_or_none,
-    RegexNotFoundError,
-)
 from ..extractor.youtube import YoutubeBaseInfoExtractor as YT_BaseIE
+from ..utils import RegexNotFoundError, dict_get, int_or_none, try_get
 
 
 class YoutubeLiveChatFD(FragmentFD):
diff --git a/yt_dlp/extractor/abematv.py b/yt_dlp/extractor/abematv.py
index c7db054751..0dc8dea264 100644
--- a/yt_dlp/extractor/abematv.py
+++ b/yt_dlp/extractor/abematv.py
@@ -1,35 +1,31 @@
-import io
-import json
-import time
+import base64
+import binascii
 import hashlib
 import hmac
+import io
+import json
 import re
 import struct
+import time
 import urllib.response
 import uuid
-from base64 import urlsafe_b64encode
-from binascii import unhexlify
 
 from .common import InfoExtractor
 from ..aes import aes_ecb_decrypt
-from ..compat import (
-    compat_urllib_parse_urlparse,
-    compat_urllib_request,
-)
+from ..compat import compat_urllib_parse_urlparse, compat_urllib_request
 from ..utils import (
     ExtractorError,
+    bytes_to_intlist,
     decode_base,
     int_or_none,
+    intlist_to_bytes,
     request_to_url,
     time_seconds,
-    update_url_query,
     traverse_obj,
-    intlist_to_bytes,
-    bytes_to_intlist,
+    update_url_query,
     urljoin,
 )
 
-
 # NOTE: network handler related code is temporary thing until network stack overhaul PRs are merged (#2861/#2862)
 
 def add_opener(ydl, handler):
@@ -130,7 +126,7 @@ def _get_videokey_from_ticket(self, ticket):
         encvideokey = bytes_to_intlist(struct.pack('>QQ', res >> 64, res & 0xffffffffffffffff))
 
         h = hmac.new(
-            unhexlify(self.HKEY),
+            binascii.unhexlify(self.HKEY),
             (license_response['cid'] + self.ie._DEVICE_ID).encode('utf-8'),
             digestmod=hashlib.sha256)
         enckey = bytes_to_intlist(h.digest())
@@ -238,7 +234,7 @@ def mix_tmp(count):
 
         def mix_twist(nonce):
             nonlocal tmp
-            mix_once(urlsafe_b64encode(tmp).rstrip(b'=') + nonce)
+            mix_once(base64.urlsafe_b64encode(tmp).rstrip(b'=') + nonce)
 
         mix_once(self._SECRETKEY)
         mix_tmp(time_struct.tm_mon)
@@ -247,7 +243,7 @@ def mix_twist(nonce):
         mix_twist(ts_1hour_str)
         mix_tmp(time_struct.tm_hour % 5)
 
-        return urlsafe_b64encode(tmp).rstrip(b'=').decode('utf-8')
+        return base64.urlsafe_b64encode(tmp).rstrip(b'=').decode('utf-8')
 
     def _get_device_token(self):
         if self._USERTOKEN:
diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py
index ef22c78765..10b297708b 100644
--- a/yt_dlp/extractor/common.py
+++ b/yt_dlp/extractor/common.py
@@ -1,16 +1,16 @@
 import base64
 import collections
-import xml.etree.ElementTree
 import hashlib
 import itertools
 import json
+import math
 import netrc
 import os
 import random
 import re
 import sys
 import time
-import math
+import xml.etree.ElementTree
 
 from ..compat import (
     compat_cookiejar_Cookie,
@@ -29,11 +29,15 @@
     compat_urlparse,
 )
 from ..downloader import FileDownloader
-from ..downloader.f4m import (
-    get_base_url,
-    remove_encrypted_media,
-)
+from ..downloader.f4m import get_base_url, remove_encrypted_media
 from ..utils import (
+    JSON_LD_RE,
+    NO_DEFAULT,
+    ExtractorError,
+    GeoRestrictedError,
+    GeoUtils,
+    RegexNotFoundError,
+    UnsupportedError,
     age_restricted,
     base_url,
     bug_reports_message,
@@ -44,20 +48,15 @@
     encode_data_uri,
     error_to_compat_str,
     extract_attributes,
-    ExtractorError,
     filter_dict,
     fix_xml_ampersands,
     float_or_none,
     format_field,
-    GeoRestrictedError,
-    GeoUtils,
     int_or_none,
     join_nonempty,
     js_to_json,
-    JSON_LD_RE,
     mimetype2ext,
     network_exceptions,
-    NO_DEFAULT,
     orderedSet,
     parse_bitrate,
     parse_codecs,
@@ -65,7 +64,6 @@
     parse_iso8601,
     parse_m3u8_attributes,
     parse_resolution,
-    RegexNotFoundError,
     sanitize_filename,
     sanitized_Request,
     str_or_none,
@@ -74,7 +72,6 @@
     traverse_obj,
     try_get,
     unescapeHTML,
-    UnsupportedError,
     unified_strdate,
     unified_timestamp,
     update_Request,
diff --git a/yt_dlp/extractor/commonprotocols.py b/yt_dlp/extractor/commonprotocols.py
index 40475f7ecc..e8f19b9e03 100644
--- a/yt_dlp/extractor/commonprotocols.py
+++ b/yt_dlp/extractor/commonprotocols.py
@@ -1,7 +1,5 @@
 from .common import InfoExtractor
-from ..compat import (
-    compat_urlparse,
-)
+from ..compat import compat_urlparse
 
 
 class RtmpIE(InfoExtractor):
diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py
index f44f19a549..c708b4cee8 100644
--- a/yt_dlp/extractor/generic.py
+++ b/yt_dlp/extractor/generic.py
@@ -2,8 +2,107 @@
 import re
 import xml.etree.ElementTree
 
+from .ant1newsgr import Ant1NewsGrEmbedIE
+from .anvato import AnvatoIE
+from .apa import APAIE
+from .arcpublishing import ArcPublishingIE
+from .arkena import ArkenaIE
+from .arte import ArteTVEmbedIE
+from .bitchute import BitChuteIE
+from .blogger import BloggerIE
+from .brightcove import BrightcoveLegacyIE, BrightcoveNewIE
+from .channel9 import Channel9IE
+from .cloudflarestream import CloudflareStreamIE
 from .common import InfoExtractor
+from .commonprotocols import RtmpIE
+from .condenast import CondeNastIE
+from .dailymail import DailyMailIE
+from .dailymotion import DailymotionIE
+from .dbtv import DBTVIE
+from .digiteka import DigitekaIE
+from .drtuber import DrTuberIE
+from .eagleplatform import EaglePlatformIE
+from .ertgr import ERTWebtvEmbedIE
+from .expressen import ExpressenIE
+from .facebook import FacebookIE
+from .foxnews import FoxNewsIE
+from .gedidigital import GediDigitalIE
+from .gfycat import GfycatIE
+from .glomex import GlomexEmbedIE
+from .googledrive import GoogleDriveIE
+from .indavideo import IndavideoEmbedIE
+from .instagram import InstagramIE
+from .joj import JojIE
+from .jwplatform import JWPlatformIE
+from .kaltura import KalturaIE
+from .kinja import KinjaEmbedIE
+from .limelight import LimelightBaseIE
+from .mainstreaming import MainStreamingIE
+from .medialaan import MedialaanIE
+from .mediaset import MediasetIE
+from .mediasite import MediasiteIE
+from .megaphone import MegaphoneIE
+from .megatvcom import MegaTVComEmbedIE
+from .mofosex import MofosexEmbedIE
+from .mtv import MTVServicesEmbeddedIE
+from .myvi import MyviIE
+from .nbc import NBCSportsVPlayerIE
+from .nexx import NexxEmbedIE, NexxIE
+from .odnoklassniki import OdnoklassnikiIE
+from .onionstudios import OnionStudiosIE
+from .ooyala import OoyalaIE
+from .panopto import PanoptoBaseIE
+from .peertube import PeerTubeIE
+from .piksel import PikselIE
+from .pladform import PladformIE
+from .pornhub import PornHubIE
+from .rcs import RCSEmbedsIE
+from .redtube import RedTubeIE
+from .rumble import RumbleEmbedIE
+from .rutube import RutubeIE
+from .rutv import RUTVIE
+from .ruutu import RuutuIE
+from .senategov import SenateISVPIE
+from .simplecast import SimplecastIE
+from .soundcloud import SoundcloudEmbedIE
+from .spankwire import SpankwireIE
+from .sportbox import SportBoxIE
+from .springboardplatform import SpringboardPlatformIE
+from .svt import SVTIE
+from .teachable import TeachableIE
+from .ted import TedEmbedIE
+from .theplatform import ThePlatformIE
+from .threeqsdn import ThreeQSDNIE
+from .tnaflix import TNAFlixNetworkEmbedIE
+from .tube8 import Tube8IE
+from .tunein import TuneInBaseIE
+from .tvc import TVCIE
+from .tvopengr import TVOpenGrEmbedIE
+from .tvp import TVPEmbedIE
+from .twentymin import TwentyMinutenIE
+from .udn import UDNEmbedIE
+from .ustream import UstreamIE
+from .vbox7 import Vbox7IE
+from .vice import ViceIE
+from .videa import VideaIE
+from .videomore import VideomoreIE
+from .videopress import VideoPressIE
+from .viewlift import ViewLiftEmbedIE
+from .vimeo import VHXEmbedIE, VimeoIE
+from .viqeo import ViqeoIE
+from .vk import VKIE
+from .vshare import VShareIE
+from .vzaar import VzaarIE
+from .washingtonpost import WashingtonPostIE
+from .webcaster import WebcasterFeedIE
+from .wimtv import WimTVIE
+from .wistia import WistiaIE
+from .xfileshare import XFileShareIE
+from .xhamster import XHamsterEmbedIE
+from .yapfiles import YapFilesIE
+from .youporn import YouPornIE
 from .youtube import YoutubeIE
+from .zype import ZypeIE
 from ..compat import (
     compat_etree_fromstring,
     compat_str,
@@ -11,15 +110,16 @@
     compat_urlparse,
 )
 from ..utils import (
+    KNOWN_EXTENSIONS,
+    ExtractorError,
+    HEADRequest,
+    UnsupportedError,
     determine_ext,
     dict_get,
-    ExtractorError,
     float_or_none,
-    HEADRequest,
     int_or_none,
     is_html,
     js_to_json,
-    KNOWN_EXTENSIONS,
     merge_dicts,
     mimetype2ext,
     orderedSet,
@@ -31,120 +131,11 @@
     unescapeHTML,
     unified_timestamp,
     unsmuggle_url,
-    UnsupportedError,
     url_or_none,
     xpath_attr,
     xpath_text,
     xpath_with_ns,
 )
-from .commonprotocols import RtmpIE
-from .brightcove import (
-    BrightcoveLegacyIE,
-    BrightcoveNewIE,
-)
-from .nexx import (
-    NexxIE,
-    NexxEmbedIE,
-)
-from .nbc import NBCSportsVPlayerIE
-from .ooyala import OoyalaIE
-from .rutv import RUTVIE
-from .tvc import TVCIE
-from .sportbox import SportBoxIE
-from .myvi import MyviIE
-from .condenast import CondeNastIE
-from .udn import UDNEmbedIE
-from .senategov import SenateISVPIE
-from .svt import SVTIE
-from .pornhub import PornHubIE
-from .xhamster import XHamsterEmbedIE
-from .tnaflix import TNAFlixNetworkEmbedIE
-from .drtuber import DrTuberIE
-from .redtube import RedTubeIE
-from .tube8 import Tube8IE
-from .mofosex import MofosexEmbedIE
-from .spankwire import SpankwireIE
-from .youporn import YouPornIE
-from .vimeo import (
-    VimeoIE,
-    VHXEmbedIE,
-)
-from .dailymotion import DailymotionIE
-from .dailymail import DailyMailIE
-from .onionstudios import OnionStudiosIE
-from .viewlift import ViewLiftEmbedIE
-from .mtv import MTVServicesEmbeddedIE
-from .pladform import PladformIE
-from .videomore import VideomoreIE
-from .webcaster import WebcasterFeedIE
-from .googledrive import GoogleDriveIE
-from .jwplatform import JWPlatformIE
-from .digiteka import DigitekaIE
-from .arkena import ArkenaIE
-from .instagram import InstagramIE
-from .threeqsdn import ThreeQSDNIE
-from .theplatform import ThePlatformIE
-from .kaltura import KalturaIE
-from .eagleplatform import EaglePlatformIE
-from .facebook import FacebookIE
-from .soundcloud import SoundcloudEmbedIE
-from .tunein import TuneInBaseIE
-from .vbox7 import Vbox7IE
-from .dbtv import DBTVIE
-from .piksel import PikselIE
-from .videa import VideaIE
-from .twentymin import TwentyMinutenIE
-from .ustream import UstreamIE
-from .arte import ArteTVEmbedIE
-from .videopress import VideoPressIE
-from .rutube import RutubeIE
-from .glomex import GlomexEmbedIE
-from .megatvcom import MegaTVComEmbedIE
-from .ant1newsgr import Ant1NewsGrEmbedIE
-from .limelight import LimelightBaseIE
-from .anvato import AnvatoIE
-from .washingtonpost import WashingtonPostIE
-from .wistia import WistiaIE
-from .mediaset import MediasetIE
-from .joj import JojIE
-from .megaphone import MegaphoneIE
-from .vzaar import VzaarIE
-from .channel9 import Channel9IE
-from .vshare import VShareIE
-from .mediasite import MediasiteIE
-from .springboardplatform import SpringboardPlatformIE
-from .ted import TedEmbedIE
-from .yapfiles import YapFilesIE
-from .vice import ViceIE
-from .xfileshare import XFileShareIE
-from .cloudflarestream import CloudflareStreamIE
-from .peertube import PeerTubeIE
-from .teachable import TeachableIE
-from .indavideo import IndavideoEmbedIE
-from .apa import APAIE
-from .foxnews import FoxNewsIE
-from .viqeo import ViqeoIE
-from .expressen import ExpressenIE
-from .zype import ZypeIE
-from .odnoklassniki import OdnoklassnikiIE
-from .vk import VKIE
-from .kinja import KinjaEmbedIE
-from .gedidigital import GediDigitalIE
-from .rcs import RCSEmbedsIE
-from .bitchute import BitChuteIE
-from .rumble import RumbleEmbedIE
-from .arcpublishing import ArcPublishingIE
-from .medialaan import MedialaanIE
-from .simplecast import SimplecastIE
-from .wimtv import WimTVIE
-from .tvopengr import TVOpenGrEmbedIE
-from .ertgr import ERTWebtvEmbedIE
-from .tvp import TVPEmbedIE
-from .blogger import BloggerIE
-from .mainstreaming import MainStreamingIE
-from .gfycat import GfycatIE
-from .panopto import PanoptoBaseIE
-from .ruutu import RuutuIE
 
 
 class GenericIE(InfoExtractor):
diff --git a/yt_dlp/extractor/mtv.py b/yt_dlp/extractor/mtv.py
index 3ef851e0bb..d161c33c19 100644
--- a/yt_dlp/extractor/mtv.py
+++ b/yt_dlp/extractor/mtv.py
@@ -1,9 +1,7 @@
 import re
 
 from .common import InfoExtractor
-from ..compat import (
-    compat_str,
-)
+from ..compat import compat_str
 from ..utils import (
     ExtractorError,
     find_xpath_attr,
diff --git a/yt_dlp/extractor/noz.py b/yt_dlp/extractor/noz.py
index 22cb08e8a2..b42a56f7e3 100644
--- a/yt_dlp/extractor/noz.py
+++ b/yt_dlp/extractor/noz.py
@@ -1,13 +1,11 @@
 from .common import InfoExtractor
-from ..compat import (
-    compat_urllib_parse_unquote,
-)
 from ..utils import (
     int_or_none,
     find_xpath_attr,
     xpath_text,
     update_url_query,
 )
+from ..compat import compat_urllib_parse_unquote
 
 
 class NozIE(InfoExtractor):
diff --git a/yt_dlp/extractor/openload.py b/yt_dlp/extractor/openload.py
index 41ef2e892b..f2600aaa4e 100644
--- a/yt_dlp/extractor/openload.py
+++ b/yt_dlp/extractor/openload.py
@@ -3,16 +3,14 @@
 import subprocess
 import tempfile
 
-from ..compat import (
-    compat_urlparse,
-)
+from ..compat import compat_urlparse
 from ..utils import (
+    ExtractorError,
+    Popen,
     check_executable,
     encodeArgument,
-    ExtractorError,
     get_exe_version,
     is_outdated_version,
-    Popen,
 )
 
 
diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py
index 21c6143bd3..dee1b23150 100644
--- a/yt_dlp/extractor/youtube.py
+++ b/yt_dlp/extractor/youtube.py
@@ -10,9 +10,9 @@
 import random
 import re
 import sys
+import threading
 import time
 import traceback
-import threading
 
 from .common import InfoExtractor, SearchInfoExtractor
 from ..compat import (
@@ -27,12 +27,13 @@
 )
 from ..jsinterp import JSInterpreter
 from ..utils import (
+    NO_DEFAULT,
+    ExtractorError,
     bug_reports_message,
     clean_html,
     datetime_from_str,
     dict_get,
     error_to_compat_str,
-    ExtractorError,
     float_or_none,
     format_field,
     get_first,
@@ -42,7 +43,6 @@
     js_to_json,
     mimetype2ext,
     network_exceptions,
-    NO_DEFAULT,
     orderedSet,
     parse_codecs,
     parse_count,
@@ -68,7 +68,6 @@
     variadic,
 )
 
-
 # any clients starting with _ cannot be explicity requested by the user
 INNERTUBE_CLIENTS = {
     'web': {
diff --git a/yt_dlp/jsinterp.py b/yt_dlp/jsinterp.py
index 3695a282d2..001836887a 100644
--- a/yt_dlp/jsinterp.py
+++ b/yt_dlp/jsinterp.py
@@ -1,12 +1,9 @@
-from collections.abc import MutableMapping
 import json
 import operator
 import re
+from collections.abc import MutableMapping
 
-from .utils import (
-    ExtractorError,
-    remove_quotes,
-)
+from .utils import ExtractorError, remove_quotes
 
 _OPERATORS = [
     ('|', operator.or_),
diff --git a/yt_dlp/minicurses.py b/yt_dlp/minicurses.py
index d7a8ffdddf..9fd679a48d 100644
--- a/yt_dlp/minicurses.py
+++ b/yt_dlp/minicurses.py
@@ -1,7 +1,7 @@
 import functools
 from threading import Lock
-from .utils import supports_terminal_sequences, write_string
 
+from .utils import supports_terminal_sequences, write_string
 
 CONTROL_SEQUENCES = {
     'DOWN': '\n',
diff --git a/yt_dlp/options.py b/yt_dlp/options.py
index c434e32b95..243beab4d1 100644
--- a/yt_dlp/options.py
+++ b/yt_dlp/options.py
@@ -1,26 +1,11 @@
-import os.path
 import optparse
+import os.path
 import re
 import shlex
 import sys
 
-from .compat import (
-    compat_expanduser,
-    compat_get_terminal_size,
-    compat_getenv,
-)
-from .utils import (
-    Config,
-    expand_path,
-    get_executable_path,
-    OUTTMPL_TYPES,
-    POSTPROCESS_WHEN,
-    remove_end,
-    write_string,
-)
+from .compat import compat_expanduser, compat_get_terminal_size, compat_getenv
 from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
-from .version import __version__
-
 from .downloader.external import list_external_downloaders
 from .postprocessor import (
     FFmpegExtractAudioPP,
@@ -30,6 +15,16 @@
     SponsorBlockPP,
 )
 from .postprocessor.modify_chapters import DEFAULT_SPONSORBLOCK_CHAPTER_TITLE
+from .utils import (
+    OUTTMPL_TYPES,
+    POSTPROCESS_WHEN,
+    Config,
+    expand_path,
+    get_executable_path,
+    remove_end,
+    write_string,
+)
+from .version import __version__
 
 
 def parseOpts(overrideArguments=None, ignore_config_files='if_override'):
diff --git a/yt_dlp/postprocessor/__init__.py b/yt_dlp/postprocessor/__init__.py
index e47631eb66..f168be46ad 100644
--- a/yt_dlp/postprocessor/__init__.py
+++ b/yt_dlp/postprocessor/__init__.py
@@ -1,27 +1,25 @@
 # flake8: noqa: F401
 
-from ..utils import load_plugins
-
 from .common import PostProcessor
 from .embedthumbnail import EmbedThumbnailPP
-from .exec import ExecPP, ExecAfterDownloadPP
+from .exec import ExecAfterDownloadPP, ExecPP
 from .ffmpeg import (
-    FFmpegPostProcessor,
-    FFmpegCopyStreamPP,
     FFmpegConcatPP,
+    FFmpegCopyStreamPP,
     FFmpegEmbedSubtitlePP,
     FFmpegExtractAudioPP,
     FFmpegFixupDuplicateMoovPP,
     FFmpegFixupDurationPP,
-    FFmpegFixupStretchedPP,
-    FFmpegFixupTimestampPP,
     FFmpegFixupM3u8PP,
     FFmpegFixupM4aPP,
+    FFmpegFixupStretchedPP,
+    FFmpegFixupTimestampPP,
     FFmpegMergerPP,
     FFmpegMetadataPP,
+    FFmpegPostProcessor,
+    FFmpegSplitChaptersPP,
     FFmpegSubtitlesConvertorPP,
     FFmpegThumbnailsConvertorPP,
-    FFmpegSplitChaptersPP,
     FFmpegVideoConvertorPP,
     FFmpegVideoRemuxerPP,
 )
@@ -35,6 +33,7 @@
 from .sponskrub import SponSkrubPP
 from .sponsorblock import SponsorBlockPP
 from .xattrpp import XAttrMetadataPP
+from ..utils import load_plugins
 
 _PLUGIN_CLASSES = load_plugins('postprocessor', 'PP', globals())
 
diff --git a/yt_dlp/postprocessor/common.py b/yt_dlp/postprocessor/common.py
index 3f55b24f2c..ce6dec2f54 100644
--- a/yt_dlp/postprocessor/common.py
+++ b/yt_dlp/postprocessor/common.py
@@ -6,10 +6,10 @@
 import urllib.error
 
 from ..utils import (
+    PostProcessingError,
     _configuration_args,
     encodeFilename,
     network_exceptions,
-    PostProcessingError,
     sanitized_Request,
     write_string,
 )
diff --git a/yt_dlp/postprocessor/embedthumbnail.py b/yt_dlp/postprocessor/embedthumbnail.py
index 2fca977846..5469f25e0e 100644
--- a/yt_dlp/postprocessor/embedthumbnail.py
+++ b/yt_dlp/postprocessor/embedthumbnail.py
@@ -1,11 +1,11 @@
 import base64
 import imghdr
 import os
-import subprocess
 import re
+import subprocess
 
 try:
-    from mutagen.flac import Picture, FLAC
+    from mutagen.flac import FLAC, Picture
     from mutagen.mp4 import MP4, MP4Cover
     from mutagen.oggopus import OggOpus
     from mutagen.oggvorbis import OggVorbis
@@ -14,17 +14,14 @@
     has_mutagen = False
 
 from .common import PostProcessor
-from .ffmpeg import (
-    FFmpegPostProcessor,
-    FFmpegThumbnailsConvertorPP,
-)
+from .ffmpeg import FFmpegPostProcessor, FFmpegThumbnailsConvertorPP
 from ..utils import (
+    Popen,
+    PostProcessingError,
     check_executable,
     encodeArgument,
     encodeFilename,
     error_to_compat_str,
-    Popen,
-    PostProcessingError,
     prepend_extension,
     shell_quote,
 )
diff --git a/yt_dlp/postprocessor/exec.py b/yt_dlp/postprocessor/exec.py
index 6621889d5c..cfc83167ce 100644
--- a/yt_dlp/postprocessor/exec.py
+++ b/yt_dlp/postprocessor/exec.py
@@ -2,11 +2,7 @@
 
 from .common import PostProcessor
 from ..compat import compat_shlex_quote
-from ..utils import (
-    encodeArgument,
-    PostProcessingError,
-    variadic,
-)
+from ..utils import PostProcessingError, encodeArgument, variadic
 
 
 class ExecPP(PostProcessor):
diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py
index 3175c8d10b..69182618bb 100644
--- a/yt_dlp/postprocessor/ffmpeg.py
+++ b/yt_dlp/postprocessor/ffmpeg.py
@@ -1,27 +1,26 @@
 import collections
 import itertools
+import json
 import os
+import re
 import subprocess
 import time
-import re
-import json
 
 from .common import AudioConversionError, PostProcessor
-
 from ..compat import compat_str
 from ..utils import (
+    ISO639Utils,
+    Popen,
+    PostProcessingError,
+    _get_exe_version_output,
+    detect_exe_version,
     determine_ext,
     dfxp2srt,
     encodeArgument,
     encodeFilename,
     float_or_none,
-    _get_exe_version_output,
-    detect_exe_version,
     is_outdated_version,
-    ISO639Utils,
     orderedSet,
-    Popen,
-    PostProcessingError,
     prepend_extension,
     replace_extension,
     shell_quote,
@@ -30,7 +29,6 @@
     write_json_file,
 )
 
-
 EXT_TO_OUT_FORMATS = {
     'aac': 'adts',
     'flac': 'flac',
diff --git a/yt_dlp/postprocessor/modify_chapters.py b/yt_dlp/postprocessor/modify_chapters.py
index 22506bc21d..7e2c232887 100644
--- a/yt_dlp/postprocessor/modify_chapters.py
+++ b/yt_dlp/postprocessor/modify_chapters.py
@@ -3,17 +3,9 @@
 import os
 
 from .common import PostProcessor
-from .ffmpeg import (
-    FFmpegPostProcessor,
-    FFmpegSubtitlesConvertorPP
-)
+from .ffmpeg import FFmpegPostProcessor, FFmpegSubtitlesConvertorPP
 from .sponsorblock import SponsorBlockPP
-from ..utils import (
-    orderedSet,
-    PostProcessingError,
-    prepend_extension,
-)
-
+from ..utils import PostProcessingError, orderedSet, prepend_extension
 
 _TINY_CHAPTER_DURATION = 1
 DEFAULT_SPONSORBLOCK_CHAPTER_TITLE = '[SponsorBlock]: %(category_names)l'
diff --git a/yt_dlp/postprocessor/movefilesafterdownload.py b/yt_dlp/postprocessor/movefilesafterdownload.py
index bc3d15ca45..436d132272 100644
--- a/yt_dlp/postprocessor/movefilesafterdownload.py
+++ b/yt_dlp/postprocessor/movefilesafterdownload.py
@@ -3,10 +3,10 @@
 
 from .common import PostProcessor
 from ..utils import (
+    PostProcessingError,
     decodeFilename,
     encodeFilename,
     make_dir,
-    PostProcessingError,
 )
 
 
diff --git a/yt_dlp/postprocessor/sponskrub.py b/yt_dlp/postprocessor/sponskrub.py
index 38089de086..1a9f5dc663 100644
--- a/yt_dlp/postprocessor/sponskrub.py
+++ b/yt_dlp/postprocessor/sponskrub.py
@@ -4,15 +4,15 @@
 
 from .common import PostProcessor
 from ..utils import (
+    Popen,
+    PostProcessingError,
     check_executable,
     cli_option,
     encodeArgument,
     encodeFilename,
+    prepend_extension,
     shell_quote,
     str_or_none,
-    Popen,
-    PostProcessingError,
-    prepend_extension,
 )
 
 
diff --git a/yt_dlp/postprocessor/sponsorblock.py b/yt_dlp/postprocessor/sponsorblock.py
index 7943014e2d..501e30320f 100644
--- a/yt_dlp/postprocessor/sponsorblock.py
+++ b/yt_dlp/postprocessor/sponsorblock.py
@@ -1,6 +1,6 @@
-from hashlib import sha256
 import json
 import re
+from hashlib import sha256
 
 from .ffmpeg import FFmpegPostProcessor
 from ..compat import compat_urllib_parse_urlencode
diff --git a/yt_dlp/postprocessor/xattrpp.py b/yt_dlp/postprocessor/xattrpp.py
index 5ad8509e7b..3c431941b3 100644
--- a/yt_dlp/postprocessor/xattrpp.py
+++ b/yt_dlp/postprocessor/xattrpp.py
@@ -1,11 +1,11 @@
 from .common import PostProcessor
 from ..compat import compat_os_name
 from ..utils import (
-    hyphenate_date,
-    write_xattr,
     PostProcessingError,
     XAttrMetadataError,
     XAttrUnavailableError,
+    hyphenate_date,
+    write_xattr,
 )
 
 
diff --git a/yt_dlp/socks.py b/yt_dlp/socks.py
index ffa960e03c..56fab08ab3 100644
--- a/yt_dlp/socks.py
+++ b/yt_dlp/socks.py
@@ -9,11 +9,7 @@
 import collections
 import socket
 
-from .compat import (
-    compat_ord,
-    compat_struct_pack,
-    compat_struct_unpack,
-)
+from .compat import compat_ord, compat_struct_pack, compat_struct_unpack
 
 __author__ = 'Timo Schmid <coding@timoschmid.de>'
 
diff --git a/yt_dlp/update.py b/yt_dlp/update.py
index 7db260e96f..eea08ce43e 100644
--- a/yt_dlp/update.py
+++ b/yt_dlp/update.py
@@ -8,8 +8,7 @@
 from zipimport import zipimporter
 
 from .compat import compat_realpath
-from .utils import encode_compat_str, Popen, write_string
-
+from .utils import Popen, encode_compat_str, write_string
 from .version import __version__
 
 
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 91e1a9870e..25ac864f38 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -9,8 +9,8 @@
 import contextlib
 import ctypes
 import datetime
-import email.utils
 import email.header
+import email.utils
 import errno
 import functools
 import gzip
@@ -22,11 +22,13 @@
 import json
 import locale
 import math
+import mimetypes
 import operator
 import os
 import platform
 import random
 import re
+import shlex
 import socket
 import ssl
 import subprocess
@@ -34,16 +36,11 @@
 import tempfile
 import time
 import traceback
+import urllib.parse
 import xml.etree.ElementTree
 import zlib
-import mimetypes
-import urllib.parse
-import shlex
 
 from .compat import (
-    compat_HTMLParseError,
-    compat_HTMLParser,
-    compat_HTTPError,
     compat_brotli,
     compat_chr,
     compat_cookiejar,
@@ -51,7 +48,10 @@
     compat_expanduser,
     compat_html_entities,
     compat_html_entities_html5,
+    compat_HTMLParseError,
+    compat_HTMLParser,
     compat_http_client,
+    compat_HTTPError,
     compat_os_name,
     compat_parse_qs,
     compat_shlex_quote,
@@ -59,18 +59,14 @@
     compat_struct_pack,
     compat_struct_unpack,
     compat_urllib_error,
+    compat_urllib_parse_unquote_plus,
     compat_urllib_parse_urlencode,
     compat_urllib_parse_urlparse,
-    compat_urllib_parse_unquote_plus,
     compat_urllib_request,
     compat_urlparse,
     compat_websockets,
 )
-
-from .socks import (
-    ProxyType,
-    sockssocket,
-)
+from .socks import ProxyType, sockssocket
 
 try:
     import certifi
diff --git a/yt_dlp/webvtt.py b/yt_dlp/webvtt.py
index e0d7f67436..3180eafde9 100644
--- a/yt_dlp/webvtt.py
+++ b/yt_dlp/webvtt.py
@@ -8,13 +8,11 @@
 in RFC 8216 §3.5 <https://tools.ietf.org/html/rfc8216#section-3.5>.
 """
 
-import re
 import io
+import re
+
+from .compat import compat_Match, compat_Pattern
 from .utils import int_or_none, timetuple_from_msec
-from .compat import (
-    compat_Pattern,
-    compat_Match,
-)
 
 
 class _MatchParser:
-- 
GitLab


From e5a998f3684e7c56f9cf1c07c4e176e891d96509 Mon Sep 17 00:00:00 2001
From: pukkandan <pukkandan.ytdlp@gmail.com>
Date: Tue, 12 Apr 2022 05:31:54 +0530
Subject: [PATCH 7/9] [cleanup] Misc cleanup (#2173)

Authored by: fstirlitz, pukkandan
---
 Changelog.md                         |  2 +-
 README.md                            |  2 +-
 devscripts/bash-completion.py        |  4 ++--
 devscripts/fish-completion.py        |  4 ++--
 devscripts/make_lazy_extractors.py   |  3 +--
 devscripts/zsh-completion.py         |  4 ++--
 test/test_overwrites.py              |  5 ++---
 yt_dlp/YoutubeDL.py                  |  4 +++-
 yt_dlp/compat.py                     |  2 +-
 yt_dlp/extractor/abematv.py          |  1 +
 yt_dlp/extractor/sonyliv.py          | 30 +++++++++++++++++++---------
 yt_dlp/postprocessor/sponsorblock.py |  4 ++--
 yt_dlp/utils.py                      | 14 ++++++-------
 13 files changed, 46 insertions(+), 33 deletions(-)

diff --git a/Changelog.md b/Changelog.md
index a4cf0e92ee..3fb6260b86 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -15,7 +15,7 @@ ### 2022.04.08
 
 * Use certificates from `certifi` if installed by [coletdjnz](https://github.com/coletdjnz)
 * Treat multiple `--match-filters` as OR
-* File locking improvevemnts:
+* File locking improvements:
     * Do not lock downloading file on Windows
     * Do not prevent download if locking is unsupported
     * Do not truncate files before locking by [jakeogh](https://github.com/jakeogh), [pukkandan](https://github.com/pukkandan)
diff --git a/README.md b/README.md
index f4b55f6d7d..8a8477c9bd 100644
--- a/README.md
+++ b/README.md
@@ -1748,7 +1748,7 @@ # EMBEDDING YT-DLP
     ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc'])
 ```
 
-Most likely, you'll want to use various options. For a list of options available, have a look at [`yt_dlp/YoutubeDL.py`](yt_dlp/YoutubeDL.py#L197).
+Most likely, you'll want to use various options. For a list of options available, have a look at [`yt_dlp/YoutubeDL.py`](yt_dlp/YoutubeDL.py#L181).
 
 Here's a more complete example demonstrating various functionality:
 
diff --git a/devscripts/bash-completion.py b/devscripts/bash-completion.py
index 73d698c39b..27ec7ca7a6 100755
--- a/devscripts/bash-completion.py
+++ b/devscripts/bash-completion.py
@@ -1,9 +1,9 @@
 #!/usr/bin/env python3
 import os
 import sys
-from os.path import dirname as dirn
 
-sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
 import yt_dlp
 
 BASH_COMPLETION_FILE = "completions/bash/yt-dlp"
diff --git a/devscripts/fish-completion.py b/devscripts/fish-completion.py
index c318b69e41..dcb1d6582a 100755
--- a/devscripts/fish-completion.py
+++ b/devscripts/fish-completion.py
@@ -2,9 +2,9 @@
 import optparse
 import os
 import sys
-from os.path import dirname as dirn
 
-sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
 import yt_dlp
 from yt_dlp.utils import shell_quote
 
diff --git a/devscripts/make_lazy_extractors.py b/devscripts/make_lazy_extractors.py
index 6d5f96cf0e..5e20706026 100644
--- a/devscripts/make_lazy_extractors.py
+++ b/devscripts/make_lazy_extractors.py
@@ -2,9 +2,8 @@
 import os
 import sys
 from inspect import getsource
-from os.path import dirname as dirn
 
-sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 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):
diff --git a/devscripts/zsh-completion.py b/devscripts/zsh-completion.py
index 2d5ac2a45d..06660d8fd4 100755
--- a/devscripts/zsh-completion.py
+++ b/devscripts/zsh-completion.py
@@ -1,9 +1,9 @@
 #!/usr/bin/env python3
 import os
 import sys
-from os.path import dirname as dirn
 
-sys.path.insert(0, dirn(dirn(os.path.abspath(__file__))))
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
 import yt_dlp
 
 ZSH_COMPLETION_FILE = "completions/zsh/_yt-dlp"
diff --git a/test/test_overwrites.py b/test/test_overwrites.py
index 39741b65c5..a6d5bae40d 100644
--- a/test/test_overwrites.py
+++ b/test/test_overwrites.py
@@ -3,14 +3,13 @@
 import subprocess
 import sys
 import unittest
-from os.path import join
 
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from test.helper import is_download_test, try_rm
 
 root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-download_file = join(root_dir, 'test.webm')
+download_file = os.path.join(root_dir, 'test.webm')
 
 
 @is_download_test
@@ -44,7 +43,7 @@ def test_yes_overwrites(self):
         self.assertTrue(os.path.getsize(download_file) > 1)
 
     def tearDown(self):
-        try_rm(join(root_dir, 'test.webm'))
+        try_rm(os.path.join(root_dir, 'test.webm'))
 
 
 if __name__ == '__main__':
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py
index a8bb7f45c3..eaf2d92167 100644
--- a/yt_dlp/YoutubeDL.py
+++ b/yt_dlp/YoutubeDL.py
@@ -888,6 +888,7 @@ class Styles(Enum):
         SUPPRESS = 'light black'
 
     def _format_text(self, handle, allow_colors, text, f, fallback=None, *, test_encoding=False):
+        text = str(text)
         if test_encoding:
             original_text = text
             # handle.encoding can be None. See https://github.com/yt-dlp/yt-dlp/issues/2711
@@ -895,7 +896,7 @@ def _format_text(self, handle, allow_colors, text, f, fallback=None, *, test_enc
             text = text.encode(encoding, 'ignore').decode(encoding)
             if fallback is not None and text != original_text:
                 text = fallback
-        if isinstance(f, self.Styles):
+        if isinstance(f, Enum):
             f = f.value
         return format_text(text, f) if allow_colors else text if fallback is None else fallback
 
@@ -1708,6 +1709,7 @@ def get_entry(i):
             entries.append(entry)
             try:
                 if entry is not None:
+                    # TODO: Add auto-generated fields
                     self._match_entry(entry, incomplete=True, silent=True)
             except (ExistingVideoReached, RejectedVideoReached):
                 broken = True
diff --git a/yt_dlp/compat.py b/yt_dlp/compat.py
index 7a15004350..9d3a6bbfd0 100644
--- a/yt_dlp/compat.py
+++ b/yt_dlp/compat.py
@@ -196,7 +196,7 @@ def windows_enable_vt_mode():  # TODO: Do this the proper way https://bugs.pytho
 compat_urlparse = compat_urllib_parse = urllib.parse
 
 
-# To be removed
+# To be removed - Do not use
 
 compat_basestring = str
 compat_collections_abc = collections.abc
diff --git a/yt_dlp/extractor/abematv.py b/yt_dlp/extractor/abematv.py
index 0dc8dea264..1b9deeae84 100644
--- a/yt_dlp/extractor/abematv.py
+++ b/yt_dlp/extractor/abematv.py
@@ -28,6 +28,7 @@
 
 # NOTE: network handler related code is temporary thing until network stack overhaul PRs are merged (#2861/#2862)
 
+
 def add_opener(ydl, handler):
     ''' Add a handler for opening URLs, like _download_webpage '''
     # https://github.com/python/cpython/blob/main/Lib/urllib/request.py#L426
diff --git a/yt_dlp/extractor/sonyliv.py b/yt_dlp/extractor/sonyliv.py
index 771f890cc9..17d28478f9 100644
--- a/yt_dlp/extractor/sonyliv.py
+++ b/yt_dlp/extractor/sonyliv.py
@@ -1,4 +1,5 @@
 import datetime
+import json
 import math
 import random
 import time
@@ -82,21 +83,32 @@ def _perform_login(self, username, password):
             raise ExtractorError(f'Invalid username/password; {self._LOGIN_HINT}')
 
         self.report_login()
-        data = '''{"mobileNumber":"%s","channelPartnerID":"MSMIND","country":"IN","timestamp":"%s",
-        "otpSize":6,"loginType":"REGISTERORSIGNIN","isMobileMandatory":true}
-         ''' % (username, datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%MZ"))
         otp_request_json = self._download_json(
             'https://apiv2.sonyliv.com/AGL/1.6/A/ENG/WEB/IN/HR/CREATEOTP-V2',
-            None, note='Sending OTP', data=data.encode(), headers=self._HEADERS)
+            None, note='Sending OTP', headers=self._HEADERS, data=json.dumps({
+                'mobileNumber': username,
+                'channelPartnerID': 'MSMIND',
+                'country': 'IN',
+                'timestamp': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%MZ'),
+                'otpSize': 6,
+                'loginType': 'REGISTERORSIGNIN',
+                'isMobileMandatory': True,
+            }).encode())
         if otp_request_json['resultCode'] == 'KO':
             raise ExtractorError(otp_request_json['message'], expected=True)
-        otp_code = self._get_tfa_info('OTP')
-        data = '''{"channelPartnerID":"MSMIND","mobileNumber":"%s","country":"IN","otp":"%s",
-        "dmaId":"IN","ageConfirmation":true,"timestamp":"%s","isMobileMandatory":true}
-         ''' % (username, otp_code, datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%MZ"))
+
         otp_verify_json = self._download_json(
             'https://apiv2.sonyliv.com/AGL/2.0/A/ENG/WEB/IN/HR/CONFIRMOTP-V2',
-            None, note='Verifying OTP', data=data.encode(), headers=self._HEADERS)
+            None, note='Verifying OTP', headers=self._HEADERS, data=json.dumps({
+                'channelPartnerID': 'MSMIND',
+                'mobileNumber': username,
+                'country': 'IN',
+                'otp': self._get_tfa_info('OTP'),
+                'dmaId': 'IN',
+                'ageConfirmation': True,
+                'timestamp': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%MZ'),
+                'isMobileMandatory': True,
+            }).encode())
         if otp_verify_json['resultCode'] == 'KO':
             raise ExtractorError(otp_request_json['message'], expected=True)
         self._HEADERS['authorization'] = otp_verify_json['resultObj']['accessToken']
diff --git a/yt_dlp/postprocessor/sponsorblock.py b/yt_dlp/postprocessor/sponsorblock.py
index 501e30320f..7749ffe054 100644
--- a/yt_dlp/postprocessor/sponsorblock.py
+++ b/yt_dlp/postprocessor/sponsorblock.py
@@ -1,6 +1,6 @@
+import hashlib
 import json
 import re
-from hashlib import sha256
 
 from .ffmpeg import FFmpegPostProcessor
 from ..compat import compat_urllib_parse_urlencode
@@ -84,7 +84,7 @@ def to_chapter(s):
         return sponsor_chapters
 
     def _get_sponsor_segments(self, video_id, service):
-        hash = sha256(video_id.encode('ascii')).hexdigest()
+        hash = hashlib.sha256(video_id.encode('ascii')).hexdigest()
         # SponsorBlock API recommends using first 4 hash characters.
         url = f'{self._API_URL}/api/skipSegments/{hash[:4]}?' + compat_urllib_parse_urlencode({
             'service': service,
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 25ac864f38..35e8d1d5b6 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -4793,12 +4793,12 @@ def random_birthday(year_field, month_field, day_field):
 
 
 # Templates for internet shortcut files, which are plain text files.
-DOT_URL_LINK_TEMPLATE = '''
+DOT_URL_LINK_TEMPLATE = '''\
 [InternetShortcut]
 URL=%(url)s
-'''.lstrip()
+'''
 
-DOT_WEBLOC_LINK_TEMPLATE = '''
+DOT_WEBLOC_LINK_TEMPLATE = '''\
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
@@ -4807,16 +4807,16 @@ def random_birthday(year_field, month_field, day_field):
 \t<string>%(url)s</string>
 </dict>
 </plist>
-'''.lstrip()
+'''
 
-DOT_DESKTOP_LINK_TEMPLATE = '''
+DOT_DESKTOP_LINK_TEMPLATE = '''\
 [Desktop Entry]
 Encoding=UTF-8
 Name=%(filename)s
 Type=Link
 URL=%(url)s
 Icon=text-html
-'''.lstrip()
+'''
 
 LINK_TEMPLATES = {
     'url': DOT_URL_LINK_TEMPLATE,
@@ -4872,7 +4872,7 @@ def iri_to_uri(iri):
 def to_high_limit_path(path):
     if sys.platform in ['win32', 'cygwin']:
         # Work around MAX_PATH limitation on Windows. The maximum allowed length for the individual path segments may still be quite limited.
-        return r'\\?\ '.rstrip() + os.path.abspath(path)
+        return '\\\\?\\' + os.path.abspath(path)
 
     return path
 
-- 
GitLab


From b07897ef5bcdb865991d8601faef64a451da39fc Mon Sep 17 00:00:00 2001
From: pukkandan <pukkandan.ytdlp@gmail.com>
Date: Tue, 12 Apr 2022 05:23:27 +0530
Subject: [PATCH 8/9] [utils] certifi: Make sure the pem file exists

Closes #3353
---
 yt_dlp/utils.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 35e8d1d5b6..966548466e 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -70,7 +70,8 @@
 
 try:
     import certifi
-    has_certifi = True
+    # The certificate may not be bundled in executable
+    has_certifi = os.path.exists(certifi.where())
 except ImportError:
     has_certifi = False
 
-- 
GitLab


From 66cf3e1001b6d9a2829fe834c3f9103b0890918e Mon Sep 17 00:00:00 2001
From: pukkandan <pukkandan.ytdlp@gmail.com>
Date: Tue, 12 Apr 2022 05:27:17 +0530
Subject: [PATCH 9/9] [EmbedSubtitle] Enable for more video extensions

Closes #3382
---
 yt_dlp/postprocessor/ffmpeg.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py
index 69182618bb..4b61693a20 100644
--- a/yt_dlp/postprocessor/ffmpeg.py
+++ b/yt_dlp/postprocessor/ffmpeg.py
@@ -577,14 +577,16 @@ def _options(target_ext):
 
 
 class FFmpegEmbedSubtitlePP(FFmpegPostProcessor):
+    SUPPORTED_EXTS = ('mp4', 'mov', 'm4a', 'webm', 'mkv', 'mka')
+
     def __init__(self, downloader=None, already_have_subtitle=False):
         super().__init__(downloader)
         self._already_have_subtitle = already_have_subtitle
 
     @PostProcessor._restrict_to(images=False)
     def run(self, info):
-        if info['ext'] not in ('mp4', 'webm', 'mkv'):
-            self.to_screen('Subtitles can only be embedded in mp4, webm or mkv files')
+        if info['ext'] not in self.SUPPORTED_EXTS:
+            self.to_screen(f'Subtitles can only be embedded in {", ".join(self.SUPPORTED_EXTS)} files')
             return [], info
         subtitles = info.get('requested_subtitles')
         if not subtitles:
-- 
GitLab