diff --git a/src/ytdl_sub/downloaders/url/multi_url.py b/src/ytdl_sub/downloaders/url/multi_url.py index 43599781..a4ada5e7 100644 --- a/src/ytdl_sub/downloaders/url/multi_url.py +++ b/src/ytdl_sub/downloaders/url/multi_url.py @@ -1,3 +1,6 @@ +from typing import Dict +from typing import List + from ytdl_sub.downloaders.url.downloader import BaseUrlDownloader from ytdl_sub.downloaders.url.downloader import DownloaderValidator from ytdl_sub.downloaders.url.validators import MultiUrlValidator @@ -43,6 +46,23 @@ class MultiUrlDownloadOptions(MultiUrlValidator, DownloaderValidator): """Returns itself!""" return self + def validate_with_variables( + self, source_variables: List[str], override_variables: Dict[str, str] + ) -> None: + """ + Validates any source variables added by the collection + """ + super().validate_with_variables( + source_variables=source_variables, override_variables=override_variables + ) + + has_non_empty_url = False + for url_validator in self.urls.list: + has_non_empty_url |= bool(url_validator.url.apply_formatter(override_variables)) + + if not has_non_empty_url: + raise self._validation_exception("Must contain at least one url that is non-empty") + class MultiUrlDownloader(BaseUrlDownloader[MultiUrlDownloadOptions]): downloader_options_type = MultiUrlDownloadOptions diff --git a/src/ytdl_sub/downloaders/url/validators.py b/src/ytdl_sub/downloaders/url/validators.py index 5694a7ba..36e1fc36 100644 --- a/src/ytdl_sub/downloaders/url/validators.py +++ b/src/ytdl_sub/downloaders/url/validators.py @@ -156,8 +156,8 @@ class UrlListValidator(ListValidator[UrlValidator]): added_variables: Dict[str, str] = self.list[0].variables.dict_with_format_strings - for idx, collection_url_validator in enumerate(self.list[1:]): - collection_variables = collection_url_validator.variables.dict_with_format_strings + for idx, url_validator in enumerate(self.list[1:]): + collection_variables = url_validator.variables.dict_with_format_strings # see if this collection contains new added vars (it should not) for var in collection_variables.keys(): diff --git a/tests/unit/config/test_preset.py b/tests/unit/config/test_preset.py index 4fc87fe0..e6d65fe8 100644 --- a/tests/unit/config/test_preset.py +++ b/tests/unit/config/test_preset.py @@ -1,6 +1,9 @@ +import re + import pytest from ytdl_sub.config.preset import Preset +from ytdl_sub.downloaders.url.multi_url import MultiUrlDownloadOptions from ytdl_sub.plugins.nfo_tags import NfoTagsOptions from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException from ytdl_sub.utils.exceptions import ValidationException @@ -192,7 +195,7 @@ class TestPreset: name="test", value={ "download": youtube_video, - "output_options": {"output_directory": "dir", "file_name": "file"}, + "output_options": output_options, "output_directory_nfo_tags": { "nfo_name": "the nfo name", "nfo_root": "the root", @@ -200,3 +203,39 @@ class TestPreset: }, }, ) + + def test_preset_with_multi_url__contains_empty_url(self, config_file, output_options): + _ = Preset( + config=config_file, + name="test", + value={ + "download": { + "download_strategy": "multi_url", + "urls": [{"url": "non-empty url"}, {"url": ""}], # empty url + }, + "output_options": output_options, + }, + ) + + def test_preset_with_multi_url__contains_all_empty_urls_errors( + self, config_file, output_options + ): + with pytest.raises( + ValidationException, + match=re.escape( + "Validation error in test.download: Must contain at least one " + "url that is non-empty" + ), + ): + _ = Preset( + config=config_file, + name="test", + value={ + "download": { + "download_strategy": "multi_url", + "urls": [{"url": "{url}"}, {"url": "{url2}"}], + }, + "output_options": output_options, + "overrides": {"url": "", "url2": ""}, + }, + )