mirror of
https://github.com/yt-dlp/yt-dlp
synced 2025-01-15 03:41:33 +01:00
Add --no-plugins
This commit is contained in:
parent
109c019e8a
commit
97684b0f2c
7 changed files with 70 additions and 6 deletions
|
@ -371,6 +371,12 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git
|
||||||
sequences). Use "auto-tty" or "no_color-tty"
|
sequences). Use "auto-tty" or "no_color-tty"
|
||||||
to decide based on terminal support only.
|
to decide based on terminal support only.
|
||||||
Can be used multiple times
|
Can be used multiple times
|
||||||
|
--plugin-dirs PATH Directory to search for plugins. Can be used
|
||||||
|
multiple times to add multiple directories.
|
||||||
|
Add "no-external" to disable searching
|
||||||
|
default external plugin directories (outside
|
||||||
|
of python environment)
|
||||||
|
--no-plugins Do not load plugins
|
||||||
--compat-options OPTS Options that can help keep compatibility
|
--compat-options OPTS Options that can help keep compatibility
|
||||||
with youtube-dl or youtube-dlc
|
with youtube-dl or youtube-dlc
|
||||||
configurations by reverting some of the
|
configurations by reverting some of the
|
||||||
|
|
|
@ -5,7 +5,8 @@ import sys
|
||||||
import unittest
|
import unittest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import yt_dlp._globals
|
import yt_dlp._globals
|
||||||
from yt_dlp.plugins import set_plugin_dirs, add_plugin_dirs, PluginDirs
|
from yt_dlp.plugins import set_plugin_dirs, add_plugin_dirs, PluginDirs, disable_plugins
|
||||||
|
from yt_dlp.utils import YoutubeDLError
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
TEST_DATA_DIR = Path(os.path.dirname(os.path.abspath(__file__)), 'testdata')
|
TEST_DATA_DIR = Path(os.path.dirname(os.path.abspath(__file__)), 'testdata')
|
||||||
|
@ -13,7 +14,7 @@ sys.path.append(str(TEST_DATA_DIR))
|
||||||
importlib.invalidate_caches()
|
importlib.invalidate_caches()
|
||||||
|
|
||||||
from yt_dlp.plugins import PACKAGE_NAME, PluginSpec, directories, load_plugins, load_all_plugins, register_plugin_spec
|
from yt_dlp.plugins import PACKAGE_NAME, PluginSpec, directories, load_plugins, load_all_plugins, register_plugin_spec
|
||||||
from yt_dlp._globals import extractors, postprocessors, plugin_dirs, plugin_ies, plugin_pps, all_plugins_loaded, plugin_specs
|
from yt_dlp._globals import extractors, postprocessors, plugin_dirs, plugin_ies, plugin_pps, all_plugins_loaded, plugin_specs, plugins_enabled
|
||||||
|
|
||||||
|
|
||||||
EXTRACTOR_PLUGIN_SPEC = PluginSpec(
|
EXTRACTOR_PLUGIN_SPEC = PluginSpec(
|
||||||
|
@ -41,6 +42,7 @@ class TestPlugins(unittest.TestCase):
|
||||||
plugin_dirs.set((PluginDirs.DEFAULT_EXTERNAL,))
|
plugin_dirs.set((PluginDirs.DEFAULT_EXTERNAL,))
|
||||||
plugin_specs.set({})
|
plugin_specs.set({})
|
||||||
all_plugins_loaded.set(False)
|
all_plugins_loaded.set(False)
|
||||||
|
plugins_enabled.set(True)
|
||||||
importlib.invalidate_caches()
|
importlib.invalidate_caches()
|
||||||
# Clearing override plugins is probably difficult
|
# Clearing override plugins is probably difficult
|
||||||
for module_name in tuple(sys.modules):
|
for module_name in tuple(sys.modules):
|
||||||
|
@ -199,6 +201,31 @@ class TestPlugins(unittest.TestCase):
|
||||||
self.assertIn(f'{PACKAGE_NAME}.extractor.package', sys.modules.keys())
|
self.assertIn(f'{PACKAGE_NAME}.extractor.package', sys.modules.keys())
|
||||||
self.assertIn('PackagePluginIE', plugin_ies.get())
|
self.assertIn('PackagePluginIE', plugin_ies.get())
|
||||||
|
|
||||||
|
def test_disable_plugins(self):
|
||||||
|
disable_plugins()
|
||||||
|
ies = load_plugins(EXTRACTOR_PLUGIN_SPEC)
|
||||||
|
self.assertEqual(ies, {})
|
||||||
|
self.assertNotIn(f'{PACKAGE_NAME}.extractor.normal', sys.modules.keys())
|
||||||
|
self.assertNotIn('NormalPluginIE', plugin_ies.get())
|
||||||
|
|
||||||
|
pps = load_plugins(POSTPROCESSOR_PLUGIN_SPEC)
|
||||||
|
self.assertEqual(pps, {})
|
||||||
|
self.assertNotIn(f'{PACKAGE_NAME}.postprocessor.normal', sys.modules.keys())
|
||||||
|
self.assertNotIn('NormalPluginPP', plugin_pps.get())
|
||||||
|
|
||||||
|
def test_disable_plugins_already_loaded(self):
|
||||||
|
register_plugin_spec(EXTRACTOR_PLUGIN_SPEC)
|
||||||
|
register_plugin_spec(POSTPROCESSOR_PLUGIN_SPEC)
|
||||||
|
load_all_plugins()
|
||||||
|
|
||||||
|
with self.assertRaises(YoutubeDLError):
|
||||||
|
disable_plugins()
|
||||||
|
|
||||||
|
self.assertTrue(plugins_enabled.get())
|
||||||
|
|
||||||
|
ies = load_plugins(EXTRACTOR_PLUGIN_SPEC)
|
||||||
|
self.assertIn('NormalPluginIE', ies)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -40,6 +40,7 @@ from ._globals import (
|
||||||
plugin_overrides,
|
plugin_overrides,
|
||||||
plugin_pps,
|
plugin_pps,
|
||||||
all_plugins_loaded,
|
all_plugins_loaded,
|
||||||
|
plugins_enabled,
|
||||||
)
|
)
|
||||||
from .minicurses import format_text
|
from .minicurses import format_text
|
||||||
from .networking import HEADRequest, Request, RequestDirector
|
from .networking import HEADRequest, Request, RequestDirector
|
||||||
|
@ -4088,8 +4089,11 @@ class YoutubeDL:
|
||||||
continue
|
continue
|
||||||
write_debug(f'{plugin_type} Plugins: {", ".join(sorted(display_list))}')
|
write_debug(f'{plugin_type} Plugins: {", ".join(sorted(display_list))}')
|
||||||
|
|
||||||
|
if not plugins_enabled.get():
|
||||||
|
write_debug('Plugins are disabled')
|
||||||
|
|
||||||
plugin_dirs = plugin_directories()
|
plugin_dirs = plugin_directories()
|
||||||
if plugin_dirs:
|
if plugin_dirs and plugins_enabled.get():
|
||||||
write_debug(f'Plugin directories: {plugin_dirs}')
|
write_debug(f'Plugin directories: {plugin_dirs}')
|
||||||
|
|
||||||
# Not implemented
|
# Not implemented
|
||||||
|
|
|
@ -23,6 +23,7 @@ from .networking.impersonate import ImpersonateTarget
|
||||||
from ._globals import IN_CLI as _IN_CLI
|
from ._globals import IN_CLI as _IN_CLI
|
||||||
from .options import parseOpts
|
from .options import parseOpts
|
||||||
from .plugins import load_all_plugins as _load_all_plugins
|
from .plugins import load_all_plugins as _load_all_plugins
|
||||||
|
from .plugins import disable_plugins as _disable_plugins
|
||||||
from .plugins import PluginDirs as _PluginDirs
|
from .plugins import PluginDirs as _PluginDirs
|
||||||
from .plugins import set_plugin_dirs as _set_plugin_dirs
|
from .plugins import set_plugin_dirs as _set_plugin_dirs
|
||||||
from .postprocessor import (
|
from .postprocessor import (
|
||||||
|
@ -989,7 +990,11 @@ def _real_main(argv=None):
|
||||||
|
|
||||||
# load all plugins into the global lookup
|
# load all plugins into the global lookup
|
||||||
_set_plugin_dirs(*opts.plugin_dirs)
|
_set_plugin_dirs(*opts.plugin_dirs)
|
||||||
_load_all_plugins()
|
|
||||||
|
if not opts.plugins_enabled:
|
||||||
|
_disable_plugins()
|
||||||
|
else:
|
||||||
|
_load_all_plugins()
|
||||||
|
|
||||||
with YoutubeDL(ydl_opts) as ydl:
|
with YoutubeDL(ydl_opts) as ydl:
|
||||||
pre_process = opts.update_self or opts.rm_cachedir
|
pre_process = opts.update_self or opts.rm_cachedir
|
||||||
|
|
|
@ -17,6 +17,8 @@ plugin_specs = ContextVar('plugin_specs', default={})
|
||||||
# Whether plugins have been loaded once
|
# Whether plugins have been loaded once
|
||||||
all_plugins_loaded = ContextVar('all_plugins_loaded', default=False)
|
all_plugins_loaded = ContextVar('all_plugins_loaded', default=False)
|
||||||
|
|
||||||
|
plugins_enabled = ContextVar('plugins_enabled', default=True)
|
||||||
|
|
||||||
plugin_dirs = ContextVar('plugin_dirs', default=('external', ))
|
plugin_dirs = ContextVar('plugin_dirs', default=('external', ))
|
||||||
plugin_ies = ContextVar('plugin_ies', default={})
|
plugin_ies = ContextVar('plugin_ies', default={})
|
||||||
plugin_overrides = ContextVar('plugin_overrides', default=defaultdict(list))
|
plugin_overrides = ContextVar('plugin_overrides', default=defaultdict(list))
|
||||||
|
|
|
@ -475,6 +475,13 @@ def create_parser():
|
||||||
'Add "no-external" to disable searching default external plugin directories (outside of python environment)'
|
'Add "no-external" to disable searching default external plugin directories (outside of python environment)'
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
general.add_option(
|
||||||
|
'--no-plugins',
|
||||||
|
dest='plugins_enabled',
|
||||||
|
action='store_false',
|
||||||
|
default=True,
|
||||||
|
help='Do not load plugins',
|
||||||
|
)
|
||||||
general.add_option(
|
general.add_option(
|
||||||
'--compat-options',
|
'--compat-options',
|
||||||
metavar='OPTS', dest='compat_opts', default=set(), type='str',
|
metavar='OPTS', dest='compat_opts', default=set(), type='str',
|
||||||
|
|
|
@ -20,6 +20,7 @@ from ._globals import (
|
||||||
plugin_dirs,
|
plugin_dirs,
|
||||||
all_plugins_loaded,
|
all_plugins_loaded,
|
||||||
plugin_specs,
|
plugin_specs,
|
||||||
|
plugins_enabled,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .compat import functools # isort: split
|
from .compat import functools # isort: split
|
||||||
|
@ -29,7 +30,7 @@ from .utils import (
|
||||||
get_user_config_dirs,
|
get_user_config_dirs,
|
||||||
merge_dicts,
|
merge_dicts,
|
||||||
orderedSet,
|
orderedSet,
|
||||||
write_string,
|
write_string, YoutubeDLError,
|
||||||
)
|
)
|
||||||
|
|
||||||
PACKAGE_NAME = 'yt_dlp_plugins'
|
PACKAGE_NAME = 'yt_dlp_plugins'
|
||||||
|
@ -46,6 +47,7 @@ __all__ = [
|
||||||
'register_plugin_spec',
|
'register_plugin_spec',
|
||||||
'add_plugin_dirs',
|
'add_plugin_dirs',
|
||||||
'set_plugin_dirs',
|
'set_plugin_dirs',
|
||||||
|
'disable_plugins',
|
||||||
'PluginDirs',
|
'PluginDirs',
|
||||||
'get_plugin_spec',
|
'get_plugin_spec',
|
||||||
'PACKAGE_NAME',
|
'PACKAGE_NAME',
|
||||||
|
@ -197,7 +199,7 @@ def get_regular_classes(module, module_name, suffix):
|
||||||
def load_plugins(plugin_spec: PluginSpec):
|
def load_plugins(plugin_spec: PluginSpec):
|
||||||
name, suffix = plugin_spec.module_name, plugin_spec.suffix
|
name, suffix = plugin_spec.module_name, plugin_spec.suffix
|
||||||
regular_classes = {}
|
regular_classes = {}
|
||||||
if os.environ.get('YTDLP_NO_PLUGINS'):
|
if os.environ.get('YTDLP_NO_PLUGINS') or plugins_enabled.get() is False:
|
||||||
return regular_classes
|
return regular_classes
|
||||||
|
|
||||||
for finder, module_name, _ in iter_modules(name):
|
for finder, module_name, _ in iter_modules(name):
|
||||||
|
@ -268,3 +270,14 @@ def set_plugin_dirs(*paths):
|
||||||
|
|
||||||
def get_plugin_spec(module_name):
|
def get_plugin_spec(module_name):
|
||||||
return plugin_specs.get().get(module_name)
|
return plugin_specs.get().get(module_name)
|
||||||
|
|
||||||
|
|
||||||
|
def disable_plugins():
|
||||||
|
if (
|
||||||
|
all_plugins_loaded.get()
|
||||||
|
or any(len(plugin_spec.plugin_destination.get()) != 0 for plugin_spec in plugin_specs.get().values())
|
||||||
|
):
|
||||||
|
# note: we can't detect all cases when plugins are loaded (e.g. if spec isn't registered)
|
||||||
|
raise YoutubeDLError('Plugins have already been loaded. Cannot disable plugins after loading plugins.')
|
||||||
|
|
||||||
|
plugins_enabled.set(False)
|
||||||
|
|
Loading…
Reference in a new issue