cleaned up preset validation
This commit is contained in:
parent
5e85d23217
commit
aca7a461b0
3 changed files with 72 additions and 87 deletions
|
|
@ -38,6 +38,7 @@ from ytdl_sub.validators.string_formatter_validators import DictFormatterValidat
|
|||
from ytdl_sub.validators.string_formatter_validators import OverridesDictFormatterValidator
|
||||
from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator
|
||||
from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator
|
||||
from ytdl_sub.validators.string_formatter_validators import validate_formatters
|
||||
from ytdl_sub.validators.validators import DictValidator
|
||||
from ytdl_sub.validators.validators import ListValidator
|
||||
from ytdl_sub.validators.validators import StringListValidator
|
||||
|
|
@ -202,7 +203,7 @@ class Preset(_PresetShell):
|
|||
script = copy.deepcopy(self.overrides.script).add(
|
||||
ScriptUtils.add_dummy_variables(self._source_variables)
|
||||
)
|
||||
unresolved_variables = copy.deepcopy(self._added_variables)
|
||||
unresolved_variables = self._added_variables
|
||||
|
||||
added_variables: Set[str] = self.downloader_options.added_source_variables(
|
||||
unresolved_variables
|
||||
|
|
@ -236,14 +237,14 @@ class Preset(_PresetShell):
|
|||
_ = script.resolve(unresolvable=unresolved_variables, update=True)
|
||||
|
||||
# Validate that any formatter in the plugin options can resolve
|
||||
self._validate_formatters(
|
||||
mock_script=script,
|
||||
validate_formatters(
|
||||
script=script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
validator=plugin_options,
|
||||
)
|
||||
|
||||
self._validate_formatters(
|
||||
mock_script=script,
|
||||
validate_formatters(
|
||||
script=script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
validator=self.output_options,
|
||||
)
|
||||
|
|
@ -252,66 +253,6 @@ class Preset(_PresetShell):
|
|||
|
||||
return script
|
||||
|
||||
def _validate_string_formatter_validator(
|
||||
self,
|
||||
mock_script: Script,
|
||||
unresolved_variables: Set[str],
|
||||
formatter_validator: Union[StringFormatterValidator, OverridesStringFormatterValidator],
|
||||
) -> None:
|
||||
try:
|
||||
unresolvable = unresolved_variables
|
||||
if isinstance(formatter_validator, OverridesStringFormatterValidator):
|
||||
unresolvable = unresolved_variables.union({VARIABLES.entry_metadata.variable_name})
|
||||
|
||||
mock_script.resolve_once(
|
||||
{"tmp_var": formatter_validator.format_string},
|
||||
unresolvable=unresolvable,
|
||||
)
|
||||
except VariableDoesNotExist as exc:
|
||||
raise StringFormattingVariableNotFoundException(exc) from exc
|
||||
|
||||
def _validate_formatters(
|
||||
self,
|
||||
mock_script: Script,
|
||||
unresolved_variables: Set[str],
|
||||
validator: Validator,
|
||||
) -> None:
|
||||
"""
|
||||
Ensure all OverridesStringFormatterValidator's only contain variables from the overrides
|
||||
and resolve.
|
||||
"""
|
||||
if isinstance(validator, DictValidator):
|
||||
# pylint: disable=protected-access
|
||||
# Usage of protected variables in other validators is fine. The reason to keep
|
||||
# them protected is for readability when using them in subscriptions.
|
||||
for validator_value in validator._validator_dict.values():
|
||||
self._validate_formatters(
|
||||
mock_script=mock_script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
validator=validator_value,
|
||||
)
|
||||
# pylint: enable=protected-access
|
||||
elif isinstance(validator, ListValidator):
|
||||
for list_value in validator.list:
|
||||
self._validate_formatters(
|
||||
mock_script=mock_script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
validator=list_value,
|
||||
)
|
||||
elif isinstance(validator, (StringFormatterValidator, OverridesStringFormatterValidator)):
|
||||
self._validate_string_formatter_validator(
|
||||
mock_script=mock_script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
formatter_validator=validator,
|
||||
)
|
||||
elif isinstance(validator, (DictFormatterValidator, OverridesDictFormatterValidator)):
|
||||
for validator_value in validator.dict.values():
|
||||
self._validate_string_formatter_validator(
|
||||
mock_script=mock_script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
formatter_validator=validator_value,
|
||||
)
|
||||
|
||||
def _get_presets_to_merge(
|
||||
self, parent_presets: str | List[str], seen_presets: List[str], config: ConfigValidator
|
||||
) -> List[Dict]:
|
||||
|
|
@ -349,7 +290,7 @@ class Preset(_PresetShell):
|
|||
|
||||
return presets_to_merge
|
||||
|
||||
def __merge_parent_preset_dicts_if_present(self, config: ConfigValidator):
|
||||
def _merge_parent_preset_dicts_if_present(self, config: ConfigValidator):
|
||||
parent_preset_validator = self._validate_key_if_present(
|
||||
key="preset", validator=StringListValidator
|
||||
)
|
||||
|
|
@ -372,7 +313,7 @@ class Preset(_PresetShell):
|
|||
super().__init__(name=name, value=value)
|
||||
|
||||
# Perform the merge of parent presets before validating any keys
|
||||
self.__merge_parent_preset_dicts_if_present(config=config)
|
||||
self._merge_parent_preset_dicts_if_present(config=config)
|
||||
|
||||
self.downloader_options: MultiUrlValidator = self._validate_key(
|
||||
key="download", validator=MultiUrlValidator
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ from collections import OrderedDict
|
|||
from keyword import iskeyword
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Set
|
||||
from typing import Union
|
||||
from typing import final
|
||||
|
||||
from yt_dlp.utils import sanitize_filename
|
||||
|
|
@ -12,9 +14,11 @@ from ytdl_sub.script.parser import parse
|
|||
from ytdl_sub.script.script import Script
|
||||
from ytdl_sub.script.types.resolvable import Resolvable
|
||||
from ytdl_sub.script.utils.exceptions import UserException
|
||||
from ytdl_sub.script.utils.exceptions import VariableDoesNotExist
|
||||
from ytdl_sub.utils.exceptions import InvalidVariableNameException
|
||||
from ytdl_sub.utils.exceptions import StringFormattingException
|
||||
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
|
||||
from ytdl_sub.validators.validators import DictValidator
|
||||
from ytdl_sub.validators.validators import ListValidator
|
||||
from ytdl_sub.validators.validators import LiteralDictValidator
|
||||
from ytdl_sub.validators.validators import StringValidator
|
||||
|
|
@ -172,3 +176,63 @@ class OverridesDictFormatterValidator(DictFormatterValidator):
|
|||
"""
|
||||
|
||||
_key_validator = OverridesStringFormatterValidator
|
||||
|
||||
|
||||
def _validate_formatter(
|
||||
mock_script: Script,
|
||||
unresolved_variables: Set[str],
|
||||
formatter_validator: Union[StringFormatterValidator, OverridesStringFormatterValidator],
|
||||
) -> None:
|
||||
try:
|
||||
unresolvable = unresolved_variables
|
||||
if isinstance(formatter_validator, OverridesStringFormatterValidator):
|
||||
unresolvable = unresolved_variables.union({VARIABLES.entry_metadata.variable_name})
|
||||
|
||||
mock_script.resolve_once(
|
||||
{"tmp_var": formatter_validator.format_string},
|
||||
unresolvable=unresolvable,
|
||||
)
|
||||
except VariableDoesNotExist as exc:
|
||||
raise StringFormattingVariableNotFoundException(exc) from exc
|
||||
|
||||
|
||||
def validate_formatters(
|
||||
script: Script,
|
||||
unresolved_variables: Set[str],
|
||||
validator: Validator,
|
||||
) -> None:
|
||||
"""
|
||||
Ensure all OverridesStringFormatterValidator's only contain variables from the overrides
|
||||
and resolve.
|
||||
"""
|
||||
if isinstance(validator, DictValidator):
|
||||
# pylint: disable=protected-access
|
||||
# Usage of protected variables in other validators is fine. The reason to keep
|
||||
# them protected is for readability when using them in subscriptions.
|
||||
for validator_value in validator._validator_dict.values():
|
||||
validate_formatters(
|
||||
script=script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
validator=validator_value,
|
||||
)
|
||||
# pylint: enable=protected-access
|
||||
elif isinstance(validator, ListValidator):
|
||||
for list_value in validator.list:
|
||||
validate_formatters(
|
||||
script=script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
validator=list_value,
|
||||
)
|
||||
elif isinstance(validator, (StringFormatterValidator, OverridesStringFormatterValidator)):
|
||||
_validate_formatter(
|
||||
mock_script=script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
formatter_validator=validator,
|
||||
)
|
||||
elif isinstance(validator, (DictFormatterValidator, OverridesDictFormatterValidator)):
|
||||
for validator_value in validator.dict.values():
|
||||
_validate_formatter(
|
||||
mock_script=script,
|
||||
unresolved_variables=unresolved_variables,
|
||||
formatter_validator=validator_value,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -207,23 +207,3 @@ class TestPreset:
|
|||
"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": [{"url": "{url}"}, {"url": "{url2}"}],
|
||||
"output_options": output_options,
|
||||
"overrides": {"url": "", "url2": ""},
|
||||
},
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue