Skip to content

Instantly share code, notes, and snippets.

@rrafal
Last active September 21, 2023 07:49
Show Gist options
  • Save rrafal/3f7296c03df9a9fa645f to your computer and use it in GitHub Desktop.
Save rrafal/3f7296c03df9a9fa645f to your computer and use it in GitHub Desktop.
Util for making it easier to write decorators
import functools
def kwargs_decorator(decorator):
""" Allows to easily create docorators with optional keyword argument.
Decorator must not be called with positional arguments.
"""
@functools.wraps(decorator)
def wrapper(wrapped=None, **kwargs):
if wrapped is None:
return lambda f: functools.wraps(f)(decorator(f, **kwargs))
else:
assert callable(wrapped)
return functools.wraps(wrapped)(decorator(wrapped))
return wrapper
def smart_decorator(decorator):
""" Allows to easily create docorators with arguments, without arguments and with optional arguemnts.
Does not work with decorators that take a single callable argument.
"""
@functools.wraps(decorator)
def smart_wrapper(*args, **kwargs):
if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
# single callable argument was passed; assume decorator had no arguments and this is the decorated function
return functools.wraps(args[0])(decorator(args[0]))
else:
# decorator has arguments
return lambda f: functools.wraps(f)(decorator(f, *args, **kwargs))
return smart_wrapper
@kwargs_decorator
def log_calls(f, msg='Calling: '):
def wrapper(*args, **kwargs):
print "%s %s" % (msg, f.__name__)
return f(*args, **kwargs)
return wrapper
@log_calls
def multiply(a, b):
return a * b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment