diff --git a/src/ytdl_sub/config/preset.py b/src/ytdl_sub/config/preset.py index db77412e..4a4554ca 100644 --- a/src/ytdl_sub/config/preset.py +++ b/src/ytdl_sub/config/preset.py @@ -203,16 +203,18 @@ class Preset(StrictDictValidator): # Validate added download option variables here since plugins could subsequently use them self.downloader_options.validate_with_variables( - source_variables=source_variables, override_variables=self.overrides.keys + source_variables=source_variables, + override_variables=self.overrides.dict_with_format_strings, ) source_variables.extend(self.downloader_options.added_source_variables()) - for plugin_options in sorted( - self.plugins.plugin_options, key=lambda pl_options: pl_options.priority.modify_entry + for _, plugin_options in sorted( + self.plugins.zipped(), key=lambda pl: pl[0].priority.modify_entry ): # Validate current plugin using source + added plugin variables plugin_options.validate_with_variables( - source_variables=source_variables, override_variables=self.overrides.keys + source_variables=source_variables, + override_variables=self.overrides.dict_with_format_strings, ) # Extend existing source variables with ones created from this plugin diff --git a/src/ytdl_sub/config/preset_options.py b/src/ytdl_sub/config/preset_options.py index ed96b333..2a67b011 100644 --- a/src/ytdl_sub/config/preset_options.py +++ b/src/ytdl_sub/config/preset_options.py @@ -33,7 +33,7 @@ class AddsVariablesMixin(ABC): return [] def validate_with_variables( - self, source_variables: List[str], override_variables: List[str] + self, source_variables: List[str], override_variables: Dict[str, str] ) -> None: """ Optional validation after init with the session's source and override variables. diff --git a/src/ytdl_sub/downloaders/generic/collection.py b/src/ytdl_sub/downloaders/generic/collection.py index ef42e64b..3488b672 100644 --- a/src/ytdl_sub/downloaders/generic/collection.py +++ b/src/ytdl_sub/downloaders/generic/collection.py @@ -13,6 +13,7 @@ from ytdl_sub.entries.entry_parent import EntryParent from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.validators.strict_dict_validator import StrictDictValidator from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator +from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator from ytdl_sub.validators.validators import ListValidator from ytdl_sub.validators.validators import StringValidator @@ -124,19 +125,29 @@ class CollectionDownloadOptions(DownloaderValidator): return list(self._urls.list[0].variables.keys()) def validate_with_variables( - self, source_variables: List[str], override_variables: List[str] + self, source_variables: List[str], override_variables: Dict[str, str] ) -> None: """ Ensures new variables added are not existing variables """ - # TODO: Make sure they resolve - for added_source_var in self.added_source_variables(): - if added_source_var in source_variables: + for source_var_name in self.added_source_variables(): + if source_var_name in source_variables: raise self._validation_exception( - f"'{added_source_var}' cannot be used as a variable name because it " + f"'{source_var_name}' cannot be used as a variable name because it " f"is an existing source variable" ) + base_variables = dict( + override_variables, **{source_var: "dummy_string" for source_var in source_variables} + ) + + # Apply formatting to each new source variable, ensure it resolves + for collection_url in self.collection_urls.list: + for source_var_name, source_var_formatter_str in collection_url.variables.items(): + _ = StringFormatterValidator( + name=f"{self._name}.{source_var_name}", value=source_var_formatter_str + ).apply_formatter(base_variables) + class CollectionDownloader(Downloader[CollectionDownloadOptions, Entry]): downloader_options_type = CollectionDownloadOptions diff --git a/src/ytdl_sub/plugins/regex.py b/src/ytdl_sub/plugins/regex.py index 34070fbd..b818e9da 100644 --- a/src/ytdl_sub/plugins/regex.py +++ b/src/ytdl_sub/plugins/regex.py @@ -165,7 +165,7 @@ class RegexOptions(PluginOptions): return self._skip_if_match_fails def validate_with_variables( - self, source_variables: List[str], override_variables: List[str] + self, source_variables: List[str], override_variables: Dict[str, str] ) -> None: """ Ensures each source variable capture group is valid