Full process to execute before, during and after actions.
    If func is specified, it will be called after exec_request_actions()
    unless a ContextExitException was raised. If render_func is specified,
    it will be called after exec_request_actions() only if there is no
    response. exec_after_request_actions() is always called.

def full_exec_request_actions(actions, func=None, render_func=None):
    """Full process to execute before, during and after actions.
    If func is specified, it will be called after exec_request_actions()
    unless a ContextExitException was raised. If render_func is specified,
    it will be called after exec_request_actions() only if there is no
    response. exec_after_request_actions() is always called.
    """
    response = None
    try:
        exec_before_request_actions(actions, catch_context_exit=False)
        exec_request_actions(actions, catch_context_exit=False)
        if func:
            response = func()
    except ContextExitException as e:
        response = e.result
    except ReturnValueException as e:
        response = e.value
    if render_func and response is None:
        response = render_func()
    return exec_after_request_actions(actions, response)