clean var val

This commit is contained in:
Jesse Bannon 2026-01-16 14:26:26 -08:00
parent 97df4dac1d
commit 21643a2d7b
2 changed files with 26 additions and 12 deletions

View file

@ -7,6 +7,7 @@ from ytdl_sub.config.plugin.preset_plugins import PresetPlugins
from ytdl_sub.config.preset_options import OutputOptions from ytdl_sub.config.preset_options import OutputOptions
from ytdl_sub.config.validators.options import OptionsValidator 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.script.variable_definitions import VARIABLES
from ytdl_sub.validators.string_formatter_validators import validate_formatters from ytdl_sub.validators.string_formatter_validators import validate_formatters
@ -26,18 +27,21 @@ class VariableValidation:
self.script = self.overrides.script self.script = self.overrides.script
self.unresolved_variables = self.plugins.get_all_variables( self.unresolved_variables = self.plugins.get_all_variables(
additional_options=[self.output_options, self.downloader_options] additional_options=[self.output_options, self.downloader_options]
) | {VARIABLES.entry_metadata.variable_name}
self.unresolved_runtime_variables = self.plugins.get_all_variables(
additional_options=[self.output_options, self.downloader_options]
) )
def _add_variables(self, plugin_op: PluginOperation, options: OptionsValidator) -> None: def _add_runtime_variables(self, plugin_op: PluginOperation, options: OptionsValidator) -> None:
""" """
Add dummy variables for script validation Add dummy variables for script validation
""" """
added_variables = options.added_variables( added_variables = options.added_variables(
unresolved_variables=self.unresolved_variables, unresolved_variables=self.unresolved_runtime_variables,
).get(plugin_op, set()) ).get(plugin_op, set())
modified_variables = options.modified_variables().get(plugin_op, set()) modified_variables = options.modified_variables().get(plugin_op, set())
self.unresolved_variables -= added_variables | modified_variables self.unresolved_runtime_variables -= added_variables | modified_variables
def ensure_proper_usage(self) -> Dict: def ensure_proper_usage(self) -> Dict:
""" """
@ -47,32 +51,38 @@ class VariableValidation:
resolved_subscription: Dict = {} resolved_subscription: Dict = {}
self._add_variables(PluginOperation.DOWNLOADER, options=self.downloader_options) self._add_runtime_variables(PluginOperation.DOWNLOADER, options=self.downloader_options)
# Always add output options first # Always add output options first
self._add_variables(PluginOperation.MODIFY_ENTRY_METADATA, options=self.output_options) self._add_runtime_variables(
PluginOperation.MODIFY_ENTRY_METADATA, options=self.output_options
)
# Metadata variables to be added # Metadata variables to be added
for plugin_options in PluginMapping.order_options_by( for plugin_options in PluginMapping.order_options_by(
self.plugins.zipped(), PluginOperation.MODIFY_ENTRY_METADATA self.plugins.zipped(), PluginOperation.MODIFY_ENTRY_METADATA
): ):
self._add_variables(PluginOperation.MODIFY_ENTRY_METADATA, options=plugin_options) self._add_runtime_variables(
PluginOperation.MODIFY_ENTRY_METADATA, options=plugin_options
)
for plugin_options in PluginMapping.order_options_by( for plugin_options in PluginMapping.order_options_by(
self.plugins.zipped(), PluginOperation.MODIFY_ENTRY self.plugins.zipped(), PluginOperation.MODIFY_ENTRY
): ):
self._add_variables(PluginOperation.MODIFY_ENTRY, options=plugin_options) self._add_runtime_variables(PluginOperation.MODIFY_ENTRY, options=plugin_options)
# Validate that any formatter in the plugin options can resolve # Validate that any formatter in the plugin options can resolve
resolved_subscription |= validate_formatters( resolved_subscription |= validate_formatters(
script=self.script, script=self.script,
unresolved_variables=self.unresolved_variables, unresolved_variables=self.unresolved_variables,
unresolved_runtime_variables=self.unresolved_runtime_variables,
validator=plugin_options, validator=plugin_options,
) )
resolved_subscription |= validate_formatters( resolved_subscription |= validate_formatters(
script=self.script, script=self.script,
unresolved_variables=self.unresolved_variables, unresolved_variables=self.unresolved_variables,
unresolved_runtime_variables=self.unresolved_runtime_variables,
validator=self.output_options, validator=self.output_options,
) )
@ -80,6 +90,7 @@ class VariableValidation:
raw_download_output = validate_formatters( raw_download_output = validate_formatters(
script=self.script, script=self.script,
unresolved_variables=self.unresolved_variables, unresolved_variables=self.unresolved_variables,
unresolved_runtime_variables=self.unresolved_runtime_variables,
validator=self.downloader_options.urls, validator=self.downloader_options.urls,
) )
resolved_subscription["download"] = [] resolved_subscription["download"] = []
@ -90,5 +101,5 @@ class VariableValidation:
if url_output["url"]: if url_output["url"]:
resolved_subscription["download"].append(url_output) resolved_subscription["download"].append(url_output)
assert not self.unresolved_variables assert not self.unresolved_runtime_variables
return resolved_subscription return resolved_subscription

