Type checking¶
redun supports type checking workflows using Python’s type hints and mypy.
Consider the following example workflow:
from redun import task
redun_namespace = "example"
@task()
def add(a: int, b: int) -> int:
return a + b
def main(x: int) -> int:
y = add(x, 1)
# y has type TaskExpression[int]
# y can be used wherever int is allowed.
z = add(x, y)
# z has type TaskExpression[int]
# z can be returned for a type int.
return z
redun tasks are lazy functions, so when we call add
it returns immediately with an Expression
object which represents the desire to execute the add
task. The actual execution will happen sometime later by the redun Scheduler. In this example, the fully parameterized type is Expression[int]
, which represents an Expression
that will eventually evaluate to an int
. In terms of type checking, Expression[T]
will be considered equivalent to T
(for any type T
), and can be used wherever T
s are allowed.
Overly permissive type checking¶
In general, the type checking rules defined above provide good type checking coverage, however, there is one corner case that is not fully captured currently with redun. Since Expression[T]
will be considered equivalent to T
, it is possible to pass an Expression[T]
to a plain python function (not decorated by @task
) that only allows T
. This will type check as allowed but may fail at runtime.