Merge branch 'master' into j/split-function
This commit is contained in:
commit
4e477ea562
6 changed files with 149 additions and 6 deletions
|
|
@ -38,10 +38,11 @@ array_apply_fixed
|
||||||
|
|
||||||
array_at
|
array_at
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
:spec: ``array_at(array: Array, idx: Integer) -> AnyArgument``
|
:spec: ``array_at(array: Array, idx: Integer, default: Optional[AnyArgument]) -> AnyArgument``
|
||||||
|
|
||||||
:description:
|
:description:
|
||||||
Return the element in the Array at index ``idx``.
|
Return the element in the Array at index ``idx``. If ``idx`` exceeds the array length,
|
||||||
|
either return ``default`` if provided or throw an error.
|
||||||
|
|
||||||
array_contains
|
array_contains
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
@ -225,6 +226,27 @@ xor
|
||||||
Conditional Functions
|
Conditional Functions
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
elif
|
||||||
|
~~~~
|
||||||
|
:spec: ``elif(if_elif_else: AnyArgument, ...) -> AnyArgument``
|
||||||
|
|
||||||
|
:description:
|
||||||
|
Conditional ``if`` statement that is capable of doing else-ifs (``elif``) via
|
||||||
|
adjacent arguments. It is expected for there to be an odd number of arguments >= 3 to
|
||||||
|
supply at least one conditional and an else.
|
||||||
|
:usage:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
%elif(
|
||||||
|
condition1,
|
||||||
|
return1,
|
||||||
|
condition2,
|
||||||
|
return2,
|
||||||
|
...
|
||||||
|
else_return
|
||||||
|
)
|
||||||
|
|
||||||
if
|
if
|
||||||
~~
|
~~
|
||||||
:spec: ``if(condition: Boolean, true: ReturnableArgumentA, false: ReturnableArgumentB) -> Union[ReturnableArgumentA, ReturnableArgumentB]``
|
:spec: ``if(condition: Boolean, true: ReturnableArgumentA, false: ReturnableArgumentB) -> Union[ReturnableArgumentA, ReturnableArgumentB]``
|
||||||
|
|
|
||||||
|
|
@ -73,12 +73,18 @@ class ArrayFunctions:
|
||||||
return Array(output)
|
return Array(output)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def array_at(array: Array, idx: Integer) -> AnyArgument:
|
def array_at(array: Array, idx: Integer, default: Optional[AnyArgument] = None) -> AnyArgument:
|
||||||
"""
|
"""
|
||||||
:description:
|
:description:
|
||||||
Return the element in the Array at index ``idx``.
|
Return the element in the Array at index ``idx``. If ``idx`` exceeds the array length,
|
||||||
|
either return ``default`` if provided or throw an error.
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
return array.value[idx.value]
|
return array.value[idx.value]
|
||||||
|
except IndexError:
|
||||||
|
if default is not None:
|
||||||
|
return default
|
||||||
|
raise
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def array_first(array: Array, fallback: AnyArgument) -> AnyArgument:
|
def array_first(array: Array, fallback: AnyArgument) -> AnyArgument:
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
from ytdl_sub.script.types.resolvable import AnyArgument
|
||||||
from ytdl_sub.script.types.resolvable import Boolean
|
from ytdl_sub.script.types.resolvable import Boolean
|
||||||
from ytdl_sub.script.types.resolvable import ReturnableArgumentA
|
from ytdl_sub.script.types.resolvable import ReturnableArgumentA
|
||||||
from ytdl_sub.script.types.resolvable import ReturnableArgumentB
|
from ytdl_sub.script.types.resolvable import ReturnableArgumentB
|
||||||
|
from ytdl_sub.script.utils.exceptions import FunctionRuntimeException
|
||||||
|
|
||||||
|
|
||||||
class ConditionalFunctions:
|
class ConditionalFunctions:
|
||||||
|
|
@ -19,6 +21,39 @@ class ConditionalFunctions:
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def elif_(*if_elif_else: AnyArgument) -> AnyArgument:
|
||||||
|
"""
|
||||||
|
:description:
|
||||||
|
Conditional ``if`` statement that is capable of doing else-ifs (``elif``) via
|
||||||
|
adjacent arguments. It is expected for there to be an odd number of arguments >= 3 to
|
||||||
|
supply at least one conditional and an else.
|
||||||
|
:usage:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
%elif(
|
||||||
|
condition1,
|
||||||
|
return1,
|
||||||
|
condition2,
|
||||||
|
return2,
|
||||||
|
...
|
||||||
|
else_return
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
arguments = list(if_elif_else)
|
||||||
|
if len(arguments) < 3:
|
||||||
|
raise FunctionRuntimeException("elif requires at least 3 arguments")
|
||||||
|
|
||||||
|
if len(arguments) % 2 == 0:
|
||||||
|
raise FunctionRuntimeException("elif must have an odd number of arguments")
|
||||||
|
|
||||||
|
for idx in range(0, len(arguments) - 1, 2):
|
||||||
|
if bool(arguments[idx].value):
|
||||||
|
return arguments[idx + 1]
|
||||||
|
|
||||||
|
return arguments[-1]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def if_passthrough(
|
def if_passthrough(
|
||||||
maybe_true_arg: ReturnableArgumentA, else_arg: ReturnableArgumentB
|
maybe_true_arg: ReturnableArgumentA, else_arg: ReturnableArgumentB
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,14 @@ class TestArrayFunctions:
|
||||||
output = single_variable_output("{%array_at(['a', 'b', 'c'], 1)}")
|
output = single_variable_output("{%array_at(['a', 'b', 'c'], 1)}")
|
||||||
assert output == "b"
|
assert output == "b"
|
||||||
|
|
||||||
|
def test_array_at_default(self):
|
||||||
|
output = single_variable_output("{%array_at(['a', 'b', 'c'], 30, 'd')}")
|
||||||
|
assert output == "d"
|
||||||
|
|
||||||
|
def test_array_at_error(self):
|
||||||
|
with pytest.raises(FunctionRuntimeException):
|
||||||
|
single_variable_output("{%array_at(['a', 'b', 'c'], 30)}")
|
||||||
|
|
||||||
def test_array_flatten(self):
|
def test_array_flatten(self):
|
||||||
output = single_variable_output("{%array_flatten(['a', ['b'], [['c']]])}")
|
output = single_variable_output("{%array_flatten(['a', ['b'], [['c']]])}")
|
||||||
assert output == ["a", "b", "c"]
|
assert output == ["a", "b", "c"]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
|
import re
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from unit.script.conftest import single_variable_output
|
from unit.script.conftest import single_variable_output
|
||||||
|
|
||||||
|
from ytdl_sub.script.utils.exceptions import FunctionRuntimeException
|
||||||
|
|
||||||
|
|
||||||
class TestConditionalFunction:
|
class TestConditionalFunction:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|
@ -33,3 +37,67 @@ class TestConditionalFunction:
|
||||||
}"""
|
}"""
|
||||||
)
|
)
|
||||||
assert output == "winner"
|
assert output == "winner"
|
||||||
|
|
||||||
|
def test_elif_function(self):
|
||||||
|
output = single_variable_output(
|
||||||
|
"""{
|
||||||
|
%elif(
|
||||||
|
False,
|
||||||
|
"nope",
|
||||||
|
False,
|
||||||
|
"still nope",
|
||||||
|
True,
|
||||||
|
"yes",
|
||||||
|
"default value"
|
||||||
|
)
|
||||||
|
}"""
|
||||||
|
)
|
||||||
|
assert output == "yes"
|
||||||
|
|
||||||
|
def test_elif_function_default_value(self):
|
||||||
|
output = single_variable_output(
|
||||||
|
"""{
|
||||||
|
%elif(
|
||||||
|
False,
|
||||||
|
"nope",
|
||||||
|
False,
|
||||||
|
"still nope",
|
||||||
|
False,
|
||||||
|
"will be default",
|
||||||
|
"default value"
|
||||||
|
)
|
||||||
|
}"""
|
||||||
|
)
|
||||||
|
assert output == "default value"
|
||||||
|
|
||||||
|
def test_elif_function_errors_lt3(self):
|
||||||
|
with pytest.raises(
|
||||||
|
FunctionRuntimeException,
|
||||||
|
match=re.escape("elif requires at least 3 arguments"),
|
||||||
|
):
|
||||||
|
single_variable_output(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
%elif(
|
||||||
|
False,
|
||||||
|
"only two args"
|
||||||
|
)
|
||||||
|
}"""
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_elif_function_errors_odd(self):
|
||||||
|
with pytest.raises(
|
||||||
|
FunctionRuntimeException,
|
||||||
|
match=re.escape("elif must have an odd number of arguments"),
|
||||||
|
):
|
||||||
|
single_variable_output(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
%elif(
|
||||||
|
False,
|
||||||
|
"1",
|
||||||
|
False,
|
||||||
|
"even number args bad"
|
||||||
|
)
|
||||||
|
}"""
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,11 @@ class TestFunction:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"function_str, expected_types, received_types",
|
"function_str, expected_types, received_types",
|
||||||
[
|
[
|
||||||
("{%array_at({'a': 'dict?'}, 1)}", "array: Array, idx: Integer", "Map, Integer"),
|
(
|
||||||
|
"{%array_at({'a': 'dict?'}, 1)}",
|
||||||
|
"array: Array, idx: Integer, default: Optional[AnyArgument]",
|
||||||
|
"Map, Integer",
|
||||||
|
),
|
||||||
("{%array_extend('not', 'array')}", "arrays: Array, ...", "String, String"),
|
("{%array_extend('not', 'array')}", "arrays: Array, ...", "String, String"),
|
||||||
(
|
(
|
||||||
"{%replace('hi mom', 'mom', 'dad', 1, 0)}",
|
"{%replace('hi mom', 'mom', 'dad', 1, 0)}",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue