2006-03-12

How to handle object identity issues with decorators

People who have written decorators and tried to introspect them have discovered a slight problem: you end up introspecting the decorator instead of the decorated function. This is a problem since you usually want to introspect what was decorated; decorators are usually meant to be heard, not seen.

The common practice is to copy over __name__ and __doc__ from the decorated function to the decorator, and then to update the decorator's __dict__ with the decorated function's __dict__. This covers most basic issues, sans one: function parameters.

Most decorators have a signature of ``*args, **kwargs`` which does not help if the decorated function does not have the same function (which, let's face it, it probably doesn't). So, how do ou deal with this?

One possibility is introducing a __signature__ attribute. It would hold an object that represented the call signature that a function wanted to present to the world. This would allow help() along with the 'inspect' module to work off of the signature object that is set from the decorated function instead of the code object of the decorator. You get all the info you need to know about the call signature while not mutating any data about the decorator. I even have a rough PEP written and working Python code for the creation of the signature object (have not posted it after the burn-out from PEP 348 and 352 and I am just not in the mood to fight people on python-dev at the moment, although if people want to see if I can stick it online somewhere, maybe even c.l.py if I can ignore the feedback. =).

But the recent discussion on python-dev about adding a 'decorator' decorator that did the metadata update that I mentioned at the beginning made me realize that there is a problem with it: it mutates and erases perfectly valid metadata on the decorator. But what if we added something like __wraps__ or __metadata__ or something that pointed to the decorated function and that stuff like help() and 'inspect' used instead of the direct object the problem would be solved of introspecting on the right metadata all while without mutating and erasing legit metadata.

What do people think of all of this? Like the __signature__ idea? Think we need to go farther and introduce a __wraps__ attribute that points to what tools should introspect against? None of the above and I should go do my homework instead?