Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Don't assume direct parentage when emitting
used-before-assignment
#5582Don't assume direct parentage when emitting
used-before-assignment
#5582Changes from 13 commits
2d949d9
d16730b
fd4a266
65782ec
4b409a2
18dd196
ad3651e
8c26f64
43f708d
32b9d2d
7f4b88e
0329aa5
0a25e1a
6e767a5
ef7666b
836c457
3cdf244
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
I don't think I understand everything here.
If the first except is raised and the function do not return, it means in the second one
res
won't be defined ?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.
Same here, we want to avoid annoying users, and so outside a TryExcept we assume the try statements executed. By that same logic we assume that outside a TryExcept its except statements did not execute -- because it would be a bit backwards to assume the try statements never execute and thus that assignments in the except always happen.
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.
Didn't we say that like Pylance we consider that everything in a try/except can fail ? (#5384). Also, if we do not raise or return in the
except
it means we can reach line 43 from one branch or another and we would need to consider both branches in order to be correct.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.
No, that wasn't my understanding, and that's not what Pylance does. The yellow underline is Pylance, showing that the checker we just worked on is in agreement with Pylance:
![Screen Shot 2021-12-23 at 10 44 31 AM](https://user-images.githubusercontent.com/38668450/147262922-2ecc043d-820d-4b4a-960f-2ea63dca3fc2.png)
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.
I guess a good way of putting it is that's why there are different private methods in this checker now:
_uncertain_nodes_in_except_blocks
_uncertain_nodes_in_try_blocks_when_evaluating_except_blocks
_uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks
We make different control flow inferences based on where the name is being used (try, except, finally, or outside).
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.
I agree with the points you're making here. Especially the last example is something of which I can easily imagine complaints coming from. Code with requests and databases seem to often really on such patterns.
Perhaps you could add a summary of this explanation to the issue you mentioned? That way we don't lose this.
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.
My last example was not quite right π¬ -- I neglected that subsequent handlers can't swallow exceptions raised in earlier handlers, so
ValueError
can't be passed down to a subsequent handler. I'll edit it.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.
I think this discussion is getting at when an
else
clause should be used in a try/except/else. If you can depend on exhaustive handling by your except handlers, you don't need to guard yourprint(a)
after the try/except. If it's not exhaustively handled, then yourprint(a)
should be in anelse
.I guess this could even be its own checker, so it could be enabled/disabled separately. (It would probably be easier to implement that way, given how much new logic would go into the exhaustiveness checking.)
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.
I think relying on everyone knowing that
library_function_that_might_sysexit
will implicitly exit all the time is an anti-pattern. Personally I would initialize the variable to be sure, or at least to add a comment stating explicitly that there's an exit and it's ok to do that if there's a good reason to do that like performance. (a pylint disable is not that much more work then),But I get that this might be a little opinionated and that we'd get complaints from this, thank you for explaining.
π
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.
This discussion helped clarify for me that beefing up the checker to assume try statements always fail is worthy of discussion, but would need to be solved in tandem with #5524, so I suggest we keep discussing there for 2.14 or later.