1# Example use - Decorator code below -----------------------------
2import time
3
4@cache(ttl=timedelta(minutes=3), max_entries=300)
5def add(a, b):
6 time.sleep(2)
7 return a + b
8
9@cache()
10def substract(a, b):
11 time.sleep(2)
12 return a - b
13
14
15# Decorator code -----------------------------
16from datetime import datetime, timedelta
17
18def cache(**kwargs):
19 def decorator(function):
20 # static function variable for cache, lazy initialization
21 try: function.cache
22 except: function.cache = {}
23 def wrapper(*args):
24 # if nothing valid in cache, insert something
25 if not args in function.cache or datetime.now() > function.cache[args]['expiry']:
26 if 'max_entries' in kwargs:
27 max_entries = kwargs['max_entries']
28 if max_entries != None and len(function.cache) >= max_entries:
29 now = datetime.now()
30 function.cache = { key: function.cache[key] for key in function.cache.keys() if function.cache[key]['expiry'] > now }
31 # if nothing is expired that is deletable, delete the first
32 if len(function.cache) >= max_entries:
33 del function.cache[next(iter(function.cache))]
34 function.cache[args] = {'result': function(*args), 'expiry': datetime.max if 'ttl' not in kwargs else datetime.now() + kwargs['ttl']}
35
36 # answer from cache
37 return function.cache[args]['result']
38 return wrapper
39 return decorator
40