def optional_args(decorator):
    'allows a decorator to take optional positional and keyword arguments.\n        Assumes that taking a single, callable, positional argument means that\n        it is decorating a function, i.e. something like this::\n\n            @my_decorator\n            def function(): pass\n\n        Calls decorator with decorator(f, `*args`, `**kwargs`)'

    @better_wraps(decorator)
    def wrapper(*args, **kwargs):

        def dec(f):
            return decorator(f, *args, **kwargs)
        is_decorating = ((not kwargs) and (len(args) == 1) and isinstance(args[0], Callable))
        if is_decorating:
            f = args[0]
            args = []
            return dec(f)
        else:
            return dec
    return wrapper
allows a decorator to take optional positional and keyword arguments.
Assumes that taking a single, callable, positional argument means that
it is decorating a function, i.e. something like this::

    @my_decorator
    def function(): pass

Calls decorator with decorator(f, `*args`, `**kwargs`)
def optional_args(decorator):
    'allows a decorator to take optional positional and keyword arguments.\n        Assumes that taking a single, callable, positional argument means that\n        it is decorating a function, i.e. something like this::\n\n            @my_decorator\n            def function(): pass\n\n        Calls decorator with decorator(f, `*args`, `**kwargs`)'

    @better_wraps(decorator)
    def wrapper(*args, **kwargs):

        def dec(f):
            return decorator(f, *args, **kwargs)
        is_decorating = ((not kwargs) and (len(args) == 1) and isinstance(args[0], Callable))
        if is_decorating:
            f = args[0]
            args = []
            return dec(f)
        else:
            return dec
    return wrapper