From d3e127783e22d53686edbfa6d05521a1ea3ca9f4 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Tue, 21 Nov 2023 18:47:53 -0800 Subject: [PATCH] iterable arguments --- src/ytdl_sub/script/types/array.py | 8 +--- src/ytdl_sub/script/types/function.py | 8 +--- src/ytdl_sub/script/types/map.py | 10 +---- src/ytdl_sub/script/types/resolvable.py | 5 +++ src/ytdl_sub/script/types/syntax_tree.py | 10 +---- .../script/types/variable_dependency.py | 38 ++++++++++++------- 6 files changed, 37 insertions(+), 42 deletions(-) diff --git a/src/ytdl_sub/script/types/array.py b/src/ytdl_sub/script/types/array.py index 28c86c8b..cc57f95a 100644 --- a/src/ytdl_sub/script/types/array.py +++ b/src/ytdl_sub/script/types/array.py @@ -27,12 +27,8 @@ class UnresolvedArray(Array, VariableDependency, FutureResolvable): value: List[ArgumentType] @property - def variables(self) -> Set[Variable]: - return self._variables(*self.value) - - @property - def function_arguments(self) -> Set[FunctionArgument]: - return self._function_arguments(*self.value) + def _iterable_arguments(self) -> List[ArgumentType]: + return self.value def resolve( self, diff --git a/src/ytdl_sub/script/types/function.py b/src/ytdl_sub/script/types/function.py index 70852745..4055a8ef 100644 --- a/src/ytdl_sub/script/types/function.py +++ b/src/ytdl_sub/script/types/function.py @@ -40,12 +40,8 @@ from ytdl_sub.utils.exceptions import StringFormattingException @dataclass(frozen=True) class Function(FunctionType, VariableDependency, ABC): @property - def variables(self) -> Set[Variable]: - return self._variables(*self.args) - - @property - def function_arguments(self) -> Set[FunctionArgument]: - return self._function_arguments(*self.args) + def _iterable_arguments(self) -> List[ArgumentType]: + return self.args @classmethod def from_name_and_args(cls, name: str, args: List[ArgumentType]) -> "Function": diff --git a/src/ytdl_sub/script/types/map.py b/src/ytdl_sub/script/types/map.py index b9ce5d9b..df165893 100644 --- a/src/ytdl_sub/script/types/map.py +++ b/src/ytdl_sub/script/types/map.py @@ -30,17 +30,9 @@ class UnresolvedMap(Map, VariableDependency, FutureResolvable): value: Dict[ArgumentType, ArgumentType] @property - def _as_flat_list(self) -> List[ArgumentType]: + def _iterable_arguments(self) -> List[ArgumentType]: return list(itertools.chain(*self.value.items())) - @property - def variables(self) -> Set[Variable]: - return self._variables(*self._as_flat_list) - - @property - def function_arguments(self) -> Set[FunctionArgument]: - return self._function_arguments(*self._as_flat_list) - def resolve( self, resolved_variables: Dict[Variable, Resolvable], diff --git a/src/ytdl_sub/script/types/resolvable.py b/src/ytdl_sub/script/types/resolvable.py index 178e52a4..3bad00e8 100644 --- a/src/ytdl_sub/script/types/resolvable.py +++ b/src/ytdl_sub/script/types/resolvable.py @@ -121,6 +121,11 @@ class String(ResolvableT[str], Hashable, ArgumentType): pass +@dataclass(frozen=True) +class NamedCustomFunction(ArgumentType, ABC): + name: str + + @dataclass(frozen=True) class FunctionType(ArgumentType, ABC): name: str diff --git a/src/ytdl_sub/script/types/syntax_tree.py b/src/ytdl_sub/script/types/syntax_tree.py index 845514a6..d24b2371 100644 --- a/src/ytdl_sub/script/types/syntax_tree.py +++ b/src/ytdl_sub/script/types/syntax_tree.py @@ -2,12 +2,10 @@ from dataclasses import dataclass from typing import Dict from typing import List from typing import Optional -from typing import Set from ytdl_sub.script.types.resolvable import ArgumentType from ytdl_sub.script.types.resolvable import Resolvable from ytdl_sub.script.types.resolvable import String -from ytdl_sub.script.types.variable import FunctionArgument from ytdl_sub.script.types.variable import Variable from ytdl_sub.script.types.variable_dependency import VariableDependency from ytdl_sub.utils.exceptions import StringFormattingException @@ -18,12 +16,8 @@ class SyntaxTree(VariableDependency): ast: List[ArgumentType] @property - def variables(self) -> Set[Variable]: - return self._variables(*self.ast) - - @property - def function_arguments(self) -> Set[FunctionArgument]: - return self._function_arguments(*self.ast) + def _iterable_arguments(self) -> List[ArgumentType]: + return self.ast def resolve( self, diff --git a/src/ytdl_sub/script/types/variable_dependency.py b/src/ytdl_sub/script/types/variable_dependency.py index 84b32a3e..e74142a5 100644 --- a/src/ytdl_sub/script/types/variable_dependency.py +++ b/src/ytdl_sub/script/types/variable_dependency.py @@ -2,10 +2,12 @@ from abc import ABC from abc import abstractmethod from dataclasses import dataclass from typing import Dict +from typing import List from typing import Set from typing import final from ytdl_sub.script.types.resolvable import ArgumentType +from ytdl_sub.script.types.resolvable import NamedCustomFunction from ytdl_sub.script.types.resolvable import Resolvable from ytdl_sub.script.types.variable import FunctionArgument from ytdl_sub.script.types.variable import Variable @@ -15,10 +17,16 @@ from ytdl_sub.utils.exceptions import StringFormattingException @dataclass(frozen=True) class VariableDependency(ABC): - @classmethod - def _variables(cls, *args: ArgumentType) -> Set[Variable]: + @property + @abstractmethod + def _iterable_arguments(self) -> List[ArgumentType]: + pass + + @final + @property + def variables(self) -> Set[Variable]: output: Set[Variable] = set() - for arg in args: + for arg in self._iterable_arguments: if isinstance(arg, Variable): output.add(arg) elif isinstance(arg, VariableDependency): @@ -26,10 +34,11 @@ class VariableDependency(ABC): return output - @classmethod - def _function_arguments(cls, *args: ArgumentType) -> Set[FunctionArgument]: + @final + @property + def function_arguments(self) -> Set[FunctionArgument]: output: Set[FunctionArgument] = set() - for arg in args: + for arg in self._iterable_arguments: if isinstance(arg, FunctionArgument): output.add(arg) elif isinstance(arg, VariableDependency): @@ -37,15 +46,18 @@ class VariableDependency(ABC): return output + @final @property - @abstractmethod - def variables(self) -> Set[Variable]: - pass + def custom_functions(self) -> Set[NamedCustomFunction]: + output: Set[NamedCustomFunction] = set() + for arg in self._iterable_arguments: + if isinstance(arg, NamedCustomFunction): + # Custom funcs aren't hashable, so recreate just the base-class portion + output.add(NamedCustomFunction(name=arg.name)) + elif isinstance(arg, VariableDependency): + output.update(arg.custom_functions) - @property - @abstractmethod - def function_arguments(self) -> Set[FunctionArgument]: - pass + return output @abstractmethod def resolve(