Skip to content
Snippets Groups Projects
Commit e76d485e authored by Paul "LeoNerd" Evans's avatar Paul "LeoNerd" Evans
Browse files

Allow @cached-wrapped functions to have a prefill method for setting entries

parent 4631b737
Branches
Tags
No related merge requests found
...@@ -48,24 +48,30 @@ def cached(max_entries=1000): ...@@ -48,24 +48,30 @@ def cached(max_entries=1000):
The wrapped function has an additional member, a callable called The wrapped function has an additional member, a callable called
"invalidate". This can be used to remove individual entries from the cache. "invalidate". This can be used to remove individual entries from the cache.
The wrapped function has another additional callable, called "prefill",
which can be used to insert values into the cache specifically, without
calling the calculation function.
""" """
def wrap(orig): def wrap(orig):
cache = {} cache = {}
@defer.inlineCallbacks def prefill(key, value):
def wrapped(self, key):
if key in cache:
defer.returnValue(cache[key])
ret = yield orig(self, key)
while len(cache) > max_entries: while len(cache) > max_entries:
# TODO(paul): This feels too biased. However, a random index # TODO(paul): This feels too biased. However, a random index
# would be a bit inefficient, walking the list of keys just # would be a bit inefficient, walking the list of keys just
# to ignore most of them? # to ignore most of them?
del cache[cache.keys()[0]] del cache[cache.keys()[0]]
cache[key] = ret; cache[key] = value
@defer.inlineCallbacks
def wrapped(self, key):
if key in cache:
defer.returnValue(cache[key])
ret = yield orig(self, key)
prefill(key, ret)
defer.returnValue(ret) defer.returnValue(ret)
def invalidate(key): def invalidate(key):
...@@ -73,6 +79,7 @@ def cached(max_entries=1000): ...@@ -73,6 +79,7 @@ def cached(max_entries=1000):
del cache[key] del cache[key]
wrapped.invalidate = invalidate wrapped.invalidate = invalidate
wrapped.prefill = prefill
return wrapped return wrapped
return wrap return wrap
......
...@@ -87,3 +87,17 @@ class CacheDecoratorTestCase(unittest.TestCase): ...@@ -87,3 +87,17 @@ class CacheDecoratorTestCase(unittest.TestCase):
self.assertTrue(callcount[0] >= 14, self.assertTrue(callcount[0] >= 14,
msg="Expected callcount >= 14, got %d" % (callcount[0])) msg="Expected callcount >= 14, got %d" % (callcount[0]))
@defer.inlineCallbacks
def test_prefill(self):
callcount = [0]
@cached()
def func(self, key):
callcount[0] += 1
return key
func.prefill("foo", 123)
self.assertEquals((yield func(self, "foo")), 123)
self.assertEquals(callcount[0], 0)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment