Each item can be an action name as a string or a dict. When using a dict,
    one key/item pair must be the action name and its options and the rest action
    decorator names and their options.
    Example:
        load_actions(["login_required", {"flash": {"message": "hello world", "label": "warning"}}])

def load_actions(spec, group=None, expr_parser=None):
    """Each item can be an action name as a string or a dict. When using a dict,
    one key/item pair must be the action name and its options and the rest action
    decorator names and their options.
    Example:
        load_actions(["login_required", {"flash": {"message": "hello world", "label": "warning"}}])
    """
    if expr_parser is None:
        expr_parser = ExpressionParser()
    actions = ActionList()

    for name in spec:
        options = {}
        as_ = None
        decorators = []

        if isinstance(name, dict):
            actionspec = dict(name)
            as_ = actionspec.pop("as", None)
            for dec, dec_cls in action_decorators:
                if dec in actionspec:
                    decorators.append((dec_cls, expr_parser.compile(actionspec.pop(dec))))
            name, options = actionspec.popitem()
            if options:
                options = expr_parser.compile(options)

        if isinstance(name, Action):
            action = name
        elif isinstance(name, ActionFunction):
            action = name.action
        else:
            action = action_resolver.resolve_or_delayed(name, options, group, as_)

        for dec_cls, arg in decorators:
            action = dec_cls(action, arg)

        actions.append(action)

    return actions