Source code for indicator.cache
import cPickle
from datetime import datetime, date
from hashlib import sha1
from django.core.cache import cache
from django.db.models.query import QuerySet
from django.utils.translation import ugettext as _
from percentage import Percentage
from query_set_type import QuerySetType
STR_FUNCTIONS = {
int: str,
float: str,
datetime: str,
date: str,
bool: str,
dict: str,
}
"""A mapping of a type => function to
use to turn an object of this type
into a cache key
"""
CACHEABLE_TYPES = (int, float, datetime, \
date, bool, Percentage, dict)
"""Indicator output types that can be cached."""
def cache_simple(func, timeout=60*60*2):
[docs] """
:func:`cache_simple` is a decorator
for caching a function of a single
argument that returns a pickle-able
object
"""
def x(self):
cache_key = "Simple"+str(func.__name__)
# Look for the value in the cache
cached = cache.get(cache_key)
# Simple value is in the cache
if cached is not None:
print "Got cached value!"
# Cached value is a list of pks
return cached
# Value is not in the cache
# so generate the value
cache_val = func(self)
if cache_val is None:
raise ValueError(_("Cannot cache function that returns a value "\
"of None"))
# Get the pks in this queryset and pickle them
cache.set(cache_key, cache_val, timeout)
return cache_val
return x
def cache_indicator(cls, ind_func, period, data_in):
[docs] """
:func:`cache_indicator` is the function used
to cache return values of :class:`indicator.indicator.Indicator`.
:param cls: Indicator to cache
:type cls: subclass of :class:`indicator.indicator.Indicator`
:param ind_func: Function which generates the indicator value
:type ind_func: `function`
:param period: The time period with which to compute the
indicator value
:param data_in: The input data to the indicator
"""
# First, make sure we want to execute the caching logic
if not cls.cache:
print "skipping cache"
return ind_func(period, data_in)
if not cls.type_out in CACHEABLE_TYPES:
raise TypeError(_("Indicator with output type %s cannot be cached") % \
str(cls.type_out))
# Get the cache key from the function and arguments
cache_key_elms = [str(cls), cls.slug, \
str(period.start), str(period.end)]
if isinstance(cls.type_in, QuerySetType):
cache_key_elms.append("QuerySet")
cache_key_elms.append(str(type(data_in)))
cache_key_elms.append(str(data_in.model))
#cache_key_elms += [str(p[0]) for p in \
# data_in.order_by('pk').values_list('pk')]
cache_key_elms.append(repr(str(data_in.query)))
else:
cache_key_elms.append("Other")
func = STR_FUNCTIONS[cls.type_in]
cache_key_elms.append(func(data_in))
s = sha1()
for e in cache_key_elms:
s.update(e)
cache_key = s.hexdigest()
# Look for a cached value
cached = cache.get(cache_key)
if cached is not None:
print "Got cached indicator"
return cached
cache_val = ind_func(period, data_in)
if cache_val is None:
raise ValueError(_("Cannot cache function that returns a value "\
"of None"))
print "Saving in %s=%s" % (cache_key, str(cache_val))
cache.set(cache_key, cache_val, cls.valid_for)
return cache_val