From eb7895bed3f5fd421ada5ac600db0b6fa2b9a7b0 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Sat, 27 Dec 2025 17:34:38 -0800 Subject: [PATCH] fixed a few things, need to optimize --- .../config/validators/variable_validation.py | 15 +++++++++- src/ytdl_sub/downloaders/url/validators.py | 4 +-- src/ytdl_sub/utils/script.py | 2 +- .../validators/string_formatter_validators.py | 26 ++++++++--------- tests/unit/config/test_preset.py | 23 --------------- tests/unit/config/test_subscription.py | 17 +++++------ .../config/test_subscription_validation.py | 29 +++++++++++++++++++ 7 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/ytdl_sub/config/validators/variable_validation.py b/src/ytdl_sub/config/validators/variable_validation.py index b6b4439d..6d738ceb 100644 --- a/src/ytdl_sub/config/validators/variable_validation.py +++ b/src/ytdl_sub/config/validators/variable_validation.py @@ -15,7 +15,9 @@ from ytdl_sub.config.validators.options import OptionsValidator from ytdl_sub.downloaders.url.validators import MultiUrlValidator from ytdl_sub.entries.variables.override_variables import REQUIRED_OVERRIDE_VARIABLE_NAMES from ytdl_sub.script.script import Script +from ytdl_sub.script.script import _is_function from ytdl_sub.script.utils.exceptions import RuntimeException +from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.utils.scriptable import BASE_SCRIPT from ytdl_sub.validators.string_formatter_validators import to_variable_dependency_format_string from ytdl_sub.validators.string_formatter_validators import validate_formatters @@ -48,7 +50,7 @@ def _add_dummy_overrides(overrides: Overrides) -> Dict[str, str]: try: # Attempt to get the resolved version, which will only happen # if it does not have any dependencies to the entry - value = overrides.script.get(override_name).native + value = ScriptUtils.to_script(overrides.script.get(override_name).native) except RuntimeException: value = to_variable_dependency_format_string( script=overrides.script, @@ -191,5 +193,16 @@ class VariableValidation: validator=self.output_options, ) + # TODO: make this a function + raw_download_output = validate_formatters( + script=self.script, + unresolved_variables=self.unresolved_variables, + validator=self.downloader_options.urls, + ) + resolved_subscription["download"] = [] + for url_output in raw_download_output["download"]: + if url_output["url"]: + resolved_subscription["download"].append(url_output) + assert not self.unresolved_variables return resolved_subscription diff --git a/src/ytdl_sub/downloaders/url/validators.py b/src/ytdl_sub/downloaders/url/validators.py index 4504eccf..e518cdf8 100644 --- a/src/ytdl_sub/downloaders/url/validators.py +++ b/src/ytdl_sub/downloaders/url/validators.py @@ -21,7 +21,7 @@ class UrlThumbnailValidator(StrictDictValidator): def __init__(self, name, value): super().__init__(name, value) - self._name = self._validate_key(key="name", validator=StringFormatterValidator) + self._thumb_name = self._validate_key(key="name", validator=StringFormatterValidator) self._uid = self._validate_key(key="uid", validator=OverridesStringFormatterValidator) @property @@ -29,7 +29,7 @@ class UrlThumbnailValidator(StrictDictValidator): """ File name for the thumbnail """ - return self._name + return self._thumb_name @property def uid(self) -> OverridesStringFormatterValidator: diff --git a/src/ytdl_sub/utils/script.py b/src/ytdl_sub/utils/script.py index e3a17b2f..e5f40588 100644 --- a/src/ytdl_sub/utils/script.py +++ b/src/ytdl_sub/utils/script.py @@ -42,7 +42,7 @@ class ScriptUtils: if value is None: out = "" elif isinstance(value, str): - out = value + out = f'{{%string("""{value}""")}}' elif isinstance(value, bool): out = f"{{%bool({value})}}" elif isinstance(value, int): diff --git a/src/ytdl_sub/validators/string_formatter_validators.py b/src/ytdl_sub/validators/string_formatter_validators.py index 9059372f..83e47479 100644 --- a/src/ytdl_sub/validators/string_formatter_validators.py +++ b/src/ytdl_sub/validators/string_formatter_validators.py @@ -240,14 +240,13 @@ def _validate_formatter( f"formatter: {', '.join(sorted(unresolved))}" ) try: - out = mock_script.resolve_once( - {"tmp_var": formatter_validator.format_string}, - unresolvable=unresolvable, - update=True, - ) - if is_static_formatter: - return out["tmp_var"].native + return mock_script.resolve_once( + {"tmp_var": formatter_validator.format_string}, + unresolvable=unresolvable, + update=True, + )["tmp_var"].native + return formatter_validator.format_string except RuntimeException as exc: if isinstance(exc, ScriptVariableNotResolved) and is_static_formatter: @@ -274,6 +273,7 @@ def validate_formatters( and resolve. """ resolved_dict: Dict = {} + if isinstance(validator, DictValidator): resolved_dict[validator.leaf_name] = {} # pylint: disable=protected-access @@ -289,13 +289,13 @@ def validate_formatters( elif isinstance(validator, ListValidator): resolved_dict[validator.leaf_name] = [] for list_value in validator.list: - resolved_dict[validator.leaf_name].append( - validate_formatters( - script=script, - unresolved_variables=unresolved_variables, - validator=list_value, - ) + list_output = validate_formatters( + script=script, + unresolved_variables=unresolved_variables, + validator=list_value, ) + assert len(list_output) == 1 + resolved_dict[validator.leaf_name].append(list(list_output.values())[0]) elif isinstance(validator, (StringFormatterValidator, OverridesStringFormatterValidator)): resolved_dict[validator.leaf_name] = _validate_formatter( mock_script=script, diff --git a/tests/unit/config/test_preset.py b/tests/unit/config/test_preset.py index cd4f2b17..a42439be 100644 --- a/tests/unit/config/test_preset.py +++ b/tests/unit/config/test_preset.py @@ -317,26 +317,3 @@ class TestPreset: "overrides": {name: "ack"}, }, ) - - def test_preset_error_added_url_variable_cannot_resolve(self, config_file, output_options): - with pytest.raises( - ValidationException, - match=re.escape( - "variable the_bad_one cannot use the variables subtitles_ext because it " - "depends on other variables that are computed later in execution" - ), - ): - _ = Preset( - config=config_file, - name="test", - value={ - "download": { - "url": "youtube.com/watch?v=123abc", - "variables": {"the_bad_one": "{subtitles_ext}"}, - }, - "subtitles": { - "embed_subtitles": True, - }, - "output_options": {"output_directory": "dir", "file_name": "acjk"}, - }, - ) diff --git a/tests/unit/config/test_subscription.py b/tests/unit/config/test_subscription.py index 55362227..f88a80b0 100644 --- a/tests/unit/config/test_subscription.py +++ b/tests/unit/config/test_subscription.py @@ -548,12 +548,11 @@ def test_default_docker_config_and_subscriptions(docker_default_subscription_pat assert len(default_subs) == 1 -# -# def test_tv_show_resolved_yaml(config_file: ConfigFile, tv_show_subscriptions_path: Path): -# subs = Subscription.from_file_path( -# config=config_file, subscription_path=tv_show_subscriptions_path -# ) -# -# assert len(subs) == 8 -# yaml_out = subs[0].resolved_yaml() -# assert yaml_out == "nope" +def test_tv_show_resolved_yaml(config_file: ConfigFile, tv_show_subscriptions_path: Path): + subs = Subscription.from_file_path( + config=config_file, subscription_path=tv_show_subscriptions_path + ) + + assert len(subs) == 8 + yaml_out = subs[0].resolved_yaml() + assert yaml_out == "nope" diff --git a/tests/unit/config/test_subscription_validation.py b/tests/unit/config/test_subscription_validation.py index fb270d07..7a8e8ff2 100644 --- a/tests/unit/config/test_subscription_validation.py +++ b/tests/unit/config/test_subscription_validation.py @@ -1,8 +1,11 @@ +import re + import pytest from ytdl_sub.config.preset import Preset from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException +from ytdl_sub.utils.exceptions import ValidationException class TestSubscriptionValidation: @@ -114,3 +117,29 @@ class TestSubscriptionValidation: ), config=config_file, ) + + def test_preset_error_added_url_variable_cannot_resolve(self, config_file, output_options): + with pytest.raises( + ValidationException, + match=re.escape( + "variable the_bad_one cannot use the variables subtitles_ext because it " + "depends on other variables that are computed later in execution" + ), + ): + _ = Subscription.from_preset( + preset=Preset( + config=config_file, + name="test", + value={ + "download": { + "url": "youtube.com/watch?v=123abc", + "variables": {"the_bad_one": "{subtitles_ext}"}, + }, + "subtitles": { + "embed_subtitles": True, + }, + "output_options": {"output_directory": "dir", "file_name": "acjk"}, + }, + ), + config=config_file, + )