refactored, validation now in subscription
This commit is contained in:
parent
276d1de979
commit
a6702dc723
5 changed files with 92 additions and 58 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
|
from typing import Iterable
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from typing import Set
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
|
|
@ -44,3 +46,31 @@ class PresetPlugins:
|
||||||
if plugin_type in plugin_option_types:
|
if plugin_type in plugin_option_types:
|
||||||
return self.plugin_options[plugin_option_types.index(plugin_type)]
|
return self.plugin_options[plugin_option_types.index(plugin_type)]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_added_and_modified_variables(
|
||||||
|
self, additional_options: List[OptionsValidator]
|
||||||
|
) -> Iterable[Tuple[OptionsValidator, Set[str], Set[str]]]:
|
||||||
|
"""
|
||||||
|
Iterates and returns the plugin options, added variables, modified variables
|
||||||
|
"""
|
||||||
|
for plugin_options in self.plugin_options + additional_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 get_all_variables(self, additional_options: List[OptionsValidator]) -> Set[str]:
|
||||||
|
all_variables: Set[str] = set()
|
||||||
|
for _, added, modified in self.get_added_and_modified_variables(additional_options):
|
||||||
|
all_variables.update(added)
|
||||||
|
all_variables.update(modified)
|
||||||
|
|
||||||
|
return all_variables
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import copy
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from typing import Set
|
||||||
|
|
||||||
from mergedeep import mergedeep
|
from mergedeep import mergedeep
|
||||||
|
|
||||||
|
|
@ -11,7 +12,6 @@ from ytdl_sub.config.plugin.plugin_mapping import PluginMapping
|
||||||
from ytdl_sub.config.plugin.preset_plugins import PresetPlugins
|
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.preset_options import YTDLOptions
|
from ytdl_sub.config.preset_options import YTDLOptions
|
||||||
from ytdl_sub.config.validators.variable_validation import VariableValidation
|
|
||||||
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
|
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
|
||||||
from ytdl_sub.prebuilt_presets import PREBUILT_PRESET_NAMES
|
from ytdl_sub.prebuilt_presets import PREBUILT_PRESET_NAMES
|
||||||
from ytdl_sub.prebuilt_presets import PUBLISHED_PRESET_NAMES
|
from ytdl_sub.prebuilt_presets import PUBLISHED_PRESET_NAMES
|
||||||
|
|
@ -172,6 +172,37 @@ class Preset(_PresetShell):
|
||||||
mergedeep.merge({}, *reversed(presets_to_merge), strategy=mergedeep.Strategy.ADDITIVE)
|
mergedeep.merge({}, *reversed(presets_to_merge), strategy=mergedeep.Strategy.ADDITIVE)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _initialize_overrides_script(self, overrides: Overrides) -> Overrides:
|
||||||
|
"""
|
||||||
|
Do some gymnastics to initialize the Overrides script.
|
||||||
|
"""
|
||||||
|
unresolved_variables: Set[str] = set()
|
||||||
|
|
||||||
|
for (
|
||||||
|
plugin_options,
|
||||||
|
added_variables,
|
||||||
|
modified_variables,
|
||||||
|
) in self.plugins.get_added_and_modified_variables(
|
||||||
|
additional_options=[self.downloader_options, self.output_options]
|
||||||
|
):
|
||||||
|
for added_variable in added_variables:
|
||||||
|
if not overrides.ensure_added_plugin_variable_valid(added_variable=added_variable):
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
raise plugin_options._validation_exception(
|
||||||
|
f"Cannot use the variable name {added_variable} because it exists as a"
|
||||||
|
" built-in ytdl-sub variable name."
|
||||||
|
)
|
||||||
|
# pylint: enable=protected-access
|
||||||
|
|
||||||
|
# Set unresolved as variables that are added but do not exist as
|
||||||
|
# entry/override variables since they are created at run-time
|
||||||
|
unresolved_variables |= added_variables | modified_variables
|
||||||
|
|
||||||
|
# Initialize overrides with unresolved variables + modified variables to throw an error.
|
||||||
|
# For modified variables, this is to prevent a resolve(update=True) to setting any
|
||||||
|
# dependencies until it has been explicitly added
|
||||||
|
return overrides.initialize_script(unresolved_variables=unresolved_variables)
|
||||||
|
|
||||||
def __init__(self, config: ConfigValidator, name: str, value: Any):
|
def __init__(self, config: ConfigValidator, name: str, value: Any):
|
||||||
super().__init__(name=name, value=value)
|
super().__init__(name=name, value=value)
|
||||||
|
|
||||||
|
|
@ -192,16 +223,8 @@ class Preset(_PresetShell):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.plugins: PresetPlugins = self._validate_and_get_plugins()
|
self.plugins: PresetPlugins = self._validate_and_get_plugins()
|
||||||
self.overrides = self._validate_key(key="overrides", validator=Overrides, default={})
|
self.overrides = self._initialize_overrides_script(
|
||||||
|
overrides=self._validate_key(key="overrides", validator=Overrides, default={})
|
||||||
self.validated_dict = (
|
|
||||||
VariableValidation(
|
|
||||||
downloader_options=self.downloader_options,
|
|
||||||
output_options=self.output_options,
|
|
||||||
plugins=self.plugins,
|
|
||||||
)
|
|
||||||
.initialize_preset_overrides(overrides=self.overrides)
|
|
||||||
.ensure_proper_usage()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
||||||
|
|
@ -100,48 +100,21 @@ class VariableValidation:
|
||||||
self.resolved_variables: Set[str] = set()
|
self.resolved_variables: Set[str] = set()
|
||||||
self.unresolved_variables: Set[str] = set()
|
self.unresolved_variables: Set[str] = set()
|
||||||
|
|
||||||
def initialize_preset_overrides(self, overrides: Overrides) -> "VariableValidation":
|
def initialize_preset_overrides(
|
||||||
"""
|
self,
|
||||||
Do some gymnastics to initialize the Overrides script.
|
overrides: Overrides,
|
||||||
"""
|
) -> "VariableValidation":
|
||||||
override_variables = set(list(overrides.initial_variables().keys()))
|
plugin_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
|
# Set resolved variables as all entry + override variables
|
||||||
# at this point to generate every possible added/modified variable
|
# at this point to generate every possible added/modified variable
|
||||||
self.resolved_variables = set(_DUMMY_ENTRY_VARIABLES.keys()) | override_variables
|
self.resolved_variables = (
|
||||||
plugin_variables: Set[str] = set()
|
set(_DUMMY_ENTRY_VARIABLES.keys()) | set(list(overrides.initial_variables().keys()))
|
||||||
|
) - self.unresolved_variables
|
||||||
for (
|
|
||||||
plugin_options,
|
|
||||||
added_variables,
|
|
||||||
modified_variables,
|
|
||||||
) in _get_added_and_modified_variables(
|
|
||||||
plugins=self.plugins,
|
|
||||||
downloader_options=self.downloader_options,
|
|
||||||
output_options=self.output_options,
|
|
||||||
):
|
|
||||||
|
|
||||||
for added_variable in added_variables:
|
|
||||||
if not overrides.ensure_added_plugin_variable_valid(added_variable=added_variable):
|
|
||||||
# pylint: disable=protected-access
|
|
||||||
raise plugin_options._validation_exception(
|
|
||||||
f"Cannot use the variable name {added_variable} because it exists as a"
|
|
||||||
" built-in ytdl-sub variable name."
|
|
||||||
)
|
|
||||||
# pylint: enable=protected-access
|
|
||||||
|
|
||||||
# Set unresolved as variables that are added but do not exist as
|
|
||||||
# entry/override variables since they are created at run-time
|
|
||||||
self.unresolved_variables |= added_variables | modified_variables
|
|
||||||
plugin_variables |= added_variables | modified_variables
|
|
||||||
|
|
||||||
# Then update resolved variables to reflect that
|
|
||||||
self.resolved_variables -= self.unresolved_variables
|
|
||||||
|
|
||||||
# Initialize overrides with unresolved variables + modified variables to throw an error.
|
|
||||||
# For modified variables, this is to prevent a resolve(update=True) to setting any
|
|
||||||
# dependencies until it has been explicitly added
|
|
||||||
overrides = overrides.initialize_script(unresolved_variables=self.unresolved_variables)
|
|
||||||
|
|
||||||
# copy the script and mock entry variables
|
# copy the script and mock entry variables
|
||||||
self.script = copy.deepcopy(overrides.script)
|
self.script = copy.deepcopy(overrides.script)
|
||||||
|
|
@ -153,9 +126,6 @@ class VariableValidation:
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _update_script(self) -> None:
|
|
||||||
_ = self.script.resolve(unresolvable=self.unresolved_variables, update=True)
|
|
||||||
|
|
||||||
def _add_subscription_override_variables(self) -> None:
|
def _add_subscription_override_variables(self) -> None:
|
||||||
"""
|
"""
|
||||||
Add dummy subscription variables for script validation
|
Add dummy subscription variables for script validation
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from ytdl_sub.config.plugin.preset_plugins import PresetPlugins
|
||||||
from ytdl_sub.config.preset import Preset
|
from ytdl_sub.config.preset import Preset
|
||||||
from ytdl_sub.config.preset_options import OutputOptions
|
from ytdl_sub.config.preset_options import OutputOptions
|
||||||
from ytdl_sub.config.preset_options import YTDLOptions
|
from ytdl_sub.config.preset_options import YTDLOptions
|
||||||
|
from ytdl_sub.config.validators.variable_validation import VariableValidation
|
||||||
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
|
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
|
||||||
from ytdl_sub.entries.variables.override_variables import SubscriptionVariables
|
from ytdl_sub.entries.variables.override_variables import SubscriptionVariables
|
||||||
from ytdl_sub.utils.exceptions import SubscriptionPermissionError
|
from ytdl_sub.utils.exceptions import SubscriptionPermissionError
|
||||||
|
|
@ -88,9 +89,9 @@ class BaseSubscription(ABC):
|
||||||
# Add post-archive variables
|
# Add post-archive variables
|
||||||
self.overrides.add(
|
self.overrides.add(
|
||||||
{
|
{
|
||||||
SubscriptionVariables.subscription_has_download_archive(): f"""{{
|
SubscriptionVariables.subscription_has_download_archive(): (
|
||||||
%bool({self.download_archive.num_entries > 0})
|
f"{{%bool({self.download_archive.num_entries > 0})}}"
|
||||||
}}""",
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -102,6 +103,16 @@ class BaseSubscription(ABC):
|
||||||
f"{self.output_directory}"
|
f"{self.output_directory}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._validated_dict = (
|
||||||
|
VariableValidation(
|
||||||
|
downloader_options=self.downloader_options,
|
||||||
|
output_options=self.output_options,
|
||||||
|
plugins=self.plugins,
|
||||||
|
)
|
||||||
|
.initialize_preset_overrides(overrides=self.overrides)
|
||||||
|
.ensure_proper_usage()
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def download_archive(self) -> EnhancedDownloadArchive:
|
def download_archive(self) -> EnhancedDownloadArchive:
|
||||||
"""
|
"""
|
||||||
|
|
@ -247,4 +258,4 @@ class BaseSubscription(ABC):
|
||||||
return self._preset_options.yaml
|
return self._preset_options.yaml
|
||||||
|
|
||||||
def resolved_yaml(self):
|
def resolved_yaml(self):
|
||||||
return self._preset_options.validated_dict
|
return self._validated_dict
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,7 @@ def validate_formatters(
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
# Usage of protected variables in other validators is fine. The reason to keep
|
# Usage of protected variables in other validators is fine. The reason to keep
|
||||||
# them protected is for readability when using them in subscriptions.
|
# them protected is for readability when using them in subscriptions.
|
||||||
for key, validator_value in validator._validator_dict.items():
|
for validator_value in validator._validator_dict.values():
|
||||||
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,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue