From 80c32335fb0740ba9d8c105eb220d189e0f09fc6 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Thu, 30 Nov 2023 07:41:17 -0800 Subject: [PATCH] passthrough assert --- .../script/functions/error_functions.py | 11 ++++---- src/ytdl_sub/script/script.py | 1 - src/ytdl_sub/script/types/resolvable.py | 19 +++++++++----- .../script/functions/test_error_functions.py | 26 +++++++++++++++++++ tests/unit/script/types/test_function.py | 8 ------ 5 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 tests/unit/script/functions/test_error_functions.py diff --git a/src/ytdl_sub/script/functions/error_functions.py b/src/ytdl_sub/script/functions/error_functions.py index 352e80a9..7eb1420f 100644 --- a/src/ytdl_sub/script/functions/error_functions.py +++ b/src/ytdl_sub/script/functions/error_functions.py @@ -1,5 +1,5 @@ from ytdl_sub.script.types.resolvable import AnyArgument -from ytdl_sub.script.types.resolvable import Boolean +from ytdl_sub.script.types.resolvable import ReturnableArgument from ytdl_sub.script.types.resolvable import String from ytdl_sub.script.utils.exceptions import UserThrownRuntimeError @@ -13,10 +13,11 @@ class ErrorFunctions: raise UserThrownRuntimeError(error_message) @staticmethod - def assert_(condition: Boolean, assert_message: String) -> Boolean: + def assert_(value: ReturnableArgument, assert_message: String) -> ReturnableArgument: """ - Explicitly throw an error with the provided assert message if ``condition`` is False. + Explicitly throw an error with the provided assert message if ``value`` evaluates to False. + If it evaluates to True, it will return ``value``. """ - if not condition.value: + if not bool(value.value): raise UserThrownRuntimeError(assert_message) - return condition + return value diff --git a/src/ytdl_sub/script/script.py b/src/ytdl_sub/script/script.py index 798cd441..12c2ee0a 100644 --- a/src/ytdl_sub/script/script.py +++ b/src/ytdl_sub/script/script.py @@ -7,7 +7,6 @@ from typing import Set from ytdl_sub.script.functions import Functions from ytdl_sub.script.parser import parse from ytdl_sub.script.types.resolvable import Lambda -from ytdl_sub.script.types.resolvable import NamedArgument from ytdl_sub.script.types.resolvable import Resolvable from ytdl_sub.script.types.syntax_tree import SyntaxTree from ytdl_sub.script.types.variable import Variable diff --git a/src/ytdl_sub/script/types/resolvable.py b/src/ytdl_sub/script/types/resolvable.py index 071a700d..11d2b751 100644 --- a/src/ytdl_sub/script/types/resolvable.py +++ b/src/ytdl_sub/script/types/resolvable.py @@ -31,6 +31,15 @@ class Argument(NamedType, ABC): """ +@dataclass(frozen=True) +class ValueArgument(Argument, ABC): + """ + Argument that has a value + """ + + value: Any + + @dataclass(frozen=True) class NamedArgument(Argument, ABC): """ @@ -41,34 +50,32 @@ class NamedArgument(Argument, ABC): @dataclass(frozen=True) -class ReturnableArgument(NamedType, ABC): +class ReturnableArgument(ValueArgument, NamedType, ABC): """ AnyType to express generics in functions that are part of the return type """ @dataclass(frozen=True) -class ReturnableArgumentA(NamedType, ABC): +class ReturnableArgumentA(ValueArgument, NamedType, ABC): """ AnyType to express generics in functions when more than one are present (i.e. `if`) """ @dataclass(frozen=True) -class ReturnableArgumentB(NamedType, ABC): +class ReturnableArgumentB(ValueArgument, NamedType, ABC): """ AnyType to express generics in functions when more than one are present (i.e. `if`) """ @dataclass(frozen=True) -class AnyArgument(Argument, ReturnableArgument, ReturnableArgumentA, ReturnableArgumentB, ABC): +class AnyArgument(ReturnableArgument, ReturnableArgumentA, ReturnableArgumentB, ABC): """ Human-readable name for FutureResolvable """ - value: Any - @dataclass(frozen=True) class Resolvable(AnyArgument, ABC): diff --git a/tests/unit/script/functions/test_error_functions.py b/tests/unit/script/functions/test_error_functions.py new file mode 100644 index 00000000..71943a3d --- /dev/null +++ b/tests/unit/script/functions/test_error_functions.py @@ -0,0 +1,26 @@ +import re + +import pytest + +from ytdl_sub.script.script import Script +from ytdl_sub.script.utils.exceptions import UserThrownRuntimeError + + +class TestErrorFunctions: + def test_user_throw(self): + with pytest.raises(UserThrownRuntimeError, match=re.escape("test this error message")): + Script({"throw_error": "{%throw('test this error message')}"}).resolve() + + def test_user_assert_raises(self): + with pytest.raises(UserThrownRuntimeError, match=re.escape("test this error message")): + Script({"throw_error": "{%assert(False, 'test this error message')}"}).resolve() + + def test_user_assert_passthrough(self): + output = ( + Script({"output": "{%assert(['a'], 'test this error message')}"}) + .resolve(update=True) + .get("output") + .native + ) + + assert output == ["a"] diff --git a/tests/unit/script/types/test_function.py b/tests/unit/script/types/test_function.py index 9e79da0b..07733041 100644 --- a/tests/unit/script/types/test_function.py +++ b/tests/unit/script/types/test_function.py @@ -93,14 +93,6 @@ class TestFunction: ): Script({"divide_by_zero": "{%div(8820, 0)}"}).resolve() - def test_user_throw(self): - with pytest.raises(UserThrownRuntimeError, match=re.escape("test this error message")): - Script({"throw_error": "{%throw('test this error message')}"}).resolve() - - def test_user_assert(self): - with pytest.raises(UserThrownRuntimeError, match=re.escape("test this error message")): - Script({"throw_error": "{%assert(False, 'test this error message')}"}).resolve() - def test_function_does_not_exist(self): with pytest.raises( FunctionDoesNotExist,