map apply and enumerate
This commit is contained in:
parent
f9545a7e03
commit
df09fd5a99
4 changed files with 78 additions and 2 deletions
|
|
@ -1,9 +1,14 @@
|
|||
from typing import Optional
|
||||
|
||||
from ytdl_sub.script.types.array import Array
|
||||
from ytdl_sub.script.types.array import ResolvedArray
|
||||
from ytdl_sub.script.types.map import Map
|
||||
from ytdl_sub.script.types.resolvable import AnyArgument
|
||||
from ytdl_sub.script.types.resolvable import Boolean
|
||||
from ytdl_sub.script.types.resolvable import Hashable
|
||||
from ytdl_sub.script.types.resolvable import Integer
|
||||
from ytdl_sub.script.types.resolvable import Lambda2
|
||||
from ytdl_sub.script.types.resolvable import Lambda3
|
||||
from ytdl_sub.script.utils.exceptions import KeyDoesNotExistRuntimeException
|
||||
|
||||
|
||||
|
|
@ -29,3 +34,26 @@ class MapFunctions:
|
|||
Returns True if the key is in the Map. False otherwise.
|
||||
"""
|
||||
return Boolean(key in mapping.value)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
@staticmethod
|
||||
def map_apply(mapping: Map, lambda_function: Lambda2) -> Array:
|
||||
"""
|
||||
Apply a lambda function on the Map, where each arg
|
||||
passed to the lambda function is ``key, value`` as two separate args.
|
||||
"""
|
||||
return ResolvedArray([ResolvedArray([key, value]) for key, value in mapping.value.items()])
|
||||
|
||||
@staticmethod
|
||||
def map_enumerate(mapping: Map, lambda_function: Lambda3) -> Array:
|
||||
"""
|
||||
Apply a lambda function on the Map, where each arg
|
||||
passed to the lambda function is ``idx, key, value`` as three separate args.
|
||||
"""
|
||||
return ResolvedArray(
|
||||
[
|
||||
ResolvedArray([Integer(idx), key_value[0], key_value[1]])
|
||||
for idx, key_value in enumerate(mapping.value.items())
|
||||
]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -176,3 +176,14 @@ class Lambda2(Lambda):
|
|||
@classmethod
|
||||
def num_input_args(cls) -> int:
|
||||
return 2
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Lambda3(Lambda):
|
||||
"""
|
||||
Type-hinting for functions that apply lambdas with three inputs per element
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def num_input_args(cls) -> int:
|
||||
return 3
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from typing import Callable
|
|||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import Type
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
from typing import get_origin
|
||||
|
||||
|
|
@ -13,6 +14,7 @@ from ytdl_sub.script.types.resolvable import BuiltInFunctionType
|
|||
from ytdl_sub.script.types.resolvable import FunctionType
|
||||
from ytdl_sub.script.types.resolvable import Lambda
|
||||
from ytdl_sub.script.types.resolvable import Lambda2
|
||||
from ytdl_sub.script.types.resolvable import Lambda3
|
||||
from ytdl_sub.script.types.resolvable import NamedType
|
||||
from ytdl_sub.script.types.resolvable import Resolvable
|
||||
from ytdl_sub.script.types.variable import Variable
|
||||
|
|
@ -21,6 +23,9 @@ from ytdl_sub.script.utils.exceptions import UNREACHABLE
|
|||
# pylint: disable=missing-raises-doc
|
||||
|
||||
|
||||
TLambda = TypeVar("TLambda", bound=Lambda)
|
||||
|
||||
|
||||
def is_union(arg_type: Type) -> bool:
|
||||
"""
|
||||
Returns
|
||||
|
|
@ -156,10 +161,12 @@ class FunctionSpec:
|
|||
return 0 # varargs can take any number
|
||||
|
||||
@property
|
||||
def is_lambda_function(self) -> Optional[Type[Lambda | Lambda2]]:
|
||||
def is_lambda_function(self) -> Optional[Type[TLambda]]:
|
||||
if Lambda3 in (self.args or []):
|
||||
return Lambda3
|
||||
if Lambda2 in (self.args or []):
|
||||
return Lambda2
|
||||
elif Lambda in (self.args or []):
|
||||
if Lambda in (self.args or []):
|
||||
return Lambda
|
||||
return None
|
||||
|
||||
|
|
|
|||
|
|
@ -68,3 +68,33 @@ class TestMapFunctions:
|
|||
.native
|
||||
)
|
||||
assert output == expected_value
|
||||
|
||||
def test_map_apply(self):
|
||||
output = (
|
||||
Script(
|
||||
{
|
||||
"%custom_func": "{[%upper($0), %lower($1)]}",
|
||||
"map1": "{{'Key1': 'Value1', 'Key2': 'Value2'}}",
|
||||
"output": "{%map_apply(map1, %custom_func)}",
|
||||
}
|
||||
)
|
||||
.resolve(update=True)
|
||||
.get("output")
|
||||
.native
|
||||
)
|
||||
assert output == [["KEY1", "value1"], ["KEY2", "value2"]]
|
||||
|
||||
def test_map_enumerate(self):
|
||||
output = (
|
||||
Script(
|
||||
{
|
||||
"%custom_func": "{[$0, %upper($1), %lower($2)]}",
|
||||
"map1": "{{'Key1': 'Value1', 'Key2': 'Value2'}}",
|
||||
"output": "{%map_enumerate(map1, %custom_func)}",
|
||||
}
|
||||
)
|
||||
.resolve(update=True)
|
||||
.get("output")
|
||||
.native
|
||||
)
|
||||
assert output == [[0, "KEY1", "value1"], [1, "KEY2", "value2"]]
|
||||
|
|
|
|||
Loading…
Reference in a new issue