download strategy validate

This commit is contained in:
Jesse Bannon 2022-10-25 15:31:02 -07:00
parent d3c2c14452
commit c33f0d84ee
7 changed files with 109 additions and 13 deletions

View file

@ -114,6 +114,11 @@ class DownloadStrategyValidator(StrictDictValidator):
Returns
-------
The downloader class
Raises
------
ValidationException
If the download strategy is invalid
"""
try:
return DownloadStrategyMapping.get(
@ -129,15 +134,46 @@ class Preset(StrictDictValidator):
# and ensure required keys are present.
_optional_keys = PRESET_KEYS
@classmethod
def _validate_download_strategy(cls, name: str, value: Dict) -> None:
sources: List[str] = []
for source_name in DownloadStrategyMapping.sources():
if source_name in value:
sources.append(source_name)
if len(sources) > 1:
raise validation_exception(
name=name,
error_message=f"Contains the sources {', '.join(sources)} but can only have one",
)
# If no sources, nothing more to validate
if not sources:
return
source_name = sources[0]
source_dict = copy.deepcopy(value[source_name])
downloader = DownloadStrategyValidator(name=f"{name}.{source_name}", value=source_dict).get(
downloader_source=source_name
)
del source_dict["download_strategy"]
downloader.downloader_options_type.partial_validate(
name=f"{name}.{source_name}", value=source_dict
)
@classmethod
def preset_partial_validate(cls, config: ConfigValidator, name: str, value: Any) -> None:
# Ensure value is a dict
_ = DictValidator(name=name, value=value)
assert isinstance(value, dict)
cls._validate_download_strategy(name, value)
cls._partial_validate_key(name, value, "output_options", OutputOptions)
cls._partial_validate_key(name, value, "ytdl_options", YTDLOptions)
cls._partial_validate_key(name, value, "overrides", Overrides)
for plugin_name in PluginMapping.plugins():
cls._partial_validate_key(
name,

View file

@ -156,6 +156,12 @@ class CollectionValidator(StrictDictValidator, AddsVariablesMixin):
_required_keys = {"urls"}
@classmethod
def partial_validate(cls, name: str, value: Any) -> None:
if isinstance(value, dict):
value["urls"] = value.get("urls", [{"url": "placeholder"}])
_ = cls(name, value)
def __init__(self, name, value):
super().__init__(name, value)
self._urls = self._validate_key(key="urls", validator=CollectionUrlListValidator)

View file

@ -41,9 +41,13 @@ class SharedNfoTagsOptions(PluginOptions):
def __init__(self, name, value):
super().__init__(name, value)
self._nfo_name = self._validate_key(key="nfo_name", validator=StringFormatterValidator)
self._nfo_root = self._validate_key(key="nfo_root", validator=StringFormatterValidator)
self._tags = self._validate_key(key="tags", validator=NfoTagsValidator)
self._nfo_name = self._validate_key_if_present(
key="nfo_name", validator=StringFormatterValidator
)
self._nfo_root = self._validate_key_if_present(
key="nfo_root", validator=StringFormatterValidator
)
self._tags = self._validate_key_if_present(key="tags", validator=NfoTagsValidator)
self._kodi_safe = self._validate_key_if_present(
key="kodi_safe", validator=BoolValidator, default=False
).value

View file

@ -1,6 +0,0 @@
presets:
kodi-music-videos:
preset:
- "jellyfin-music-videos"
- "kodi-safe"

View file

@ -3,7 +3,7 @@ presets:
kodi_music_video:
generic:
download_strategy: "source"
music_video_url: "{music_video_url}"
url: "{music_video_url}"
output_options:
output_directory: "{music_video_directory}"

View file

@ -18,6 +18,7 @@ presets:
collection_season_1:
generic:
download_strategy: "collection"
urls:
- url: "{collection_season_1_url}"
variables:
@ -42,6 +43,7 @@ presets:
collection_season_2:
generic:
download_strategy: "collection"
urls:
- url: "{collection_season_2_url}"
variables:
@ -60,6 +62,7 @@ presets:
collection_season_3:
generic:
download_strategy: "collection"
urls:
- url: "{collection_season_3_url}"
variables:
@ -78,6 +81,7 @@ presets:
collection_season_4:
generic:
download_strategy: "collection"
urls:
- url: "{collection_season_4_url}"
variables:
@ -96,6 +100,7 @@ presets:
collection_season_5:
generic:
download_strategy: "collection"
urls:
- url: "{collection_season_5_url}"
variables:

View file

@ -2,6 +2,7 @@ from typing import Dict
import pytest
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.config.preset import Preset
from ytdl_sub.plugins.nfo_tags import NfoTagsOptions
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
@ -203,6 +204,56 @@ class TestPreset:
},
)
def test_partial_validate(self, config_file):
for preset_name, preset_dict in config_file.presets.dict.items():
Preset.preset_partial_validate(config_file, preset_name, preset_dict)
class TestPresetPartialValidate:
@pytest.mark.parametrize(
"preset_dict",
[
{"nfo_tags": {"tags": {"key-1": "preset_0"}}},
{"output_directory_nfo_tags": {"nfo_root": "test"}},
{"output_directory": {"file_name": "test"}},
{"output_directory": {"keep_files_after": "today"}},
{"ytdl_options": {"format": "best"}},
],
)
def test_partial_validate(self, preset_dict):
_ = ConfigFile(
name="test_partial_validate",
value={
"configuration": {"working_directory": "."},
"presets": {"partial_preset": preset_dict},
},
)
@pytest.mark.parametrize(
"preset_dict",
[
{"youtube": {}, "generic": {}}, # multiple sources
],
)
def test_partial_validate__bad_sources(self, preset_dict):
with pytest.raises(ValidationException):
_ = ConfigFile(
name="test_partial_validate",
value={
"configuration": {"working_directory": "."},
"presets": {"partial_preset": preset_dict},
},
)
@pytest.mark.parametrize(
"preset_dict",
[
{"nfo_tags": {"tags": {"key-1": {"attributes": {"test": "2"}}}}},
{"generic": {"urls": {"variables_to_set": {"name": "value"}}}},
],
)
def test_partial_validate__incomplete_list_item(self, preset_dict):
with pytest.raises(ValidationException):
_ = ConfigFile(
name="test_partial_validate",
value={
"configuration": {"working_directory": "."},
"presets": {"partial_preset": preset_dict},
},
)