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.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.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
@ -45,18 +44,15 @@ def _add_dummy_variables(variables: Iterable[str]) -> Dict[str, str]:
def _add_dummy_overrides(overrides: Overrides) -> 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 # Have the dummy override variable contain all variable deps that it uses in the string
dummy_overrides: Dict[str, str] = {} dummy_overrides: Dict[str, str] = {}
for override_name, format_string in overrides.dict_with_format_strings.items(): for override_name in overrides.script.variable_names:
if _is_function(override_name):
continue
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 = 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, parsed_format_string=overrides.script._variables[override_name] script=overrides.script,
parsed_format_string=overrides.script._variables[override_name],
) )
dummy_overrides[override_name] = value dummy_overrides[override_name] = value
@ -130,9 +126,9 @@ class VariableValidation:
# copy the script and mock entry variables # copy the script and mock entry variables
self.script = copy.deepcopy(self.overrides.script) self.script = copy.deepcopy(self.overrides.script)
self.script.add( self.script.add(
variables=_add_dummy_overrides(overrides=self.overrides) variables=_DUMMY_ENTRY_VARIABLES
| _add_dummy_variables(variables=plugin_variables) | _add_dummy_variables(variables=plugin_variables)
| _DUMMY_ENTRY_VARIABLES | _add_dummy_overrides(overrides=self.overrides)
) )
return self 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 FileHandler
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.logger import Logger 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 from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
logger = Logger.get("subscription") 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] = ( self._enhanced_download_archive: Optional[EnhancedDownloadArchive] = (
_initialize_download_archive( _initialize_download_archive(
output_options=self.output_options, output_options=self.output_options,
@ -103,13 +112,6 @@ class BaseSubscription(ABC):
f"{self.output_directory}" 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 @property
def download_archive(self) -> EnhancedDownloadArchive: def download_archive(self) -> EnhancedDownloadArchive:
""" """
@ -254,10 +256,10 @@ class BaseSubscription(ABC):
""" """
return self._preset_options.yaml return self._preset_options.yaml
def resolved_yaml(self): def resolved_yaml(self) -> str:
""" """
Returns Returns
------- -------
Human-readable, condensed YAML definition of the subscription. 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.parser import parse
from ytdl_sub.script.script import Script from ytdl_sub.script.script import Script
from ytdl_sub.script.types.syntax_tree import SyntaxTree 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 ScriptVariableNotResolved
from ytdl_sub.script.utils.exceptions import UserException 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.exceptions import StringFormattingVariableNotFoundException
from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.utils.script import ScriptUtils
from ytdl_sub.validators.validators import DictValidator 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.config.preset import Preset
from ytdl_sub.plugins.nfo_tags import NfoTagsOptions from ytdl_sub.plugins.nfo_tags import NfoTagsOptions
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
from ytdl_sub.utils.exceptions import ValidationException 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): def test_preset_with_multi_url__contains_empty_url(self, config_file, output_options):
_ = Preset( _ = Preset(
config=config_file, 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 assert len(default_subs) == 1
def test_tv_show_resolved_yaml(config_file: ConfigFile, tv_show_subscriptions_path: Path): #
subs = Subscription.from_file_path( # def test_tv_show_resolved_yaml(config_file: ConfigFile, tv_show_subscriptions_path: Path):
config=config_file, subscription_path=tv_show_subscriptions_path # subs = Subscription.from_file_path(
) # config=config_file, subscription_path=tv_show_subscriptions_path
# )
assert len(subs) == 8 #
assert subs[0].resolved_yaml() == {} # 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,
)