11import functools
22import time
33from collections import OrderedDict
4- from typing import Any , Callable , Generic , Iterable , Iterator , Tuple , TypeVar
4+ from typing import TYPE_CHECKING , Any , Generic , Iterable , Iterator , Tuple , TypeVar
5+
6+ if TYPE_CHECKING :
7+ from typing import Callable , TypeVarTuple , Unpack
8+
9+ PosArgsT = TypeVarTuple ("PosArgsT" )
10+ T_Retval = TypeVar ("T_Retval" )
11+ FuncType = Callable [[Unpack [PosArgsT ]], T_Retval ]
12+ FuncDecoType = Callable [[FuncType ], FuncType ]
513
614T = TypeVar ("T" )
715
816
917class Cache (Generic [T ]):
1018 """In-memory LRU cache implementation."""
1119
12- def __init__ (self , max_size : int = 500 ):
20+ def __init__ (self , max_size : int = 500 ) -> None :
1321 self ._bag : OrderedDict [Any , Any ] = OrderedDict ()
1422 self ._max_size = - 1
1523 self .max_size = max_size
@@ -50,7 +58,7 @@ def get(self, key, default=None) -> T:
5058 def set (self , key , value ) -> None :
5159 self [key ] = value
5260
53- def _check_size (self ):
61+ def _check_size (self ) -> None :
5462 while len (self ._bag ) > self .max_size :
5563 self ._bag .popitem (last = False )
5664
@@ -85,7 +93,7 @@ class CachedItem(Generic[T]):
8593
8694 __slots__ = ("_value" , "_time" )
8795
88- def __init__ (self , value : T ):
96+ def __init__ (self , value : T ) -> None :
8997 self ._value = value
9098 self ._time = time .time ()
9199
@@ -94,7 +102,7 @@ def value(self) -> T:
94102 return self ._value
95103
96104 @value .setter
97- def value (self , value : T ):
105+ def value (self , value : T ) -> None :
98106 self ._value = value
99107 self ._time = time .time ()
100108
@@ -107,8 +115,8 @@ class ExpiringCache(Cache[T]):
107115 """A cache whose items can expire by a given function."""
108116
109117 def __init__ (
110- self , expiration_policy : Callable [[CachedItem [T ]], bool ], max_size : int = 500
111- ):
118+ self , expiration_policy : " Callable[[CachedItem[T]], bool]" , max_size : int = 500
119+ ) -> None :
112120 super ().__init__ (max_size )
113121 assert expiration_policy is not None
114122 self .expiration_policy = expiration_policy
@@ -120,12 +128,12 @@ def full(self) -> bool:
120128 def expired (self , item : CachedItem ) -> bool :
121129 return self .expiration_policy (item )
122130
123- def _remove_expired_items (self ):
131+ def _remove_expired_items (self ) -> None :
124132 for key , item in list (self ._bag .items ()):
125133 if self .expired (item ):
126134 del self [key ]
127135
128- def _check_size (self ):
136+ def _check_size (self ) -> None :
129137 if self .full :
130138 self ._remove_expired_items ()
131139 super ()._check_size ()
@@ -148,7 +156,7 @@ def __setitem__(self, key, value: T) -> None:
148156 self ._check_size ()
149157
150158 @classmethod
151- def with_max_age (cls , max_age : float , max_size : int = 500 ):
159+ def with_max_age (cls , max_age : float , max_size : int = 500 ) -> "ExpiringCache" :
152160 """
153161 Returns an instance of ExpiringCache whose items are invalidated
154162 when they were set more than a given number of seconds ago.
@@ -174,7 +182,7 @@ def __iter__(self) -> Iterator[Tuple[Any, T]]:
174182 yield (key , item .value )
175183
176184
177- def lazy (max_seconds : int = 1 , cache = None ):
185+ def lazy (max_seconds : int = 1 , cache = None ) -> "FuncDecoType" :
178186 """
179187 Wraps a function so that it is called up to once
180188 every max_seconds, by input arguments.
0 commit comments