Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inspect.getsourcelines is wrong #13

Open
altanh opened this issue Oct 8, 2021 · 1 comment
Open

inspect.getsourcelines is wrong #13

altanh opened this issue Oct 8, 2021 · 1 comment
Labels
bug Something isn't working

Comments

@altanh
Copy link
Contributor

altanh commented Oct 8, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants