'How to annotate the type of a decorator of an async function in Python 3.7?
I'd like to write a decorator for an async function. How can I annotate the type of the decorator definition?
Here's an example of what I'd like to do:
from typing import TypeVar # will Awaitable help?
AsyncFn = TypeVar('AsyncFn') # how to narrow this type definition down to async functions?
def my_decorator(to_decorate: AsyncFn) -> AsyncFn:
async def decorated(*args, **kwargs): # mypy keeps saying "Function is missing a type"
return await to_decorate(*args, **kwargs)
@my_decorator
async def foo(bar: int) -> str:
return f"async: {bar}"
@my_decorator
async def quux(spam: str, **eggs: str) -> None:
return
foo(1) # should check
foo("baz") # mypy should yell
quux("spam") # should check
quux(1) # mypy should complain
quux(spam="lovely", eggs="plentiful") # ok
quux(spam=1, eggs=0) # mypy should throw a fit
Solution 1:[1]
An async function is a function that returns an Awaitable.
With ParamSpec introduced in Python 3.10 the complete type annotations for a decorator for an async function is:
from typing import Awaitable, Callable, ParamSpec, TypeVar
T = TypeVar("T")
P = ParamSpec("P")
def decorator(fn: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]:
async def decorated(*args: P.args, **kwargs: P.kwargs) -> T:
return await fn(*args, **kwargs)
return decorated
In Python 3.7 ParamSpec can be imported from typing_extensions.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
