def memoize()

in Allura/allura/lib/decorators.py [0:0]


def memoize(func, instance, args, kwargs):
    """
    Cache the method's result, for the given args
    """
    if instance is None:
        # decorating a simple function
        dic = getattr_(func, "_memoize_dic", dict)
    else:
        # decorating a method
        dic = getattr_(instance, f"_memoize_dic__{func.__name__}", dict)

    cache_key = (args, frozenset(list(kwargs.items())))
    if cache_key in dic:
        return dic[cache_key]
    else:
        result = func(*args, **kwargs)
        dic[cache_key] = result
        return result


def memoize_cleanup(obj):
    """
    Remove any _memoize_dic_* keys that were created by @memoize on methods
    """
    attrs = obj.keys() if hasattr(obj, 'keys') else obj.__dir__()
    for k in list(attrs):
        if k.startswith('_memoize_dic'):
            try:
                del obj[k]
            except TypeError:
                delattr(obj, k)


def memorable_forget():
    """
    Decorator to mark a controller action as needing to "forget" remembered input values on the next
    page render, if we detect that the form post was processed successfully
    """

    def _ok_to_forget(response, controller_result, raised):
        """
        Look for signals that say it's probably ok to forget remembered inputs for the current form.
        Checks here will need to be expanded for controller actions that behave differently
        than others upon successful processing of their particular request
        """
        # if there is a flash message with status "ok", then we can forget.  If it is "error" we cannot.
        if response.headers:
            cookies = Cookie(response.headers.get('Set-Cookie', ''))
            if cookies and 'webflash' in cookies:
                webflash_value = json.loads(unquote(cookies['webflash'].value))
                if webflash_value['status'] == 'ok':
                    return True
                elif webflash_value['status'] == 'error':
                    return False

        # if the controller raised a 302, we can assume the value will be remembered by the app
        # if needed, and forget.
        if raised and isinstance(raised, HTTPFound):
            return True

        return False

    def forget(controller_result, raised=None):
        """
        Check if the form's inputs can be forgotten, and set the cookie to forget if so.
        :param res: the result of the controller action
        :param raised: any error (redirect or exception) raised by the controller action