Description
Feature
Add type checking for passing *args
and **kwargs
to another function.
It may be enabled by default when mypy detects *args
and **kwargs
are passed to the same function or it may be enabled only by decorator (for example, @mypy_extensions.pass_args
. This will overwrite *args
and **kwargs
in the function signature with signature of the function to which they are passed. Also it should be possible to explicitly mark the function to which arguments are passed and specify whether to pass *args
, **kwargs
or both.
Pitch
I'll give an example with usual functions but it will be useful for decorators too.
For example, function wrapper
passes its arguments to function inner
and adds its own arguments:
def inner(a: int, b: int) -> None:
...
def wrapper(arg1: str, *args, **kwargs) -> None:
inner(*args, **kwargs) # It will automatically detect passing arguments to another function
This will automatically detect passing *args
and **kwargs
to another function and change the function signature to:
def wrapper(arg1: str, a: int, b: int):
...
It should successfully process and type-check the following calls:
wrapper("foo", 1, 2) # All positional arguments
wrapper(arg1="foo", b=1, a=2) # All keyword arguments
wrapper("foo", 1, a=2) # Mix positional and keyword
wrapper([], 1, 2)
# ^^ Type error in wrapper's argument (list passed instead of str)
wrapper("foo", [], 2)
# ^^ Type error in inner's argument (list passed instead of int)
Also multiple passes to the same function should be successfully processed:
def wrapper(arg1: str, *args, **kwargs) -> None:
if some_condition:
inner(1, *args, **kwargs) # Multiple same function calls with passed arguments
elif condition2:
inner(2, *args, **kwargs)
else:
inner(*args, **kwargs)
Also these cases should be processed:
def wrapper(arg1: str, *args, **kwargs) -> None:
inner(*args) # Only args are passed
def wrapper(arg1: str, *args, **kwargs) -> None:
inner(**kwargs) # Only kwargs are passed
There should be an option to overwrite this behavior using decorator (or this feature may be disabled by default and be enabled by the decorator). The decorator factory signature concept:
def pass_args(func: collections.abc.Callable | None, pass_args: bool = False, pass_kwargs: bool = False):
...
func
– The function to copy arguments from. Use None
value to force disable this feature.
pass_args
– whether to copy arguments that may be passed as positional (passing *args
)
pass_kwargs
– whether to copy arguments that may be passed as keyword (passing **kwargs
)