if now uses psuedo generics
This commit is contained in:
parent
b371a29500
commit
2bf4f01b8d
7 changed files with 49 additions and 38 deletions
|
|
@ -1,8 +1,9 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from ytdl_sub.script.functions.numeric_functions import NumericFunctions
|
from ytdl_sub.script.functions.numeric_functions import NumericFunctions
|
||||||
|
from ytdl_sub.script.functions.special_functions import SpecialFunctions
|
||||||
from ytdl_sub.script.functions.string_functions import StringFunctions
|
from ytdl_sub.script.functions.string_functions import StringFunctions
|
||||||
|
|
||||||
|
|
||||||
class Functions(StringFunctions, NumericFunctions):
|
class Functions(StringFunctions, NumericFunctions, SpecialFunctions):
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
from ytdl_sub.script.types.resolvable import Boolean
|
from ytdl_sub.script.types.resolvable import Boolean
|
||||||
from ytdl_sub.script.types.resolvable import Resolvable
|
from ytdl_sub.script.types.resolvable import Resolvable
|
||||||
|
from ytdl_sub.script.types.resolvable import Resolvable_1
|
||||||
|
from ytdl_sub.script.types.resolvable import Resolvable_2
|
||||||
|
|
||||||
|
|
||||||
class SpecialFunctions:
|
class SpecialFunctions:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def if_(condition: Boolean, true: Resolvable, false: Resolvable) -> Resolvable:
|
def if_(
|
||||||
|
condition: Boolean, true: Resolvable, false: Resolvable
|
||||||
|
) -> Union[Resolvable_1, Resolvable_2]:
|
||||||
if condition.value:
|
if condition.value:
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ from typing import Optional
|
||||||
from ytdl_sub.script.syntax_tree import SyntaxTree
|
from ytdl_sub.script.syntax_tree import SyntaxTree
|
||||||
from ytdl_sub.script.types.function import ArgumentType
|
from ytdl_sub.script.types.function import ArgumentType
|
||||||
from ytdl_sub.script.types.function import Function
|
from ytdl_sub.script.types.function import Function
|
||||||
from ytdl_sub.script.types.function import IfFunction
|
|
||||||
from ytdl_sub.script.types.resolvable import Boolean
|
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 Integer
|
from ytdl_sub.script.types.resolvable import Integer
|
||||||
|
|
@ -158,10 +157,6 @@ class _Parser:
|
||||||
|
|
||||||
while ch := self._read():
|
while ch := self._read():
|
||||||
if ch == ")":
|
if ch == ")":
|
||||||
# Special case for If functions since it can return a Union based on input types
|
|
||||||
if function_name == "if":
|
|
||||||
return IfFunction(name=function_name, args=function_args)
|
|
||||||
|
|
||||||
return Function(name=function_name, args=function_args)
|
return Function(name=function_name, args=function_args)
|
||||||
|
|
||||||
if ch != "(":
|
if ch != "(":
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ 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 Integer
|
from ytdl_sub.script.types.resolvable import Integer
|
||||||
from ytdl_sub.script.types.resolvable import Resolvable
|
from ytdl_sub.script.types.resolvable import Resolvable
|
||||||
|
from ytdl_sub.script.types.resolvable import Resolvable_0
|
||||||
|
from ytdl_sub.script.types.resolvable import Resolvable_1
|
||||||
|
from ytdl_sub.script.types.resolvable import Resolvable_2
|
||||||
from ytdl_sub.script.types.resolvable import String
|
from ytdl_sub.script.types.resolvable import String
|
||||||
from ytdl_sub.script.types.variable import Variable
|
from ytdl_sub.script.types.variable import Variable
|
||||||
from ytdl_sub.utils.exceptions import StringFormattingException
|
from ytdl_sub.utils.exceptions import StringFormattingException
|
||||||
|
|
@ -173,10 +176,12 @@ class Function(VariableDependency):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def callable(self) -> Callable[..., Resolvable]:
|
def callable(self) -> Callable[..., Resolvable]:
|
||||||
try:
|
if hasattr(Functions, self.name):
|
||||||
return getattr(Functions, self.name)
|
return getattr(Functions, self.name)
|
||||||
except AttributeError:
|
if hasattr(Functions, self.name + "_"):
|
||||||
raise StringFormattingException(f"Function name {self.name} does not exist")
|
return getattr(Functions, self.name + "_")
|
||||||
|
|
||||||
|
raise StringFormattingException(f"Function name {self.name} does not exist")
|
||||||
|
|
||||||
@functools.cached_property
|
@functools.cached_property
|
||||||
def arg_spec(self) -> FullArgSpec:
|
def arg_spec(self) -> FullArgSpec:
|
||||||
|
|
@ -188,7 +193,22 @@ class Function(VariableDependency):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def output_type(self) -> Type[Resolvable]:
|
def output_type(self) -> Type[Resolvable]:
|
||||||
return self.arg_spec.annotations["return"]
|
output_type = self.arg_spec.annotations["return"]
|
||||||
|
if is_union(output_type):
|
||||||
|
union_types_list = []
|
||||||
|
for union_type in output_type.__args__:
|
||||||
|
if union_type == Resolvable_0:
|
||||||
|
union_types_list.append(type(self.args[0]))
|
||||||
|
elif union_type == Resolvable_1:
|
||||||
|
union_types_list.append(type(self.args[1]))
|
||||||
|
elif union_type == Resolvable_2:
|
||||||
|
union_types_list.append(type(self.args[2]))
|
||||||
|
else:
|
||||||
|
union_types_list.append(union_type)
|
||||||
|
|
||||||
|
return Union[tuple(union_types_list)]
|
||||||
|
|
||||||
|
return output_type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def variables(self) -> Set[Variable]:
|
def variables(self) -> Set[Variable]:
|
||||||
|
|
@ -208,18 +228,3 @@ class Function(VariableDependency):
|
||||||
|
|
||||||
def resolve(self, resolved_variables: Dict[Variable, Resolvable]) -> Resolvable:
|
def resolve(self, resolved_variables: Dict[Variable, Resolvable]) -> Resolvable:
|
||||||
raise NotImplemented()
|
raise NotImplemented()
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class IfFunction(Function):
|
|
||||||
def __post_init__(self):
|
|
||||||
super().__post_init__()
|
|
||||||
assert len(self.args) == 3 # bool, true, false
|
|
||||||
|
|
||||||
@property
|
|
||||||
def callable(self) -> Callable[..., Resolvable]:
|
|
||||||
return SpecialFunctions.if_
|
|
||||||
|
|
||||||
@property
|
|
||||||
def output_type(self) -> Type[Resolvable]:
|
|
||||||
return Union[self.args[1].__class__, self.args[2].__class__]
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,20 @@ T = TypeVar("T")
|
||||||
NumericT = TypeVar("NumericT", bound=int | float)
|
NumericT = TypeVar("NumericT", bound=int | float)
|
||||||
|
|
||||||
|
|
||||||
|
class Resolvable_0(ABC):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Resolvable_1(ABC):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Resolvable_2(ABC):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Resolvable(ABC):
|
class Resolvable(Resolvable_0, Resolvable_1, Resolvable_2, ABC):
|
||||||
value: Any
|
value: Any
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import pytest
|
||||||
from ytdl_sub.script.parser import parse
|
from ytdl_sub.script.parser import parse
|
||||||
from ytdl_sub.script.syntax_tree import SyntaxTree
|
from ytdl_sub.script.syntax_tree import SyntaxTree
|
||||||
from ytdl_sub.script.types.function import Function
|
from ytdl_sub.script.types.function import Function
|
||||||
from ytdl_sub.script.types.function import IfFunction
|
|
||||||
from ytdl_sub.script.types.resolvable import Boolean
|
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 Integer
|
from ytdl_sub.script.types.resolvable import Integer
|
||||||
|
|
@ -34,7 +33,7 @@ class TestParser:
|
||||||
assert parsed == SyntaxTree(
|
assert parsed == SyntaxTree(
|
||||||
[
|
[
|
||||||
String("hello "),
|
String("hello "),
|
||||||
IfFunction(
|
Function(
|
||||||
name="if", args=[Boolean(value=True), String(value="hi"), Float(value=3.4)]
|
name="if", args=[Boolean(value=True), String(value="hi"), Float(value=3.4)]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
@ -49,7 +48,7 @@ class TestParser:
|
||||||
Function(
|
Function(
|
||||||
name="concat",
|
name="concat",
|
||||||
args=[
|
args=[
|
||||||
IfFunction(
|
Function(
|
||||||
name="if", args=[Boolean(value=True), String("hi"), String("mom")]
|
name="if", args=[Boolean(value=True), String("hi"), String("mom")]
|
||||||
),
|
),
|
||||||
String(value="and dad"),
|
String(value="and dad"),
|
||||||
|
|
@ -66,7 +65,7 @@ class TestParser:
|
||||||
Function(
|
Function(
|
||||||
name="string",
|
name="string",
|
||||||
args=[
|
args=[
|
||||||
IfFunction(name="if", args=[Boolean(True), String("hi"), Integer(4)]),
|
Function(name="if", args=[Boolean(True), String("hi"), Integer(4)]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,8 @@
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ytdl_sub.script.parser import parse
|
|
||||||
from ytdl_sub.script.syntax_tree import SyntaxTree
|
from ytdl_sub.script.syntax_tree import SyntaxTree
|
||||||
from ytdl_sub.script.types.function import Function
|
|
||||||
from ytdl_sub.script.types.function import IfFunction
|
|
||||||
from ytdl_sub.script.types.resolvable import Boolean
|
|
||||||
from ytdl_sub.script.types.resolvable import Float
|
|
||||||
from ytdl_sub.script.types.resolvable import Integer
|
|
||||||
from ytdl_sub.script.types.resolvable import String
|
from ytdl_sub.script.types.resolvable import String
|
||||||
from ytdl_sub.script.types.variable import Variable
|
from ytdl_sub.script.types.variable import Variable
|
||||||
from ytdl_sub.utils.exceptions import StringFormattingException
|
from ytdl_sub.utils.exceptions import StringFormattingException
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue