Mark decorated function as a hook to be picked up later.

    .. note::
        Currently only works with functions and instance methods. Class and
        static methods are not supported.

    :return: Decorated function if supplied, else this decorator with its args
        bound.

def set_hook(fn, key, **kwargs):
    """Mark decorated function as a hook to be picked up later.

    .. note::
        Currently only works with functions and instance methods. Class and
        static methods are not supported.

    :return: Decorated function if supplied, else this decorator with its args
        bound.
    """
    # Allow using this as either a decorator or a decorator factory.
    if fn is None:
        return functools.partial(set_hook, key=key, **kwargs)

    # Set a __marshmallow_hook__ attribute instead of wrapping in some class,
    # because I still want this to end up as a normal (unbound) method.
    try:
        hook_config = fn.__marshmallow_hook__
    except AttributeError:
        fn.__marshmallow_hook__ = hook_config = {}
    # Also save the kwargs for the tagged function on
    # __marshmallow_hook__, keyed by (<tag>, <pass_many>)
    hook_config[key] = kwargs

    return fn