[BUGFIX] Fix variable collision when disabling plugins (#1072)

Fixes https://github.com/jmbannon/ytdl-sub/issues/1071
This commit is contained in:
Jesse Bannon 2024-09-29 22:38:26 -07:00 committed by GitHub
parent 1b57d79c8f
commit f2ec26d77e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 84 additions and 31 deletions

View file

@ -2,7 +2,6 @@ from enum import Enum
class PluginOperation(Enum):
ANY = -2
DOWNLOADER = -1
MODIFY_ENTRY_METADATA = 0
MODIFY_ENTRY = 1

View file

@ -42,9 +42,7 @@ class OptionsValidator(Validator, ABC):
def added_variables(
self,
resolved_variables: Set[str],
unresolved_variables: Set[str],
plugin_op: PluginOperation,
) -> Dict[PluginOperation, Set[str]]:
"""
If the plugin adds source variables, list them here.

View file

@ -70,9 +70,7 @@ def _get_added_and_modified_variables(
modified_variables: Set[str] = set()
for plugin_added_variables in plugin_options.added_variables(
resolved_variables=set(),
unresolved_variables=set(),
plugin_op=PluginOperation.ANY,
).values():
added_variables |= set(plugin_added_variables)
@ -167,9 +165,7 @@ class VariableValidation:
Add dummy variables for script validation
"""
added_variables = options.added_variables(
resolved_variables=self.resolved_variables,
unresolved_variables=self.unresolved_variables,
plugin_op=plugin_op,
).get(plugin_op, set())
modified_variables = options.modified_variables().get(plugin_op, set())

View file

@ -320,24 +320,21 @@ class MultiUrlValidator(OptionsValidator):
def added_variables(
self,
resolved_variables: Set[str],
unresolved_variables: Set[str],
plugin_op: PluginOperation,
) -> Dict[PluginOperation, Set[str]]:
"""
Returns
-------
List of variables added. The first collection url always contains all the variables.
"""
if plugin_op != PluginOperation.ANY:
for url in self._urls.list:
for variable_name, definition in url.variables.dict_with_format_strings.items():
used_variables = set(var.name for var in parse(definition).variables)
if unresolved := used_variables & unresolved_variables:
raise self._validation_exception(
f"variable {variable_name} cannot use the variables "
f"{', '.join(sorted(list(unresolved)))} because it depends on other"
" variables that are computed later in execution"
)
for url in self._urls.list:
for variable_name, definition in url.variables.dict_with_format_strings.items():
used_variables = set(var.name for var in parse(definition).variables)
if unresolved := used_variables & unresolved_variables:
raise self._validation_exception(
f"variable {variable_name} cannot use the variables "
f"{', '.join(sorted(list(unresolved)))} because it depends on other"
" variables that are computed later in execution"
)
return {PluginOperation.DOWNLOADER: set(self._urls.list[0].variables.keys)}

View file

@ -207,9 +207,7 @@ class ChaptersOptions(ToggleableOptionsDictValidator):
def added_variables(
self,
resolved_variables: Set[str],
unresolved_variables: Set[str],
plugin_op: PluginOperation,
) -> Dict[PluginOperation, Set[str]]:
return {PluginOperation.MODIFY_ENTRY: {ytdl_sub_chapters_from_comments.variable_name}}

View file

@ -82,9 +82,7 @@ class SplitByChaptersOptions(OptionsDictValidator):
def added_variables(
self,
resolved_variables: Set[str],
unresolved_variables: Set[str],
plugin_op: PluginOperation,
) -> Dict[PluginOperation, Set[str]]:
return {
PluginOperation.MODIFY_ENTRY: {

View file

@ -132,9 +132,7 @@ class SubtitleOptions(ToggleableOptionsDictValidator):
def added_variables(
self,
resolved_variables: Set[str],
unresolved_variables: Set[str],
plugin_op: PluginOperation,
) -> Dict[PluginOperation, Set[str]]:
"""
Returns

View file

@ -190,15 +190,24 @@ class SubscriptionDownload(BaseSubscription, ABC):
-------
List of plugins defined in the subscription, initialized and ready to use.
"""
plugins = [
plugin_type(
initialized_plugins: List[Plugin] = []
for plugin_type, plugin_options in self.plugins.zipped():
plugin = plugin_type(
options=plugin_options,
overrides=self.overrides,
enhanced_download_archive=self.download_archive,
)
for plugin_type, plugin_options in self.plugins.zipped()
]
return [plugin for plugin in plugins if plugin.is_enabled]
if plugin.is_enabled:
initialized_plugins.append(plugin)
else:
# Set any plugin variables to null if it is disabled
for variable_set in plugin_options.added_variables(
unresolved_variables=self.overrides.unresolvable
).values():
nulled_variable_set = {var_name: "" for var_name in variable_set}
self.overrides.add(nulled_variable_set)
return initialized_plugins
@classmethod
def _cleanup_entry_files(cls, entry: Entry):

View file

@ -0,0 +1,60 @@
from typing import Dict
import pytest
from ytdl_sub.entries.entry import ytdl_sub_chapters_from_comments
from ytdl_sub.subscriptions.subscription import Subscription
@pytest.fixture
def sponsorblock_disabled_dict(output_directory) -> Dict:
return {
"preset": "Jellyfin Music Videos",
"output_options": {"output_directory": output_directory},
"chapters": {
"enable": "{enable_sponsorblock}",
"sponsorblock_categories": [
"outro",
"selfpromo",
"preview",
"interaction",
"sponsor",
"music_offtopic",
"intro",
],
"remove_sponsorblock_categories": "all",
"remove_chapters_regex": [
"Intro",
"Outro",
],
},
"overrides": {
"music_video_artist": "JMC",
"url": "https://your.name.here",
"enable_sponsorblock": "False",
},
}
class TestChapters:
def test_chapters_disabled_respected(
self,
config,
subscription_name,
sponsorblock_disabled_dict,
output_directory,
mock_download_collection_entries,
):
subscription = Subscription.from_dict(
config=config,
preset_name=subscription_name,
preset_dict=sponsorblock_disabled_dict,
)
with mock_download_collection_entries(
is_youtube_channel=False, num_urls=1, is_extracted_audio=False, is_dry_run=True
):
_ = subscription.download(dry_run=True)
script = subscription.overrides.script
assert script.get(ytdl_sub_chapters_from_comments.variable_name).native == ""

View file

@ -19,7 +19,7 @@ def regex_subscription_dict_base(output_directory):
"filter_include": ["{%not(%is_null(description_website))}"],
"overrides": {
"in_regex_default": "in regex default",
"url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35",
"url": "https://your.name.here",
"upload_capture": """{
%regex_capture_many_with_defaults(
upload_date_standardized,