Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions stubs/cachetools/@tests/test_cases/check_cachetools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
from __future__ import annotations

from collections.abc import Hashable
from typing import Any
from typing_extensions import assert_type

from cachetools import LRUCache, cached, keys as cachekeys
from cachetools.func import fifo_cache, lfu_cache, lru_cache, rr_cache, ttl_cache

# Tests for cachetools.cached

# Explicitly parameterize the cache to avoid Unknown types
cache_inst: LRUCache[int, int] = LRUCache(maxsize=128)


@cached(cache_inst)
def check_cached(x: int) -> int:
return x * 2


assert_type(check_cached(3), int)
# Methods cache_info/cache_clear are only present when info=True; do not access them here.


@cached(cache_inst, info=True)
def check_cached_with_info(x: int) -> int:
return x + 1


assert_type(check_cached_with_info(4), int)
assert_type(check_cached_with_info.cache_info().misses, int)
check_cached_with_info.cache_clear()


# Tests for cachetools.func decorators


@lru_cache
def lru_noparens(x: int) -> int:
return x * 2


@lru_cache(maxsize=32)
def lru_with_maxsize(x: int) -> int:
return x * 3


assert_type(lru_noparens(3), int)
assert_type(lru_with_maxsize(3), int)
assert_type(lru_noparens.cache_info().hits, int)
assert_type(lru_with_maxsize.cache_info().misses, int)
assert_type(lru_with_maxsize.cache_parameters(), dict[str, Any])
lru_with_maxsize.cache_clear()


@fifo_cache
def fifo_func(x: int) -> int:
return x


@lfu_cache
def lfu_func(x: int) -> int:
return x


@rr_cache
def rr_func(x: int) -> int:
return x


@ttl_cache
def ttl_func(x: int) -> int:
return x


assert_type(fifo_func(1), int)
assert_type(lfu_func(1), int)
assert_type(rr_func(1), int)
assert_type(ttl_func(1), int)
assert_type(fifo_func.cache_info().currsize, int)
assert_type(lfu_func.cache_parameters(), dict[str, Any])


# Tests for cachetools.keys

k1 = cachekeys.hashkey(1, "a")
assert_type(k1, tuple[Hashable, ...])


class C:
def method(self, a: int) -> int:
return a


inst = C()

k2 = cachekeys.methodkey(inst, 5)
assert_type(k2, tuple[Hashable, ...])

k3 = cachekeys.typedkey(1, "x")
assert_type(k3, tuple[Hashable, ...])

k4 = cachekeys.typedmethodkey(inst, 2)
assert_type(k4, tuple[Hashable, ...])
41 changes: 36 additions & 5 deletions stubs/cachetools/cachetools/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ from _typeshed import IdentityFunction, Unused
from collections.abc import Callable, Iterator, MutableMapping, Sequence
from contextlib import AbstractContextManager
from threading import Condition
from typing import Any, TypeVar, overload
from typing import Any, Generic, Literal, NamedTuple, TypeVar, overload
from typing_extensions import Self, deprecated

__all__ = ("Cache", "FIFOCache", "LFUCache", "LRUCache", "RRCache", "TLRUCache", "TTLCache", "cached", "cachedmethod")
Expand All @@ -11,6 +11,7 @@ __version__: str
_KT = TypeVar("_KT")
_VT = TypeVar("_VT")
_T = TypeVar("_T")
_R = TypeVar("_R")

class Cache(MutableMapping[_KT, _VT]):
@overload
Expand Down Expand Up @@ -99,22 +100,52 @@ class TLRUCache(_TimedCache[_KT, _VT]):
def ttu(self) -> Callable[[_KT, _VT, float], float]: ...
def expire(self, time: float | None = None) -> list[tuple[_KT, _VT]]: ...

class _CacheInfo(NamedTuple):
hits: int
misses: int
maxsize: int | None
currsize: int

class _cached_wrapper(Generic[_R]):
__wrapped__: Callable[..., _R]
def __call__(self, /, *args: Any, **kwargs: Any) -> _R: ...

class _cached_wrapper_info(_cached_wrapper[_R]):
def cache_info(self) -> _CacheInfo: ...
def cache_clear(self) -> None: ...

