I would like to code a wrapper that takes in arguments a function, its args and kwargs and execute them but with some kwargs precisely known while others are unknown.
Exemple:
def wrapper(custom_function: MyType, a: int, b: str, *args, **kwargs) -> float:
print(a+3)
print(b)
return custom_function(a, b, *args, **kwargs)
In this exemple I want to execute any function with first argument named a with type int and second named b with type str but I don't care about any other argument.
With this wrapper, I would like the following type hints to succeed or fail:
def f1(a: int, b: str) -> float:
...
def f2(a: int, b: str, c: float) -> float:
...
def f3(a: str, b: str) -> float:
...
def f4(a: int, b: str, *args, **kwargs) -> float:
...
wrapper(f1, 1, "a") # test 1: succeed
wrapper(f2, 1, "a", 4.6) # test 2: succeed
wrapper(f3, 1, "a") # test 3: fail
wrapper(f4, 1, "a", [1, 2, 3]) # test 4: succeed
I tried using typing.Protocol and typing.ParamSpec in the following way:
P = ParamSpec("P")
class MyType(Protocol):
def __call__(self, a: int, b: str, P):
....
but it does not work (test 1 and 2 fail)
I guess using Callable[...] like this would be the nearest I can get:
MyType = Callable[..., float]
but this solution does not satisfy me since the test 3 would succeed while I would like it to fail.
Is what I am looking for impossible ?
This is exactly the job for
typing.Concatenate. Your example is a modified version of thetypingdocs example, but instead of returning a wrappedcustom_functionwith a modified signature, your example just invokescustom_functiondirectly.