From 6302ec417dfb418367e23f4e2ed6d89ade66e693 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Tue, 30 Dec 2025 00:04:15 -0800 Subject: [PATCH] green and fast, try to not parse twice --- .../config/validators/variable_validation.py | 121 +----------------- .../validators/string_formatter_validators.py | 7 + 2 files changed, 10 insertions(+), 118 deletions(-) diff --git a/src/ytdl_sub/config/validators/variable_validation.py b/src/ytdl_sub/config/validators/variable_validation.py index 93b4dc6e..bb8ea705 100644 --- a/src/ytdl_sub/config/validators/variable_validation.py +++ b/src/ytdl_sub/config/validators/variable_validation.py @@ -1,10 +1,4 @@ -import copy from typing import Dict -from typing import Iterable -from typing import List -from typing import Optional -from typing import Set -from typing import Tuple from ytdl_sub.config.overrides import Overrides from ytdl_sub.config.plugin.plugin_mapping import PluginMapping @@ -13,80 +7,8 @@ from ytdl_sub.config.plugin.preset_plugins import PresetPlugins from ytdl_sub.config.preset_options import OutputOptions 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.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 from ytdl_sub.validators.string_formatter_validators import validate_formatters -# Entry variables to mock during validation -_DUMMY_ENTRY_VARIABLES: Dict[str, str] = { - name: to_variable_dependency_format_string( - # pylint: disable=protected-access - script=BASE_SCRIPT, - parsed_format_string=BASE_SCRIPT._variables[name], - # pylint: enable=protected-access - ) - for name in BASE_SCRIPT.variable_names -} - - -def _add_dummy_variables(variables: Iterable[str]) -> Dict[str, str]: - dummy_variables: Dict[str, str] = {} - for var in variables: - dummy_variables[var] = "" - dummy_variables[f"{var}_sanitized"] = "" - - return dummy_variables - - -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 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 = f'{{%string("""{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], - ) - - dummy_overrides[override_name] = value - return dummy_overrides - - -def _get_added_and_modified_variables( - plugins: PresetPlugins, downloader_options: MultiUrlValidator, output_options: OutputOptions -) -> Iterable[Tuple[OptionsValidator, Set[str], Set[str]]]: - """ - Iterates and returns the plugin options, added variables, modified variables - """ - options: List[OptionsValidator] = plugins.plugin_options - options.append(downloader_options) - options.append(output_options) - - for plugin_options in options: - added_variables: Set[str] = set() - modified_variables: Set[str] = set() - - for plugin_added_variables in plugin_options.added_variables( - unresolved_variables=set(), - ).values(): - added_variables |= set(plugin_added_variables) - - for plugin_modified_variables in plugin_options.modified_variables().values(): - modified_variables = plugin_modified_variables - - yield plugin_options, added_variables, modified_variables - - -def _override_variables(overrides: Overrides) -> Set[str]: - return set(list(overrides.initial_variables().keys())) - class VariableValidation: def __init__( @@ -101,44 +23,11 @@ class VariableValidation: self.output_options = output_options self.plugins = plugins - self.script: Optional[Script] = None - self.resolved_variables: Set[str] = set() - self.unresolved_variables: Set[str] = set() - - self._initialize_mock_script() - - def _initialize_mock_script( - self, - ) -> "VariableValidation": - plugin_variables = self.plugins.get_all_variables( + self.script = self.overrides.script + self.unresolved_variables = self.plugins.get_all_variables( additional_options=[self.output_options, self.downloader_options] ) - self.unresolved_variables = plugin_variables - - # Set resolved variables as all entry + override variables - # at this point to generate every possible added/modified variable - self.resolved_variables = ( - set(_DUMMY_ENTRY_VARIABLES.keys()) - | set(list(self.overrides.initial_variables().keys())) - ) - self.unresolved_variables - - # copy the script and mock entry variables - self.script = copy.deepcopy(self.overrides.script) - # self.script.add( - # variables=_DUMMY_ENTRY_VARIABLES - # | _add_dummy_variables(variables=plugin_variables) - # | _add_dummy_overrides(overrides=self.overrides) - # ) - - return self - - def _add_subscription_override_variables(self) -> None: - """ - Add dummy subscription variables for script validation - """ - self.resolved_variables |= REQUIRED_OVERRIDE_VARIABLE_NAMES - def _add_variables(self, plugin_op: PluginOperation, options: OptionsValidator) -> None: """ Add dummy variables for script validation @@ -148,10 +37,7 @@ class VariableValidation: ).get(plugin_op, set()) modified_variables = options.modified_variables().get(plugin_op, set()) - resolved_variables = added_variables | modified_variables - - self.resolved_variables |= resolved_variables - self.unresolved_variables -= resolved_variables + self.unresolved_variables -= added_variables | modified_variables def ensure_proper_usage(self) -> Dict: """ @@ -162,7 +48,6 @@ class VariableValidation: resolved_subscription: Dict = {} self._add_variables(PluginOperation.DOWNLOADER, options=self.downloader_options) - self._add_subscription_override_variables() # Always add output options first self._add_variables(PluginOperation.MODIFY_ENTRY_METADATA, options=self.output_options) diff --git a/src/ytdl_sub/validators/string_formatter_validators.py b/src/ytdl_sub/validators/string_formatter_validators.py index bdc3d196..e9090c1b 100644 --- a/src/ytdl_sub/validators/string_formatter_validators.py +++ b/src/ytdl_sub/validators/string_formatter_validators.py @@ -72,6 +72,11 @@ class StringFormatterValidator(StringValidator): @property @final def parsed(self) -> SyntaxTree: + """ + Returns + ------- + The parsed format string. + """ return self._parsed def post_process(self, resolved: str) -> str: @@ -318,6 +323,8 @@ def validate_formatters( formatter_validator=validator_value, ) else: + # pylint: disable=protected-access resolved_dict[validator.leaf_name] = validator._value + # pylint: enable=protected-access return resolved_dict