try to simplify script

This commit is contained in:
Jesse Bannon 2023-11-22 23:40:17 -08:00
parent 54a034d4a7
commit f8a2f03130
3 changed files with 25 additions and 49 deletions

View file

@ -181,13 +181,18 @@ class Script:
self._ensure_custom_function_usage_num_input_arguments_valid()
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]:
"""
Parameters
----------
pre_resolved_variables
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
-------
@ -197,60 +202,26 @@ class Script:
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] = {
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:
unresolved_count: int = len(unresolved_variables)
for variable in copy.deepcopy(unresolved_variables):
if not variables[variable].has_variable_dependency(
resolved_variables=resolved_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):
# If the variable's variable dependencies contain an unresolvable variable,
# declare it as unresolvable and continue
if variables[variable].contains(unresolvable_variables):
unresolvable_variables.add(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=resolved_variables,
custom_functions=self._functions,

View file

@ -2,6 +2,7 @@ from abc import ABC
from abc import abstractmethod
from dataclasses import dataclass
from typing import Dict
from typing import Iterable
from typing import List
from typing import Set
from typing import final
@ -94,10 +95,14 @@ class VariableDependency(ABC):
raise UNREACHABLE
@final
def has_variable_dependency(self, resolved_variables: Dict[Variable, Resolvable]) -> bool:
def is_subset_of(self, variables: Iterable[Variable]) -> bool:
"""
Returns
-------
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

View file

@ -26,7 +26,7 @@ class TestScript:
"bb": "b",
"cc": "{%custom_func(aa, bb)}",
}
).partial_resolve(unresolvable={"bb"}) == {"aa": String("a")}
).resolve(unresolvable={"bb"}) == {"aa": String("a")}
def test_partial_update_script(self):
script = Script(
@ -37,7 +37,7 @@ class TestScript:
}
)
overrides = script.partial_resolve(unresolvable={"entry"})
overrides = script.resolve(unresolvable={"entry"})
assert overrides == {"override": String("hi")}
entry_map = ResolvedMap({String("title"): String("the title")})