function type checking wip

This commit is contained in:
Jesse Bannon 2023-11-14 20:37:20 -08:00
parent c7b41a48ae
commit 9b7ba5cb3e
2 changed files with 43 additions and 5 deletions

View file

@ -43,7 +43,7 @@ class FunctionInputSpec:
input_arg: ArgumentType, input_arg: ArgumentType,
expected_arg_type: Type[Resolvable | Optional[Resolvable]], expected_arg_type: Type[Resolvable | Optional[Resolvable]],
) -> bool: ) -> bool:
if isinstance(input_arg, Function): if isinstance(input_arg, BuiltInFunction):
input_arg_type = input_arg.output_type input_arg_type = input_arg.output_type
elif isinstance(input_arg, Variable): elif isinstance(input_arg, Variable):
return True # unresolved variables can be anything, so pass for now return True # unresolved variables can be anything, so pass for now
@ -115,7 +115,7 @@ class FunctionInputSpec:
return f"({self.varargs.__name__}, ...)" return f"({self.varargs.__name__}, ...)"
@classmethod @classmethod
def from_function(cls, func: "Function") -> "FunctionInputSpec": def from_function(cls, func: "BuiltInFunction") -> "FunctionInputSpec":
if func.arg_spec.varargs: if func.arg_spec.varargs:
return FunctionInputSpec(varargs=func.arg_spec.annotations[func.arg_spec.varargs]) return FunctionInputSpec(varargs=func.arg_spec.annotations[func.arg_spec.varargs])
@ -164,7 +164,7 @@ class Function(VariableDependency, ArgumentType, ABC):
@classmethod @classmethod
def from_name_and_args(cls, name: str, args: List[ArgumentType]) -> "Function": def from_name_and_args(cls, name: str, args: List[ArgumentType]) -> "Function":
if hasattr(Functions, name) or hasattr(Functions, name + "_"): if hasattr(Functions, name) or hasattr(Functions, name + "_"):
return BuiltInFunction(name=name, args=args) return BuiltInFunction(name=name, args=args).validate_args()
return CustomFunction(name=name, args=args) return CustomFunction(name=name, args=args)
@ -214,12 +214,13 @@ class BuiltInFunction(Function):
return f"Expected {self.input_spec.expected_args_str()}.\nReceived {received_args_str}" return f"Expected {self.input_spec.expected_args_str()}.\nReceived {received_args_str}"
def __post_init__(self): def validate_args(self) -> "BuiltInFunction":
if not self.input_spec.is_compatible(input_args=self.args): if not self.input_spec.is_compatible(input_args=self.args):
raise StringFormattingException( raise StringFormattingException(
f"Invalid arguments passed to function {self.name}.\n" f"Invalid arguments passed to function {self.name}.\n"
f"{self._expected_received_error_msg()}" f"{self._expected_received_error_msg()}"
) )
return self
@property @property
def callable(self) -> Callable[..., Resolvable]: def callable(self) -> Callable[..., Resolvable]:

View file

@ -11,6 +11,7 @@ from ytdl_sub.script.parser import UNEXPECTED_COMMA_ARGUMENT
from ytdl_sub.script.parser import ArgumentParser from ytdl_sub.script.parser import ArgumentParser
from ytdl_sub.script.script import Script from ytdl_sub.script.script import Script
from ytdl_sub.script.types.array import ResolvedArray from ytdl_sub.script.types.array import ResolvedArray
from ytdl_sub.script.types.resolvable import Boolean
from ytdl_sub.script.types.resolvable import Float from ytdl_sub.script.types.resolvable import Float
from ytdl_sub.script.types.resolvable import Integer from ytdl_sub.script.types.resolvable import Integer
from ytdl_sub.script.types.resolvable import String from ytdl_sub.script.types.resolvable import String
@ -18,4 +19,40 @@ from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
class TestFunction: class TestFunction:
pass @pytest.mark.parametrize(
"function_str, expected_output",
[
("{%if(True, True, False)}", True),
("{%if(False, True, False)}", False),
],
)
def test_if_function(self, function_str: str, expected_output: bool):
assert Script({"func": function_str}).resolve() == {
"func": Boolean(expected_output),
}
def test_nested_if_function(self):
function_str = """{
%if(
True,
%if(
True,
%if(
True,
"winner",
True
),
True
),
True
)
}"""
assert Script({"func": function_str}).resolve() == {
"func": String("winner"),
}
@pytest.mark.parametrize(
"function_str", ["{%array_at({'a': 'dict?'}, 1)}" "{%array_extend('not', 'array')}"]
)
def test_incompatible_types(self, function_str):
assert Script({"func": function_str}).resolve()