try to simplify script
This commit is contained in:
parent
54a034d4a7
commit
f8a2f03130
3 changed files with 25 additions and 49 deletions
|
|
@ -181,13 +181,18 @@ class Script:
|
||||||
self._ensure_custom_function_usage_num_input_arguments_valid()
|
self._ensure_custom_function_usage_num_input_arguments_valid()
|
||||||
|
|
||||||
def resolve(
|
def resolve(
|
||||||
self, pre_resolved_variables: Optional[Dict[str, Resolvable]] = None
|
self,
|
||||||
|
pre_resolved_variables: Optional[Dict[str, Resolvable]] = None,
|
||||||
|
unresolvable: Optional[Set[str]] = None,
|
||||||
) -> Dict[str, Resolvable]:
|
) -> Dict[str, Resolvable]:
|
||||||
"""
|
"""
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
pre_resolved_variables
|
pre_resolved_variables
|
||||||
Optional variables that have been resolved elsewhere and could be used in this script
|
Optional variables that have been resolved elsewhere and could be used in this script
|
||||||
|
unresolvable
|
||||||
|
Variables that cannot be resolved, forcing any variable that depends on it to not be
|
||||||
|
resolved.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
|
@ -197,60 +202,26 @@ class Script:
|
||||||
Variable(name): ast for name, ast in self._variables.items()
|
Variable(name): ast for name, ast in self._variables.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unresolvable_variables: Set[Variable] = set(Variable(var) for var in (unresolvable or {}))
|
||||||
resolved_variables: Dict[Variable, Resolvable] = {
|
resolved_variables: Dict[Variable, Resolvable] = {
|
||||||
Variable(name): value for name, value in (pre_resolved_variables or {}).items()
|
Variable(name): value for name, value in (pre_resolved_variables or {}).items()
|
||||||
}
|
}
|
||||||
unresolved_variables: Set[Variable] = set(variables.keys()) - set(resolved_variables.keys())
|
unresolved_variables: Set[Variable] = (
|
||||||
|
set(variables.keys()) - set(resolved_variables.keys()) - unresolvable_variables
|
||||||
|
)
|
||||||
|
|
||||||
while unresolved_variables:
|
while unresolved_variables:
|
||||||
unresolved_count: int = len(unresolved_variables)
|
unresolved_count: int = len(unresolved_variables)
|
||||||
|
|
||||||
for variable in copy.deepcopy(unresolved_variables):
|
for variable in copy.deepcopy(unresolved_variables):
|
||||||
if not variables[variable].has_variable_dependency(
|
# If the variable's variable dependencies contain an unresolvable variable,
|
||||||
resolved_variables=resolved_variables
|
# declare it as unresolvable and continue
|
||||||
):
|
if variables[variable].contains(unresolvable_variables):
|
||||||
resolved_variables[variable] = variables[variable].resolve(
|
|
||||||
resolved_variables=resolved_variables,
|
|
||||||
custom_functions=self._functions,
|
|
||||||
)
|
|
||||||
unresolved_variables.remove(variable)
|
|
||||||
|
|
||||||
if len(unresolved_variables) == unresolved_count:
|
|
||||||
# Implies a cycle within the variables. Should never reach
|
|
||||||
# since cycles are detected in __init__
|
|
||||||
raise UNREACHABLE
|
|
||||||
|
|
||||||
return {variable.name: resolvable for variable, resolvable in resolved_variables.items()}
|
|
||||||
|
|
||||||
def partial_resolve(self, unresolvable: Set[str]) -> Dict[str, Resolvable]:
|
|
||||||
"""
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
unresolvable
|
|
||||||
Variables that cannot be resolved
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Dict of resolved values
|
|
||||||
"""
|
|
||||||
variables: Dict[Variable, SyntaxTree] = {
|
|
||||||
Variable(name): ast for name, ast in self._variables.items()
|
|
||||||
}
|
|
||||||
|
|
||||||
unresolvable_variables: Set[Variable] = set(Variable(var) for var in unresolvable)
|
|
||||||
unresolved_variables: Set[Variable] = set(variables.keys()) - unresolvable_variables
|
|
||||||
resolved_variables: Dict[Variable, Resolvable] = {}
|
|
||||||
|
|
||||||
while unresolved_variables:
|
|
||||||
unresolved_count: int = len(unresolved_variables)
|
|
||||||
|
|
||||||
for variable in copy.deepcopy(unresolved_variables):
|
|
||||||
if variables[variable].variables.intersection(unresolvable_variables):
|
|
||||||
unresolvable_variables.add(variable)
|
unresolvable_variables.add(variable)
|
||||||
unresolved_variables.remove(variable)
|
unresolved_variables.remove(variable)
|
||||||
elif not variables[variable].has_variable_dependency(
|
|
||||||
resolved_variables=resolved_variables
|
# Otherwise, resolve it
|
||||||
):
|
elif not variables[variable].is_subset_of(variables=resolved_variables.keys()):
|
||||||
resolved_variables[variable] = variables[variable].resolve(
|
resolved_variables[variable] = variables[variable].resolve(
|
||||||
resolved_variables=resolved_variables,
|
resolved_variables=resolved_variables,
|
||||||
custom_functions=self._functions,
|
custom_functions=self._functions,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from abc import ABC
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from typing import Iterable
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Set
|
from typing import Set
|
||||||
from typing import final
|
from typing import final
|
||||||
|
|
@ -94,10 +95,14 @@ class VariableDependency(ABC):
|
||||||
raise UNREACHABLE
|
raise UNREACHABLE
|
||||||
|
|
||||||
@final
|
@final
|
||||||
def has_variable_dependency(self, resolved_variables: Dict[Variable, Resolvable]) -> bool:
|
def is_subset_of(self, variables: Iterable[Variable]) -> bool:
|
||||||
"""
|
"""
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
True if variable dependency. False otherwise.
|
True if variable dependency. False otherwise.
|
||||||
"""
|
"""
|
||||||
return not self.variables.issubset(set(resolved_variables.keys()))
|
return not self.variables.issubset(variables)
|
||||||
|
|
||||||
|
@final
|
||||||
|
def contains(self, variables: Iterable[Variable]) -> bool:
|
||||||
|
return len(self.variables.intersection(variables)) > 0
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class TestScript:
|
||||||
"bb": "b",
|
"bb": "b",
|
||||||
"cc": "{%custom_func(aa, bb)}",
|
"cc": "{%custom_func(aa, bb)}",
|
||||||
}
|
}
|
||||||
).partial_resolve(unresolvable={"bb"}) == {"aa": String("a")}
|
).resolve(unresolvable={"bb"}) == {"aa": String("a")}
|
||||||
|
|
||||||
def test_partial_update_script(self):
|
def test_partial_update_script(self):
|
||||||
script = Script(
|
script = Script(
|
||||||
|
|
@ -37,7 +37,7 @@ class TestScript:
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
overrides = script.partial_resolve(unresolvable={"entry"})
|
overrides = script.resolve(unresolvable={"entry"})
|
||||||
assert overrides == {"override": String("hi")}
|
assert overrides == {"override": String("hi")}
|
||||||
|
|
||||||
entry_map = ResolvedMap({String("title"): String("the title")})
|
entry_map = ResolvedMap({String("title"): String("the title")})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue