typing
typing copied to clipboard
ParamSpec: No support for adding keyword-only argument
I've been looking through PEP 612 but I just wasn't able to find any way to implement behavior that would allow me to do this:
P = ParamSpec("P")
R = TypeVar("R")
def foo(f: Callable[P, R]) -> Callable[P, List[R]]: # Here, the parameters are actually P + optional kw-only int x = 3
def inner(*args: P.args, x: int = 3, **kwargs: P.kwargs) -> List[R]:
results = []
for _ in range(x):
ret = f(*args, **kwargs)
results.append(ret)
return results
return inner
@foo
def bar(p: int):
return p + 2
bar(5) # Acceptable
bar(5, x=8) # Should also be Acceptable
Proposed solution:
Callable[[P.args, x: int = 3, P.kwargs], List[R]]
EDIT: I didn't notice that this was already in rejected alternatives section (I didn't scroll that far), however I still think an implementation like this would be worth adding since I have already encountered the need for this twice and there's simply absolutely no way to handle it.
I'm fine with the proposed syntax suggestion of
Concatenate[("x", int), P]
Though it didn't mention anything about default values, but those could just be handled by a third value in that tuple. It would probably be a lot easier to implement than my proposed suggestion, though to be fair, at least to me, my suggestion looks a bit cleaner.
I've encountered this as well. In particular, I'm trying to recreate a decorator for a React-like framework in Python. I have a decorator that, given a user's function, returns a new function that accepts all the arguments of the one give, but with extra arguments that the decorator itself consumes and does not pass on. This would look a bit like this:
P = ParamSpec("P")
def component(f: Callable[P, Any]) -> Callable[Concatenate[(str | None, "key"), P], Any]: ...
One point of note is that I need (str | None, "key") to be a keyword-only arg. The syntax suggested in the PEP seems to concatenate a keyword or positional argument. Perhaps, placing it after the ParamSpec in the concatenation could indicate a keyword-only argument?
Concatenate[P, (str | None, "key")]
This is mentioned here: https://peps.python.org/pep-0612/#concatenating-keyword-parameters
But I think supporting this would open the door for typing a lot of powerful decorators that exist in the wild.