Decorators ========== .. module:: funcy .. decorator:: decorator Transforms a flat wrapper into a decorator with or without arguments. ``@decorator`` passes special ``call`` object as a first argument to a wrapper. A resulting decorator will preserve function module, name and docstring. It also adds ``__wrapped__`` attribute referring to wrapped function and ``__original__`` attribute referring to innermost wrapped one. Here is a simple logging decorator:: @decorator def log(call): print(call._func.__name__, call._args, call._kwargs) return call() ``call`` object also supports by name arg introspection and passing additional arguments to decorated function:: @decorator def with_phone(call): # call.request gets actual request value upon function call request = call.request # ... phone = Phone.objects.get(number=request.GET['phone']) # phone arg is added to *args passed to decorated function return call(phone) @with_phone def some_view(request, phone): # ... some code using phone return # ... A better practice would be adding keyword argument not positional. This makes such decorators more composable:: @decorator def with_phone(call): # ... return call(phone=phone) @decorator def with_user(call): # ... return call(user=user) @with_phone @with_user def some_view(request, phone=None, user=None): # ... return # ... If a function wrapped with ``@decorator`` has arguments other than ``call``, then decorator with arguments is created:: @decorator def joining(call, sep): return sep.join(call()) Generally a decorator with arguments is required to be called with ``()`` when applied to function. However, if you use only keyword only parameters aside from ``call`` then you can omit them:: @decorator def rate_limit(call, *, extra_labels=None): # ... @rate_limit # no extra labels, parentheses are optional def func(request, ...): # ... @rate_limit(extra_labels=lambda r: [f"user:{r.user.pk}"]) def func(request, ...): # ... You can see more examples in :mod:`flow` and :mod:`debug` submodules source code. .. decorator:: contextmanager A decorator helping to create context managers. Resulting functions also behave as decorators. This is a reexport or backport of :func:`py3:contextlib.contextmanager`. .. autodecorator:: wraps(wrapped, [assigned], [updated]) .. autofunction:: unwrap .. autoclass:: ContextDecorator .. raw:: html :file: descriptions.html