166 lines
4.8 KiB
Python
166 lines
4.8 KiB
Python
import operator
|
|
import unittest
|
|
|
|
from cachetools import LRUCache, cachedmethod, keys
|
|
|
|
|
|
class Cached:
|
|
def __init__(self, cache, count=0):
|
|
self.cache = cache
|
|
self.count = count
|
|
|
|
@cachedmethod(operator.attrgetter("cache"))
|
|
def get(self, value):
|
|
count = self.count
|
|
self.count += 1
|
|
return count
|
|
|
|
@cachedmethod(operator.attrgetter("cache"), key=keys.typedkey)
|
|
def get_typed(self, value):
|
|
count = self.count
|
|
self.count += 1
|
|
return count
|
|
|
|
# https://github.com/tkem/cachetools/issues/107
|
|
def __hash__(self):
|
|
raise TypeError("unhashable type")
|
|
|
|
|
|
class Locked:
|
|
def __init__(self, cache):
|
|
self.cache = cache
|
|
self.count = 0
|
|
|
|
@cachedmethod(operator.attrgetter("cache"), lock=lambda self: self)
|
|
def get(self, value):
|
|
return self.count
|
|
|
|
def __enter__(self):
|
|
self.count += 1
|
|
|
|
def __exit__(self, *exc):
|
|
pass
|
|
|
|
|
|
class CachedMethodTest(unittest.TestCase):
|
|
def test_dict(self):
|
|
cached = Cached({})
|
|
|
|
self.assertEqual(cached.get(0), 0)
|
|
self.assertEqual(cached.get(1), 1)
|
|
self.assertEqual(cached.get(1), 1)
|
|
self.assertEqual(cached.get(1.0), 1)
|
|
self.assertEqual(cached.get(1.0), 1)
|
|
|
|
cached.cache.clear()
|
|
self.assertEqual(cached.get(1), 2)
|
|
|
|
def test_typed_dict(self):
|
|
cached = Cached(LRUCache(maxsize=2))
|
|
|
|
self.assertEqual(cached.get_typed(0), 0)
|
|
self.assertEqual(cached.get_typed(1), 1)
|
|
self.assertEqual(cached.get_typed(1), 1)
|
|
self.assertEqual(cached.get_typed(1.0), 2)
|
|
self.assertEqual(cached.get_typed(1.0), 2)
|
|
self.assertEqual(cached.get_typed(0.0), 3)
|
|
self.assertEqual(cached.get_typed(0), 4)
|
|
|
|
def test_lru(self):
|
|
cached = Cached(LRUCache(maxsize=2))
|
|
|
|
self.assertEqual(cached.get(0), 0)
|
|
self.assertEqual(cached.get(1), 1)
|
|
self.assertEqual(cached.get(1), 1)
|
|
self.assertEqual(cached.get(1.0), 1)
|
|
self.assertEqual(cached.get(1.0), 1)
|
|
|
|
cached.cache.clear()
|
|
self.assertEqual(cached.get(1), 2)
|
|
|
|
def test_typed_lru(self):
|
|
cached = Cached(LRUCache(maxsize=2))
|
|
|
|
self.assertEqual(cached.get_typed(0), 0)
|
|
self.assertEqual(cached.get_typed(1), 1)
|
|
self.assertEqual(cached.get_typed(1), 1)
|
|
self.assertEqual(cached.get_typed(1.0), 2)
|
|
self.assertEqual(cached.get_typed(1.0), 2)
|
|
self.assertEqual(cached.get_typed(0.0), 3)
|
|
self.assertEqual(cached.get_typed(0), 4)
|
|
|
|
def test_nospace(self):
|
|
cached = Cached(LRUCache(maxsize=0))
|
|
|
|
self.assertEqual(cached.get(0), 0)
|
|
self.assertEqual(cached.get(1), 1)
|
|
self.assertEqual(cached.get(1), 2)
|
|
self.assertEqual(cached.get(1.0), 3)
|
|
self.assertEqual(cached.get(1.0), 4)
|
|
|
|
def test_nocache(self):
|
|
cached = Cached(None)
|
|
|
|
self.assertEqual(cached.get(0), 0)
|
|
self.assertEqual(cached.get(1), 1)
|
|
self.assertEqual(cached.get(1), 2)
|
|
self.assertEqual(cached.get(1.0), 3)
|
|
self.assertEqual(cached.get(1.0), 4)
|
|
|
|
def test_weakref(self):
|
|
import weakref
|
|
import fractions
|
|
import gc
|
|
|
|
# in Python 3.4, `int` does not support weak references even
|
|
# when subclassed, but Fraction apparently does...
|
|
class Int(fractions.Fraction):
|
|
def __add__(self, other):
|
|
return Int(fractions.Fraction.__add__(self, other))
|
|
|
|
cached = Cached(weakref.WeakValueDictionary(), count=Int(0))
|
|
|
|
self.assertEqual(cached.get(0), 0)
|
|
gc.collect()
|
|
self.assertEqual(cached.get(0), 1)
|
|
|
|
ref = cached.get(1)
|
|
self.assertEqual(ref, 2)
|
|
self.assertEqual(cached.get(1), 2)
|
|
self.assertEqual(cached.get(1.0), 2)
|
|
|
|
ref = cached.get_typed(1)
|
|
self.assertEqual(ref, 3)
|
|
self.assertEqual(cached.get_typed(1), 3)
|
|
self.assertEqual(cached.get_typed(1.0), 4)
|
|
|
|
cached.cache.clear()
|
|
self.assertEqual(cached.get(1), 5)
|
|
|
|
def test_locked_dict(self):
|
|
cached = Locked({})
|
|
|
|
self.assertEqual(cached.get(0), 1)
|
|
self.assertEqual(cached.get(1), 3)
|
|
self.assertEqual(cached.get(1), 3)
|
|
self.assertEqual(cached.get(1.0), 3)
|
|
self.assertEqual(cached.get(2.0), 7)
|
|
|
|
def test_locked_nocache(self):
|
|
cached = Locked(None)
|
|
|
|
self.assertEqual(cached.get(0), 0)
|
|
self.assertEqual(cached.get(1), 0)
|
|
self.assertEqual(cached.get(1), 0)
|
|
self.assertEqual(cached.get(1.0), 0)
|
|
self.assertEqual(cached.get(1.0), 0)
|
|
|
|
def test_locked_nospace(self):
|
|
cached = Locked(LRUCache(maxsize=0))
|
|
|
|
self.assertEqual(cached.get(0), 1)
|
|
self.assertEqual(cached.get(1), 3)
|
|
self.assertEqual(cached.get(1), 5)
|
|
self.assertEqual(cached.get(1.0), 7)
|
|
self.assertEqual(cached.get(1.0), 9)
|