-
Notifications
You must be signed in to change notification settings - Fork 192
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
Fix StopIteration exception during scope analysis #298
Fix StopIteration exception during scope analysis #298
Conversation
During scope analysis all attribute accesses are collected for matching on import names. The matching code (specifically `_gen_dotted_names`) was not prepared for all types of expressions. In particular, complex expressions like `foo[0].bar.baz()` caused a `StopIteration` exception when `_gen_dotted_names` calls itself recursively. The nested call doesn't yield any values, and so calling `next()` on it raises. This commit fixes these types of errors.
next_pair = next(name_values, None) | ||
if next_pair is None: | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just add try ... except StopIteration
? That can be more efficient and probably easier to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, sure. Why is it more efficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That way we saved one extra next
call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then I don't understand your suggestion :)
Apart from the way it's currently written, I can imagine this:
try:
(next_name, next_node) = next(name_values)
yield (f"...", ...)
...
except StopIteration:
return
which is the same amount of next
calls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than the comments LGTM.
Have you tried running this change on large codebase to test more edge cases?
I haven't yet. |
next_pair = next(name_values, None) | ||
if next_pair is None: | ||
return | ||
(next_name, next_node) = next_pair |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We just need try catch on this line. Then we can save the next
in next_pair = next(name_values, None)
.
Merge this for now and will submit the proposed change in another PR. |
Summary
During scope analysis all attribute accesses are collected for matching on
import names. The matching code (specifically
_gen_dotted_names
) was notprepared for all types of expressions. In particular, complex expressions like
foo[0].bar.baz()
caused aStopIteration
exception when_gen_dotted_names
calls itself recursively. The nested call doesn't yield any values, and so
calling
next()
on it raises.This commit fixes these types of errors.
Test Plan
Added test case