mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-03-09 12:50:23 -05:00
update
This commit is contained in:
parent
e0697299b6
commit
87218ed239
4 changed files with 21 additions and 25 deletions
|
@ -218,7 +218,7 @@ class TestPhantomJS(Base.TestExternalJSI):
|
||||||
_JSI_CLASS = PhantomJSJSI
|
_JSI_CLASS = PhantomJSJSI
|
||||||
|
|
||||||
|
|
||||||
expect_covered_features = set(_ALL_FEATURES) - {'js'}
|
expect_covered_features = set(_ALL_FEATURES)
|
||||||
assert covered_features.issuperset(expect_covered_features), f'Missing tests for features: {expect_covered_features - covered_features}'
|
assert covered_features.issuperset(expect_covered_features), f'Missing tests for features: {expect_covered_features - covered_features}'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
@register_jsi
|
@register_jsi
|
||||||
class DenoJSI(ExternalJSI):
|
class DenoJSI(ExternalJSI):
|
||||||
"""JS interpreter class using Deno binary"""
|
"""JS interpreter class using Deno binary"""
|
||||||
_SUPPORTED_FEATURES = {'js', 'wasm', 'location'}
|
_SUPPORTED_FEATURES = {'wasm', 'location'}
|
||||||
_BASE_PREFERENCE = 5
|
_BASE_PREFERENCE = 5
|
||||||
_EXE_NAME = 'deno'
|
_EXE_NAME = 'deno'
|
||||||
_DENO_FLAGS = ['--cached-only', '--no-prompt', '--no-check']
|
_DENO_FLAGS = ['--cached-only', '--no-prompt', '--no-check']
|
||||||
|
@ -60,7 +60,7 @@ def execute(self, jscode, video_id=None, note='Executing JS in Deno'):
|
||||||
|
|
||||||
@register_jsi
|
@register_jsi
|
||||||
class DenoJITlessJSI(DenoJSI):
|
class DenoJITlessJSI(DenoJSI):
|
||||||
_SUPPORTED_FEATURES = {'js', 'location'}
|
_SUPPORTED_FEATURES = {'location'}
|
||||||
_BASE_PREFERENCE = 6
|
_BASE_PREFERENCE = 6
|
||||||
_EXE_NAME = DenoJSI._EXE_NAME
|
_EXE_NAME = DenoJSI._EXE_NAME
|
||||||
_DENO_FLAGS = ['--cached-only', '--no-prompt', '--no-check', '--v8-flags=--jitless,--noexpose-wasm']
|
_DENO_FLAGS = ['--cached-only', '--no-prompt', '--no-check', '--v8-flags=--jitless,--noexpose-wasm']
|
||||||
|
@ -72,7 +72,7 @@ def exe_version(cls):
|
||||||
|
|
||||||
@register_jsi
|
@register_jsi
|
||||||
class DenoJSDomJSI(DenoJSI):
|
class DenoJSDomJSI(DenoJSI):
|
||||||
_SUPPORTED_FEATURES = {'js', 'wasm', 'location', 'dom', 'cookies'}
|
_SUPPORTED_FEATURES = {'wasm', 'location', 'dom', 'cookies'}
|
||||||
_BASE_PREFERENCE = 4
|
_BASE_PREFERENCE = 4
|
||||||
_DENO_FLAGS = ['--cached-only', '--no-prompt', '--no-check']
|
_DENO_FLAGS = ['--cached-only', '--no-prompt', '--no-check']
|
||||||
_JSDOM_IMPORT_CHECKED = False
|
_JSDOM_IMPORT_CHECKED = False
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
@register_jsi
|
@register_jsi
|
||||||
class PhantomJSJSI(ExternalJSI):
|
class PhantomJSJSI(ExternalJSI):
|
||||||
_EXE_NAME = 'phantomjs'
|
_EXE_NAME = 'phantomjs'
|
||||||
_SUPPORTED_FEATURES = {'js', 'location', 'cookies', 'dom'}
|
_SUPPORTED_FEATURES = {'location', 'cookies', 'dom'}
|
||||||
_BASE_PREFERENCE = 3
|
_BASE_PREFERENCE = 3
|
||||||
|
|
||||||
_BASE_JS = R'''
|
_BASE_JS = R'''
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
_JSI_HANDLERS: dict[str, type[JSI]] = {}
|
_JSI_HANDLERS: dict[str, type[JSI]] = {}
|
||||||
_JSI_PREFERENCES: set[JSIPreference] = set()
|
_JSI_PREFERENCES: set[JSIPreference] = set()
|
||||||
_ALL_FEATURES = {
|
_ALL_FEATURES = {
|
||||||
'js',
|
|
||||||
'wasm',
|
'wasm',
|
||||||
'location',
|
'location',
|
||||||
'dom',
|
'dom',
|
||||||
|
@ -41,10 +40,6 @@ def _pref(jsi: JSI, *args):
|
||||||
return _pref
|
return _pref
|
||||||
|
|
||||||
|
|
||||||
def join_jsi_name(jsi_list: typing.Iterable[str | type[JSI] | JSI], sep=', '):
|
|
||||||
return sep.join(get_jsi_keys(jok if isinstance(jok, str) else jok.JSI_NAME for jok in jsi_list))
|
|
||||||
|
|
||||||
|
|
||||||
def require_features(param_features: dict[str, str | typing.Iterable[str]]):
|
def require_features(param_features: dict[str, str | typing.Iterable[str]]):
|
||||||
assert all(_ALL_FEATURES.issuperset(variadic(kw_feature)) for kw_feature in param_features.values())
|
assert all(_ALL_FEATURES.issuperset(variadic(kw_feature)) for kw_feature in param_features.values())
|
||||||
|
|
||||||
|
@ -73,15 +68,14 @@ def _real_extract(self, url):
|
||||||
```
|
```
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
- `js`: supports js syntax
|
- `wasm`: supports window.WebAssembly
|
||||||
- `wasm`: supports WebAssembly interface
|
- `location`: supports mocking window.location
|
||||||
- `location`: supports setting window.location
|
- `dom`: supports DOM interface (not necessarily rendering)
|
||||||
- `dom`: supports DOM interface
|
|
||||||
- `cookies`: supports document.cookie read & write
|
- `cookies`: supports document.cookie read & write
|
||||||
|
|
||||||
@param dl_or_ie: `YoutubeDL` or `InfoExtractor` instance.
|
@param dl_or_ie: `YoutubeDL` or `InfoExtractor` instance.
|
||||||
@param url: setting url context, used by JSI that supports `location` feature
|
@param url: setting url context, used by JSI that supports `location` feature
|
||||||
@param features: list of features that are necessary for JS interpretation.
|
@param features: only JSI that supports all of these features will be selected
|
||||||
@param only_include: limit JSI to choose from.
|
@param only_include: limit JSI to choose from.
|
||||||
@param exclude: JSI to avoid using.
|
@param exclude: JSI to avoid using.
|
||||||
@param jsi_params: extra kwargs to pass to `JSI.__init__()` for each JSI, using jsi key as dict key.
|
@param jsi_params: extra kwargs to pass to `JSI.__init__()` for each JSI, using jsi key as dict key.
|
||||||
|
@ -94,7 +88,7 @@ def _real_extract(self, url):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
dl_or_ie: YoutubeDL | InfoExtractor,
|
dl_or_ie: YoutubeDL | InfoExtractor,
|
||||||
url: str,
|
url: str = '',
|
||||||
features: typing.Iterable[str] = [],
|
features: typing.Iterable[str] = [],
|
||||||
only_include: typing.Iterable[str | type[JSI]] = [],
|
only_include: typing.Iterable[str | type[JSI]] = [],
|
||||||
exclude: typing.Iterable[str | type[JSI]] = [],
|
exclude: typing.Iterable[str | type[JSI]] = [],
|
||||||
|
@ -119,11 +113,13 @@ def __init__(
|
||||||
if _JSI_HANDLERS[key]._SUPPORTED_FEATURES.issuperset(self._features)]
|
if _JSI_HANDLERS[key]._SUPPORTED_FEATURES.issuperset(self._features)]
|
||||||
self.write_debug(f'Select JSI for features={self._features}: {get_jsi_keys(handler_classes)}, '
|
self.write_debug(f'Select JSI for features={self._features}: {get_jsi_keys(handler_classes)}, '
|
||||||
f'included: {get_jsi_keys(only_include) or "all"}, excluded: {get_jsi_keys(exclude)}')
|
f'included: {get_jsi_keys(only_include) or "all"}, excluded: {get_jsi_keys(exclude)}')
|
||||||
|
if not handler_classes:
|
||||||
|
raise ExtractorError(f'No JSI supports features={self._features}')
|
||||||
|
|
||||||
self._handler_dict = {
|
self._handler_dict = {cls.JSI_KEY: cls(
|
||||||
cls.JSI_KEY: cls(self._downloader, url=self._url, timeout=timeout,
|
self._downloader, url=self._url, timeout=timeout, features=self._features,
|
||||||
features=self._features, user_agent=user_agent,
|
user_agent=user_agent, **jsi_params.get(cls.JSI_KEY, {})
|
||||||
**jsi_params.get(cls.JSI_KEY, {})) for cls in handler_classes}
|
) for cls in handler_classes}
|
||||||
self.preferences: set[JSIPreference] = {order_to_pref(preferred_order, 100)} | _JSI_PREFERENCES
|
self.preferences: set[JSIPreference] = {order_to_pref(preferred_order, 100)} | _JSI_PREFERENCES
|
||||||
self._fallback_jsi = get_jsi_keys(handler_classes) if fallback_jsi == 'all' else get_jsi_keys(fallback_jsi)
|
self._fallback_jsi = get_jsi_keys(handler_classes) if fallback_jsi == 'all' else get_jsi_keys(fallback_jsi)
|
||||||
self._is_test = self._downloader.params.get('test', False)
|
self._is_test = self._downloader.params.get('test', False)
|
||||||
|
@ -153,7 +149,7 @@ def _get_handlers(self, method_name: str, *args, **kwargs) -> list[JSI]:
|
||||||
def _dispatch_request(self, method_name: str, *args, **kwargs):
|
def _dispatch_request(self, method_name: str, *args, **kwargs):
|
||||||
handlers = self._get_handlers(method_name, *args, **kwargs)
|
handlers = self._get_handlers(method_name, *args, **kwargs)
|
||||||
|
|
||||||
unavailable: list[JSI] = []
|
unavailable: list[str] = []
|
||||||
exceptions: list[tuple[JSI, Exception]] = []
|
exceptions: list[tuple[JSI, Exception]] = []
|
||||||
test_results: list[tuple[JSI, typing.Any]] = []
|
test_results: list[tuple[JSI, typing.Any]] = []
|
||||||
|
|
||||||
|
@ -162,8 +158,8 @@ def _dispatch_request(self, method_name: str, *args, **kwargs):
|
||||||
if self._is_test:
|
if self._is_test:
|
||||||
raise Exception(f'{handler.JSI_NAME} is not available for testing, '
|
raise Exception(f'{handler.JSI_NAME} is not available for testing, '
|
||||||
f'add "{handler.JSI_KEY}" in `exclude` if it should not be used')
|
f'add "{handler.JSI_KEY}" in `exclude` if it should not be used')
|
||||||
self.write_debug(f'{handler.JSI_NAME} is not available')
|
self.write_debug(f'{handler.JSI_KEY} is not available')
|
||||||
unavailable.append(handler)
|
unavailable.append(handler.JSI_NAME)
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
self.write_debug(f'Dispatching `{method_name}` task to {handler.JSI_NAME}')
|
self.write_debug(f'Dispatching `{method_name}` task to {handler.JSI_NAME}')
|
||||||
|
@ -188,11 +184,11 @@ def _dispatch_request(self, method_name: str, *args, **kwargs):
|
||||||
return ref_result
|
return ref_result
|
||||||
|
|
||||||
if not exceptions:
|
if not exceptions:
|
||||||
msg = f'No available JSI installed, please install one of: {join_jsi_name(unavailable)}'
|
msg = f'No available JSI installed, please install one of: {", ".join(unavailable)}'
|
||||||
else:
|
else:
|
||||||
msg = f'Failed to perform {method_name}, total {len(exceptions)} errors'
|
msg = f'Failed to perform {method_name}, total {len(exceptions)} errors'
|
||||||
if unavailable:
|
if unavailable:
|
||||||
msg = f'{msg}. You can try installing one of unavailable JSI: {join_jsi_name(unavailable)}'
|
msg = f'{msg}. You can try installing one of unavailable JSI: {", ".join(unavailable)}'
|
||||||
raise ExtractorError(msg)
|
raise ExtractorError(msg)
|
||||||
|
|
||||||
@require_features({'location': 'location', 'html': 'dom', 'cookiejar': 'cookies'})
|
@require_features({'location': 'location', 'html': 'dom', 'cookiejar': 'cookies'})
|
||||||
|
|
Loading…
Reference in a new issue