recursive type checking
This commit is contained in:
parent
6bb9e96384
commit
95948bce9e
1 changed files with 21 additions and 14 deletions
|
|
@ -17,6 +17,7 @@ from ytdl_sub.script.types.resolvable import Lambda
|
||||||
from ytdl_sub.script.types.resolvable import LambdaReduce
|
from ytdl_sub.script.types.resolvable import LambdaReduce
|
||||||
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
|
||||||
|
from ytdl_sub.script.types.resolvable import NamedCustomFunction
|
||||||
from ytdl_sub.script.types.resolvable import NamedType
|
from ytdl_sub.script.types.resolvable import NamedType
|
||||||
from ytdl_sub.script.types.resolvable import Resolvable
|
from ytdl_sub.script.types.resolvable import Resolvable
|
||||||
from ytdl_sub.script.types.variable import Variable
|
from ytdl_sub.script.types.variable import Variable
|
||||||
|
|
@ -55,8 +56,8 @@ def get_optional_type(optional_type: Type) -> Type[NamedType]:
|
||||||
return [arg for arg in optional_type.__args__ if arg != type(None)][0]
|
return [arg for arg in optional_type.__args__ if arg != type(None)][0]
|
||||||
|
|
||||||
|
|
||||||
def is_type_compatible(
|
def _is_type_compatible(
|
||||||
arg: NamedType,
|
arg_type: Type[NamedType],
|
||||||
expected_arg_type: Type[Resolvable | Optional[Resolvable]],
|
expected_arg_type: Type[Resolvable | Optional[Resolvable]],
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|
@ -64,16 +65,6 @@ def is_type_compatible(
|
||||||
-------
|
-------
|
||||||
True if arg is compatible with expected_arg_type. False otherwise.
|
True if arg is compatible with expected_arg_type. False otherwise.
|
||||||
"""
|
"""
|
||||||
arg_type: Type[NamedType] = arg.__class__
|
|
||||||
if isinstance(arg, BuiltInFunctionType):
|
|
||||||
arg_type = arg.output_type() # built-in function
|
|
||||||
|
|
||||||
if 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):
|
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
|
||||||
|
|
@ -94,9 +85,12 @@ def is_type_compatible(
|
||||||
# each possible union input is compatible with the expected type
|
# each possible union input is compatible with the expected type
|
||||||
elif is_union(arg_type):
|
elif is_union(arg_type):
|
||||||
for union_type in arg_type.__args__:
|
for union_type in arg_type.__args__:
|
||||||
if not issubclass(union_type, expected_arg_type):
|
if not _is_type_compatible(union_type, expected_arg_type):
|
||||||
return False
|
return False
|
||||||
|
elif issubclass(arg_type, NamedCustomFunction):
|
||||||
|
return True # custom-function, can be anything, so pass for now
|
||||||
|
elif issubclass(arg_type, Variable):
|
||||||
|
return True # unresolved variables can be anything, so pass for now
|
||||||
elif issubclass(arg_type, Lambda) and issubclass(expected_arg_type, arg_type):
|
elif issubclass(arg_type, Lambda) and issubclass(expected_arg_type, arg_type):
|
||||||
# lambda, check if expected_arg_type is a subclass
|
# lambda, check if expected_arg_type is a subclass
|
||||||
# Do not return on just that to also allow lambdas to be returned as
|
# Do not return on just that to also allow lambdas to be returned as
|
||||||
|
|
@ -109,6 +103,19 @@ def is_type_compatible(
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def is_type_compatible(
|
||||||
|
arg: NamedType,
|
||||||
|
expected_arg_type: Type[Resolvable | Optional[Resolvable]],
|
||||||
|
) -> bool:
|
||||||
|
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()
|
||||||
|
|
||||||
|
return _is_type_compatible(arg_type, expected_arg_type)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class FunctionSpec:
|
class FunctionSpec:
|
||||||
return_type: Type[Resolvable]
|
return_type: Type[Resolvable]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue