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 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 Boolean
|
||||
from ytdl_sub.script.types.resolvable import Integer
|
||||
|
|
@ -23,7 +22,7 @@ class ArrayFunctions:
|
|||
for array in arrays:
|
||||
output.extend(array.value)
|
||||
|
||||
return ResolvedArray(output)
|
||||
return Array(output)
|
||||
|
||||
@staticmethod
|
||||
def array_at(array: Array, idx: Integer) -> Resolvable:
|
||||
|
|
@ -61,8 +60,8 @@ class ArrayFunctions:
|
|||
Returns the slice of the Array.
|
||||
"""
|
||||
if end is not None:
|
||||
return ResolvedArray(array.value[start.value : end.value])
|
||||
return ResolvedArray(array.value[start.value :])
|
||||
return Array(array.value[start.value : end.value])
|
||||
return Array(array.value[start.value :])
|
||||
|
||||
@staticmethod
|
||||
def array_flatten(array: Array) -> Array:
|
||||
|
|
@ -76,14 +75,14 @@ class ArrayFunctions:
|
|||
else:
|
||||
output.append(elem)
|
||||
|
||||
return ResolvedArray(output)
|
||||
return Array(output)
|
||||
|
||||
@staticmethod
|
||||
def array_reverse(array: Array) -> Array:
|
||||
"""
|
||||
Reverse an Array.
|
||||
"""
|
||||
return ResolvedArray(list(reversed(array.value)))
|
||||
return Array(list(reversed(array.value)))
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
|
|
@ -92,7 +91,7 @@ class ArrayFunctions:
|
|||
"""
|
||||
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
|
||||
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
|
||||
passed to the lambda function is ``idx, element`` as two separate args.
|
||||
"""
|
||||
return ResolvedArray(
|
||||
[ResolvedArray([Integer(idx), val]) for idx, val in enumerate(array.value)]
|
||||
)
|
||||
return Array([Array([Integer(idx), val]) for idx, val in enumerate(array.value)])
|
||||
|
||||
# pylint: enable=unused-argument
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
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
|
||||
|
|
@ -43,7 +42,7 @@ class MapFunctions:
|
|||
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()])
|
||||
return Array([Array([key, value]) for key, value in mapping.value.items()])
|
||||
|
||||
@staticmethod
|
||||
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
|
||||
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())
|
||||
]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,17 +3,14 @@ from typing import AnyStr
|
|||
from typing import Match
|
||||
|
||||
from ytdl_sub.script.types.array import Array
|
||||
from ytdl_sub.script.types.array import ResolvedArray
|
||||
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:
|
||||
return ResolvedArray([])
|
||||
return Array([])
|
||||
|
||||
return ResolvedArray(
|
||||
list([String(re_out.string)]) + list(String(group) for group in re_out.groups())
|
||||
)
|
||||
return Array(list([String(re_out.string)]) + list(String(group) for group in re_out.groups()))
|
||||
|
||||
|
||||
class RegexFunctions:
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ from dataclasses import dataclass
|
|||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Type
|
||||
|
||||
from ytdl_sub.script.types.resolvable import AnyArgument
|
||||
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 Resolvable
|
||||
from ytdl_sub.script.types.resolvable import ResolvableToJson
|
||||
|
|
@ -13,7 +15,7 @@ from ytdl_sub.script.types.variable_dependency import VariableDependency
|
|||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Array(NonHashable):
|
||||
class _Array(NonHashable):
|
||||
value: List[Resolvable]
|
||||
|
||||
@classmethod
|
||||
|
|
@ -22,7 +24,7 @@ class Array(NonHashable):
|
|||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class UnresolvedArray(Array, VariableDependency, AnyArgument):
|
||||
class UnresolvedArray(_Array, VariableDependency, FutureResolvable):
|
||||
value: List[Argument]
|
||||
|
||||
@property
|
||||
|
|
@ -34,7 +36,7 @@ class UnresolvedArray(Array, VariableDependency, AnyArgument):
|
|||
resolved_variables: Dict[Variable, Resolvable],
|
||||
custom_functions: Dict[str, "VariableDependency"],
|
||||
) -> Resolvable:
|
||||
return ResolvedArray(
|
||||
return Array(
|
||||
[
|
||||
self._resolve_argument_type(
|
||||
arg=arg,
|
||||
|
|
@ -45,9 +47,12 @@ class UnresolvedArray(Array, VariableDependency, AnyArgument):
|
|||
]
|
||||
)
|
||||
|
||||
def future_resolvable_type(self) -> Type[Resolvable]:
|
||||
return Array
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvedArray(Array, ResolvableToJson):
|
||||
class Array(_Array, ResolvableToJson):
|
||||
@property
|
||||
def native(self) -> Any:
|
||||
return [val.native for val in self.value]
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from typing import Type
|
|||
from typing import Union
|
||||
|
||||
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.resolvable import Argument
|
||||
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)}"
|
||||
) from exc
|
||||
|
||||
assert isinstance(lambda_args, ResolvedArray)
|
||||
assert isinstance(lambda_args, Array)
|
||||
|
||||
return self._resolve_argument_type(
|
||||
arg=UnresolvedArray(
|
||||
|
|
|
|||
|
|
@ -87,6 +87,13 @@ class Resolvable(AnyArgument, ABC):
|
|||
return self.value
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FutureResolvable(AnyArgument, ABC):
|
||||
@abstractmethod
|
||||
def future_resolvable_type(self) -> Type[Resolvable]:
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Hashable(Resolvable, ABC):
|
||||
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 BuiltInFunctionType
|
||||
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 LambdaThree
|
||||
from ytdl_sub.script.types.resolvable import LambdaTwo
|
||||
|
|
@ -65,11 +66,12 @@ def is_type_compatible(
|
|||
arg_type: Type[NamedType] = arg.__class__
|
||||
if isinstance(arg, BuiltInFunctionType):
|
||||
arg_type = arg.output_type() # built-in function
|
||||
elif isinstance(arg, FutureResolvable):
|
||||
arg_type = arg.future_resolvable_type()
|
||||
elif isinstance(arg, FunctionType):
|
||||
return True # custom-function, can be anything, so pass for now
|
||||
elif isinstance(arg, Variable):
|
||||
return True # unresolved variables can be anything, so pass for now
|
||||
|
||||
if is_union(expected_arg_type):
|
||||
# See if the arg is a valid against the union
|
||||
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 ParsedArgType
|
||||
from ytdl_sub.script.script import Script
|
||||
from ytdl_sub.script.types.array import ResolvedArray
|
||||
from ytdl_sub.script.types.resolvable import Boolean
|
||||
from ytdl_sub.script.types.array import Array
|
||||
from ytdl_sub.script.types.resolvable import Float
|
||||
from ytdl_sub.script.types.resolvable import String
|
||||
from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
|
||||
|
|
@ -16,7 +15,7 @@ from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
|
|||
class TestArray:
|
||||
def test_return(self):
|
||||
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):
|
||||
|
|
@ -28,13 +27,13 @@ class TestArray:
|
|||
assert Script(
|
||||
{"array": "{['level1', ['level2', ['level3', 'level3'], 'level2'], 'level1']}"}
|
||||
).resolve() == {
|
||||
"array": ResolvedArray(
|
||||
"array": Array(
|
||||
[
|
||||
String("level1"),
|
||||
ResolvedArray(
|
||||
Array(
|
||||
[
|
||||
String("level2"),
|
||||
ResolvedArray([String("level3"), String("level3")]),
|
||||
Array([String("level3"), String("level3")]),
|
||||
String("level2"),
|
||||
],
|
||||
),
|
||||
|
|
@ -53,7 +52,7 @@ class TestArray:
|
|||
],
|
||||
)
|
||||
def test_empty(self, array: str):
|
||||
assert Script({"array": array}).resolve() == {"array": ResolvedArray([])}
|
||||
assert Script({"array": array}).resolve() == {"array": Array([])}
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"array",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import re
|
|||
import pytest
|
||||
|
||||
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.utils.exceptions import IncompatibleFunctionArguments
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ class TestLambdaFunction:
|
|||
def test_lambda_with_custom_function(self):
|
||||
assert Script(
|
||||
{"%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):
|
||||
assert Script(
|
||||
|
|
@ -21,7 +21,7 @@ class TestLambdaFunction:
|
|||
"%times_two": "{%mul($0, 2)}",
|
||||
"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):
|
||||
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.script import Script
|
||||
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 String
|
||||
from ytdl_sub.script.utils.exceptions import InvalidSyntaxException
|
||||
|
|
|
|||
Loading…
Reference in a new issue