test setup
This commit is contained in:
parent
bca397cd7b
commit
6ecd04619e
7 changed files with 614 additions and 574 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from ytdl_sub.config.overrides import Overrides
|
from ytdl_sub.config.overrides import Overrides
|
||||||
from ytdl_sub.config.plugin.plugin_mapping import PluginMapping
|
from ytdl_sub.config.plugin.plugin_mapping import PluginMapping
|
||||||
|
|
@ -19,6 +20,23 @@ class ResolutionLevel:
|
||||||
RESOLVE = 2
|
RESOLVE = 2
|
||||||
INTERNAL = 3
|
INTERNAL = 3
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def name_of(cls, resolution_level: int) -> str:
|
||||||
|
if resolution_level == cls.ORIGINAL:
|
||||||
|
return "original"
|
||||||
|
if resolution_level == cls.FILL:
|
||||||
|
return "fill"
|
||||||
|
if resolution_level == cls.RESOLVE:
|
||||||
|
return "resolve"
|
||||||
|
if resolution_level == cls.INTERNAL:
|
||||||
|
return "internal"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def all(cls) -> List[int]:
|
||||||
|
return [cls.ORIGINAL, cls.FILL, cls.RESOLVE, cls.INTERNAL]
|
||||||
|
|
||||||
|
raise ValueError("Invalid resolution level")
|
||||||
|
|
||||||
|
|
||||||
class VariableValidation:
|
class VariableValidation:
|
||||||
|
|
||||||
|
|
@ -30,25 +48,20 @@ class VariableValidation:
|
||||||
elif self._resolution_level == ResolutionLevel.RESOLVE:
|
elif self._resolution_level == ResolutionLevel.RESOLVE:
|
||||||
# Partial resolve everything, but not including internal variables
|
# Partial resolve everything, but not including internal variables
|
||||||
self.unresolved_variables |= VARIABLES.variable_names(include_sanitized=True)
|
self.unresolved_variables |= VARIABLES.variable_names(include_sanitized=True)
|
||||||
self.script = self.script.resolve_partial(
|
self.script = self.script.resolve_partial(unresolvable=self.unresolved_variables)
|
||||||
unresolvable=self.unresolved_variables
|
|
||||||
)
|
|
||||||
elif self._resolution_level == ResolutionLevel.INTERNAL:
|
elif self._resolution_level == ResolutionLevel.INTERNAL:
|
||||||
# Partial resolve everything including internal variables
|
# Partial resolve everything including internal variables
|
||||||
self.script = self.script.resolve_partial(
|
self.script = self.script.resolve_partial(unresolvable=self.unresolved_variables)
|
||||||
unresolvable=self.unresolved_variables
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid resolution level for validation")
|
raise ValueError("Invalid resolution level for validation")
|
||||||
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
overrides: Overrides,
|
overrides: Overrides,
|
||||||
downloader_options: MultiUrlValidator,
|
downloader_options: MultiUrlValidator,
|
||||||
output_options: OutputOptions,
|
output_options: OutputOptions,
|
||||||
plugins: PresetPlugins,
|
plugins: PresetPlugins,
|
||||||
resolution_level: int = ResolutionLevel.FILL
|
resolution_level: int = ResolutionLevel.FILL,
|
||||||
):
|
):
|
||||||
self.overrides = overrides
|
self.overrides = overrides
|
||||||
self.downloader_options = downloader_options
|
self.downloader_options = downloader_options
|
||||||
|
|
@ -77,7 +90,6 @@ class VariableValidation:
|
||||||
|
|
||||||
self.unresolved_runtime_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:
|
||||||
"""
|
"""
|
||||||
Validate variables resolve as plugins are executed, and return
|
Validate variables resolve as plugins are executed, and return
|
||||||
|
|
@ -136,17 +148,18 @@ class VariableValidation:
|
||||||
resolved_subscription["download"].append(url_output)
|
resolved_subscription["download"].append(url_output)
|
||||||
|
|
||||||
# TODO: make function
|
# TODO: make function
|
||||||
resolved_subscription['overrides'] = {}
|
resolved_subscription["overrides"] = {}
|
||||||
for name in self.overrides.keys:
|
for name in self.overrides.keys:
|
||||||
value = self.script.definition_of(name)
|
value = self.script.definition_of(name)
|
||||||
if name in self.script.function_names:
|
if name in self.script.function_names:
|
||||||
# Keep custom functions as-is
|
# Keep custom functions as-is
|
||||||
resolved_subscription['overrides'][name] = self.overrides.dict_with_format_strings[name]
|
resolved_subscription["overrides"][name] = self.overrides.dict_with_format_strings[
|
||||||
|
name
|
||||||
|
]
|
||||||
elif resolved := value.maybe_resolvable:
|
elif resolved := value.maybe_resolvable:
|
||||||
resolved_subscription['overrides'][name] = resolved.native
|
resolved_subscription["overrides"][name] = resolved.native
|
||||||
else:
|
else:
|
||||||
resolved_subscription['overrides'][name] = ScriptUtils.to_native_script(value)
|
resolved_subscription["overrides"][name] = ScriptUtils.to_native_script(value)
|
||||||
|
|
||||||
assert not self.unresolved_runtime_variables
|
assert not self.unresolved_runtime_variables
|
||||||
return resolved_subscription
|
return resolved_subscription
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -680,7 +680,7 @@ class Script:
|
||||||
raise RuntimeException(f"Tried to get unresolved variable {variable_name}")
|
raise RuntimeException(f"Tried to get unresolved variable {variable_name}")
|
||||||
|
|
||||||
def definition_of(self, name: str) -> SyntaxTree:
|
def definition_of(self, name: str) -> SyntaxTree:
|
||||||
if name.startswith('%') and name[1:] in self._functions:
|
if name.startswith("%") and name[1:] in self._functions:
|
||||||
return self._functions[name[1:]]
|
return self._functions[name[1:]]
|
||||||
if name in self._variables:
|
if name in self._variables:
|
||||||
return self._variables[name]
|
return self._variables[name]
|
||||||
|
|
|
||||||
|
|
@ -263,14 +263,14 @@ class BaseSubscription(ABC):
|
||||||
-------
|
-------
|
||||||
Human-readable, condensed YAML definition of the subscription.
|
Human-readable, condensed YAML definition of the subscription.
|
||||||
"""
|
"""
|
||||||
out = (
|
if resolution_level == ResolutionLevel.ORIGINAL:
|
||||||
VariableValidation(
|
return self._preset_options.yaml
|
||||||
overrides=self.overrides,
|
|
||||||
downloader_options=self.downloader_options,
|
out = VariableValidation(
|
||||||
output_options=self.output_options,
|
overrides=self.overrides,
|
||||||
plugins=self.plugins,
|
downloader_options=self.downloader_options,
|
||||||
resolution_level=resolution_level,
|
output_options=self.output_options,
|
||||||
)
|
plugins=self.plugins,
|
||||||
.ensure_proper_usage()
|
resolution_level=resolution_level,
|
||||||
)
|
).ensure_proper_usage()
|
||||||
return dump_yaml(out)
|
return dump_yaml(out)
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ def _validate_formatter(
|
||||||
unresolved_variables: Set[str],
|
unresolved_variables: Set[str],
|
||||||
unresolved_runtime_variables: Set[str],
|
unresolved_runtime_variables: Set[str],
|
||||||
formatter_validator: Union[StringFormatterValidator, OverridesStringFormatterValidator],
|
formatter_validator: Union[StringFormatterValidator, OverridesStringFormatterValidator],
|
||||||
resolve_partial: bool = True
|
resolve_partial: bool = True,
|
||||||
) -> str:
|
) -> str:
|
||||||
parsed = formatter_validator.parsed
|
parsed = formatter_validator.parsed
|
||||||
if resolved := parsed.maybe_resolvable:
|
if resolved := parsed.maybe_resolvable:
|
||||||
|
|
@ -253,9 +253,11 @@ def _validate_formatter(
|
||||||
|
|
||||||
if resolve_partial and not is_static_formatter:
|
if resolve_partial and not is_static_formatter:
|
||||||
formatter_hash = get_md5_hash(formatter_validator.format_string)
|
formatter_hash = get_md5_hash(formatter_validator.format_string)
|
||||||
parsed = mock_script.add_parsed(
|
parsed = (
|
||||||
{formatter_hash: formatter_validator.parsed}
|
mock_script.add_parsed({formatter_hash: formatter_validator.parsed})
|
||||||
).resolve_partial(unresolvable=unresolved_variables).definition_of(formatter_hash)
|
.resolve_partial(unresolvable=unresolved_variables)
|
||||||
|
.definition_of(formatter_hash)
|
||||||
|
)
|
||||||
|
|
||||||
# Add lambda functions to custom function names, if it's custom
|
# Add lambda functions to custom function names, if it's custom
|
||||||
for lambda_func in parsed.lambdas:
|
for lambda_func in parsed.lambdas:
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
DISABLE_YOUTUBE_TESTS: bool = True
|
DISABLE_YOUTUBE_TESTS: bool = True
|
||||||
REGENERATE_FIXTURES: bool = False
|
REGENERATE_FIXTURES: bool = True
|
||||||
|
|
||||||
RESOURCE_PATH: Path = Path("tests") / "resources"
|
RESOURCE_PATH: Path = Path("tests") / "resources"
|
||||||
_FILE_FIXTURE_PATH: Path = RESOURCE_PATH / "file_fixtures"
|
_FILE_FIXTURE_PATH: Path = RESOURCE_PATH / "file_fixtures"
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
32
tests/unit/config/test_subscription_resolution.py
Normal file
32
tests/unit/config/test_subscription_resolution.py
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import yaml
|
||||||
|
from resources import expected_json
|
||||||
|
|
||||||
|
from ytdl_sub.config.config_file import ConfigFile
|
||||||
|
from ytdl_sub.config.validators.variable_validation import ResolutionLevel
|
||||||
|
from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_resolved_yaml(sub: Subscription, preset_type: str, resolution_level: int) -> None:
|
||||||
|
output_yaml = sub.resolved_yaml(resolution_level=resolution_level)
|
||||||
|
out = yaml.safe_load(output_yaml)
|
||||||
|
|
||||||
|
expected_out_filename = (
|
||||||
|
f"{preset_type}/inspect_sub_{ResolutionLevel.name_of(resolution_level)}.json"
|
||||||
|
)
|
||||||
|
assert out == expected_json(out, expected_out_filename)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("resolution_level", ResolutionLevel.all())
|
||||||
|
def test_resolution_original_tv_show(
|
||||||
|
resolution_level: int, config_file: ConfigFile, tv_show_subscriptions_path: Path
|
||||||
|
):
|
||||||
|
_ensure_resolved_yaml(
|
||||||
|
sub=Subscription.from_file_path(
|
||||||
|
config=config_file, subscription_path=tv_show_subscriptions_path
|
||||||
|
)[0],
|
||||||
|
preset_type="tv_show",
|
||||||
|
resolution_level=resolution_level,
|
||||||
|
)
|
||||||
Loading…
Reference in a new issue