From https://guneysu.firebaseapp.com/node/2404/ (http://blog.teknikprogramlama.net/en/node/2404 is broken)
def func_hash(*args, **kwargs):
def hash_args(*args):
"""docstring for main"""
hlist = []
for v in sorted(args):
if hasattr(v, '__iter__'):
result = {
'tuple': lambda: v,
'list': lambda: tuple(sorted(v)),
'dict': lambda: tuple(sorted(v.items()))
}[type(v).__name__]()
hlist.append(result)
else:
hlist.append(v)
return hash(tuple(hlist))
def hash_kwargs(**kwargs):
"""docstring for main"""
hlist = []
for k, v in sorted(kwargs.iteritems()):
if hasattr(v, '__iter__'):
result = {
'tuple': lambda: v,
'list': lambda: tuple(sorted(v)),
'dict': lambda: tuple(sorted(v.items()))
}[type(v).__name__]()
hlist.append(result)
else:
hlist.append((k, v))
return hash(tuple(hlist))
return str(hash_kwargs(**kwargs) + hash_args(*args))
class cache(object):
# TODO expire='1d at 00:00'
# call with @cache(expire=\d+s|m|h|d|w @00:00)
def __init__(self, func, expire=None):
self.func = func
for name in set(dir(func)) - set(dir(self)):
setattr(self, name, getattr(func, name))
def __call__(self, *args, **kwargs):
self.key = func_hash(*args, **kwargs)
if self.is_cached():
logging.warning(
'>>>>> Serving from cache for key :\t %s' % self.key)
return self.cache_data()
else:
# call function to get data
data = self.func(*args, **kwargs)
# Put this data to memcache
memcache.set(self.key, data, time=60 * 60 * 24)
# Return function
return self.func(*args, **kwargs)
return self.func(*args, **kwargs) # OK
def is_cached(self):
data = memcache.get(self.key)
return data is not None
def cache_data(self, *args, **kwargs):
# data = self.func(*args, **kwargs)
return memcache.get(self.key)