[flake8-simplify] Preserve original behavior for except () and bare except (SIM105) (#18213)

The PR addresses issue #18209.
This commit is contained in:
Vasco Schiavo 2025-06-23 16:01:57 +02:00 committed by GitHub
parent 315fb0f3da
commit ca8ed35275
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 117 additions and 24 deletions

View file

@ -128,3 +128,16 @@ def write_models(directory, Models):
pass; \
\
#
# Regression tests for: https://github.com/astral-sh/ruff/issues/18209
try:
1 / 0
except ():
pass
BaseException = ValueError
try:
int("a")
except BaseException:
pass

View file

@ -102,8 +102,11 @@ pub(crate) fn suppressible_exception(
return;
}
let [ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { body, range, .. })] =
handlers
let [
ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
body, range, type_, ..
}),
] = handlers
else {
return;
};
@ -121,7 +124,13 @@ pub(crate) fn suppressible_exception(
};
let exception = if handler_names.is_empty() {
"Exception".to_string()
if type_.is_none() {
// case where there are no handler names provided at all
"BaseException".to_string()
} else {
// case where handler names is an empty tuple
String::new()
}
} else {
handler_names.join(", ")
};
@ -142,15 +151,29 @@ pub(crate) fn suppressible_exception(
stmt.start(),
checker.semantic(),
)?;
let replace_try = Edit::range_replacement(
format!("with {binding}({exception})"),
let mut rest: Vec<Edit> = Vec::new();
let content: String;
if exception == "BaseException" && handler_names.is_empty() {
let (import_exception, binding_exception) =
checker.importer().get_or_import_symbol(
&ImportRequest::import("builtins", &exception),
stmt.start(),
checker.semantic(),
)?;
content = format!("with {binding}({binding_exception})");
rest.push(import_exception);
} else {
content = format!("with {binding}({exception})");
}
rest.push(Edit::range_deletion(
checker.locator().full_lines_range(*range),
));
rest.push(Edit::range_replacement(
content,
TextRange::at(stmt.start(), "try".text_len()),
);
let remove_handler = Edit::range_deletion(checker.locator().full_lines_range(*range));
Ok(Fix::unsafe_edits(
import_edit,
[replace_try, remove_handler],
))
));
Ok(Fix::unsafe_edits(import_edit, rest))
});
}
}

View file

@ -90,7 +90,7 @@ SIM105_0.py:19:1: SIM105 [*] Use `contextlib.suppress(ValueError, OSError)` inst
24 23 | # SIM105
25 24 | try:
SIM105_0.py:25:1: SIM105 [*] Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
SIM105_0.py:25:1: SIM105 [*] Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
|
24 | # SIM105
25 | / try:
@ -101,25 +101,26 @@ SIM105_0.py:25:1: SIM105 [*] Use `contextlib.suppress(Exception)` instead of `tr
29 |
30 | # SIM105
|
= help: Replace with `contextlib.suppress(Exception)`
= help: Replace with `contextlib.suppress(BaseException)`
Unsafe fix
1 |+import contextlib
1 2 | def foo():
2 3 | pass
3 4 |
2 |+import builtins
1 3 | def foo():
2 4 | pass
3 5 |
--------------------------------------------------------------------------------
22 23 | pass
23 24 |
24 25 | # SIM105
22 24 | pass
23 25 |
24 26 | # SIM105
25 |-try:
26 |+with contextlib.suppress(Exception):
26 27 | foo()
27 |+with contextlib.suppress(builtins.BaseException):
26 28 | foo()
27 |-except:
28 |- pass
29 28 |
30 29 | # SIM105
31 30 | try:
29 29 |
30 30 | # SIM105
31 31 | try:
SIM105_0.py:31:1: SIM105 [*] Use `contextlib.suppress(a.Error, b.Error)` instead of `try`-`except`-`pass`
|
@ -285,3 +286,59 @@ SIM105_0.py:126:5: SIM105 [*] Use `contextlib.suppress(OSError)` instead of `try
127 |+ with contextlib.suppress(OSError): os.makedirs(model_dir);
129 128 | \
130 129 | #
131 130 |
SIM105_0.py:133:1: SIM105 [*] Use `contextlib.suppress()` instead of `try`-`except`-`pass`
|
132 | # Regression tests for: https://github.com/astral-sh/ruff/issues/18209
133 | / try:
134 | | 1 / 0
135 | | except ():
136 | | pass
| |________^ SIM105
|
= help: Replace with `contextlib.suppress()`
Unsafe fix
1 |+import contextlib
1 2 | def foo():
2 3 | pass
3 4 |
--------------------------------------------------------------------------------
130 131 | #
131 132 |
132 133 | # Regression tests for: https://github.com/astral-sh/ruff/issues/18209
133 |-try:
134 |+with contextlib.suppress():
134 135 | 1 / 0
135 |-except ():
136 |- pass
137 136 |
138 137 |
139 138 | BaseException = ValueError
SIM105_0.py:140:1: SIM105 [*] Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
|
139 | BaseException = ValueError
140 | / try:
141 | | int("a")
142 | | except BaseException:
143 | | pass
| |________^ SIM105
|
= help: Replace with `contextlib.suppress(BaseException)`
Unsafe fix
1 |+import contextlib
1 2 | def foo():
2 3 | pass
3 4 |
--------------------------------------------------------------------------------
137 138 |
138 139 |
139 140 | BaseException = ValueError
140 |-try:
141 |+with contextlib.suppress(BaseException):
141 142 | int("a")
142 |-except BaseException:
143 |- pass