Static Type Checking¶
Crochet comes with type hints for Python 3.6+. However, due to current
limitations in Callable
generic construction (see
PEP 612 — Parameter Specification Variables), the arguments of a call to
a @run_in_reactor
-decorated function or method cannot be checked without
giving type checkers some special help. Crochet ships with a plugin which
fills this role when the mypy
static type checker is used. It resides in
crochet.mypy
and must be configured as described in
Configuring mypy to use plugins. For example, in a mypy.ini
configuration file:
[mypy]
plugins = crochet.mypy
This type checking is intended primarily for code which calls the decorated
function. As Twisted isn’t fully type-hinted yet, and in particular Deferred
does not yet have a generic type argument so that the eventual result type can
vary, the analysis of the return type of a @run_in_reactor
function/method
does not account for a Deferred result. This requires you to lie to the type
checker when returning a Deferred; just cast it to the known, eventual result
type using typing.cast
. For example:
@run_in_reactor
def get_time_in_x_seconds(delay: float) -> float:
def get_time() -> float:
return reactor.seconds() # type: ignore
if delay < 0.001:
# Close enough; just return the current time.
return get_time()
else:
d = Deferred()
def complete():
d.callback(get_time())
reactor.callLater(delay, complete) # type: ignore
return typing.cast(float, d)
If the mypy plugin is correctly installed, the client code will expect a float
from the wait()
of the EventualResult
returned by a call to this
function:
# OK
t1: float = get_time_in_x_seconds(2).wait(3)
print(f"The reactor time is {t1}")
# mypy error: Incompatible types in assignment
# (expression has type "float", variable has type "str")
t2: str = get_time_in_x_seconds(2).wait(3)
print(f"The reactor time is {t2}")