Description
The Feature Request
It would be awesome if it were possible to create a partial type spec for Callable
. For example, I might want to be able to specify that the first argument of a function must be an integer, but that any other parameters are allowed. This could be accomplished with the following extension to PEP-484 which would allow ...
to be included in the argument list to Callable
if it followed any extended callable types. As a result we could write a type spec FirstArgIsInt
which would match all the following functions and any number of other arbitrary functions so long as their first argument is an integer:
FirstArgIsInt = Callable[[Arg(int), ...], int]
f1: FirstArgIsInt
def f1(x: int) -> int: ...
f2: FirstArgIsInt
def f2(x: int, y: int) -> int: ...
f3: FirstArgIsInt
def f3(x: int, *args, **kwargs) -> int: ...
A Real World Use Case
Partial type specifications for Callable
are useful if parameters are being passed on to a function from a decorator as in request handlers for many web frameworks like Django's view funtions or Sanic's routes:
def route_1(request: Request) -> Response: ...
def route_2(request: Request, username: str) -> Response: ...
def route_3(request: Request, comment_id: int, content: str) -> Response: ...
# adinfinitum...
Imagine that you wanted to write an authenticated
decorator which ensures a user who accesses any particular route is logged in. What would be the type of RouteHandler
if not Callable[..., Response]
:
RouteHandler = ?
def authenticated(r: RouteHandler) -> RouteHandler: ...
It would be Callable[[Arg(Request), ...], Any]
, or some other expression of the same idea.
Current Work Arounds
Callable[..., Response]
, however this provides no precision for the function parameters.- Use
Callable[[Arg(Request), VarArg(), KwArg()], Response]
however this is problematic since, these route handlers don't actually need to be able to accept arbitrary arguments. - Use
Protocol
with overloads, however there are cases (e.g. decorators for route handlers as above) where it's not feasible to enumerate all possible route handler implementations.