diff --git a/src/ytdl_sub/script/script.py b/src/ytdl_sub/script/script.py index cfad8aee..b35f492c 100644 --- a/src/ytdl_sub/script/script.py +++ b/src/ytdl_sub/script/script.py @@ -699,15 +699,11 @@ class Script: """ return set(to_function_definition_name(name) for name in self._functions.keys()) - def _to_syntax_tree( - self, maybe_resolved: SyntaxTree | Resolvable | VariableDependency - ) -> SyntaxTree: + def _to_syntax_tree(self, maybe_resolved: SyntaxTree | Argument) -> SyntaxTree: if isinstance(maybe_resolved, SyntaxTree): return maybe_resolved - if isinstance(maybe_resolved, (Variable, VariableDependency, Resolvable)): - return SyntaxTree(ast=[maybe_resolved]) - return maybe_resolved + return SyntaxTree(ast=[maybe_resolved]) def resolve_partial( self, @@ -724,22 +720,13 @@ class Script: ScriptVariableNotResolved If specifying a filter of variable to resolve, and one of them does not. """ + unresolvable: Set[str] = unresolvable or {} resolved: Dict[Variable, Resolvable] = {} - unresolved: Dict[Variable, Argument] = {} - 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 - else: - unresolved[variable] = arg + unresolved: Dict[Variable, Argument] = { + Variable(name): definition + for name, definition in self._variables.items() + if name not in unresolvable + } partially_resolved = True while partially_resolved: @@ -749,13 +736,10 @@ class Script: for variable in list(unresolved.keys()): definition = unresolved[variable] - if isinstance(definition, Variable): - if definition in unresolvable: - maybe_resolved = definition - else: - maybe_resolved = resolved.get(definition, unresolved[definition]) - else: - assert isinstance(definition, VariableDependency) + maybe_resolved = definition + if isinstance(definition, Variable) and definition.name not in unresolvable: + maybe_resolved = resolved.get(definition, unresolved[definition]) + elif isinstance(definition, VariableDependency): maybe_resolved = definition.partial_resolve( resolved_variables=resolved, unresolved_variables=unresolved, @@ -764,8 +748,8 @@ class Script: if isinstance(maybe_resolved, Resolvable): resolved[variable] = maybe_resolved - partially_resolved = True del unresolved[variable] + partially_resolved = True else: unresolved[variable] = maybe_resolved @@ -774,7 +758,7 @@ class Script: partially_resolved |= definition != maybe_resolved return copy.deepcopy(self).add_parsed( - {var.name: self._variables[var.name] for var in unresolvable} + {var_name: self._variables[var_name] for var_name in unresolvable} | {var.name: self._to_syntax_tree(definition) for var, definition in resolved.items()} | {var.name: self._to_syntax_tree(definition) for var, definition in unresolved.items()} ) diff --git a/src/ytdl_sub/script/types/array.py b/src/ytdl_sub/script/types/array.py index 4dd39ca3..42ceda14 100644 --- a/src/ytdl_sub/script/types/array.py +++ b/src/ytdl_sub/script/types/array.py @@ -11,7 +11,6 @@ from ytdl_sub.script.types.resolvable import NonHashable from ytdl_sub.script.types.resolvable import Resolvable from ytdl_sub.script.types.resolvable import ResolvableToJson 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 @@ -49,11 +48,11 @@ class UnresolvedArray(_Array, VariableDependency, FutureResolvable): ) def partial_resolve( - self: TypeT, + self, resolved_variables: Dict[Variable, Resolvable], unresolved_variables: Dict[Variable, Argument], - custom_functions: Dict[str, "VariableDependency"], - ) -> TypeT | Resolvable: + custom_functions: Dict[str, VariableDependency], + ) -> Argument | Resolvable: maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve( args=self.value, resolved_variables=resolved_variables, diff --git a/src/ytdl_sub/script/types/function.py b/src/ytdl_sub/script/types/function.py index 8e09e333..e8bb8419 100644 --- a/src/ytdl_sub/script/types/function.py +++ b/src/ytdl_sub/script/types/function.py @@ -24,7 +24,6 @@ from ytdl_sub.script.types.resolvable import ReturnableArgumentA from ytdl_sub.script.types.resolvable import ReturnableArgumentB from ytdl_sub.script.types.variable import FunctionArgument 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.utils.exception_formatters import FunctionArgumentsExceptionFormatter from ytdl_sub.script.utils.exceptions import UNREACHABLE @@ -91,8 +90,8 @@ class CustomFunction(Function, NamedCustomFunction): self, resolved_variables: Dict[Variable, Resolvable], unresolved_variables: Dict[Variable, Argument], - custom_functions: Dict[str, "VariableDependency"], - ) -> TypeT | Resolvable: + custom_functions: Dict[str, VariableDependency], + ) -> Argument | Resolvable: maybe_resolvable_args, _ = VariableDependency.try_partial_resolve( args=self.args, resolved_variables=resolved_variables, @@ -445,8 +444,8 @@ class BuiltInFunction(Function, BuiltInFunctionType): self, resolved_variables: Dict[Variable, Resolvable], unresolved_variables: Dict[Variable, Argument], - custom_functions: Dict[str, "VariableDependency"], - ) -> TypeT | Resolvable: + custom_functions: Dict[str, VariableDependency], + ) -> Argument | Resolvable: conditional_return_args = self.function_spec.conditional_arg_indices( num_input_args=len(self.args) ) diff --git a/src/ytdl_sub/script/types/map.py b/src/ytdl_sub/script/types/map.py index 9f129ef2..f9222286 100644 --- a/src/ytdl_sub/script/types/map.py +++ b/src/ytdl_sub/script/types/map.py @@ -13,7 +13,6 @@ from ytdl_sub.script.types.resolvable import NonHashable from ytdl_sub.script.types.resolvable import Resolvable from ytdl_sub.script.types.resolvable import ResolvableToJson 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.utils.exceptions import KeyNotHashableRuntimeException @@ -57,11 +56,11 @@ class UnresolvedMap(_Map, VariableDependency, FutureResolvable): return Map(output) def partial_resolve( - self: TypeT, + self, resolved_variables: Dict[Variable, Resolvable], unresolved_variables: Dict[Variable, Argument], - custom_functions: Dict[str, "VariableDependency"], - ) -> TypeT | Resolvable: + custom_functions: Dict[str, VariableDependency], + ) -> Argument | Resolvable: maybe_resolvable_keys, is_keys_resolvable = VariableDependency.try_partial_resolve( args=self.value.keys(), resolved_variables=resolved_variables, diff --git a/src/ytdl_sub/script/types/syntax_tree.py b/src/ytdl_sub/script/types/syntax_tree.py index 1d56b0fc..e145a2ea 100644 --- a/src/ytdl_sub/script/types/syntax_tree.py +++ b/src/ytdl_sub/script/types/syntax_tree.py @@ -3,11 +3,11 @@ from typing import Dict from typing import List from typing import Optional +from ytdl_sub.script.types.function import BuiltInFunction from ytdl_sub.script.types.resolvable import Argument from ytdl_sub.script.types.resolvable import Resolvable from ytdl_sub.script.types.resolvable import String 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 @@ -42,25 +42,22 @@ class SyntaxTree(VariableDependency): return String("".join([str(res) for res in resolved])) def partial_resolve( - self: TypeT, + self, resolved_variables: Dict[Variable, Resolvable], unresolved_variables: Dict[Variable, Argument], custom_functions: Dict[str, VariableDependency], - ) -> TypeT | Resolvable: - maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve( + ) -> Argument | Resolvable: + maybe_resolvable_values, _ = VariableDependency.try_partial_resolve( args=self.ast, resolved_variables=resolved_variables, unresolved_variables=unresolved_variables, custom_functions=custom_functions, ) - if is_resolvable: - return self.resolve( - resolved_variables=resolved_variables, - custom_functions=custom_functions, - ) + if len(maybe_resolvable_values) > 1: + return BuiltInFunction(name="concat", args=maybe_resolvable_values) - return SyntaxTree(ast=maybe_resolvable_values) + return maybe_resolvable_values[0] @property def maybe_resolvable(self) -> Optional[Resolvable]: @@ -100,9 +97,9 @@ class ResolvedSyntaxTree(SyntaxTree): return self.ast[0] def partial_resolve( - self: TypeT, + self, resolved_variables: Dict[Variable, Resolvable], unresolved_variables: Dict[Variable, Argument], custom_functions: Dict[str, VariableDependency], - ) -> TypeT | Resolvable: + ) -> Argument | Resolvable: return self.ast[0] diff --git a/src/ytdl_sub/script/types/variable_dependency.py b/src/ytdl_sub/script/types/variable_dependency.py index 155f2215..1101be8e 100644 --- a/src/ytdl_sub/script/types/variable_dependency.py +++ b/src/ytdl_sub/script/types/variable_dependency.py @@ -141,11 +141,11 @@ class VariableDependency(ABC): @abstractmethod def partial_resolve( - self: TypeT, + self, resolved_variables: Dict[Variable, Resolvable], unresolved_variables: Dict[Variable, Argument], custom_functions: Dict[str, "VariableDependency"], - ) -> TypeT | Resolvable: + ) -> Argument | Resolvable: """ Parameters ---------- @@ -258,7 +258,7 @@ class VariableDependency(ABC): Attempts to resolve a list of arguments. Returns a tuple of them post partially resolved, and a boolean indicating whether all of them are fully resolved. """ - maybe_resolvable_args: List[Resolvable | Argument] = [] + maybe_resolvable_args: List[Resolvable | Argument | "VariableDependency"] = [] is_resolvable = True for arg in args: if isinstance(arg, Lambda) and arg.value in custom_functions: