Closed as not planned
Description
I'm trying to add types to a decorator that can be used on methods in classes containing a database_store
property. The decorator logs the start/end time to the instance's database_store.
For simplicity, I'll just use a logging.Logger
here. (mypy playground)
import logging
import time
from typing import *
class Loggable(Protocol):
logger: logging.Logger
P = ParamSpec("P")
T = TypeVar("T", covariant=True)
class TimedFunc(Protocol, Generic[P, T]):
def __call__(_self, self: Loggable, *args: P.args, **kwargs: P.kwargs) -> T:
...
def timer(func: TimedFunc[P, T]) -> TimedFunc[P, T]:
def wrapper(self: Loggable, *args: P.args, **kwargs: P.kwargs) -> T:
self.logger.info(f"{func} - Start {time.time()}")
resp = func(self, *args, **kwargs)
self.logger.info(f"{func} - End {time.time()}")
return resp
return wrapper
class Foo:
def __init__(self) -> None:
self.logger = logging.getLogger()
@timer
def bar(self, value: str) -> str:
return value
This results in an error
main.py:26: error: Argument 1 to "timer" has incompatible type "Callable[[Foo, str], str]"; expected "TimedFunc[Never, Never]" [arg-type]
main.py:26: note: "TimedFunc[Never, Never].__call__" has type "Callable[[Arg(Loggable, 'self'), VarArg(Never), KwArg(Never)], Never]"
It works if I hardcode self: Foo
instead of self: Loggable
.
- Why are the type variables being inferred as Never?
- Is this intended to work, or am I doing something wrong?
Other things I tried
- I tried using
Concatenate[Loggable, P]
, but with--strict
, this forcesself
to be a positional argument, and I don't want to update all the methods to dodef foo(self, /, ...)
.