Skip to content

inspect.getsourcelines is wrong #13

@altanh

Description

@altanh

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions