-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[flake8-logging] Add ExcInfoOutsideExceptionHandler
(LOG014)
#14682
base: main
Are you sure you want to change the base?
[flake8-logging] Add ExcInfoOutsideExceptionHandler
(LOG014)
#14682
Conversation
5697248
to
4584733
Compare
4584733
to
1a602a4
Compare
ExcInfoOutsideExceptionHandler
(LOG014)
|
code | total | + violation | - violation | + fix | - fix |
---|---|---|---|---|---|
LOG014 | 15 | 15 | 0 | 0 | 0 |
try: | ||
a = 1 * 2 | ||
except Exception: | ||
banana() |
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.
The ecosystem checks are turning up a few instances just like this.
Technically in this case, if we are able to tell that banana()
is only ever called from inside an exception handling block, then we could mark this as okay. But I don't think it's possible to check all calling sites?
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.
It's possible, but you'd need to move the rule to crates/ruff_linter/src/checkers/ast/analyze/bindings.rs
rather than crates/ruff_linter/src/checkers/ast/analyze/expression.rs
. The difference is that the rules executed from bindings.rs
are run after the entire semantic model has been built, so they have more information available to them in some ways: they're able to iterate through all the references to a binding as well as looking at the original binding itself. You can see an example of how to do it in a PR I merged this morning: #14661.
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.
Ahh. I'll revise it to include that check then. Thanks.
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 problem, thanks for the PR!
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.
Forgive me if I'm misunderstanding, but I don't think moving it to bindings.rs
works?
An expression like logging.info("foo", exc_info=True)
isn't a binding, so if I move my lint function call to bindings.rs
, then the only situation the lint could possibly apply would be x = logging.info("foo", exc_info=True)
or (x := logging.info("foo", exc_info=True))
, which no one writes.
Is it possible to make a new version of expression.rs
that's called after the entire semantic model has been built? I don't think there's any way around calling the lint function on expressions, since the lint is designed to find bad function 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.
An expression like
logging.info("foo", exc_info=True)
isn't a binding, so if I move my lint function call tobindings.rs
, then the only situation the lint could possibly apply would bex = logging.info("foo", exc_info=True)
or(x := logging.info("foo", exc_info=True))
, which no one writes.
ah, you're quite right.
I suppose what would be best would be to collect all logging.(...)
calls into a Vec
stored on this struct as we traverse the AST in https://github.com/astral-sh/ruff/blob/main/crates/ruff_linter/src/checkers/ast/mod.rs. Then after the AST has been fully visited and the SemanticModel
has been fully constructed, we can call this rule on each logging(...)
call we stored in the Vec.
@snowdrop4 Thanks for working on this! Would you, by any chance, be able to walk me through (at least some of) the ecosystem results and help me understand why/whether they are true positives? I'm a little worried (probably unnecessarily) that a library may define a function in a publicly accessible namespace def foo():
# <-- function logic here --- >
# exc_info outside of except
logging.exception(..., exc_info=True) and then any of the following (or a mixture) may occur:
I don't think I know enough about the use-cases for specifying I don't think there's a problem with performing this lint for functions defined inside another function scope, since they cannot be used elsewhere, but for the above case I'm less sure. Apologies if I'm making a mountain out of a molehill here - you probably know more than me about Python logging practices and can tell me I'm off base here! |
@snowdrop4 Sorry again for the added complexity here. What do you think of the following conservative approach to this rule?
As I said in the previous comment, I'm happy to be overruled here if you think the current ecosystem check and scope of the rule seems reasonable given how Python developers use this logging option generally. Thanks for your patience and your contribution! |
Summary
Add
ExcInfoOutsideExceptionHandler
(LOG014
) from theflake8-logging
plugin (parent issue #7248).This rule detects the
exc_info
kwarg being set toTrue
outside of an exception handling block, which results in unwanted logging output.I did some mild refactoring by adding a
helpers.rs
in the crate to reduce duplication.Test Plan
Lots of fixtures.