summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabrice Douchant <Fabrice.Douchant@logilab.fr>2008-10-16 11:44:30 +0200
committerFabrice Douchant <Fabrice.Douchant@logilab.fr>2008-10-16 11:44:30 +0200
commitb55677ac8a8aaeaae8b73a293f5a2a8d79a93ca2 (patch)
tree4598221004dcf4a08a96fc4d69ebe3fe63bb3e59
parentff54dde60b9aab97438cf6d1ae93024cd6a74ea0 (diff)
downloadlogilab-common-b55677ac8a8aaeaae8b73a293f5a2a8d79a93ca2.tar.gz
reimplement Cache. Noew inheriting from dict (#3841)
changing corresponding unittests
-rw-r--r--cache.py59
-rw-r--r--test/unittest_cache.py40
2 files changed, 43 insertions, 56 deletions
diff --git a/cache.py b/cache.py
index 7ee697f..fa9a34c 100644
--- a/cache.py
+++ b/cache.py
@@ -13,7 +13,7 @@ from logilab.common.decorators import locked
_marker = object()
-class Cache:
+class Cache(dict):
"""A dictionnary like cache.
inv:
@@ -22,18 +22,16 @@ class Cache:
"""
def __init__(self, size=100):
+ """ Warning : Cache.__init__() != dict.__init__().
+ Constructor does not take any arguments beside size.
+ """
+ print '__init__'
assert size >= 0, 'cache size must be >= 0 (0 meaning no caching)'
- self.data = {}
self.size = size
self._usage = []
self._lock = Lock()
+ super(Cache, self).__init__()
- def __repr__(self):
- return repr(self.data)
-
- def __len__(self):
- return len(self.data)
-
def _acquire(self):
self._lock.acquire()
@@ -51,54 +49,45 @@ class Cache:
# check the size of the dictionnary
# and remove the oldest item in the cache
if self.size and len(self._usage) >= self.size:
- del self.data[self._usage[0]]
+ super(Cache, self).__delitem__(self._usage[0])
del self._usage[0]
self._usage.append(key)
else:
pass # key is already the most recently used key
def __getitem__(self, key):
- value = self.data[key]
+ print '__getitem__'
self._update_usage(key)
- return value
+ return super(Cache, self).__getitem__(key)
__getitem__ = locked(_acquire, _release)(__getitem__)
def __setitem__(self, key, item):
+ print '__setitem__'
# Just make sure that size > 0 before inserting a new item in the cache
if self.size > 0:
- self.data[key] = item
+ super(Cache, self).__setitem__(key, item)
self._update_usage(key)
__setitem__ = locked(_acquire, _release)(__setitem__)
def __delitem__(self, key):
- del self.data[key]
+ print '__delitem__'
+ super(Cache, self).__delitem__(key)
self._usage.remove(key)
__delitem__ = locked(_acquire, _release)(__delitem__)
- def pop(self, value, default=_marker):
- if value in self.data:
- self._usage.remove(value)
- if default is _marker:
- return self.data.pop(value)
- return self.data.pop(value, default)
- pop = locked(_acquire, _release)(pop)
-
def clear(self):
- self.data.clear()
+ print 'clear'
+ super(Cache, self).clear()
self._usage = []
clear = locked(_acquire, _release)(clear)
- def keys(self):
- return self.data.keys()
-
- def items(self):
- return self.data.items()
-
- def values(self):
- return self.data.values()
+ def pop(self, key, default=_marker):
+ print 'pop'
+ if super(Cache, self).has_key(key):
+ self._usage.remove(key)
+ if default is _marker:
+ return super(Cache, self).pop(key)
+ return super(Cache, self).pop(key, default)
+ pop = locked(_acquire, _release)(pop)
- def has_key(self, key):
- return self.data.has_key(key)
-
- __contains__ = has_key
-
+ #__contains__ = has_key
diff --git a/test/unittest_cache.py b/test/unittest_cache.py
index fbe8cc0..ec1d87d 100644
--- a/test/unittest_cache.py
+++ b/test/unittest_cache.py
@@ -1,46 +1,47 @@
# unit tests for the cache module
-from logilab.common.testlib import TestCase, unittest_main
+from logilab.common.testlib import TestCase, unittest_main, TestSuite
from logilab.common.cache import Cache
class CacheTestCase(TestCase):
def setUp(self):
self.cache = Cache(5)
+ self.testdict = {}
def test_setitem1(self):
"""Checks that the setitem method works"""
self.cache[1] = 'foo'
- self.assertEqual(self.cache.data[1], 'foo', "1:foo is not in cache")
+ self.assertEqual(self.cache[1], 'foo', "1:foo is not in cache")
self.assertEqual(len(self.cache._usage), 1)
self.assertEqual(self.cache._usage[-1], 1,
'1 is not the most recently used key')
- self.assertSetEqual(self.cache._usage,
- self.cache.data.keys(),
+ self.assertUnorderedIterableEquals(self.cache._usage,
+ self.cache.keys(),
"usage list and data keys are different")
def test_setitem2(self):
"""Checks that the setitem method works for multiple items"""
self.cache[1] = 'foo'
self.cache[2] = 'bar'
- self.assertEqual(self.cache.data[2], 'bar',
+ self.assertEqual(self.cache[2], 'bar',
"2 : 'bar' is not in cache.data")
self.assertEqual(len(self.cache._usage), 2,
"lenght of usage list is not 2")
self.assertEqual(self.cache._usage[-1], 2,
'1 is not the most recently used key')
- self.assertSetEqual(self.cache._usage,
- self.cache.data.keys())# usage list and data keys are different
+ self.assertUnorderedIterableEquals(self.cache._usage,
+ self.cache.keys())# usage list and data keys are different
def test_setitem3(self):
"""Checks that the setitem method works when replacing an element in the cache"""
self.cache[1] = 'foo'
self.cache[1] = 'bar'
- self.assertEqual(self.cache.data[1], 'bar', "1 : 'bar' is not in cache.data")
+ self.assertEqual(self.cache[1], 'bar', "1 : 'bar' is not in cache.data")
self.assertEqual(len(self.cache._usage), 1, "lenght of usage list is not 1")
self.assertEqual(self.cache._usage[-1], 1, '1 is not the most recently used key')
- self.assertSetEqual(self.cache._usage,
- self.cache.data.keys())# usage list and data keys are different
+ self.assertUnorderedIterableEquals(self.cache._usage,
+ self.cache.keys())# usage list and data keys are different
def test_recycling1(self):
"""Checks the removal of old elements"""
@@ -50,14 +51,14 @@ class CacheTestCase(TestCase):
self.cache[4] = 'foz'
self.cache[5] = 'fuz'
self.cache[6] = 'spam'
- self.assert_(not self.cache.data.has_key(1),
+ self.assert_(not self.cache.has_key(1),
'key 1 has not been suppressed from the cache dictionnary')
self.assert_(1 not in self.cache._usage,
'key 1 has not been suppressed from the cache LRU list')
self.assertEqual(len(self.cache._usage), 5, "lenght of usage list is not 5")
self.assertEqual(self.cache._usage[-1], 6, '6 is not the most recently used key')
- self.assertSetEqual(self.cache._usage,
- self.cache.data.keys())# usage list and data keys are different
+ self.assertUnorderedIterableEquals(self.cache._usage,
+ self.cache.keys())# usage list and data keys are different
def test_recycling2(self):
"""Checks that accessed elements get in the front of the list"""
@@ -68,8 +69,8 @@ class CacheTestCase(TestCase):
a = self.cache[1]
self.assertEqual(a, 'foo')
self.assertEqual(self.cache._usage[-1], 1, '1 is not the most recently used key')
- self.assertSetEqual(self.cache._usage,
- self.cache.data.keys())# usage list and data keys are different
+ self.assertUnorderedIterableEquals(self.cache._usage,
+ self.cache.keys())# usage list and data keys are different
def test_delitem(self):
"""Checks that elements are removed from both element dict and element
@@ -77,10 +78,10 @@ class CacheTestCase(TestCase):
"""
self.cache['foo'] = 'bar'
del self.cache['foo']
- self.assert_('foo' not in self.cache.data.keys(),"Element 'foo' was not removed cache dictionnary")
+ self.assert_('foo' not in self.cache.keys(),"Element 'foo' was not removed cache dictionnary")
self.assert_('foo' not in self.cache._usage,"Element 'foo' was not removed usage list")
- self.assertSetEqual(self.cache._usage,
- self.cache.data.keys())# usage list and data keys are different
+ self.assertUnorderedIterableEquals(self.cache._usage,
+ self.cache.keys())# usage list and data keys are different
def test_nullsize(self):
@@ -99,6 +100,3 @@ class CacheTestCase(TestCase):
if __name__ == "__main__":
unittest_main()
-
-
-