I want to annotate a generic function which takes as arguments another function and its parameters.
def forward(func, **kwargs):
func(**kwargs)
So, if I have a function which takes two integers:
def sum_int(a: int, b: int):
...
in my editor I want help if I pass the wrong object types:
forward(sum_int, 1.5, 2.6) # want type checker to complain about using floats instead of integers
How can I annotate forward? Something like:
def forward(func: Callable[rest, ret], **kwargs: rest] -> ret:
...
So, the first argument to forward is func and the rest are the keyword arguments. The return is ret. But rest and ret are also the keyword arguments and return type for func.
I used to do generics years (decades!) ago in C++, and there were tricks for capturing and unpacking various types, but I don't know whether we have to jump through those kind of hoops with Python, or whether it's even possible.
I don't really know what to search for, and didn't turn up anything anywhere near helpful.
Thanks!
You can use typing.ParamSpec to associate the arguments expected by func with the arguments expected by forward, though you do apparently need to use both positional and keyword arguments in the definition of forward:
RV = TypeVar('RV')
P = ParamSpec('P')
def forward(func: Callable[P, RV], *args: P.args, **kwargs: P.kwargs) -> RV:
...
def foo(*, a: int, b: int) -> str:
...
forward(foo, a=3, b=5) # OK
forward(foo, 3, 5) # Not OK, too many positional arguments for foo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With