View file

@ -5,7 +5,6 @@ from typing import Set
from typing import Union from typing import Union
from typing import final from typing import final
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
@ -238,6 +237,7 @@ def to_variable_dependency_format_string(script: Script, parsed_format_string: S
def _validate_formatter( def _validate_formatter(
mock_script: Script, mock_script: Script,
unresolved_variables: Set[str], unresolved_variables: Set[str],
unresolved_runtime_variables: Set[str],
formatter_validator: Union[StringFormatterValidator, OverridesStringFormatterValidator], formatter_validator: Union[StringFormatterValidator, OverridesStringFormatterValidator],
) -> str: ) -> str:
parsed = formatter_validator.parsed parsed = formatter_validator.parsed
@ -245,8 +245,6 @@ def _validate_formatter(
return resolved.native return resolved.native
is_static_formatter = isinstance(formatter_validator, OverridesStringFormatterValidator) is_static_formatter = isinstance(formatter_validator, OverridesStringFormatterValidator)
if is_static_formatter:
unresolved_variables = unresolved_variables.union({VARIABLES.entry_metadata.variable_name})
variable_names = {var.name for var in parsed.variables} variable_names = {var.name for var in parsed.variables}
custom_function_names = {f"%{func.name}" for func in parsed.custom_functions} custom_function_names = {f"%{func.name}" for func in parsed.custom_functions}
@ -266,7 +264,7 @@ def _validate_formatter(
"contains the following custom functions that do not exist: " "contains the following custom functions that do not exist: "
f"{', '.join(sorted(custom_function_names - mock_script.function_names))}" f"{', '.join(sorted(custom_function_names - mock_script.function_names))}"
) )
if unresolved := variable_names.intersection(unresolved_variables): if unresolved := variable_names.intersection(unresolved_runtime_variables):
raise StringFormattingVariableNotFoundException( raise StringFormattingVariableNotFoundException(
"contains the following variables that are unresolved when executing this " "contains the following variables that are unresolved when executing this "
f"formatter: {', '.join(sorted(unresolved))}" f"formatter: {', '.join(sorted(unresolved))}"
@ -298,6 +296,7 @@ def _validate_formatter(
def validate_formatters( def validate_formatters(
script: Script, script: Script,
unresolved_variables: Set[str], unresolved_variables: Set[str],
unresolved_runtime_variables: Set[str],
validator: Validator, validator: Validator,
) -> Dict: ) -> Dict:
""" """
@ -314,6 +313,7 @@ def validate_formatters(
resolved_dict[validator.leaf_name] |= validate_formatters( resolved_dict[validator.leaf_name] |= validate_formatters(
script=script, script=script,
unresolved_variables=unresolved_variables, unresolved_variables=unresolved_variables,
unresolved_runtime_variables=unresolved_runtime_variables,
validator=validator_value, validator=validator_value,
) )
elif isinstance(validator, ListValidator): elif isinstance(validator, ListValidator):
@ -322,6 +322,7 @@ def validate_formatters(
list_output = validate_formatters( list_output = validate_formatters(
script=script, script=script,
unresolved_variables=unresolved_variables, unresolved_variables=unresolved_variables,
unresolved_runtime_variables=unresolved_runtime_variables,
validator=list_value, validator=list_value,
) )
assert len(list_output) == 1 assert len(list_output) == 1
@ -330,6 +331,7 @@ def validate_formatters(
resolved_dict[validator.leaf_name] = _validate_formatter( resolved_dict[validator.leaf_name] = _validate_formatter(
mock_script=script, mock_script=script,
unresolved_variables=unresolved_variables, unresolved_variables=unresolved_variables,
unresolved_runtime_variables=unresolved_runtime_variables,
formatter_validator=validator, formatter_validator=validator,
) )
elif isinstance(validator, (DictFormatterValidator, OverridesDictFormatterValidator)): elif isinstance(validator, (DictFormatterValidator, OverridesDictFormatterValidator)):
@ -338,6 +340,7 @@ def validate_formatters(
resolved_dict[validator.leaf_name] |= _validate_formatter( resolved_dict[validator.leaf_name] |= _validate_formatter(
mock_script=script, mock_script=script,
unresolved_variables=unresolved_variables, unresolved_variables=unresolved_variables,
unresolved_runtime_variables=unresolved_runtime_variables,
formatter_validator=validator_value, formatter_validator=validator_value,
) )
else: else: