Commits

Anonymous committed 1c60d0a

Add buffering and caching property descriptors

  • Participants
  • Parent commits c02f1a3

Comments (0)

Files changed (1)

File gnocchi/tools/cache.py

+'''Buffering and Caching Descriptors'''
+import functools
+from django.core.cache import get_cache
+import pickle
+
+class buffered_property(object):
+    '''Buffer the result of a method on the class instance'''
+    def __init__(self, getter):
+        functools.update_wrapper(self, getter)
+        self.getter = getter
+        self.propname = '__cache__%s' % getter.__name__
+
+    def __get__(self, instance, owner):
+        if not hasattr(instance, self.propname):
+            setattr(instance, self.propname, self.getter(instance))
+        return getattr(instance, self.propname)
+
+    def __delete__(self, instance):
+        delattr(instance, self.propname)
+
+class _cached_property(object):
+    '''Cache the result of a method in the Django cache'''
+    def __init__(self, getter, backend='default', timeout=False,
+        use_pickle=False):
+        '''Get values from cache'''
+        functools.update_wrapper(self, getter)
+        self.getter = getter
+        self.timeout = timeout
+        self.pickle = use_pickle
+        self.cache = get_cache(backend)
+
+    def _make_key(self, instance):
+        '''Build the cache key to use'''
+        parts = [instance.__class__.__name__]
+        if hasattr(instance, '_meta'):
+            # If this looks like a Model, use app label and pk
+            parts.insert(0, instance._meta.app_label)
+            parts.append(str(instance.pk))
+        parts.append(self.__name__)
+        return ':'.join(parts)
+
+    def __get__(self, instance, owner):
+        key = self._make_key(instance)
+        value = self.cache.get(key)
+        if value is None:
+            value = self.getter(instance)
+            if self.pickle:
+                value = pickle.dumps(value)
+            self.cache.set(key, value, self.timeout)
+        if self.pickle:
+            value = pickle.loads(value)
+        return value
+
+    def __delete__(self, instance):
+        key = self._make_key(instance)
+        self.cache.delete(key)
+
+def cached_property(func=None, backend='default', timeout=False, use_pickle=False):
+    if func is None:
+        return functools.partial(cached_property,
+            backend=backend,
+            timeout=timeout,
+            use_pickle=use_pickle
+        )
+    return _cached_property(func, backend=backend, timeout=timeout,
+        use_pickle=use_pickle)