Return decorated function that caches the results.
505573
def cache_results(function):
    """"""
    def save_to_permacache():
        """Save the in-memory cache data to the permacache.

        There is a race condition here between two processes updating at the
        same time. It's perfectly acceptable to lose and/or corrupt the
        permacache information as each process's in-memory cache will remain
        in-tact.

        """
        update_from_permacache()
        try:
            with open(filename, 'wb') as fp:
                pickle.dump(cache, fp, pickle.HIGHEST_PROTOCOL)
        except IOError:
            pass  # Ignore permacache saving exceptions

    def update_from_permacache():
        """Attempt to update newer items from the permacache."""
        try:
            with open(filename, 'rb') as fp:
                permacache = pickle.load(fp)
        except Exception:  # TODO: Handle specific exceptions
            return  # It's okay if it cannot load
        for key, value in permacache.items():
            if key not in cache or value[0] > cache[key][0]:
                cache[key] = value

    cache = {}
    cache_expire_time = 3600
    try:
        filename = os.path.join(gettempdir(), 'update_checker_cache.pkl')
        update_from_permacache()
    except NotImplementedError:
        filename = None

    @wraps(function)
    def wrapped(obj, package_name, package_version, **extra_data):
        """Return cached results if available."""
        now = time.time()
        key = (package_name, package_version)
        if not obj.bypass_cache and key in cache:  # Check the in-memory cache
            cache_time, retval = cache[key]
            if now - cache_time < cache_expire_time:
                return retval
        retval = function(obj, package_name, package_version, **extra_data)
        cache[key] = now, retval
        if filename:
            save_to_permacache()
        return retval
    return wrapped
301094
def memoize(function):
    """"""
    _cache = {}
    @wraps(function)
    def wrapper(*args, **kwargs):
        key = str(args) + str(kwargs)
        if key not in _cache:
            _cache[key] = function(*args, **kwargs)
        return _cache[key]
    return wrapper
1263190
def memoize_methodcalls(func, pickle=False, dumps=pickle.dumps):
    '''
    '''
    cache = func._memoize_cache = {}
    @functools.wraps(func)
    def memoizer(self, *args, **kwargs):
        if pickle:
            key = dumps((args, kwargs))
        else:
            key = args
        if key not in cache:
            cache[key] = func(self, *args, **kwargs)
        return cache[key]
    return memoizer
897110
def cache(cls, key_attrs, expires=None):
        

        def decorator(func):

            @functools.wraps(func)
            def wrapper(self, *args, **kwargs):
                module = type(self).__module__
                classname = type(self).__name__
                method_name = func.__name__

                data = {}
                if isinstance(key_attrs, basestring):
                    _key_attrs = key_attrs.split()
                else:
                    _key_attrs = key_attrs
                for key_attr in _key_attrs:
                    key_value = getattr(self, key_attr)
                    if isinstance(key_value, dict):
                        key_value = ('dict', sorted(key_value.items()))
                    elif isinstance(key_value, set):
                        key_value = ('set', sorted(key_value))
                    else:
                        key_value = (type(key_value).__name__, key_value)
                    data[key_attr] = key_value
                data = sorted(data.items())

                result_cache, new = cls.get_or_create(
                    module=module,
                    classname=classname,
                    method_name=method_name,
                    data=data,
                    args=args,
                    kwargs=sorted(kwargs.items()),
                )

                if new:
                    result_cache.result = func(self, *args, **kwargs)
                    result_cache.save(expires)

                return result_cache.result

            return wrapper

        return decorator
1147866
def get_func_result_cachekey(func_, args_=tuple(), kwargs_={}):
    
    import utool as ut
    # Rectify partials and whatnot
    true_args = args_
    true_kwargs = kwargs_
    true_func = func_
    if isinstance(func_, partial):
        true_func = func_.func
        if func_.args is not None:
            true_args = tuple(list(func_.args) + list(args_))
        if func_.keywords is not None:
            true_kwargs.update(func_.keywords)

    if ut.is_method(true_func):
        method = true_func
        true_func = method.im_func
        self = method.im_self
        true_args = tuple([self] + list(true_args))

    # Build up cachekey
    funcname = ut.get_funcname(true_func)
    kwdefaults = ut.get_kwdefaults(true_func, parse_source=False)
    #kwdefaults = ut.get_kwdefaults(true_func, parse_source=True)
    argnames   = ut.get_argnames(true_func)
    key_argx = None
    key_kwds = None
    func = true_func  # NOQA
    args = true_args  # NOQA
    kwargs = true_kwargs  # NOQA
    args_key = ut.get_cfgstr_from_args(true_func, true_args, true_kwargs,
                                       key_argx, key_kwds, kwdefaults,
                                       argnames)
    cachekey = funcname + '(' + args_key + ')'
    return cachekey
