Skip to content
Snippets Groups Projects
caching.py 3 KiB
Newer Older
mads's avatar
mads committed
'''
Created on 07/02/2014

@author: MMPE
'''
from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future import standard_library
Mads M. Pedersen's avatar
Mads M. Pedersen committed
import sys
standard_library.install_aliases()
mads's avatar
mads committed
import inspect

def set_cache_property(obj, name, get_func, set_func=None):
    """Create a cached property

    Parameters
    ----------
    obj : object
        Class to add property to
    name : str
        Name of property
    get_func : func
        Getter function
    set_func : func, optional
        Setter function

    Examples
    --------
    >>> class Example(object):
    >>>     def __init__(self):
    >>>        set_cache_property(self, "test", self.slow_function)
    >>>
    >>> e = Example()
    >>> e.test # Call, store and return result of e.slow_function
    >>> e.test # Return stored result of e.slow_function
    >>> e._test = None # clear cache result
    >>> e.test # Call, store and return result of e.slow_function
mads's avatar
mads committed
    """
    _name = "_" + name
    setattr(obj, _name, None)
    def get(self):
        if getattr(obj, _name) is None:
            setattr(obj, _name, get_func())
        return getattr(obj, _name)

    p = property(lambda self:get(self), set_func)
    return setattr(obj.__class__, name, p)

def cache_function(f):
    """Cache function decorator

    Example:
    >>> class Example(object):
    >>>    @cache_function
    >>>    def slow_function(self):
    >>>        # calculate slow result
    >>>        return 1
    >>>
    >>> e = Example()
    >>> e.slow_function() # Call, store and return result of e.slow_function
    >>> e.slow_function() # Return stored result of e.slow_function
    """
    def wrap(*args, **kwargs):
        self = args[0]
        name = "_" + f.__name__
        if not hasattr(self, name) or getattr(self, name) is None or kwargs.get("reload", False):
            try:
                del kwargs['reload']
            except KeyError:
                pass
            # ======HERE============
            setattr(self, name, f(*args, **kwargs))
            # ======================
            if not hasattr(self, "cache_attr_lst"):
                self.cache_attr_lst = set()
                def clear_cache():
                    for attr in self.cache_attr_lst:
                        delattr(self, attr)
                    self.cache_attr_lst = set()
                self.clear_cache = clear_cache
            self.cache_attr_lst.add(name)

        return getattr(self, name)
Mads M. Pedersen's avatar
Mads M. Pedersen committed
    version = sys.version_info
    if version >= (3,3):
        if 'reload' in inspect.signature(f).parameters.values():
            raise AttributeError("Functions decorated with cache_function are not allowed to take a parameter called 'reload'")
    elif 'reload' in inspect.getargspec(f)[0]:
mads's avatar
mads committed
        raise AttributeError("Functions decorated with cache_function are not allowed to take a parameter called 'reload'")
    return wrap