Michele Simionato
unread,May 23, 2012, 2:21:35 AM5/23/12You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
Python 3.2 enhanced contextlib.contextmanager so that it is possible to
use a context manager as a decorator. For instance, given the
contextmanager factory below
@contextmanager
def before_after():
print(before)
yield
print(after)
it is possibile to use it to generate decorators:
@before_after()
def hello(user):
print('hello', user)
This is equivalent to the more traditional
def hello(user):
with before_after():
print('hello', user)
but it has the advantage of saving a level of indentation and we all
know that flat is better than nested. Cool, but there are three issues:
1. I am using Python 2.7, not Python 3.2, so contextmanager has not such feature
2. The contextmanager decorator is losing the signature of the before_after factory:
>>> help(before_after)
Help on function before_after in module __main__:
before_after(*args, **kwds)
3. before_after() decorators do not preserve the signature of the decorated function either.
Since I am the author of the decorator module I have easily found out a recipe to solve both issues. Here it is:
from decorator import decorator, FunctionMaker
from contextlib import GeneratorContextManager
class GeneratorCM(GeneratorContextManager):
def __call__(self, func):
return FunctionMaker.create(
func, "with _cm_: return _func_(%(shortsignature)s)",
dict(_cm_=self, _func_=func), __wrapped__=func)
@decorator
def contextmanager(func, *args, **kwds):
return GeneratorCM(func(*args, **kwds))
before_after() objects obtained by using this version of
contextmanager become signature-preserving decorators. I am not going
to explain how FunctionMaker performs its magic (hint: it uses eval),
but I am asking a question instead: should I add this feature to the
next release of the decorator module? Do people use the
context-manager-as-decorator functionality? It is quite handy in unit
tests and actually I think it came from the unittest2 module. But I am
reluctant to complicate the API of the module, which currently is
really really small and such has been for many years.