Repository navigation
Description
Whether this is a bug report or an enhancement request depends on whether the current behavior is as designed.
The unwanted behavior
Let me illustrate the behavior I am talking about with very contrived example. The error is reported for the def mass in the Spam class (line 26).
from functools import cache
from typing import Protocol
class SupportsMass(Protocol):
@property
def density(self) -> float:
"""Grams per milliliter."""
...
def mass(self, volume: float) -> float:
"""Mass of object in grams given volume in milliliters."""
...
class Spam(SupportsMass):
def __init__(self) -> None:
# Spam is allegedly 237 grams per metric cup.
self._density = 237 / 240 # g/ml
@property
def density(self) -> float:
return self._density
@cache
def mass(self, volume: float) -> float: # pyright reports error here
return volume * self._densityRunning pyright on that file yields this:
% pyright cache_protocol.py
/PATH_TO/cache_protocol.py
/PATH_TO/cache_protocol.py:26:9 - error: "mass" overrides method of same name in class "SupportsMass" with incompatible type "_lru_cache_wrapper[float]" (reportIncompatibleMethodOverride)
1 error, 0 warnings, 0 informationsI do understand that using the @cache decorator from functools changes the type of mass(), but it doesn't do so from the perspective of the user of the protocol and the class. That is, the use of a decorator like @cache is an implementation detail of the Spam class that should not be relevant for the protocol.
Contrast this with @property for density(), where it has a direct impact on how the method is to be called. Pyright behaves correctly in insisting that the decorator be specified the same in both the definition of the protocol and in the definition of a subclass of the protocol.
Note: if you are reporting a wrong signature of a function or a class in the standard library, then the typeshed tracker is better suited for this report: https://github.com/python/typeshed/issues.
If you have a question about typing or a behavior that you’re seeing in Pyright (as opposed to a bug report or enhancement request), consider posting to the Pyright discussion forum.
VS Code extension or command-line
I first noticed the behavior within VS Code, but I have reproduced on the command-line
% pyright --version
pyright 1.1.401
% python --version
Python 3.13.3
Activity
erictraut commentedon May 25, 2025
Pyright is working as designed here. It's applying the normal typing rules based on the type definition of
functools.cache. The return type offunctools.cacheis_lru_cache_wrapper[_T].There is a long discussion among typeshed maintainers about whether
_lru_cache_wrappershould use aParamSpecto preserve the signature of the function it is wrapping. I think it should for the reasons that you point out. The way it's currently defined, it defines the__call__method using in such a way that all parameters are typed asHashable, which is a requirement offunctools.cache. If_lru_cache_wrapperwere redefined to use aParamSpec, it would lose the ability to check for hashability. I personally think that it should be changed because the current approach creates significant usability problems, as you've highlighted. If you'd like to voice your opinion, feel free to post to this thread.In any case, I don't consider this a pyright bug. It's a choice that the typing community (or at least the typeshed maintainers) have made.