Future resolvable
This commit is contained in:
parent
321e45b75c
commit
abf60f5052
10 changed files with 43 additions and 38 deletions
|
|
@ -2,7 +2,6 @@ from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from ytdl_sub.script.types.array import Array
|
from ytdl_sub.script.types.array import Array
|
||||||
from ytdl_sub.script.types.array import ResolvedArray
|
|
||||||
from ytdl_sub.script.types.resolvable import AnyArgument
|
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 Integer
|
from ytdl_sub.script.types.resolvable import Integer
|
||||||
|
|
@ -23,7 +22,7 @@ class ArrayFunctions:
|
||||||
for array in arrays:
|
for array in arrays:
|
||||||
output.extend(array.value)
|
output.extend(array.value)
|
||||||
|
|
||||||
return ResolvedArray(output)
|
return Array(output)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def array_at(array: Array, idx: Integer) -> Resolvable:
|
def array_at(array: Array, idx: Integer) -> Resolvable:
|
||||||
|
|
@ -61,8 +60,8 @@ class ArrayFunctions:
|
||||||
Returns the slice of the Array.
|
Returns the slice of the Array.
|
||||||
"""
|
"""
|
||||||
if end is not None:
|
if end is not None:
|
||||||
return ResolvedArray(array.value[start.value : end.value])
|
return Array(array.value[start.value : end.value])
|
||||||
return ResolvedArray(array.value[start.value :])
|
return Array(array.value[start.value :])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def array_flatten(array: Array) -> Array:
|
def array_flatten(array: Array) -> Array:
|
||||||
|
|
@ -76,14 +75,14 @@ class ArrayFunctions:
|
||||||
else:
|
else:
|
||||||
output.append(elem)
|
output.append(elem)
|
||||||
|
|
||||||
return ResolvedArray(output)
|
return Array(output)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def array_reverse(array: Array) -> Array:
|
def array_reverse(array: Array) -> Array:
|
||||||
"""
|
"""
|
||||||
Reverse an Array.
|
Reverse an Array.
|
||||||
"""
|
"""
|
||||||
return ResolvedArray(list(reversed(array.value)))
|
return Array(list(reversed(array.value)))
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
|
|
||||||
|
|
@ -92,7 +91,7 @@ class ArrayFunctions:
|
||||||
"""
|
"""
|
||||||
Apply a lambda function on every element in the Array.
|
Apply a lambda function on every element in the Array.
|
||||||
"""
|
"""
|
||||||
return ResolvedArray([ResolvedArray([val]) for val in array.value])
|
return Array([Array([val]) for val in array.value])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def array_enumerate(array: Array, lambda_function: LambdaTwo) -> Array:
|
def array_enumerate(array: Array, lambda_function: LambdaTwo) -> Array:
|
||||||
|
|
@ -100,8 +99,6 @@ class ArrayFunctions:
|
||||||
Apply a lambda function on every element in the Array, where each arg
|
Apply a lambda function on every element in the Array, where each arg
|
||||||
passed to the lambda function is ``idx, element`` as two separate args.
|
passed to the lambda function is ``idx, element`` as two separate args.
|
||||||
"""
|
"""
|
||||||
return ResolvedArray(
|
return Array([Array([Integer(idx), val]) for idx, val in enumerate(array.value)])
|
||||||
[ResolvedArray([Integer(idx), val]) for idx, val in enumerate(array.value)]
|
|
||||||
)
|
|
||||||
|
|
||||||
# pylint: enable=unused-argument
|
# pylint: enable=unused-argument
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from ytdl_sub.script.types.array import Array
|
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.map import Map
|
||||||
from ytdl_sub.script.types.resolvable import AnyArgument
|
from ytdl_sub.script.types.resolvable import AnyArgument
|
||||||
from ytdl_sub.script.types.resolvable import Boolean
|
from ytdl_sub.script.types.resolvable import Boolean
|
||||||
|
|
@ -43,7 +42,7 @@ class MapFunctions:
|
||||||
Apply a lambda function on the Map, where each arg
|
Apply a lambda function on the Map, where each arg
|
||||||
passed to the lambda function is ``key, value`` as two separate args.
|
passed to the lambda function is ``key, value`` as two separate args.
|
||||||
"""
|
"""
|
||||||
return ResolvedArray([ResolvedArray([key, value]) for key, value in mapping.value.items()])
|
return Array([Array([key, value]) for key, value in mapping.value.items()])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def map_enumerate(mapping: Map, lambda_function: LambdaThree) -> Array:
|
def map_enumerate(mapping: Map, lambda_function: LambdaThree) -> Array:
|
||||||
|
|
@ -51,9 +50,9 @@ class MapFunctions:
|
||||||
Apply a lambda function on the Map, where each arg
|
Apply a lambda function on the Map, where each arg
|
||||||
passed to the lambda function is ``idx, key, value`` as three separate args.
|
passed to the lambda function is ``idx, key, value`` as three separate args.
|
||||||
"""
|
"""
|
||||||
return ResolvedArray(
|
return Array(
|
||||||
[
|
[
|
||||||
ResolvedArray([Integer(idx), key_value[0], key_value[1]])
|
Array([Integer(idx), key_value[0], key_value[1]])
|
||||||
for idx, key_value in enumerate(mapping.value.items())
|
for idx, key_value in enumerate(mapping.value.items())
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,14 @@ from typing import AnyStr
|
||||||
from typing import Match
|
from typing import Match
|
||||||
|
|
||||||
from ytdl_sub.script.types.array import Array
|
from ytdl_sub.script.types.array import Array
|
||||||
from ytdl_sub.script.types.array import ResolvedArray
|
|
||||||
from ytdl_sub.script.types.resolvable import String
|
from ytdl_sub.script.types.resolvable import String
|
||||||
|
|
||||||
|
|
||||||
def _re_output_to_array(re_out: Match[AnyStr] | None) -> ResolvedArray:
|
def _re_output_to_array(re_out: Match[AnyStr] | None) -> Array:
|
||||||
if re_out is None:
|
if re_out is None:
|
||||||
return ResolvedArray([])
|
return Array([])
|
||||||
|
|
||||||
return ResolvedArray(
|
return Array(list([String(re_out.string)]) + list(String(group) for group in re_out.groups()))
|
||||||
list([String(re_out.string)]) + list(String(group) for group in re_out.groups())
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class RegexFunctions:
|
class RegexFunctions:
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@ from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
from ytdl_sub.script.types.resolvable import AnyArgument
|
from ytdl_sub.script.types.resolvable import AnyArgument
|
||||||
from ytdl_sub.script.types.resolvable import Argument
|
from ytdl_sub.script.types.resolvable import Argument
|
||||||
|
from ytdl_sub.script.types.resolvable import FutureResolvable
|
||||||
from ytdl_sub.script.types.resolvable import NonHashable
|
from ytdl_sub.script.types.resolvable import NonHashable
|
||||||
from ytdl_sub.script.types.resolvable import Resolvable
|
from ytdl_sub.script.types.resolvable import Resolvable
|
||||||
from ytdl_sub.script.types.resolvable import ResolvableToJson
|
from ytdl_sub.script.types.resolvable import ResolvableToJson
|
||||||
|
|
@ -13,7 +15,7 @@ from ytdl_sub.script.types.variable_dependency import VariableDependency
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Array(NonHashable):
|
class _Array(NonHashable):
|
||||||
value: List[Resolvable]
|
value: List[Resolvable]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -22,7 +24,7 @@ class Array(NonHashable):
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class UnresolvedArray(Array, VariableDependency, AnyArgument):
|
class UnresolvedArray(_Array, VariableDependency, FutureResolvable):
|
||||||
value: List[Argument]
|
value: List[Argument]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -34,7 +36,7 @@ class UnresolvedArray(Array, VariableDependency, AnyArgument):
|
||||||
resolved_variables: Dict[Variable, Resolvable],
|
resolved_variables: Dict[Variable, Resolvable],
|
||||||
custom_functions: Dict[str, "VariableDependency"],
|
custom_functions: Dict[str, "VariableDependency"],
|
||||||
) -> Resolvable:
|
) -> Resolvable:
|
||||||
return ResolvedArray(
|
return Array(
|
||||||
[
|
[
|
||||||
self._resolve_argument_type(
|
self._resolve_argument_type(
|
||||||
arg=arg,
|
arg=arg,
|
||||||
|
|
@ -45,9 +47,12 @@ class UnresolvedArray(Array, VariableDependency, AnyArgument):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def future_resolvable_type(self) -> Type[Resolvable]:
|
||||||
|
return Array
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class ResolvedArray(Array, ResolvableToJson):
|
class Array(_Array, ResolvableToJson):
|
||||||
@property
|
@property
|
||||||
def native(self) -> Any:
|
def native(self) -> Any:
|
||||||
return [val.native for val in self.value]
|
return [val.native for val in self.value]
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from typing import Type
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from ytdl_sub.script.functions import Functions
|
from ytdl_sub.script.functions import Functions
|
||||||
from ytdl_sub.script.types.array import ResolvedArray
|
from ytdl_sub.script.types.array import Array
|
||||||
from ytdl_sub.script.types.array import UnresolvedArray
|
from ytdl_sub.script.types.array import UnresolvedArray
|
||||||
from ytdl_sub.script.types.resolvable import Argument
|
from ytdl_sub.script.types.resolvable import Argument
|
||||||
from ytdl_sub.script.types.resolvable import BuiltInFunctionType
|
from ytdl_sub.script.types.resolvable import BuiltInFunctionType
|
||||||
|
|
@ -151,7 +151,7 @@ class BuiltInFunction(Function, BuiltInFunctionType):
|
||||||
f"Runtime error occurred when executing the function %{self.name}: {str(exc)}"
|
f"Runtime error occurred when executing the function %{self.name}: {str(exc)}"
|
||||||
) from exc
|
) from exc
|
||||||
|
|
||||||
assert isinstance(lambda_args, ResolvedArray)
|
assert isinstance(lambda_args, Array)
|
||||||
|
|
||||||
return self._resolve_argument_type(
|
return self._resolve_argument_type(
|
||||||
arg=UnresolvedArray(
|
arg=UnresolvedArray(
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,13 @@ class Resolvable(AnyArgument, ABC):
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class FutureResolvable(AnyArgument, ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def future_resolvable_type(self) -> Type[Resolvable]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Hashable(Resolvable, ABC):
|
class Hashable(Resolvable, ABC):
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ from typing import get_origin
|
||||||
from ytdl_sub.script.types.resolvable import Argument
|
from ytdl_sub.script.types.resolvable import Argument
|
||||||
from ytdl_sub.script.types.resolvable import BuiltInFunctionType
|
from ytdl_sub.script.types.resolvable import BuiltInFunctionType
|
||||||
from ytdl_sub.script.types.resolvable import FunctionType
|
from ytdl_sub.script.types.resolvable import FunctionType
|
||||||
|
from ytdl_sub.script.types.resolvable import FutureResolvable
|
||||||
from ytdl_sub.script.types.resolvable import Lambda
|
from ytdl_sub.script.types.resolvable import Lambda
|
||||||
from ytdl_sub.script.types.resolvable import LambdaThree
|
from ytdl_sub.script.types.resolvable import LambdaThree
|
||||||
from ytdl_sub.script.types.resolvable import LambdaTwo
|
from ytdl_sub.script.types.resolvable import LambdaTwo
|
||||||
|
|
@ -65,11 +66,12 @@ def is_type_compatible(
|
||||||
arg_type: Type[NamedType] = arg.__class__
|
arg_type: Type[NamedType] = arg.__class__
|
||||||
if isinstance(arg, BuiltInFunctionType):
|
if isinstance(arg, BuiltInFunctionType):
|
||||||
arg_type = arg.output_type() # built-in function
|
arg_type = arg.output_type() # built-in function
|
||||||
|
elif isinstance(arg, FutureResolvable):
|
||||||
|
arg_type = arg.future_resolvable_type()
|
||||||
elif isinstance(arg, FunctionType):
|
elif isinstance(arg, FunctionType):
|
||||||
return True # custom-function, can be anything, so pass for now
|
return True # custom-function, can be anything, so pass for now
|
||||||
elif isinstance(arg, Variable):
|
elif isinstance(arg, Variable):
|
||||||
return True # unresolved variables can be anything, so pass for now
|
return True # unresolved variables can be anything, so pass for now
|
||||||
|
|
||||||
if is_union(expected_arg_type):
|
if is_union(expected_arg_type):
|
||||||
# See if the arg is a valid against the union
|
# See if the arg is a valid against the union
|
||||||
valid_type = False
|
valid_type = False
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@ from ytdl_sub.script.parser import _UNEXPECTED_CHAR_ARGUMENT
|
||||||
from ytdl_sub.script.parser import _UNEXPECTED_COMMA_ARGUMENT
|
from ytdl_sub.script.parser import _UNEXPECTED_COMMA_ARGUMENT
|
||||||
from ytdl_sub.script.parser import ParsedArgType
|
from ytdl_sub.script.parser import ParsedArgType
|
||||||
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 Array
|
||||||
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 String
|
from ytdl_sub.script.types.resolvable import String
|
||||||
from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
|
from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
|
||||||
|
|
@ -16,7 +15,7 @@ from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
|
||||||
class TestArray:
|
class TestArray:
|
||||||
def test_return(self):
|
def test_return(self):
|
||||||
assert Script({"array": "{['a', 3.14]}"}).resolve() == {
|
assert Script({"array": "{['a', 3.14]}"}).resolve() == {
|
||||||
"array": ResolvedArray([String("a"), Float(3.14)])
|
"array": Array([String("a"), Float(3.14)])
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_return_as_str(self):
|
def test_return_as_str(self):
|
||||||
|
|
@ -28,13 +27,13 @@ class TestArray:
|
||||||
assert Script(
|
assert Script(
|
||||||
{"array": "{['level1', ['level2', ['level3', 'level3'], 'level2'], 'level1']}"}
|
{"array": "{['level1', ['level2', ['level3', 'level3'], 'level2'], 'level1']}"}
|
||||||
).resolve() == {
|
).resolve() == {
|
||||||
"array": ResolvedArray(
|
"array": Array(
|
||||||
[
|
[
|
||||||
String("level1"),
|
String("level1"),
|
||||||
ResolvedArray(
|
Array(
|
||||||
[
|
[
|
||||||
String("level2"),
|
String("level2"),
|
||||||
ResolvedArray([String("level3"), String("level3")]),
|
Array([String("level3"), String("level3")]),
|
||||||
String("level2"),
|
String("level2"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -53,7 +52,7 @@ class TestArray:
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_empty(self, array: str):
|
def test_empty(self, array: str):
|
||||||
assert Script({"array": array}).resolve() == {"array": ResolvedArray([])}
|
assert Script({"array": array}).resolve() == {"array": Array([])}
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"array",
|
"array",
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import re
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
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 Array
|
||||||
from ytdl_sub.script.types.resolvable import Integer
|
from ytdl_sub.script.types.resolvable import Integer
|
||||||
from ytdl_sub.script.utils.exceptions import IncompatibleFunctionArguments
|
from ytdl_sub.script.utils.exceptions import IncompatibleFunctionArguments
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ class TestLambdaFunction:
|
||||||
def test_lambda_with_custom_function(self):
|
def test_lambda_with_custom_function(self):
|
||||||
assert Script(
|
assert Script(
|
||||||
{"%times_two": "{%mul($0, 2)}", "wip": "{%array_apply([1, 2, 3], %times_two)}"}
|
{"%times_two": "{%mul($0, 2)}", "wip": "{%array_apply([1, 2, 3], %times_two)}"}
|
||||||
).resolve() == {"wip": ResolvedArray([Integer(2), Integer(4), Integer(6)])}
|
).resolve() == {"wip": Array([Integer(2), Integer(4), Integer(6)])}
|
||||||
|
|
||||||
def test_conditional_lambda_with_custom_functions(self):
|
def test_conditional_lambda_with_custom_functions(self):
|
||||||
assert Script(
|
assert Script(
|
||||||
|
|
@ -21,7 +21,7 @@ class TestLambdaFunction:
|
||||||
"%times_two": "{%mul($0, 2)}",
|
"%times_two": "{%mul($0, 2)}",
|
||||||
"wip": "{%array_apply([1, 2, 3], %if(False, %times_two, %times_three))}",
|
"wip": "{%array_apply([1, 2, 3], %if(False, %times_two, %times_three))}",
|
||||||
}
|
}
|
||||||
).resolve() == {"wip": ResolvedArray([Integer(3), Integer(6), Integer(9)])}
|
).resolve() == {"wip": Array([Integer(3), Integer(6), Integer(9)])}
|
||||||
|
|
||||||
def test_nested_custom_functions(self):
|
def test_nested_custom_functions(self):
|
||||||
assert Script(
|
assert Script(
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ from ytdl_sub.script.parser import MAP_MISSING_KEY
|
||||||
from ytdl_sub.script.parser import ParsedArgType
|
from ytdl_sub.script.parser import ParsedArgType
|
||||||
from ytdl_sub.script.script import Script
|
from ytdl_sub.script.script import Script
|
||||||
from ytdl_sub.script.types.map import ResolvedMap
|
from ytdl_sub.script.types.map import ResolvedMap
|
||||||
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 String
|
from ytdl_sub.script.types.resolvable import String
|
||||||
from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
|
from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue