""" Utilities related to caching. """ import cPickle as pickle import functools import zlib from xblock.core import XBlock def memoize_in_request_cache(request_cache_attr_name=None): """ Memoize a method call's results in the request_cache if there's one. Creates the cache key by joining the unicode of all the args with &; so, if your arg may use the default &, it may have false hits. Arguments: request_cache_attr_name - The name of the field or property in this method's containing class that stores the request_cache. """ def _decorator(func): """Outer method decorator.""" @functools.wraps(func) def _wrapper(self, *args, **kwargs): """ Wraps a method to memoize results. """ request_cache = getattr(self, request_cache_attr_name, None) if request_cache: cache_key = '&'.join([hashvalue(arg) for arg in args]) if cache_key in request_cache.data.setdefault(func.__name__, {}): return request_cache.data[func.__name__][cache_key] result = func(self, *args, **kwargs) request_cache.data[func.__name__][cache_key] = result return result else: return func(self, *args, **kwargs) return _wrapper return _decorator def hashvalue(arg): """ If arg is an xblock, use its location. otherwise just turn it into a string """ if isinstance(arg, XBlock): return unicode(arg.location) else: return unicode(arg) def zpickle(data): """Given any data structure, returns a zlib compressed pickled serialization.""" return zlib.compress(pickle.dumps(data, pickle.HIGHEST_PROTOCOL)) def zunpickle(zdata): """Given a zlib compressed pickled serialization, returns the deserialized data.""" return pickle.loads(zlib.decompress(zdata))