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

def optional_args ( decorator ) : @ wraps ( decorator ) def wrapper ( * args , ** kwargs ) : def dec ( f ) : return decorator ( f , * args , ** kwargs ) is_decorating = ( ( not kwargs ) and ( len ( args ) == 1 ) and callable ( args [ 0 ] ) ) 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 .