@@ -35,6 +35,7 @@ class BaseCacheImpl(typing.Generic[KT, VT]):
35
35
"""
36
36
This is the base class of all cache classes such as Cache, FIFOCache, ...
37
37
"""
38
+
38
39
pass
39
40
40
41
@@ -57,13 +58,12 @@ class Cache(BaseCacheImpl[KT, VT]):
57
58
"""
58
59
A simple cache that has no algorithm; this is only a hashmap.
59
60
60
- Cache vs dict:
61
-
62
- it is thread-safe and unordered, while dict isn't thread-safe and ordered (Python 3.6+).
63
- it uses very lower memory than dict.
64
- it supports useful and new methods for managing memory, while dict does not.
65
- it does not support popitem, while dict does.
66
- You can limit the size of Cache, but you cannot for dict.
61
+ `Cache` vs `dict`:
62
+ - it is thread-safe and unordered, while `dict` isn't thread-safe and ordered (Python 3.6+).
63
+ - it uses very lower memory than `dict`.
64
+ - it supports useful and new methods for managing memory, while `dict` does not.
65
+ - it does not support popitem, while `dict` does.
66
+ - You can limit the size of Cache, but you cannot for `dict`.
67
67
"""
68
68
69
69
def __init__ (
@@ -165,14 +165,16 @@ def __setitem__(self, key: KT, value: VT) -> None:
165
165
self .insert (key , value )
166
166
167
167
def __getitem__ (self , key : KT ) -> VT :
168
- val = self .get (key , _sential )
168
+ val = self ._raw . get (key , _sential )
169
169
if val is _sential :
170
170
raise KeyError (key )
171
171
172
172
return val
173
173
174
174
def __delitem__ (self , key : KT ) -> None :
175
- self ._raw .remove (key )
175
+ val = self ._raw .pop (key , _sential )
176
+ if val is _sential :
177
+ raise KeyError (key )
176
178
177
179
def __eq__ (self , other ) -> bool :
178
180
return self ._raw == other
@@ -232,3 +234,122 @@ def __repr__(self) -> str:
232
234
self ._raw .maxsize (),
233
235
_items_to_str (self ._raw .items (), len (self ._raw )),
234
236
)
237
+
238
+
239
+ class FIFOCache (BaseCacheImpl [KT , VT ]):
240
+ def __init__ (
241
+ self ,
242
+ maxsize : int ,
243
+ iterable : typing .Union ["Cache" , dict , tuple , typing .Generator , None ] = None ,
244
+ * ,
245
+ capacity : int = 0 ,
246
+ ) -> None :
247
+ self ._raw = _core .FIFOCache (maxsize , capacity = capacity )
248
+
249
+ if iterable is not None :
250
+ self .update (iterable )
251
+
252
+ @property
253
+ def maxsize (self ) -> int :
254
+ return self ._raw .maxsize ()
255
+
256
+ def capacity (self ) -> int :
257
+ return self ._raw .capacity ()
258
+
259
+ def __len__ (self ) -> int :
260
+ return len (self ._raw )
261
+
262
+ def __sizeof__ (self ):
263
+ return self ._raw .__sizeof__ ()
264
+
265
+ def __contains__ (self , key : KT ) -> bool :
266
+ return key in self ._raw
267
+
268
+ def __bool__ (self ) -> bool :
269
+ return not self .is_empty ()
270
+
271
+ def is_empty (self ) -> bool :
272
+ return self ._raw .is_empty ()
273
+
274
+ def is_full (self ) -> bool :
275
+ return self ._raw .is_full ()
276
+
277
+ def insert (self , key : KT , value : VT ) -> typing .Optional [VT ]:
278
+ return self ._raw .insert (key , value )
279
+
280
+ def get (self , key : KT , default : typing .Optional [DT ] = None ) -> typing .Union [VT , DT ]:
281
+ return self ._raw .get (key , default )
282
+
283
+ def pop (self , key : KT , default : typing .Optional [DT ] = None ) -> typing .Union [VT , DT ]:
284
+ return self ._raw .pop (key , default )
285
+
286
+ def setdefault (self , key : KT , default : typing .Optional [DT ] = None ) -> typing .Union [VT , DT ]:
287
+ return self ._raw .setdefault (key , default )
288
+
289
+ def popitem (self ) -> typing .Tuple [KT , VT ]:
290
+ return self ._raw .popitem ()
291
+
292
+ def drain (self , n : int ) -> int :
293
+ if n == 0 :
294
+ return 0
295
+
296
+ for i in range (n ):
297
+ try :
298
+ self ._raw .popitem ()
299
+ except KeyError :
300
+ return i
301
+
302
+ return i
303
+
304
+ def update (self , iterable : typing .Union ["Cache" , dict , tuple , typing .Generator ]) -> None :
305
+ if hasattr (iterable , "items" ):
306
+ iterable = iterable .items ()
307
+
308
+ self ._raw .update (iterable )
309
+
310
+ def __setitem__ (self , key : KT , value : VT ) -> None :
311
+ self .insert (key , value )
312
+
313
+ def __getitem__ (self , key : KT ) -> VT :
314
+ val = self ._raw .get (key , _sential )
315
+ if val is _sential :
316
+ raise KeyError (key )
317
+
318
+ return val
319
+
320
+ def __delitem__ (self , key : KT ) -> None :
321
+ val = self ._raw .pop (key , _sential )
322
+ if val is _sential :
323
+ raise KeyError (key )
324
+
325
+ def __eq__ (self , other ) -> bool :
326
+ return self ._raw == other
327
+
328
+ def __ne__ (self , other ) -> bool :
329
+ return self ._raw != other
330
+
331
+ def shrink_to_fit (self ) -> None :
332
+ self ._raw .shrink_to_fit ()
333
+
334
+ def clear (self , * , reuse : bool = False ) -> None :
335
+ self ._raw .clear (reuse )
336
+
337
+ def items (self ) -> IteratorView [typing .Tuple [KT , VT ]]:
338
+ return IteratorView (self ._raw .items (), lambda x : x )
339
+
340
+ def keys (self ) -> IteratorView [KT ]:
341
+ return IteratorView (self ._raw .items (), lambda x : x [0 ])
342
+
343
+ def values (self ) -> IteratorView [VT ]:
344
+ return IteratorView (self ._raw .items (), lambda x : x [1 ])
345
+
346
+ def __iter__ (self ) -> IteratorView [KT ]:
347
+ return self .keys ()
348
+
349
+ def __repr__ (self ) -> str :
350
+ return "{}[{}/{}]({})" .format (
351
+ type (self ).__name__ ,
352
+ len (self ._raw ),
353
+ self ._raw .maxsize (),
354
+ _items_to_str (self ._raw .items (), len (self ._raw )),
355
+ )
0 commit comments