Future resolvable

This commit is contained in:
Jesse Bannon 2023-12-06 23:13:43 -08:00
parent 321e45b75c
commit abf60f5052
10 changed files with 43 additions and 38 deletions

View file

@ -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

View file

@ -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())
]
)

View file

@ -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:

View file

@ -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]

View file

@ -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(

View file

@ -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

View file

@ -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

View file

@ -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",

View file

@ -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(

View file

@ -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