Skip to content

Commit 47b4422

Browse files
committed
Make unsafe sometimes
1 parent 6e63f4d commit 47b4422

File tree

2 files changed

+46
-12
lines changed

2 files changed

+46
-12
lines changed

crates/ruff_linter/src/rules/tryceratops/rules/error_instead_of_exception.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
1+
use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation};
22
use ruff_macros::{derive_message_formats, violation};
33
use ruff_python_ast::visitor::Visitor;
44
use ruff_python_ast::{self as ast, ExceptHandler, Expr};
@@ -43,6 +43,12 @@ use crate::rules::tryceratops::helpers::LoggerCandidateVisitor;
4343
/// logging.exception("Exception occurred")
4444
/// ```
4545
///
46+
/// ## Fix safety
47+
/// This rule's fix is marked as safe when run against `logging.error` calls,
48+
/// but unsafe when marked against other logger-like calls (e.g.,
49+
/// `logger.error`), since the rule is prone to false positives when detecting
50+
/// logger-like calls outside of the `logging` module.
51+
///
4652
/// ## References
4753
/// - [Python documentation: `logging.exception`](https://docs.python.org/3/library/logging.html#logging.exception)
4854
#[violation]
@@ -78,10 +84,22 @@ pub(crate) fn error_instead_of_exception(checker: &mut Checker, handlers: &[Exce
7884
if checker.settings.preview.is_enabled() {
7985
match expr.func.as_ref() {
8086
Expr::Attribute(ast::ExprAttribute { attr, .. }) => {
81-
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
82-
"exception".to_string(),
83-
attr.range(),
84-
)));
87+
diagnostic.set_fix(Fix::applicable_edit(
88+
Edit::range_replacement("exception".to_string(), attr.range()),
89+
// When run against `logging.error`, the fix is safe; otherwise,
90+
// the object _may_ not be a logger.
91+
if checker
92+
.semantic()
93+
.resolve_call_path(expr.func.as_ref())
94+
.is_some_and(|call_path| {
95+
matches!(call_path.as_slice(), ["logging", "error"])
96+
})
97+
{
98+
Applicability::Safe
99+
} else {
100+
Applicability::Unsafe
101+
},
102+
));
85103
}
86104
Expr::Name(_) => {
87105
diagnostic.try_set_fix(|| {
@@ -93,7 +111,23 @@ pub(crate) fn error_instead_of_exception(checker: &mut Checker, handlers: &[Exce
93111
)?;
94112
let name_edit =
95113
Edit::range_replacement(binding, expr.func.range());
96-
Ok(Fix::safe_edits(import_edit, [name_edit]))
114+
Ok(Fix::applicable_edits(
115+
import_edit,
116+
[name_edit],
117+
// When run against `logging.error`, the fix is safe; otherwise,
118+
// the object _may_ not be a logger.
119+
if checker
120+
.semantic()
121+
.resolve_call_path(expr.func.as_ref())
122+
.is_some_and(|call_path| {
123+
matches!(call_path.as_slice(), ["logging", "error"])
124+
})
125+
{
126+
Applicability::Safe
127+
} else {
128+
Applicability::Unsafe
129+
},
130+
))
97131
});
98132
}
99133
_ => {}

crates/ruff_linter/src/rules/tryceratops/snapshots/ruff_linter__rules__tryceratops__tests__preview__TRY400_TRY400.py.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ TRY400.py:26:9: TRY400 [*] Use `logging.exception` instead of `logging.error`
5151
|
5252
= help: Replace with `exception`
5353

54-
Safe fix
54+
Unsafe fix
5555
23 23 | try:
5656
24 24 | a = 1
5757
25 25 | except Exception:
@@ -69,7 +69,7 @@ TRY400.py:29:13: TRY400 [*] Use `logging.exception` instead of `logging.error`
6969
|
7070
= help: Replace with `exception`
7171

72-
Safe fix
72+
Unsafe fix
7373
26 26 | logger.error("Context message here")
7474
27 27 |
7575
28 28 | if True:
@@ -90,7 +90,7 @@ TRY400.py:36:9: TRY400 [*] Use `logging.exception` instead of `logging.error`
9090
|
9191
= help: Replace with `exception`
9292

93-
Safe fix
93+
Unsafe fix
9494
33 33 | try:
9595
34 34 | a = 1
9696
35 35 | except Exception:
@@ -108,7 +108,7 @@ TRY400.py:39:13: TRY400 [*] Use `logging.exception` instead of `logging.error`
108108
|
109109
= help: Replace with `exception`
110110

111-
Safe fix
111+
Unsafe fix
112112
36 36 | log.error("Context message here")
113113
37 37 |
114114
38 38 | if True:
@@ -129,7 +129,7 @@ TRY400.py:46:9: TRY400 [*] Use `logging.exception` instead of `logging.error`
129129
|
130130
= help: Replace with `exception`
131131

132-
Safe fix
132+
Unsafe fix
133133
43 43 | try:
134134
44 44 | a = 1
135135
45 45 | except Exception:
@@ -147,7 +147,7 @@ TRY400.py:49:13: TRY400 [*] Use `logging.exception` instead of `logging.error`
147147
|
148148
= help: Replace with `exception`
149149

150-
Safe fix
150+
Unsafe fix
151151
46 46 | self.logger.error("Context message here")
152152
47 47 |
153153
48 48 | if True:

0 commit comments

Comments
 (0)