blob: b7f9e6cccfda49cfae79f0e34321f3665c82ab76 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
class PropertyCache(object):
""" Mixin class providing a simple cache. """
def __init__(self):
self._cache = {}
def _try_cache(self, cache_key, cache_populate_func):
""" Tries to get a value from the cache identified by `cache_key`.
If no value is found in the cache, do a function call to `cache_populate_func` to populate the cache
and then return the value from the cache. """
if cache_key not in self._cache:
cache_populate_func()
return self._cache[cache_key]
def cache(original_func=None, cachekey=None):
""" Cache decorator. Caches function return values.
Requires the parent class to extend and initialize PropertyCache.
Usage:
# Use function name as cache key
@cache
def myfunc(args):
...
# Specify cache key
@cache(cachekey="foobar")
def myfunc(args):
...
"""
# Decorators with optional arguments are a bit convoluted in python, especially if you want to support both
# Python 2 and 3. See some of the links below for details.
def cache_decorator(func):
# If no specific cache key is given, use the function name as cache key
if not cache_decorator.cachekey:
cache_decorator.cachekey = func.__name__
def wrapped(*args):
def cache_func_result():
# Call decorated function and store its result in the cache
args[0]._cache[cache_decorator.cachekey] = func(*args)
return args[0]._try_cache(cache_decorator.cachekey, cache_func_result)
return wrapped
# Passing parent function variables to child functions requires special voodoo in python2:
# https://stackoverflow.com/a/14678445/381010
cache_decorator.cachekey = cachekey # attribute on the function
# To support optional kwargs for decorators, we need to check if a function is passed as first argument or not.
# https://stackoverflow.com/a/24617244/381010
if original_func:
return cache_decorator(original_func)
return cache_decorator
|