I'm trying to do "wrapper" class for any callable. Here is minimal example:
from typing import Any, TypeVar, Generic, Callable
ReturnType = TypeVar("ReturnType", bound=Any)
CallableType = Callable[..., ReturnT]
class Wrapper(Generic[ReturnType]):
def __init__(self, callable_: CallableType[ReturnType]) -> None:
self.callable_ = callable_
def __call__(self, *args: Any, **kwargs: Any) -> ReturnType:
return self.callable_(*args, **kwargs)
class Action:
def __init__(self, title: str) -> None:
"""docstring"""
self.title = title
wrapped = Wrapper(Action)
action = wrapped("title")
Pylance can understand, that action
type is Action
, but I can't see __init__
docsting and needed arguments:
What do I do wrong and how can I fix it?
You've annotated your __call__
with Any
. Pyright doesn't restrict these Any
to more narrow types just based on your usage. You'll need to use a ParamSpec to capture the parameters of the callable you accept as the argument (similar how you capture the return type with a TypeVar).
from typing import Any, TypeVar, ParamSpec, Generic, Callable
Params = ParamSpec("Params")
ReturnType = TypeVar("ReturnType")
class Wrapper(Generic[Params, ReturnType]):
def __init__(self, callable_: Callable[Params, ReturnType]) -> None:
self.callable_ = callable_
def __call__(self, *args: Params.args, **kwargs: Params.kwargs) -> ReturnType:
return self.callable_(*args, **kwargs)
class Action:
def __init__(self, title: str) -> None:
"""docstring"""
self.title = title
wrapped = Wrapper(Action)
action = wrapped("title")
Note1: If you're using python<3.10 you'll need to import ParamSpec
from typing_extensions
.
Note2: You don't need to pass a bound=Any
to the TypeVar as that's (more or less) the default anyway. Passing bound=Any
doesn't change anything nevertheless.