Simple cache decorator
This commit is contained in:
parent
6eb79ba75e
commit
119e1a9bf0
3 changed files with 128 additions and 0 deletions
59
src/Test/TestCached.py
Normal file
59
src/Test/TestCached.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import time
|
||||||
|
|
||||||
|
from util import Cached
|
||||||
|
|
||||||
|
|
||||||
|
class CachedObject:
|
||||||
|
def __init__(self):
|
||||||
|
self.num_called_add = 0
|
||||||
|
self.num_called_multiply = 0
|
||||||
|
self.num_called_none = 0
|
||||||
|
|
||||||
|
@Cached(timeout=1)
|
||||||
|
def calcAdd(self, a, b):
|
||||||
|
self.num_called_add += 1
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
@Cached(timeout=1)
|
||||||
|
def calcMultiply(self, a, b):
|
||||||
|
self.num_called_multiply += 1
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
@Cached(timeout=1)
|
||||||
|
def none(self):
|
||||||
|
self.num_called_none += 1
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class TestCached:
|
||||||
|
def testNoneValue(self):
|
||||||
|
cached_object = CachedObject()
|
||||||
|
assert cached_object.none() is None
|
||||||
|
assert cached_object.none() is None
|
||||||
|
assert cached_object.num_called_none == 1
|
||||||
|
time.sleep(2)
|
||||||
|
assert cached_object.none() is None
|
||||||
|
assert cached_object.num_called_none == 2
|
||||||
|
|
||||||
|
def testCall(self):
|
||||||
|
cached_object = CachedObject()
|
||||||
|
|
||||||
|
assert cached_object.calcAdd(1, 2) == 3
|
||||||
|
assert cached_object.calcAdd(1, 2) == 3
|
||||||
|
assert cached_object.calcMultiply(1, 2) == 2
|
||||||
|
assert cached_object.calcMultiply(1, 2) == 2
|
||||||
|
assert cached_object.num_called_add == 1
|
||||||
|
assert cached_object.num_called_multiply == 1
|
||||||
|
|
||||||
|
assert cached_object.calcAdd(2, 3) == 5
|
||||||
|
assert cached_object.calcAdd(2, 3) == 5
|
||||||
|
assert cached_object.num_called_add == 2
|
||||||
|
|
||||||
|
assert cached_object.calcAdd(1, 2) == 3
|
||||||
|
assert cached_object.calcMultiply(2, 3) == 6
|
||||||
|
assert cached_object.num_called_add == 2
|
||||||
|
assert cached_object.num_called_multiply == 2
|
||||||
|
|
||||||
|
time.sleep(2)
|
||||||
|
assert cached_object.calcAdd(1, 2) == 3
|
||||||
|
assert cached_object.num_called_add == 3
|
68
src/util/Cached.py
Normal file
68
src/util/Cached.py
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class Cached(object):
|
||||||
|
def __init__(self, timeout):
|
||||||
|
self.cache_db = {}
|
||||||
|
self.timeout = timeout
|
||||||
|
|
||||||
|
def __call__(self, func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
key = "%s %s" % (args, kwargs)
|
||||||
|
cached_value = None
|
||||||
|
cache_hit = False
|
||||||
|
if key in self.cache_db:
|
||||||
|
cache_hit = True
|
||||||
|
cached_value, time_cached_end = self.cache_db[key]
|
||||||
|
if time.time() > time_cached_end:
|
||||||
|
self.cleanupExpired()
|
||||||
|
cached_value = None
|
||||||
|
cache_hit = False
|
||||||
|
|
||||||
|
if cache_hit:
|
||||||
|
return cached_value
|
||||||
|
else:
|
||||||
|
cached_value = func(*args, **kwargs)
|
||||||
|
time_cached_end = time.time() + self.timeout
|
||||||
|
self.cache_db[key] = (cached_value, time_cached_end)
|
||||||
|
return cached_value
|
||||||
|
|
||||||
|
wrapper.emptyCache = self.emptyCache
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
def cleanupExpired(self):
|
||||||
|
for key in list(self.cache_db.keys()):
|
||||||
|
cached_value, time_cached_end = self.cache_db[key]
|
||||||
|
if time.time() > time_cached_end:
|
||||||
|
del(self.cache_db[key])
|
||||||
|
|
||||||
|
def emptyCache(self):
|
||||||
|
num = len(self.cache_db)
|
||||||
|
self.cache_db.clear()
|
||||||
|
return num
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from gevent import monkey
|
||||||
|
monkey.patch_all()
|
||||||
|
|
||||||
|
@Cached(timeout=2)
|
||||||
|
def calcAdd(a, b):
|
||||||
|
print("CalcAdd", a, b)
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
@Cached(timeout=1)
|
||||||
|
def calcMultiply(a, b):
|
||||||
|
print("calcMultiply", a, b)
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
for i in range(5):
|
||||||
|
print("---")
|
||||||
|
print("Emptied", calcAdd.emptyCache())
|
||||||
|
assert calcAdd(1, 2) == 3
|
||||||
|
print("Emptied", calcAdd.emptyCache())
|
||||||
|
assert calcAdd(1, 2) == 3
|
||||||
|
assert calcAdd(2, 3) == 5
|
||||||
|
assert calcMultiply(2, 3) == 6
|
||||||
|
time.sleep(1)
|
|
@ -1,3 +1,4 @@
|
||||||
|
from .Cached import Cached
|
||||||
from .Event import Event
|
from .Event import Event
|
||||||
from .Noparallel import Noparallel
|
from .Noparallel import Noparallel
|
||||||
from .Pooled import Pooled
|
from .Pooled import Pooled
|
||||||
|
|
Loading…
Reference in a new issue