nearly working, need cleanup and resolving conditionals

This commit is contained in:
Jesse Bannon 2026-01-11 14:20:57 -08:00
parent 93cfe59330
commit 1f8e6b2786
7 changed files with 65 additions and 11 deletions

View file

@ -15,6 +15,7 @@ from ytdl_sub.script.types.syntax_tree import ResolvedSyntaxTree
from ytdl_sub.script.types.syntax_tree import SyntaxTree from ytdl_sub.script.types.syntax_tree import SyntaxTree
from ytdl_sub.script.types.variable import FunctionArgument from ytdl_sub.script.types.variable import FunctionArgument
from ytdl_sub.script.types.variable import Variable from ytdl_sub.script.types.variable import Variable
from ytdl_sub.script.types.variable_dependency import VariableDependency
from ytdl_sub.script.utils.exceptions import UNREACHABLE from ytdl_sub.script.utils.exceptions import UNREACHABLE
from ytdl_sub.script.utils.exceptions import CycleDetected from ytdl_sub.script.utils.exceptions import CycleDetected
from ytdl_sub.script.utils.exceptions import IncompatibleFunctionArguments from ytdl_sub.script.utils.exceptions import IncompatibleFunctionArguments
@ -697,9 +698,16 @@ class 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 _to_syntax_tree(self, maybe_resolved: SyntaxTree | Resolvable) -> SyntaxTree: def _to_syntax_tree(
self, maybe_resolved: SyntaxTree | Resolvable | VariableDependency
) -> SyntaxTree:
if isinstance(maybe_resolved, Resolvable): if isinstance(maybe_resolved, Resolvable):
return ResolvedSyntaxTree(ast=[maybe_resolved]) return ResolvedSyntaxTree(ast=[maybe_resolved])
if isinstance(maybe_resolved, SyntaxTree):
return maybe_resolved
if isinstance(maybe_resolved, VariableDependency):
return SyntaxTree(ast=[maybe_resolved])
return maybe_resolved return maybe_resolved
def resolve_partial( def resolve_partial(
@ -718,22 +726,45 @@ class Script:
If specifying a filter of variable to resolve, and one of them does not. If specifying a filter of variable to resolve, and one of them does not.
""" """
resolved: Dict[Variable, Resolvable] = {} resolved: Dict[Variable, Resolvable] = {}
unresolved: Dict[Variable, SyntaxTree] = { unresolved: Dict[Variable, VariableDependency] = {}
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 {})} unresolvable: Set[Variable] = {Variable(name) for name in (unresolvable or {})}
for variable_name, definition in self._variables.items():
assert len(definition.ast) == 1
arg = definition.ast[0]
variable = Variable(variable_name)
if variable in unresolvable:
continue
if isinstance(arg, Resolvable):
resolved[variable] = arg
elif isinstance(arg, Variable):
while isinstance(arg, Variable):
if arg in unresolvable:
break
arg = self._variables[arg.name]
if resolved_arg := arg.maybe_resolvable:
resolved[variable] = resolved_arg
else:
assert isinstance(arg, SyntaxTree)
unresolved[variable] = arg.ast[0]
else:
unresolved[variable] = arg
partially_resolved = True partially_resolved = True
while partially_resolved: while partially_resolved:
partially_resolved = False partially_resolved = False
for variable in list(unresolved.keys()): for variable in list(unresolved.keys()):
definition = unresolved[variable] definition = unresolved[variable]
maybe_resolved = definition.partial_resolve( maybe_resolved = definition.partial_resolve(
resolved_variables=resolved, custom_functions=self._functions resolved_variables=resolved,
unresolved_variables=unresolved,
custom_functions=self._functions,
) )
if isinstance(maybe_resolved, Resolvable): if isinstance(maybe_resolved, Resolvable):
resolved[variable] = maybe_resolved resolved[variable] = maybe_resolved

View file

@ -51,11 +51,13 @@ class UnresolvedArray(_Array, VariableDependency, FutureResolvable):
def partial_resolve( def partial_resolve(
self: TypeT, self: TypeT,
resolved_variables: Dict[Variable, Resolvable], resolved_variables: Dict[Variable, Resolvable],
unresolved_variables: Dict[Variable, Argument],
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.value,
resolved_variables=resolved_variables, resolved_variables=resolved_variables,
unresolved_variables=unresolved_variables,
custom_functions=custom_functions, custom_functions=custom_functions,
) )

View file

@ -88,11 +88,13 @@ class CustomFunction(Function, NamedCustomFunction):
def partial_resolve( def partial_resolve(
self, self,
resolved_variables: Dict[Variable, Resolvable], resolved_variables: Dict[Variable, Resolvable],
unresolved_variables: Dict[Variable, Argument],
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.args, args=self.args,
resolved_variables=resolved_variables, resolved_variables=resolved_variables,
unresolved_variables=unresolved_variables,
custom_functions=custom_functions, custom_functions=custom_functions,
) )
@ -338,6 +340,7 @@ class BuiltInFunction(Function, BuiltInFunctionType):
def partial_resolve( def partial_resolve(
self, self,
resolved_variables: Dict[Variable, Resolvable], resolved_variables: Dict[Variable, Resolvable],
unresolved_variables: Dict[Variable, Argument],
custom_functions: Dict[str, "VariableDependency"], custom_functions: Dict[str, "VariableDependency"],
) -> TypeT | Resolvable: ) -> TypeT | Resolvable:
conditional_return_args = self.function_spec.conditional_arg_indices( conditional_return_args = self.function_spec.conditional_arg_indices(
@ -358,6 +361,7 @@ class BuiltInFunction(Function, BuiltInFunctionType):
maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve( maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve(
args=self.args, args=self.args,
resolved_variables=resolved_variables, resolved_variables=resolved_variables,
unresolved_variables=unresolved_variables,
custom_functions=custom_functions, custom_functions=custom_functions,
) )

View file

@ -59,17 +59,20 @@ class UnresolvedMap(_Map, VariableDependency, FutureResolvable):
def partial_resolve( def partial_resolve(
self: TypeT, self: TypeT,
resolved_variables: Dict[Variable, Resolvable], resolved_variables: Dict[Variable, Resolvable],
unresolved_variables: Dict[Variable, Argument],
custom_functions: Dict[str, "VariableDependency"], custom_functions: Dict[str, "VariableDependency"],
) -> TypeT | 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,
unresolved_variables=unresolved_variables,
custom_functions=custom_functions, custom_functions=custom_functions,
) )
maybe_resolvable_values, is_values_resolvable = VariableDependency.try_partial_resolve( maybe_resolvable_values, is_values_resolvable = VariableDependency.try_partial_resolve(
args=self.value.values(), args=self.value.values(),
resolved_variables=resolved_variables, resolved_variables=resolved_variables,
unresolved_variables=unresolved_variables,
custom_functions=custom_functions, custom_functions=custom_functions,
) )

View file

@ -44,11 +44,13 @@ class SyntaxTree(VariableDependency):
def partial_resolve( def partial_resolve(
self: TypeT, self: TypeT,
resolved_variables: Dict[Variable, Resolvable], resolved_variables: Dict[Variable, Resolvable],
unresolved_variables: Dict[Variable, Argument],
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.ast, args=self.ast,
resolved_variables=resolved_variables, resolved_variables=resolved_variables,
unresolved_variables=unresolved_variables,
custom_functions=custom_functions, custom_functions=custom_functions,
) )
@ -100,6 +102,7 @@ class ResolvedSyntaxTree(SyntaxTree):
def partial_resolve( def partial_resolve(
self: TypeT, self: TypeT,
resolved_variables: Dict[Variable, Resolvable], resolved_variables: Dict[Variable, Resolvable],
unresolved_variables: Dict[Variable, Argument],
custom_functions: Dict[str, VariableDependency], custom_functions: Dict[str, VariableDependency],
) -> TypeT | Resolvable: ) -> TypeT | Resolvable:
return self.ast[0] return self.ast[0]

View file

@ -143,6 +143,7 @@ class VariableDependency(ABC):
def partial_resolve( def partial_resolve(
self: TypeT, self: TypeT,
resolved_variables: Dict[Variable, Resolvable], resolved_variables: Dict[Variable, Resolvable],
unresolved_variables: Dict[Variable, Argument],
custom_functions: Dict[str, "VariableDependency"], custom_functions: Dict[str, "VariableDependency"],
) -> TypeT | Resolvable: ) -> TypeT | Resolvable:
""" """
@ -150,6 +151,8 @@ class VariableDependency(ABC):
---------- ----------
resolved_variables resolved_variables
Lookup of variables that have been resolved Lookup of variables that have been resolved
unresolved_variables
Lookup of variables that have not been resolved
custom_functions custom_functions
Lookup of any custom functions that have been parsed Lookup of any custom functions that have been parsed
@ -248,6 +251,7 @@ class VariableDependency(ABC):
cls, cls,
args: Iterable[Argument], args: Iterable[Argument],
resolved_variables: Dict[Variable, Resolvable], resolved_variables: Dict[Variable, Resolvable],
unresolved_variables: Dict[Variable, Argument],
custom_functions: Dict[str, "VariableDependency"], custom_functions: Dict[str, "VariableDependency"],
) -> Tuple[List[Argument], bool]: ) -> Tuple[List[Argument], bool]:
maybe_resolvable_args: List[Resolvable | Argument] = [] maybe_resolvable_args: List[Resolvable | Argument] = []
@ -265,7 +269,9 @@ class VariableDependency(ABC):
elif isinstance(arg, VariableDependency): elif isinstance(arg, VariableDependency):
maybe_resolvable_args.append( maybe_resolvable_args.append(
arg.partial_resolve( arg.partial_resolve(
resolved_variables=resolved_variables, custom_functions=custom_functions resolved_variables=resolved_variables,
unresolved_variables=unresolved_variables,
custom_functions=custom_functions,
) )
) )
@ -275,10 +281,14 @@ class VariableDependency(ABC):
if arg not in resolved_variables: if arg not in resolved_variables:
is_resolvable = False is_resolvable = False
if arg in unresolved_variables:
maybe_resolvable_args.append(unresolved_variables[arg])
else:
# Must be unresolvable
maybe_resolvable_args.append(arg)
else:
maybe_resolvable_args.append(arg) 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

View file

@ -617,6 +617,7 @@ def test_default_docker_config_and_subscriptions(
unresolvable.add("sibling_metadata") unresolvable.add("sibling_metadata")
out = default_subs[0].overrides.script.resolve_partial(unresolvable=unresolvable) out = default_subs[0].overrides.script.resolve_partial(unresolvable=unresolvable)
prev = ScriptUtils.to_native_script(out._variables["episode_file_name"]) test1 = ScriptUtils.to_native_script(out._variables["episode_file_name"])
test2 = ScriptUtils.to_native_script(out._variables["episode_file_path"])
print("hi") print("hi")