aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Kemmer <tkemmer@computer.org>2021-01-24 20:31:40 +0100
committerThomas Kemmer <tkemmer@computer.org>2021-01-24 20:35:54 +0100
commit4862ce336ca177dd79bafea67a05302c22102532 (patch)
tree49e8a027d5ac0ad45c1d5882f75c01a5ce79d913
parente6acc1eaff5593158933d24ca035d746d5a13899 (diff)
downloadcachetools-4862ce336ca177dd79bafea67a05302c22102532.tar.gz
Fix #200: Handle __missing__ not storing cache items.
-rw-r--r--cachetools/lfu.py3
-rw-r--r--cachetools/lru.py3
-rw-r--r--cachetools/mru.py3
-rw-r--r--tests/__init__.py49
4 files changed, 38 insertions, 20 deletions
diff --git a/cachetools/lfu.py b/cachetools/lfu.py
index 17c2b9d..894a326 100644
--- a/cachetools/lfu.py
+++ b/cachetools/lfu.py
@@ -12,7 +12,8 @@ class LFUCache(Cache):
def __getitem__(self, key, cache_getitem=Cache.__getitem__):
value = cache_getitem(self, key)
- self.__counter[key] -= 1
+ if key in self: # __missing__ may not store item
+ self.__counter[key] -= 1
return value
def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
diff --git a/cachetools/lru.py b/cachetools/lru.py
index 2508e5d..33749d1 100644
--- a/cachetools/lru.py
+++ b/cachetools/lru.py
@@ -12,7 +12,8 @@ class LRUCache(Cache):
def __getitem__(self, key, cache_getitem=Cache.__getitem__):
value = cache_getitem(self, key)
- self.__update(key)
+ if key in self: # __missing__ may not store item
+ self.__update(key)
return value
def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
diff --git a/cachetools/mru.py b/cachetools/mru.py
index 92b8e76..41e2aa1 100644
--- a/cachetools/mru.py
+++ b/cachetools/mru.py
@@ -12,7 +12,8 @@ class MRUCache(Cache):
def __getitem__(self, key, cache_getitem=Cache.__getitem__):
value = cache_getitem(self, key)
- self.__update(key)
+ if key in self: # __missing__ may not store item
+ self.__update(key)
return value
def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
diff --git a/tests/__init__.py b/tests/__init__.py
index 82f85ef..70a0f03 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -120,7 +120,14 @@ class CacheTestMixin(object):
self.assertIsNone(exception.__cause__)
self.assertTrue(exception.__suppress_context__)
- def _test_missing(self, cache):
+ def test_missing(self):
+ class DefaultCache(self.Cache):
+ def __missing__(self, key):
+ self[key] = key
+ return key
+
+ cache = DefaultCache(maxsize=2)
+
self.assertEqual(0, cache.currsize)
self.assertEqual(2, cache.maxsize)
self.assertEqual(0, len(cache))
@@ -172,30 +179,38 @@ class CacheTestMixin(object):
self.assertTrue(1 in cache or 2 in cache)
self.assertTrue(1 not in cache or 2 not in cache)
- def _test_missing_getsizeof(self, cache):
+ def test_missing_getsizeof(self):
+ class DefaultCache(self.Cache):
+ def __missing__(self, key):
+ try:
+ self[key] = key
+ except ValueError:
+ pass # not stored
+ return key
+
+ cache = DefaultCache(maxsize=2, getsizeof=lambda x: x)
+
self.assertEqual(0, cache.currsize)
self.assertEqual(2, cache.maxsize)
+
self.assertEqual(1, cache[1])
+ self.assertEqual(1, len(cache))
+ self.assertEqual(1, cache.currsize)
self.assertIn(1, cache)
+
self.assertEqual(2, cache[2])
+ self.assertEqual(1, len(cache))
+ self.assertEqual(2, cache.currsize)
self.assertNotIn(1, cache)
self.assertIn(2, cache)
- self.assertEqual(3, cache[3])
- self.assertNotIn(1, cache)
- self.assertIn(2, cache)
- self.assertNotIn(3, cache)
- def test_missing_subclass(self):
- class Cache(self.Cache):
- def __missing__(self, key):
- try:
- self[key] = key
- except ValueError:
- pass
- return key
-
- self._test_missing(Cache(maxsize=2))
- self._test_missing_getsizeof(Cache(maxsize=2, getsizeof=lambda x: x))
+ self.assertEqual(3, cache[3]) # not stored
+ self.assertEqual(1, len(cache))
+ self.assertEqual(2, cache.currsize)
+ self.assertEqual(1, cache[1])
+ self.assertEqual(1, len(cache))
+ self.assertEqual(1, cache.currsize)
+ self.assertEqual((1, 1), cache.popitem())
def _test_getsizeof(self, cache):
self.assertEqual(0, cache.currsize)