tenacity
tenacity copied to clipboard
mypy error: "Callable[..., Any]" has no attribute "retry"
I have this example code (typing_bug_example.py):
from tenacity import retry
@retry
def do_stuff():
print("doing stuff")
do_stuff()
retry_stats = do_stuff.retry.statistics
print(retry_stats)
Checking it with mypy, I get this error:
$ mypy typing_bug_example.py
typing_bug_example.py:10: error: "Callable[..., Any]" has no attribute "retry"
Found 1 error in 1 file (checked 1 source file)
The code runs as expected:
$ python typing_bug_example.py
doing stuff
{'start_time': 176438.277915419, 'attempt_number': 1, 'idle_for': 0}
Adding # type: ignore[attr-defined]
bypasses the issue.
I'm using tenacity 8.0.1 and running Python 3.10.1.
I've had this problem with decorators of my own that add attributes to the decorated function. I noticed that the core Python function functools.wraps
adds an attribute __wrapped__
which likewise mypy knows nothing about.
I think it could be worked around by the decorator returning, instead of a function, an instance of a class with __call__
overridden. But to me it feels unnatural to add that runtime mechanism just to satisfy static code checks. In recent Python versions it might be doable with a protocol, but I figure that since typeshed doesn't contain a solution for functools.wraps
then likely there is no good solution yet.
Test to check whether there's a solution yet for functools
:
from functools import wraps
@wraps(len)
def my_len(val: str) -> int:
return len(val)
if __name__ == '__main__':
assert my_len.__wrapped__ is len
Current results:
$ python check_wraps.py
$ mypy check_wraps.py --strict
check_wraps.py:9: error: "Callable[[str], int]" has no attribute "__wrapped__"
Found 1 error in 1 file (checked 1 source file)
$ python --version
Python 3.10.2
$ mypy --version
mypy 0.942