dek: the decorator-decorator
Project description
dek decorates your decorators to diminish defects and drudgery.
Writing a Python decorator which takes no parameters is easy.
But writing a decorator with parameters requires three nested levels of function and offers several opportunities for error - and more work if you want to decorate classes like unittest.mock.patch does.
dek is a decorator for decorators that does this deftly with a single tiny function.
EXAMPLE
Write a decorator print_before that prints a function’s arguments with an optional label before it executes.
Without dek all is confusion:
import functools
def print_before(label='label'):
def deferred(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print(label, args, kwargs)
return func(*args, **kwargs)
return wrapped
if callable(label):
return deferred(label)
return deferred
dek handles all the boilerplate:
import dek
@dek
def print_before(pfunc, label='debug'):
print(label, pfunc)
return pfunc()
For finer control over function signatures there is deferred mode:
@dek(defer=True)
def print_before(func, label='debug'):
def wrapped(foo, bar):
print(label, foo, bar)
return func(foo, bar)
return wrapped
NOTES:
This article talks more about decorators that take parameters and about dek in general.
For your advanced decorator problems, the PyPi module decorator does not duplicate duties that dek does, but does pretty anything else you could conceive of in a decorator library.
API
dek.dek(decorator, defer=False, methods=None)
Decorate a decorator so it works with or without parameters and can decorate all the members of a class.
- ARGUMENTS
- decorator
The function being decorated
- defer
Switch between “simple” and “defer” modes
- methods
What to do with class methods when wrapping a class
dek has two modes, simple and deferred. Simple mode, the default, is less work but offers less control.
In simple mode the trivial decorator, the decorator that does nothing, is trivial to write:
@dek
def trivial(pfunc):
return pfunc()
In this mode, decorator’s first argument is pfunc, a functools.partial() which bundles the original function together with its arguments.
Decorators with parameters aren’t much harder:
@dek
def print_before(pfunc, label='debug'):
print(label, pfunc)
return pfunc()
@print_before
def do_stuff(a, b='default'):
# do stuff
do_stuff(1)
# also prints 'debug do_stuff 1'
In deferred mode, decorator is a function that returns a function that does the work. This is more code but more flexible.
@dek(defer=True)
def trivial(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@dek(defer=True)
def print_before(func, label='label'):
def wrapper(foo, bar):
print(label, foo, bar)
return func(foo, bar)
return wrapper
The methods parameter describe how classes (as opposed to functions or methods) are decorated.
If methods is None then classes are decorated like any callable. If methods is _not_ None then classes are not decorated.
If methods is a string, then only methods whose names start with that string are decorated (which means that if methods is the empty string, that all methods are decorated).
If methods is a callable, then only methods that return true when passed to the callable are decorated.
If methods is True, then only public, non-magic methods - methods whose names do not start with _ - are decorated.
If methods is False, then methods are not decorated (and neither is the class).
(automatically generated by doks on 2020-07-15T12:00:02.300119)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.