fixed a few things, need to optimize

This commit is contained in:
Jesse Bannon 2025-12-27 17:34:38 -08:00
parent cfcaa1878a
commit eb7895bed3
7 changed files with 67 additions and 49 deletions

View file

@ -15,7 +15,9 @@ from ytdl_sub.config.validators.options import OptionsValidator
from ytdl_sub.downloaders.url.validators import MultiUrlValidator from ytdl_sub.downloaders.url.validators import MultiUrlValidator
from ytdl_sub.entries.variables.override_variables import REQUIRED_OVERRIDE_VARIABLE_NAMES 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 Script
from ytdl_sub.script.script import _is_function
from ytdl_sub.script.utils.exceptions import RuntimeException 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.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 to_variable_dependency_format_string
from ytdl_sub.validators.string_formatter_validators import validate_formatters from ytdl_sub.validators.string_formatter_validators import validate_formatters
@ -48,7 +50,7 @@ def _add_dummy_overrides(overrides: Overrides) -> Dict[str, str]:
try: try:
# Attempt to get the resolved version, which will only happen # Attempt to get the resolved version, which will only happen
# if it does not have any dependencies to the entry # 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: except RuntimeException:
value = to_variable_dependency_format_string( value = to_variable_dependency_format_string(
script=overrides.script, script=overrides.script,
@ -191,5 +193,16 @@ class VariableValidation:
validator=self.output_options, 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 assert not self.unresolved_variables
return resolved_subscription return resolved_subscription

View file

@ -21,7 +21,7 @@ class UrlThumbnailValidator(StrictDictValidator):
def __init__(self, name, value): def __init__(self, name, value):
super().__init__(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) self._uid = self._validate_key(key="uid", validator=OverridesStringFormatterValidator)
@property @property
@ -29,7 +29,7 @@ class UrlThumbnailValidator(StrictDictValidator):
""" """
File name for the thumbnail File name for the thumbnail
""" """
return self._name return self._thumb_name
@property @property
def uid(self) -> OverridesStringFormatterValidator: def uid(self) -> OverridesStringFormatterValidator:

View file

@ -42,7 +42,7 @@ class ScriptUtils:
if value is None: if value is None:
out = "" out = ""
elif isinstance(value, str): elif isinstance(value, str):
out = value out = f'{{%string("""{value}""")}}'
elif isinstance(value, bool): elif isinstance(value, bool):
out = f"{{%bool({value})}}" out = f"{{%bool({value})}}"
elif isinstance(value, int): elif isinstance(value, int):

View file

@ -240,14 +240,13 @@ def _validate_formatter(
f"formatter: {', '.join(sorted(unresolved))}" f"formatter: {', '.join(sorted(unresolved))}"
) )
try: try:
out = mock_script.resolve_once(
{"tmp_var": formatter_validator.format_string},
unresolvable=unresolvable,
update=True,
)
if is_static_formatter: 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 return formatter_validator.format_string
except RuntimeException as exc: except RuntimeException as exc:
if isinstance(exc, ScriptVariableNotResolved) and is_static_formatter: if isinstance(exc, ScriptVariableNotResolved) and is_static_formatter:
@ -274,6 +273,7 @@ def validate_formatters(
and resolve. and resolve.
""" """
resolved_dict: Dict = {} resolved_dict: Dict = {}
if isinstance(validator, DictValidator): if isinstance(validator, DictValidator):
resolved_dict[validator.leaf_name] = {} resolved_dict[validator.leaf_name] = {}
# pylint: disable=protected-access # pylint: disable=protected-access
@ -289,13 +289,13 @@ def validate_formatters(
elif isinstance(validator, ListValidator): elif isinstance(validator, ListValidator):
resolved_dict[validator.leaf_name] = [] resolved_dict[validator.leaf_name] = []
for list_value in validator.list: for list_value in validator.list:
resolved_dict[validator.leaf_name].append( list_output = validate_formatters(
validate_formatters( script=script,
script=script, unresolved_variables=unresolved_variables,
unresolved_variables=unresolved_variables, validator=list_value,
validator=list_value,
)
) )
assert len(list_output) == 1
resolved_dict[validator.leaf_name].append(list(list_output.values())[0])
elif isinstance(validator, (StringFormatterValidator, OverridesStringFormatterValidator)): elif isinstance(validator, (StringFormatterValidator, OverridesStringFormatterValidator)):
resolved_dict[validator.leaf_name] = _validate_formatter( resolved_dict[validator.leaf_name] = _validate_formatter(
mock_script=script, mock_script=script,

View file

@ -317,26 +317,3 @@ class TestPreset:
"overrides": {name: "ack"}, "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"},
},
)

View file

@ -548,12 +548,11 @@ def test_default_docker_config_and_subscriptions(docker_default_subscription_pat
assert len(default_subs) == 1 assert len(default_subs) == 1
# def test_tv_show_resolved_yaml(config_file: ConfigFile, tv_show_subscriptions_path: Path):
# def test_tv_show_resolved_yaml(config_file: ConfigFile, tv_show_subscriptions_path: Path): subs = Subscription.from_file_path(
# subs = Subscription.from_file_path( config=config_file, subscription_path=tv_show_subscriptions_path
# config=config_file, subscription_path=tv_show_subscriptions_path )
# )
# assert len(subs) == 8
# assert len(subs) == 8 yaml_out = subs[0].resolved_yaml()
# yaml_out = subs[0].resolved_yaml() assert yaml_out == "nope"
# assert yaml_out == "nope"

View file

@ -1,8 +1,11 @@
import re
import pytest import pytest
from ytdl_sub.config.preset import Preset from ytdl_sub.config.preset import Preset
from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
from ytdl_sub.utils.exceptions import ValidationException
class TestSubscriptionValidation: class TestSubscriptionValidation:
@ -114,3 +117,29 @@ class TestSubscriptionValidation:
), ),
config=config_file, 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,
)