single cycle custom func

This commit is contained in:
Jesse Bannon 2023-11-21 18:01:54 -08:00
parent 4c70e3fe0b
commit 2aa24ba67e
3 changed files with 21 additions and 1 deletions

View file

@ -18,6 +18,7 @@ from ytdl_sub.script.types.variable import FunctionArgument
from ytdl_sub.script.types.variable import Variable
from ytdl_sub.script.utils.exception_formatters import ParserExceptionFormatter
from ytdl_sub.script.utils.exceptions import UNREACHABLE
from ytdl_sub.script.utils.exceptions import CycleDetected
from ytdl_sub.script.utils.exceptions import IncompatibleFunctionArguments
from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
from ytdl_sub.script.utils.exceptions import UserException
@ -334,8 +335,14 @@ class _Parser:
while ch := self._read():
if ch == ")":
# Had '(' to indicate there are args
if function_args is not None:
# Had '(' to indicate there are args
if self._custom_function_name == function_name:
self._set_highlight_position(function_start_pos)
raise CycleDetected(
f"The custom function %{function_name} cannot call itself."
)
try:
return Function.from_name_and_args(name=function_name, args=function_args)
except IncompatibleFunctionArguments:

View file

@ -19,6 +19,10 @@ class FunctionDoesNotExist(UserException):
"""Tried to use a function that does not exist"""
class CycleDetected(UserException):
"""A cycle exists within a user's script"""
class FunctionRuntimeException(ValueError):
"""Exception thrown when a ytdl-sub function has an error occur at runtime"""

View file

@ -8,6 +8,7 @@ from ytdl_sub.script.types.array import ResolvedArray
from ytdl_sub.script.types.resolvable import Boolean
from ytdl_sub.script.types.resolvable import Integer
from ytdl_sub.script.types.resolvable import String
from ytdl_sub.script.utils.exceptions import CycleDetected
from ytdl_sub.script.utils.exceptions import FunctionDoesNotExist
from ytdl_sub.script.utils.exceptions import FunctionRuntimeException
from ytdl_sub.script.utils.exceptions import IncompatibleFunctionArguments
@ -117,6 +118,14 @@ class TestFunction:
):
Script({"dne": "{%throw}"}).resolve()
def test_custom_function_cycle(self):
with pytest.raises(
CycleDetected, match=re.escape("The custom function %cycle_func cannot call itself.")
):
Script(
{"%cycle_func": "{%mul(%cycle_func(1), $0)}", "output": "{%cycle_func(1)}"}
).resolve()
def test_lambda_with_custom_function(self):
assert Script(
{"%times_two": "{%mul($0, 2)}", "wip": "{%array_apply([1, 2, 3], %times_two)}"}