synr icon indicating copy to clipboard operation
synr copied to clipboard

inspect.getsourcelines is wrong

Open altanh opened this issue 2 years ago • 1 comments

The behavior of inspect.getsourcelines is incorrect for different classes with the same name (defined in different scopes). Observe the following excerpt from inspect.findsource (used by getsourcelines internally):

    if isclass(object):
        name = object.__name__
        pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
        # make some effort to find the best matching class definition:
        # use the one with the least indentation, which is the one
        # that's most probably not inside a function definition.
        candidates = []
        for i in range(len(lines)):
            match = pat.match(lines[i])
            if match:
                # if it's at toplevel, it's already the best one
                if lines[i][0] == 'c':
                    return lines, i
                # else add whitespace to candidate list
                candidates.append((match.group(1), i))
        if candidates:
            # this will sort by whitespace, and by line number,
            # less whitespace first
            candidates.sort()
            return lines, candidates[0][1]

In other words, it returns the source for the "best" matching class definition instead of the correct class definition. So, code like this would break:

def foo():
    class Baz: ...
    ast = synr.to_ast(Baz)

def bar():
    class Baz: ... # something different
    ast = synr.to_ast(Baz)  # this will parse the first Baz in foo

Not sure there's an easy solution. We could do our own check that there aren't multiple classes with the same name in a source file and error out if there is (to be conservative). inspect should really have a disclaimer somewhere in the visible documentation for this, or implement a correct solution (perhaps using the __qualname__ field of the class).

altanh avatar Oct 08 '21 19:10 altanh

this is related https://github.com/python/cpython/pull/10307

vinx13 avatar Dec 08 '21 23:12 vinx13