mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-07-13 16:58:32 +00:00
jsi override
This commit is contained in:
parent
d74f921e37
commit
f058874929
@ -124,6 +124,11 @@ def test_jsi_runtime_classes(self):
|
||||
self.assertIn(f'{PACKAGE_NAME}.jsinterp.normal', sys.modules.keys())
|
||||
self.assertIn('NormalPluginJSI', plugin_jsis.value)
|
||||
|
||||
self.assertNotIn('OverrideDenoJSI', plugins_jsi.keys())
|
||||
self.assertNotIn('OverrideDenoJSI', plugin_jsis.value)
|
||||
self.assertNotIn('_UnderscoreOverrideDenoJSI', plugins_jsi.keys())
|
||||
self.assertNotIn('_UnderscoreOverrideDenoJSI', plugin_jsis.value)
|
||||
|
||||
def test_importing_zipped_module(self):
|
||||
zip_path = TEST_DATA_DIR / 'zipped_plugins.zip'
|
||||
shutil.make_archive(str(zip_path)[:-4], 'zip', str(zip_path)[:-4])
|
||||
@ -209,6 +214,24 @@ def test_extractor_override_plugin(self):
|
||||
from yt_dlp.extractor.generic import GenericIE
|
||||
self.assertEqual(GenericIE.IE_NAME, 'generic+override+underscore-override')
|
||||
|
||||
def test_jsi_override_plugin(self):
|
||||
load_plugins(JSI_PLUGIN_SPEC)
|
||||
|
||||
from yt_dlp.jsinterp._deno import DenoJSI
|
||||
|
||||
# test that jsi_runtimes is updated with override jsi
|
||||
self.assertTrue(DenoJSI is jsi_runtimes.value['Deno'])
|
||||
self.assertEqual(jsi_runtimes.value['Deno'].TEST_FIELD, 'override')
|
||||
self.assertEqual(jsi_runtimes.value['Deno'].SECONDARY_TEST_FIELD, 'underscore-override')
|
||||
|
||||
self.assertEqual(jsi_runtimes.value['Deno'].JSI_NAME, 'Deno+override+underscore-override')
|
||||
importlib.invalidate_caches()
|
||||
# test that loading a second time doesn't wrap a second time
|
||||
load_plugins(EXTRACTOR_PLUGIN_SPEC)
|
||||
from yt_dlp.jsinterp._deno import DenoJSI
|
||||
self.assertTrue(DenoJSI is jsi_runtimes.value['Deno'])
|
||||
self.assertEqual(jsi_runtimes.value['Deno'].JSI_NAME, 'Deno+override+underscore-override')
|
||||
|
||||
def test_load_all_plugin_types(self):
|
||||
|
||||
# no plugin specs registered
|
||||
|
5
test/testdata/yt_dlp_plugins/jsinterp/override.py
vendored
Normal file
5
test/testdata/yt_dlp_plugins/jsinterp/override.py
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
from yt_dlp.jsinterp._deno import DenoJSI
|
||||
|
||||
|
||||
class OverrideDenoJSI(DenoJSI, plugin_name='override'):
|
||||
TEST_FIELD = 'override'
|
5
test/testdata/yt_dlp_plugins/jsinterp/overridetwo.py
vendored
Normal file
5
test/testdata/yt_dlp_plugins/jsinterp/overridetwo.py
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
from yt_dlp.jsinterp._deno import DenoJSI
|
||||
|
||||
|
||||
class _UnderscoreOverrideDenoJSI(DenoJSI, plugin_name='underscore-override'):
|
||||
SECONDARY_TEST_FIELD = 'underscore-override'
|
@ -39,6 +39,8 @@
|
||||
plugin_ies,
|
||||
plugin_ies_overrides,
|
||||
plugin_pps,
|
||||
plugin_jsis,
|
||||
plugin_jsis_overrides,
|
||||
all_plugins_loaded,
|
||||
plugin_dirs,
|
||||
)
|
||||
@ -4090,13 +4092,17 @@ def get_encoding(stream):
|
||||
write_debug(f'Proxy map: {self.proxies}')
|
||||
write_debug(f'Request Handlers: {", ".join(rh.RH_NAME for rh in self._request_director.handlers.values())}')
|
||||
|
||||
for plugin_type, plugins in (('Extractor', plugin_ies), ('Post-Processor', plugin_pps)):
|
||||
for plugin_type, plugins in (('Extractor', plugin_ies), ('Post-Processor', plugin_pps),
|
||||
('JSI-Runtime', plugin_jsis)):
|
||||
display_list = [
|
||||
klass.__name__ if klass.__name__ == name else f'{klass.__name__} as {name}'
|
||||
for name, klass in plugins.value.items()]
|
||||
if plugin_type == 'Extractor':
|
||||
display_list.extend(f'{plugins[-1].IE_NAME.partition("+")[2]} ({parent.__name__})'
|
||||
for parent, plugins in plugin_ies_overrides.value.items())
|
||||
elif plugin_type == 'JSI-Runtime':
|
||||
display_list.extend(f'{plugins[-1].JSI_NAME.partition("+")[2]} ({parent.__name__})'
|
||||
for parent, plugins in plugin_jsis_overrides.value.items())
|
||||
if not display_list:
|
||||
continue
|
||||
write_debug(f'{plugin_type} Plugins: {", ".join(sorted(display_list))}')
|
||||
|
@ -26,6 +26,7 @@ def __repr__(self, /):
|
||||
plugin_pps = Indirect({})
|
||||
plugin_jsis = Indirect({})
|
||||
plugin_ies_overrides = Indirect(defaultdict(list))
|
||||
plugin_jsis_overrides = Indirect(defaultdict(list))
|
||||
|
||||
# Misc
|
||||
IN_CLI = Indirect(False)
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
import abc
|
||||
import inspect
|
||||
import sys
|
||||
import typing
|
||||
|
||||
from ..globals import jsi_runtimes
|
||||
from ..globals import jsi_runtimes, plugin_jsis_overrides
|
||||
from ..extractor.common import InfoExtractor
|
||||
from ..utils import (
|
||||
classproperty,
|
||||
@ -214,24 +215,44 @@ def __init__(self, downloader: YoutubeDL, url: str, timeout: float | int, user_a
|
||||
self.timeout = timeout
|
||||
self.user_agent: str = user_agent or self._downloader.params['http_headers']['User-Agent']
|
||||
|
||||
@classmethod
|
||||
def __init_subclass__(cls, *, plugin_name=None, **kwargs):
|
||||
if plugin_name:
|
||||
mro = inspect.getmro(cls)
|
||||
next_mro_class = super_class = mro[mro.index(cls) + 1]
|
||||
|
||||
while getattr(super_class, '__wrapped__', None):
|
||||
super_class = super_class.__wrapped__
|
||||
|
||||
if not any(override.PLUGIN_NAME == plugin_name for override in plugin_jsis_overrides.value[super_class]):
|
||||
cls.__wrapped__ = next_mro_class
|
||||
cls.PLUGIN_NAME, cls.JSI_KEY = plugin_name, next_mro_class.JSI_KEY
|
||||
cls.JSI_NAME = f'{next_mro_class.JSI_NAME}+{plugin_name}'
|
||||
|
||||
setattr(sys.modules[super_class.__module__], super_class.__name__, cls)
|
||||
# additional update jsi_runtime because jsis are not further loaded like extractors
|
||||
jsi_runtimes.value[super_class.JSI_KEY] = cls
|
||||
plugin_jsis_overrides.value[super_class].append(cls)
|
||||
return super().__init_subclass__(**kwargs)
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_available(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def write_debug(self, message, *args, **kwargs):
|
||||
self._downloader.write_debug(f'[{self.JSI_KEY}] {message}', *args, **kwargs)
|
||||
def write_debug(self, msg, *args, **kwargs):
|
||||
self._downloader.write_debug(f'[{self.JSI_NAME}] {msg}', *args, **kwargs)
|
||||
|
||||
def report_warning(self, message, *args, **kwargs):
|
||||
self._downloader.report_warning(f'[{self.JSI_KEY}] {message}', *args, **kwargs)
|
||||
def report_warning(self, msg, *args, **kwargs):
|
||||
self._downloader.report_warning(f'[{self.JSI_NAME}] {msg}', *args, **kwargs)
|
||||
|
||||
def to_screen(self, msg, *args, **kwargs):
|
||||
self._downloader.to_screen(f'[{self.JSI_KEY}] {msg}', *args, **kwargs)
|
||||
self._downloader.to_screen(f'[{self.JSI_NAME}] {msg}', *args, **kwargs)
|
||||
|
||||
def report_note(self, video_id, note):
|
||||
self.to_screen(f'{format_field(video_id, None, "%s: ")}{note}')
|
||||
|
||||
def report_version(self):
|
||||
raise NotImplementedError
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def supports_extractor(cls, ie_key: str):
|
||||
|
Loading…
Reference in New Issue
Block a user