Description
When subclassing TTLCache[KT, VT] with explicit generic parameters,
type checkers (tested with Pyright and mypy) fail to infer the correct
type on instantiation, reporting _SubClass[Any, Any, float] instead
of _SubClass[KT, VT].
Reproduction
from typing import Any
from cachetools import TTLCache
class _TrackedTTLCache[KT, VT](TTLCache[KT, VT]):
def popitem(self) -> tuple[KT, VT]:
key, value = super().popitem()
return key, value
cache: _TrackedTTLCache[str, int] = _TrackedTTLCache(maxsize=128, ttl=600)
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Error: Expected type '_TrackedTTLCache[str, int]',
# got '_TrackedTTLCache[Any, Any, float]' instead
Expected behavior
_TrackedTTLCache(maxsize=128, ttl=600) should be inferred as
_TrackedTTLCache[str, int] — consistent with how the explicit
annotation on the left-hand side is declared.
Root cause
The stub signature for TTLCache.__init__ likely includes float
as a third implicit type parameter (from the timer argument),
which leaks into subclass inference and overrides the declared
generic parameters.
Workaround
from typing import cast
cache = cast(
"_TrackedTTLCache[str, int]",
_TrackedTTLCache(maxsize=128, ttl=600),
)
Environment
cachetools version: 7.1.1
- PyCharm linter
- Python: 3.12
Description
When subclassing
TTLCache[KT, VT]with explicit generic parameters,type checkers (tested with Pyright and mypy) fail to infer the correct
type on instantiation, reporting
_SubClass[Any, Any, float]insteadof
_SubClass[KT, VT].Reproduction
Expected behavior
_TrackedTTLCache(maxsize=128, ttl=600)should be inferred as_TrackedTTLCache[str, int]— consistent with how the explicitannotation on the left-hand side is declared.
Root cause
The stub signature for
TTLCache.__init__likely includesfloatas a third implicit type parameter (from the
timerargument),which leaks into subclass inference and overrides the declared
generic parameters.
Workaround
Environment
cachetoolsversion: 7.1.1