649541
def memoize(func):
    

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        """ wrap it up and store info in a cache """
        cache = args[0].memoized
        refresh = args[0].refresh_interval
        use_cache = args[0].use_cache

        # short circuit if not using cache
        if use_cache is False:
            return func(*args, **kwargs)

        if func.__name__ not in cache:
            cache[func.__name__] = dict()
            if "defaults" not in cache:
                cache["defaults"] = dict()
            cache["defaults"][func.__name__] = parse_all_arguments(func)
        # build a key; should also consist of the default values
        defaults = cache["defaults"][func.__name__].copy()
        for key, val in kwargs.items():
            defaults[key] = val
        tmp = list()
        tmp.extend(args[1:])
        for k in sorted(defaults.keys()):
            tmp.append("({0}: {1})".format(k, defaults[k]))

        # handle possible unicode characters
        if sys.version_info < (3, 0):
            tmp = [unicode(x) for x in tmp]
        key = " - ".join(tmp)

        # set the value in the cache if missing or needs to be refreshed
        if key not in cache[func.__name__]:
            cache[func.__name__][key] = (time.time(), func(*args, **kwargs))
        else:
            tmp = cache[func.__name__][key]
            # determine if we need to refresh the data...
            if refresh is not None and time.time() - tmp[0] > refresh:
                cache[func.__name__][key] = (time.time(), func(*args, **kwargs))
        return cache[func.__name__][key][1]

    return wrapper
358465
def update_cache(func):
    
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        """The wrapper function."""
        lazy = kwargs.get('lazy', False)
        kwargs.pop('lazy', None)

        if not lazy:
            self.get_json()

        ret = func(self, *args, **kwargs)

        # If returning a string assume it is an update message
        if isinstance(ret, str) and not lazy:
            self.set_json(ret)
        else:
            return ret

    return wrapper
519848
def cached_generator(function):
    """"""
    cache_variable = '_cached_' + function.__name__
    @wraps(function)
    def function_wrapper(obj, *args, **kwargs):
        # values are cached in a list stored in the object
        try:
            for item in getattr(obj, cache_variable):
                yield item
        except AttributeError:
            setattr(obj, cache_variable, [])
            cache = getattr(obj, cache_variable)
            for item in function(obj, *args, **kwargs):
                cache.append(item)
                yield item
    return function_wrapper
1200996
def methods(*meth):
    
    def decorator(f):
        if not hasattr(f, '_methods_cache'):
            f._methods_cache = [m.upper() for m in meth]
        return f
    return decorator
78289
def cache(*args, **kwargs):
    
    ## only one argument ?
    if len(args) == 1 and len(kwargs) == 0 and \
           (callable(args[0]) or \
            isinstance(args[0], tuple(SUPPORTED_DECORATOR.keys()))):
        return _cache_w_args(args[0])
    return lambda f: _cache_w_args(f, *args, **kwargs)
1171078
def cached_accessor(func_or_att):
    """"""
    if callable(func_or_att): #allows decorator to be called without arguments
        att = func_or_att.__name__
        return cached_accessor(func_or_att.__name__)(func_or_att)
    att = func_or_att
    def make_cached_function(func):
        @wraps(func)
        def cached_check_version(self):
            private_att = '_'+att
            if getattr(self, private_att):
                return getattr(self, private_att)
            setattr(self, private_att, self.load_key(att))
            if getattr(self, private_att):
                return getattr(self, private_att)
            value = func(self)
            setattr(self, private_att, value)
            self.save_key(att, value)
            return value
        return cached_check_version
    return make_cached_function
493859
def memoize(f):
    
    cache = {}

    @wraps(f)
    def inner(arg):
        if arg not in cache:
            cache[arg] = f(arg)
        return cache[arg]
    return inner
1230600
def cachedproperty(func):
    """"""
    key = '_' + func.__name__
    @wraps(func)
    def get(self):
        try:
            return getattr(self, key)
        except AttributeError:
            val = func(self)
            setattr(self, key, val)
            return val
    return property(get)
758523
def cachedmethod(cache, key=keys.hashkey, lock=None):
    
    def decorator(method):
        if lock is None:
            def wrapper(self, *args, **kwargs):
                c = cache(self)
                if c is None:
                    return method(self, *args, **kwargs)
                k = key(*args, **kwargs)
                try:
                    return c[k]
                except KeyError:
                    pass  # key not found
                v = method(self, *args, **kwargs)
                try:
                    c[k] = v
                except ValueError:
                    pass  # value too large
                return v
        else:
            def wrapper(self, *args, **kwargs):
                c = cache(self)
                if c is None:
                    return method(self, *args, **kwargs)
                k = key(*args, **kwargs)
                try:
                    with lock(self):
                        return c[k]
                except KeyError:
                    pass  # key not found
                v = method(self, *args, **kwargs)
                try:
                    with lock(self):
                        c[k] = v
                except ValueError:
                    pass  # value too large
                return v
        return _update_wrapper(wrapper, method)
    return decorator
345093
def cached(f):
    

    cache = f.cache = {}

    @functools.wraps(f)
    def decorator(*args, **kwargs):
        key = str(args) + str(kwargs)
        if key not in cache:
            cache[key] = f(*args, **kwargs)
        return cache[key]
    return decorator
320973
def evaluate_cached(self, **kwargs):
        """"""
        if not hasattr(self, 'result'):
            self.result = self.evaluate(cache=True, **kwargs)

        return self.result
460900
def cached(function):
    """"""
    cache_variable = '_cached_' + function.__name__
    @wraps(function)
    def function_wrapper(obj, *args, **kwargs):
        # values are cached in a dict stored in the object
        try:
            cache = getattr(obj, cache_variable)
        except AttributeError:
            cache = {}
            setattr(obj, cache_variable, cache)
        args_kwargs = args + tuple(kwargs.values())
        try:
            return cache[args_kwargs]
        except KeyError:
            cache_value = function(obj, *args, **kwargs)
            cache[args_kwargs] = cache_value
            return cache_value
    return function_wrapper