@overload
def cached(
cache: MutableMapping[_KT, Any] | None,
key: Callable[..., _KT] = ...,
lock: AbstractContextManager[Any] | None = None,
condition: Condition | None = None,
info: bool = False,
) -> IdentityFunction: ...
info: Literal[True] = ...,
) -> Callable[[Callable[..., _R]], _cached_wrapper_info[_R]]: ...
@overload
def cached(
cache: MutableMapping[_KT, Any] | None,
key: Callable[..., _KT] = ...,
lock: AbstractContextManager[Any] | None = None,
condition: Condition | None = None,
info: Literal[False] = ...,
) -> Callable[[Callable[..., _R]], _cached_wrapper[_R]]: ...
@overload
@deprecated("Passing `info` as positional parameter is deprecated.")
def cached(
cache: MutableMapping[_KT, Any] | None,
key: Callable[..., _KT] = ...,
lock: AbstractContextManager[Any] | None = None,
condition: bool | None = None,
) -> IdentityFunction: ...
condition: Literal[True] = ...,
) -> Callable[[Callable[..., _R]], _cached_wrapper_info[_R]]: ...
@overload
@deprecated("Passing `info` as positional parameter is deprecated.")
def cached(
cache: MutableMapping[_KT, Any] | None,
key: Callable[..., _KT] = ...,
lock: AbstractContextManager[Any] | None = None,
condition: Literal[False] | None = ...,
) -> Callable[[Callable[..., _R]], _cached_wrapper[_R]]: ...
def cachedmethod(
cache: Callable[[Any], MutableMapping[_KT, Any] | None],
key: Callable[..., _KT] = ...,
Expand Down
55 changes: 45 additions & 10 deletions stubs/cachetools/cachetools/func.pyi
Original file line number Diff line number Diff line change
@@ -1,16 +1,51 @@
from _typeshed import IdentityFunction
from collections.abc import Callable, Sequence
from typing import TypeVar
from typing import Any, Final, Generic, NamedTuple, TypeVar, overload

__all__: Final = ("fifo_cache", "lfu_cache", "lru_cache", "rr_cache", "ttl_cache")

__all__ = ("fifo_cache", "lfu_cache", "lru_cache", "rr_cache", "ttl_cache")
_T = TypeVar("_T")
_R = TypeVar("_R")

class _CacheInfo(NamedTuple):
hits: int
misses: int
maxsize: int | None
currsize: int

class _cachetools_cache_wrapper(Generic[_R]):
__wrapped__: Callable[..., _R]
def __call__(self, /, *args: Any, **kwargs: Any) -> _R: ...
def cache_info(self) -> _CacheInfo: ...
def cache_clear(self) -> None: ...
def cache_parameters(self) -> dict[str, Any]: ...

def fifo_cache(maxsize: float | None = 128, typed: bool = False) -> IdentityFunction: ...
def lfu_cache(maxsize: float | None = 128, typed: bool = False) -> IdentityFunction: ...
def lru_cache(maxsize: float | None = 128, typed: bool = False) -> IdentityFunction: ...
@overload
def fifo_cache(
maxsize: int | None = 128, typed: bool = False
) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
@overload
def fifo_cache(maxsize: Callable[..., _R], typed: bool = False) -> _cachetools_cache_wrapper[_R]: ...
@overload
def lfu_cache(maxsize: int | None = 128, typed: bool = False) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
@overload
def lfu_cache(maxsize: Callable[..., _R], typed: bool = False) -> _cachetools_cache_wrapper[_R]: ...
@overload
def lru_cache(maxsize: int | None = 128, typed: bool = False) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
@overload
def lru_cache(maxsize: Callable[..., _R], typed: bool = False) -> _cachetools_cache_wrapper[_R]: ...
@overload
def rr_cache(
maxsize: float | None = 128, choice: Callable[[Sequence[_T]], _T] | None = ..., typed: bool = False
) -> IdentityFunction: ...
maxsize: int | None = 128, choice: Callable[[Sequence[_T]], _T] | None = ..., typed: bool = False
) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
@overload
def rr_cache(
maxsize: Callable[..., _R], choice: Callable[[Sequence[_T]], _T] | None = ..., typed: bool = False
) -> _cachetools_cache_wrapper[_R]: ...
@overload
def ttl_cache(
maxsize: int | None = 128, ttl: float = 600, timer: Callable[[], float] = ..., typed: bool = False
) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
@overload
def ttl_cache(
maxsize: float | None = 128, ttl: float = 600, timer: Callable[[], float] = ..., typed: bool = False
) -> IdentityFunction: ...
maxsize: Callable[..., _R], ttl: float = 600, timer: Callable[[], float] = ..., typed: bool = False
) -> _cachetools_cache_wrapper[_R]: ...
4 changes: 2 additions & 2 deletions stubs/cachetools/cachetools/keys.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ from collections.abc import Hashable
__all__ = ("hashkey", "methodkey", "typedkey", "typedmethodkey")

def hashkey(*args: Hashable, **kwargs: Hashable) -> tuple[Hashable, ...]: ...
def methodkey(self: Unused, *args: Hashable, **kwargs: Hashable) -> tuple[Hashable, ...]: ...
def methodkey(self: Unused, /, *args: Hashable, **kwargs: Hashable) -> tuple[Hashable, ...]: ...
def typedkey(*args: Hashable, **kwargs: Hashable) -> tuple[Hashable, ...]: ...
def typedmethodkey(self: Unused, *args: Hashable, **kwargs: Hashable) -> tuple[Hashable, ...]: ...
def typedmethodkey(self: Unused, /, *args: Hashable, **kwargs: Hashable) -> tuple[Hashable, ...]: ...