nearly there, need url support

This commit is contained in:
Jesse Bannon 2025-12-27 16:27:41 -08:00
parent af527bd2ef
commit cfcaa1878a
6 changed files with 143 additions and 121 deletions

View file

@ -15,7 +15,6 @@ 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.scriptable import BASE_SCRIPT
from ytdl_sub.validators.string_formatter_validators import to_variable_dependency_format_string
@ -45,18 +44,15 @@ def _add_dummy_variables(variables: Iterable[str]) -> Dict[str, str]:
def _add_dummy_overrides(overrides: Overrides) -> Dict[str, str]:
# Have the dummy override variable contain all variable deps that it uses in the string
dummy_overrides: Dict[str, str] = {}
for override_name, format_string in overrides.dict_with_format_strings.items():
if _is_function(override_name):
continue
for override_name in overrides.script.variable_names:
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
except RuntimeException:
value = to_variable_dependency_format_string(
script=overrides.script, parsed_format_string=overrides.script._variables[override_name]
script=overrides.script,
parsed_format_string=overrides.script._variables[override_name],
)
dummy_overrides[override_name] = value
@ -130,9 +126,9 @@ class VariableValidation:
# copy the script and mock entry variables
self.script = copy.deepcopy(self.overrides.script)
self.script.add(
variables=_add_dummy_overrides(overrides=self.overrides)
variables=_DUMMY_ENTRY_VARIABLES
| _add_dummy_variables(variables=plugin_variables)
| _DUMMY_ENTRY_VARIABLES
| _add_dummy_overrides(overrides=self.overrides)
)
return self

View file

@ -15,6 +15,7 @@ from ytdl_sub.utils.exceptions import SubscriptionPermissionError
from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.logger import Logger
from ytdl_sub.utils.yaml import dump_yaml
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
logger = Logger.get("subscription")
@ -77,6 +78,14 @@ class BaseSubscription(ABC):
}
)
# Validate after adding the subscription name
self._validated_dict = VariableValidation(
overrides=self.overrides,
downloader_options=self.downloader_options,
output_options=self.output_options,
plugins=self.plugins,
).ensure_proper_usage()
self._enhanced_download_archive: Optional[EnhancedDownloadArchive] = (
_initialize_download_archive(
output_options=self.output_options,
@ -103,13 +112,6 @@ class BaseSubscription(ABC):
f"{self.output_directory}"
)
self._validated_dict = VariableValidation(
overrides=self.overrides,
downloader_options=self.downloader_options,
output_options=self.output_options,
plugins=self.plugins,
).ensure_proper_usage()
@property
def download_archive(self) -> EnhancedDownloadArchive:
"""
@ -254,10 +256,10 @@ class BaseSubscription(ABC):
"""
return self._preset_options.yaml
def resolved_yaml(self):
def resolved_yaml(self) -> str:
"""
Returns
-------
Human-readable, condensed YAML definition of the subscription.
"""
return self._validated_dict
return dump_yaml(self._validated_dict)

View file

@ -8,9 +8,10 @@ from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.script.parser import parse
from ytdl_sub.script.script import Script
from ytdl_sub.script.types.syntax_tree import SyntaxTree
from ytdl_sub.script.utils.exceptions import RuntimeException, UserThrownRuntimeError
from ytdl_sub.script.utils.exceptions import RuntimeException
from ytdl_sub.script.utils.exceptions import ScriptVariableNotResolved
from ytdl_sub.script.utils.exceptions import UserException
from ytdl_sub.script.utils.exceptions import UserThrownRuntimeError
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
from ytdl_sub.utils.script import ScriptUtils
from ytdl_sub.validators.validators import DictValidator

View file

@ -6,7 +6,6 @@ import pytest
from ytdl_sub.config.preset import Preset
from ytdl_sub.plugins.nfo_tags import NfoTagsOptions
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
from ytdl_sub.utils.exceptions import ValidationException
@ -157,100 +156,6 @@ class TestPreset:
},
)
def test_preset_error__source_variable_does_not_exist(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="contains the following variables that do not exist: dne_var",
):
_ = Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": {"output_directory": "dir", "file_name": "{dne_var}"},
},
)
def test_preset_error__override_variable_does_not_exist(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="contains the following variables that do not exist: dne_var",
):
_ = Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": {"output_directory": "{dne_var}", "file_name": "file"},
},
)
def test_preset_error__dict_source_variable_does_not_exist(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="contains the following variables that do not exist: dne_var",
):
_ = Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": {"output_directory": "dir", "file_name": "file"},
"nfo_tags": {
"nfo_name": "the nfo name",
"nfo_root": "the root",
"tags": {"tag_a": "{dne_var}"},
},
},
)
def test_preset_error__dict_override_variable_does_not_exist(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="contains the following variables that do not exist: dne_var",
):
_ = Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": output_options,
"output_directory_nfo_tags": {
"nfo_name": "the nfo name",
"nfo_root": "the root",
"tags": {"tag_a": "{dne_var}"},
},
},
)
def test_preset_error__dict_override_variable_not_static(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="static formatters must contain variables that "
"have no dependency to entry variables",
):
_ = Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": {
"output_directory": "{title}",
"file_name": "{uid}",
},
},
)
def test_preset_with_multi_url__contains_empty_url(self, config_file, output_options):
_ = Preset(
config=config_file,

View file

@ -548,10 +548,12 @@ 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
assert subs[0].resolved_yaml() == {}
#
# 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"

View file

@ -0,0 +1,116 @@
import pytest
from ytdl_sub.config.preset import Preset
from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
class TestSubscriptionValidation:
def test_preset_error__source_variable_does_not_exist(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="contains the following variables that do not exist: dne_var",
):
_ = Subscription.from_preset(
preset=Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": {"output_directory": "dir", "file_name": "{dne_var}"},
},
),
config=config_file,
)
def test_preset_error__override_variable_does_not_exist(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="contains the following variables that do not exist: dne_var",
):
_ = Subscription.from_preset(
preset=Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": {"output_directory": "{dne_var}", "file_name": "file"},
},
),
config=config_file,
)
def test_preset_error__dict_source_variable_does_not_exist(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="contains the following variables that do not exist: dne_var",
):
_ = Subscription.from_preset(
preset=Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": {"output_directory": "dir", "file_name": "file"},
"nfo_tags": {
"nfo_name": "the nfo name",
"nfo_root": "the root",
"tags": {"tag_a": "{dne_var}"},
},
},
),
config=config_file,
)
def test_preset_error__dict_override_variable_does_not_exist(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="contains the following variables that do not exist: dne_var",
):
_ = Subscription.from_preset(
preset=Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": output_options,
"output_directory_nfo_tags": {
"nfo_name": "the nfo name",
"nfo_root": "the root",
"tags": {"tag_a": "{dne_var}"},
},
},
),
config=config_file,
)
def test_preset_error__dict_override_variable_not_static(
self, config_file, output_options, youtube_video
):
with pytest.raises(
StringFormattingVariableNotFoundException,
match="static formatters must contain variables that "
"have no dependency to entry variables",
):
_ = Subscription.from_preset(
preset=Preset(
config=config_file,
name="test",
value={
"download": youtube_video,
"output_options": {
"output_directory": "{title}",
"file_name": "{uid}",
},
},
),
config=config_file,
)