close, do not use recursion to determine unresolvable, instead, only look at current layer
This commit is contained in:
parent
e86e414ad9
commit
eeea7be52d
7 changed files with 108 additions and 5 deletions
|
|
@ -695,3 +695,52 @@ class Script:
|
||||||
Names of all functions within the Script.
|
Names of all functions within the Script.
|
||||||
"""
|
"""
|
||||||
return set(to_function_definition_name(name) for name in self._functions.keys())
|
return set(to_function_definition_name(name) for name in self._functions.keys())
|
||||||
|
|
||||||
|
def resolve_partial(
|
||||||
|
self,
|
||||||
|
unresolvable: Optional[Set[str]] = None,
|
||||||
|
) -> "Script":
|
||||||
|
"""
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Dict of resolved values
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
ScriptVariableNotResolved
|
||||||
|
If specifying a filter of variable to resolve, and one of them does not.
|
||||||
|
"""
|
||||||
|
resolved: Dict[Variable, Resolvable] = {}
|
||||||
|
unresolved: Dict[Variable, SyntaxTree] = {
|
||||||
|
Variable(name): ast for name, ast in self._variables.items() if name not in unresolvable
|
||||||
|
}
|
||||||
|
unresolvable: Set[Variable] = {Variable(name) for name in (unresolvable or {})}
|
||||||
|
|
||||||
|
partially_resolved = True
|
||||||
|
while partially_resolved:
|
||||||
|
|
||||||
|
partially_resolved = False
|
||||||
|
|
||||||
|
for variable in list(unresolved.keys()):
|
||||||
|
|
||||||
|
definition = unresolved[variable]
|
||||||
|
|
||||||
|
maybe_resolved = definition.partial_resolve(
|
||||||
|
resolved_variables=resolved, custom_functions=self._functions
|
||||||
|
)
|
||||||
|
if isinstance(maybe_resolved, Resolvable):
|
||||||
|
resolved[variable] = maybe_resolved
|
||||||
|
del unresolved[variable]
|
||||||
|
else:
|
||||||
|
unresolved[variable] = maybe_resolved
|
||||||
|
|
||||||
|
# If the definition changed, then the script changed
|
||||||
|
# which means we can iterate again
|
||||||
|
partially_resolved |= definition != maybe_resolved
|
||||||
|
|
||||||
|
return Script({}).add_parsed(
|
||||||
|
self._functions
|
||||||
|
| {var.name: definition for var, definition in resolved.items()}
|
||||||
|
| unresolved
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,10 @@ class UnresolvedArray(_Array, VariableDependency, FutureResolvable):
|
||||||
)
|
)
|
||||||
|
|
||||||
def partial_resolve(
|
def partial_resolve(
|
||||||
self,
|
self: TypeT,
|
||||||
resolved_variables: Dict[Variable, Resolvable],
|
resolved_variables: Dict[Variable, Resolvable],
|
||||||
custom_functions: Dict[str, "VariableDependency"],
|
custom_functions: Dict[str, "VariableDependency"],
|
||||||
) -> "UnresolvedArray" | Resolvable:
|
) -> TypeT | Resolvable:
|
||||||
maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve(
|
maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve(
|
||||||
args=self.value,
|
args=self.value,
|
||||||
resolved_variables=resolved_variables,
|
resolved_variables=resolved_variables,
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ class Function(FunctionType, VariableDependency, ABC):
|
||||||
custom_functions: Dict[str, "VariableDependency"],
|
custom_functions: Dict[str, "VariableDependency"],
|
||||||
) -> TypeT | Resolvable:
|
) -> TypeT | Resolvable:
|
||||||
maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve(
|
maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve(
|
||||||
args=self.value,
|
args=self.args,
|
||||||
resolved_variables=resolved_variables,
|
resolved_variables=resolved_variables,
|
||||||
custom_functions=custom_functions,
|
custom_functions=custom_functions,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ from ytdl_sub.script.types.resolvable import NonHashable
|
||||||
from ytdl_sub.script.types.resolvable import Resolvable
|
from ytdl_sub.script.types.resolvable import Resolvable
|
||||||
from ytdl_sub.script.types.resolvable import ResolvableToJson
|
from ytdl_sub.script.types.resolvable import ResolvableToJson
|
||||||
from ytdl_sub.script.types.variable import Variable
|
from ytdl_sub.script.types.variable import Variable
|
||||||
|
from ytdl_sub.script.types.variable_dependency import TypeT
|
||||||
from ytdl_sub.script.types.variable_dependency import VariableDependency
|
from ytdl_sub.script.types.variable_dependency import VariableDependency
|
||||||
from ytdl_sub.script.utils.exceptions import KeyNotHashableRuntimeException
|
from ytdl_sub.script.utils.exceptions import KeyNotHashableRuntimeException
|
||||||
|
|
||||||
|
|
@ -56,10 +57,10 @@ class UnresolvedMap(_Map, VariableDependency, FutureResolvable):
|
||||||
return Map(output)
|
return Map(output)
|
||||||
|
|
||||||
def partial_resolve(
|
def partial_resolve(
|
||||||
self,
|
self: TypeT,
|
||||||
resolved_variables: Dict[Variable, Resolvable],
|
resolved_variables: Dict[Variable, Resolvable],
|
||||||
custom_functions: Dict[str, "VariableDependency"],
|
custom_functions: Dict[str, "VariableDependency"],
|
||||||
) -> "UnresolvedMap" | Resolvable:
|
) -> TypeT | Resolvable:
|
||||||
maybe_resolvable_keys, is_keys_resolvable = VariableDependency.try_partial_resolve(
|
maybe_resolvable_keys, is_keys_resolvable = VariableDependency.try_partial_resolve(
|
||||||
args=self.value.keys(),
|
args=self.value.keys(),
|
||||||
resolved_variables=resolved_variables,
|
resolved_variables=resolved_variables,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ from ytdl_sub.script.types.resolvable import Argument
|
||||||
from ytdl_sub.script.types.resolvable import Resolvable
|
from ytdl_sub.script.types.resolvable import Resolvable
|
||||||
from ytdl_sub.script.types.resolvable import String
|
from ytdl_sub.script.types.resolvable import String
|
||||||
from ytdl_sub.script.types.variable import Variable
|
from ytdl_sub.script.types.variable import Variable
|
||||||
|
from ytdl_sub.script.types.variable_dependency import TypeT
|
||||||
from ytdl_sub.script.types.variable_dependency import VariableDependency
|
from ytdl_sub.script.types.variable_dependency import VariableDependency
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -40,6 +41,25 @@ class SyntaxTree(VariableDependency):
|
||||||
# Otherwise, to concat multiple resolved outputs, we must concat as strings
|
# Otherwise, to concat multiple resolved outputs, we must concat as strings
|
||||||
return String("".join([str(res) for res in resolved]))
|
return String("".join([str(res) for res in resolved]))
|
||||||
|
|
||||||
|
def partial_resolve(
|
||||||
|
self: TypeT,
|
||||||
|
resolved_variables: Dict[Variable, Resolvable],
|
||||||
|
custom_functions: Dict[str, VariableDependency],
|
||||||
|
) -> TypeT | Resolvable:
|
||||||
|
maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve(
|
||||||
|
args=self.ast,
|
||||||
|
resolved_variables=resolved_variables,
|
||||||
|
custom_functions=custom_functions,
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_resolvable:
|
||||||
|
return self.resolve(
|
||||||
|
resolved_variables=resolved_variables,
|
||||||
|
custom_functions=custom_functions,
|
||||||
|
)
|
||||||
|
|
||||||
|
return SyntaxTree(ast=maybe_resolvable_values)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def maybe_resolvable(self) -> Optional[Resolvable]:
|
def maybe_resolvable(self) -> Optional[Resolvable]:
|
||||||
"""
|
"""
|
||||||
|
|
@ -76,3 +96,10 @@ class ResolvedSyntaxTree(SyntaxTree):
|
||||||
@property
|
@property
|
||||||
def maybe_resolvable(self) -> Optional[Resolvable]:
|
def maybe_resolvable(self) -> Optional[Resolvable]:
|
||||||
return self.ast[0]
|
return self.ast[0]
|
||||||
|
|
||||||
|
def partial_resolve(
|
||||||
|
self: TypeT,
|
||||||
|
resolved_variables: Dict[Variable, Resolvable],
|
||||||
|
custom_functions: Dict[str, VariableDependency],
|
||||||
|
) -> TypeT | Resolvable:
|
||||||
|
return self.ast[0]
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,14 @@ class VariableDependency(ABC):
|
||||||
|
|
||||||
if not isinstance(maybe_resolvable_args[-1], Resolvable):
|
if not isinstance(maybe_resolvable_args[-1], Resolvable):
|
||||||
is_resolvable = False
|
is_resolvable = False
|
||||||
|
elif isinstance(arg, Variable):
|
||||||
|
if arg not in resolved_variables:
|
||||||
|
is_resolvable = False
|
||||||
|
|
||||||
|
maybe_resolvable_args.append(arg)
|
||||||
else:
|
else:
|
||||||
maybe_resolvable_args.append(arg)
|
maybe_resolvable_args.append(arg)
|
||||||
|
|
||||||
|
if is_resolvable:
|
||||||
|
print("hmm")
|
||||||
return maybe_resolvable_args, is_resolvable
|
return maybe_resolvable_args, is_resolvable
|
||||||
|
|
|
||||||
|
|
@ -598,3 +598,22 @@ def test_default_docker_config_and_subscriptions(
|
||||||
"year": "{episode_year}",
|
"year": "{episode_year}",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_docker_config_and_subscriptions(
|
||||||
|
docker_default_subscription_path: Path, output_directory: str
|
||||||
|
):
|
||||||
|
default_config = ConfigFile.from_file_path("docker/root/defaults/config.yaml")
|
||||||
|
default_subs = Subscription.from_file_path(
|
||||||
|
config=default_config, subscription_path=docker_default_subscription_path
|
||||||
|
)
|
||||||
|
assert len(default_subs) == 1
|
||||||
|
|
||||||
|
unresolvable = default_subs[0].plugins.get_all_variables(
|
||||||
|
additional_options=[default_subs[0].downloader_options, default_subs[0].output_options]
|
||||||
|
)
|
||||||
|
unresolvable.add("entry_metadata")
|
||||||
|
unresolvable.add("sibling_metadata")
|
||||||
|
|
||||||
|
out = default_subs[0].overrides.script.resolve_partial(unresolvable=unresolvable)
|
||||||
|
print("hi")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue