'The @app.cached decorator caches the return value of the given handler.
This is useful if the handler is computationally expensive,
and often called with the same arguments (e.g., recursion).'

@property
def cached(self):

    def decorator(handler):
        def wrapper(*args, **kwargs):
            k = sorted(((k, v) for (k, v) in kwargs.items() if (not isinstance(v, Database))))
            k = (handler, pickle.dumps(args), pickle.dumps(k))
            if (len(self._cache) >= self._cached):
                self._cache.clear()
            if (k not in self._cache):
                self._cache[k] = handler(*args, **kwargs)
            return self._cache[k]
        return wrapper
    return decorator
