I'm using a decorator(@render_to
from the django_annoying
package) in a view function.
But the thing is that I wanted to get the original dict that is returned by the view function for test purposes, instead of the HttpResponse
object that the decorator returns.
The decorator uses @wraps
(from functools
).
If there is no way to access this, then do you have any idea of how to test this?
The wrapped function will be available as a function closure cell. Which cell exactly depends on how many closure variables there are.
For a simple wrapper where the only closure variable is the function-to-wrap, it'll be the first one:
wrapped = decorated.func_closure[0].cell_contents
but you may have to inspect all func_closure
values.
Demo using the functools.wraps()
example decorator:
>>> from functools import wraps
>>> def my_decorator(f):
... @wraps(f)
... def wrapper(*args, **kwds):
... print 'Calling decorated function'
... return f(*args, **kwds)
... return wrapper
...
>>> @my_decorator
... def example():
... """Docstring"""
... print 'Called example function'
...
>>> example
<function example at 0x107ddfaa0>
>>> example.func_closure
(<cell at 0x107de3d70: function object at 0x107dc3b18>,)
>>> example.func_closure[0].cell_contents
<function example at 0x107dc3b18>
>>> example()
Calling decorated function
Called example function
>>> example.func_closure[0].cell_contents()
Called example function
Looking at the source code for @render_to
you don't have to worry about this though; the wrapped function will be stored in the first closure slot, guaranteed.
If this was Python 3 instead, the wrapped function can be accessed with the __wrapped__
attribute instead:
>>> example.__wrapped__
<function example at 0x103329050>
And if you had access to the decorator code itself, you can easily add that same reference in Python 2 code too:
def my_decorator(f):
@wraps(f)
def wrapper(*args, **kwds):
# implementation
wrapper.__wrapped__ = f
return wrapper
making introspection just that little bit easier.