A decorator that facilitates authentication per method. Setting
    C{expose_request} to C{True} will set the underlying request object (if
    there is one), usually HTTP and set it to the first argument of the
    authenticating callable. If there is no request object, the default is
    C{None}.

    @raise TypeError: C{func} and authenticator must be callable.

def authenticate(func, c, expose_request=False):
    """
    A decorator that facilitates authentication per method. Setting
    C{expose_request} to C{True} will set the underlying request object (if
    there is one), usually HTTP and set it to the first argument of the
    authenticating callable. If there is no request object, the default is
    C{None}.

    @raise TypeError: C{func} and authenticator must be callable.
    """
    if not python.callable(func):
        raise TypeError('func must be callable')

    if not python.callable(c):
        raise TypeError('Authenticator must be callable')

    attr = func

    if isinstance(func, types.UnboundMethodType):
        attr = func.im_func

    if expose_request is True:
        c = globals()['expose_request'](c)

    setattr(attr, '_pyamf_authenticator', c)

    return func