1919
2020if TYPE_CHECKING :
2121 from collections .abc import Callable
22+ from typing import TypeAlias
23+
24+ from ty_extensions import Intersection
25+
26+ Memoized : TypeAlias = "Intersection[Callable[P, R], HasCache]"
2227
2328P = ParamSpec ("P" )
2429R = TypeVar ("R" )
2530
2631
27- class MemoizedCallable (Protocol [ P , R ] ):
28- """A callable that has been memoized and has a cache attribute."""
32+ class HasCache (Protocol ):
33+ """Protocol for objects that have a cache attribute."""
2934
3035 cache : Cache
3136
32- def __call__ (self , * args : P .args , ** kwargs : P .kwargs ) -> R :
33- """Call the memoized function."""
34- ...
35-
3637
3738@define
3839class CacheInfo :
@@ -46,7 +47,7 @@ class Cache:
4647 _sentinel : Any = field (factory = object )
4748 cache_info : CacheInfo = field (factory = CacheInfo )
4849
49- def memoize (self , func : Callable [P , R ]) -> MemoizedCallable [P , R ]:
50+ def memoize (self , func : Callable [P , R ]) -> Memoized [P , R ]:
5051 func_module = getattr (func , "__module__" , "" )
5152 func_name = getattr (func , "__name__" , "" )
5253 prefix = f"{ func_module } .{ func_name } :"
@@ -68,9 +69,9 @@ def wrapped(*args: P.args, **kwargs: P.kwargs) -> R:
6869
6970 return value
7071
71- wrapped .cache = self # type : ignore[attr-defined ]
72+ wrapped .cache = self # ty : ignore[unresolved-attribute ]
7273
73- return wrapped # type: ignore[return-value]
74+ return wrapped
7475
7576 def add (self , key : str , value : Any ) -> None :
7677 self ._cache [key ] = value
0 commit comments