Message 32574 - Python tracker (original) (raw)

Here is the issue:

$ cat example.py import functools # I am using Python 2.5

def identity_dec(func): def wrapper(*args, **kw): return func(*args, **kw) return functools.update_wrapper(wrapper, func)

@identity_dec def example(): pass

import inspect from example import example print inspect.getsource(example) def wrapper(*args, **kw): return func(*args, **kw)

You get the source code of the closure and not what would be more meaningful, i.e. the string

""" @identity_dec def example(): pass """

Of course one could argue that this is not a bug (in a sense the inspect module is doing the right thing) but still it is giving information which is not very useful.

Looking at the guts of inspect.getsource, one discovers the origin of the problem: inspect.findsource is looking at the attribute .co_firstlineno of the decorated function code object. Unfortunately .co_firstlineno is a read-only attribute, otherwise it would be possibile to change functools.update_wrapper to set it to the correct line number (i.e. the line where the undecorated function is defined, -1). So I don't think you can fix this in current Python, but it is something to keep in mind for Python 2.6 and 3.0. It should also manage classmethods/ staticmethods and other decorators not implemented as closures.