diff options
author | Fabrice Douchant <Fabrice.Douchant@logilab.fr> | 2008-10-16 11:44:30 +0200 |
---|---|---|
committer | Fabrice Douchant <Fabrice.Douchant@logilab.fr> | 2008-10-16 11:44:30 +0200 |
commit | b55677ac8a8aaeaae8b73a293f5a2a8d79a93ca2 (patch) | |
tree | 4598221004dcf4a08a96fc4d69ebe3fe63bb3e59 | |
parent | ff54dde60b9aab97438cf6d1ae93024cd6a74ea0 (diff) | |
download | logilab-common-b55677ac8a8aaeaae8b73a293f5a2a8d79a93ca2.tar.gz |
reimplement Cache. Noew inheriting from dict (#3841)
changing corresponding unittests
-rw-r--r-- | cache.py | 59 | ||||
-rw-r--r-- | test/unittest_cache.py | 40 |
2 files changed, 43 insertions, 56 deletions
@@ -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() - - - |