Skip to content

Commit 8890735

Browse files
authored
[flake8-bugbear] Allow singleton tuples with starred expressions in B013 (#12484)
1 parent eac965e commit 8890735

File tree

3 files changed

+23
-25
lines changed

3 files changed

+23
-25
lines changed

crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B013.py

+7
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,10 @@
1212
pass
1313
except(ValueError,):
1414
pass
15+
16+
list_exceptions = [FileExistsError, FileNotFoundError]
17+
18+
try:
19+
pass
20+
except (*list_exceptions,):
21+
pass

crates/ruff_linter/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
22
use ruff_macros::{derive_message_formats, violation};
3-
use ruff_python_ast::helpers::map_starred;
43
use ruff_python_ast::{self as ast, ExceptHandler, Expr};
54
use ruff_text_size::Ranged;
65

@@ -11,6 +10,9 @@ use crate::fix::edits::pad;
1110
/// Checks for single-element tuples in exception handlers (e.g.,
1211
/// `except (ValueError,):`).
1312
///
13+
/// Note: Single-element tuples consisting of a starred expression
14+
/// are allowed.
15+
///
1416
/// ## Why is this bad?
1517
/// A tuple with a single element can be more concisely and idiomatically
1618
/// expressed as a single value.
@@ -69,7 +71,17 @@ pub(crate) fn redundant_tuple_in_exception_handler(
6971
let [elt] = elts.as_slice() else {
7072
continue;
7173
};
72-
let elt = map_starred(elt);
74+
// It is not safe to replace a single-element
75+
// tuple consisting of a starred expression
76+
// by the unstarred expression because the unstarred
77+
// expression can be any iterable whereas `except` must
78+
// be followed by a literal or a tuple. For example:
79+
// ```python
80+
// except (*[ValueError,FileNotFoundError],)
81+
// ```
82+
if elt.is_starred_expr() {
83+
continue;
84+
}
7385
let mut diagnostic = Diagnostic::new(
7486
RedundantTupleInExceptionHandler {
7587
name: checker.generator().expr(elt),

crates/ruff_linter/src/rules/flake8_bugbear/snapshots/ruff_linter__rules__flake8_bugbear__tests__B013_B013.py.snap

+2-23
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,6 @@ B013.py:5:8: B013 [*] A length-one tuple literal is redundant in exception handl
2222
7 7 | except AttributeError:
2323
8 8 | pass
2424

25-
B013.py:11:8: B013 [*] A length-one tuple literal is redundant in exception handlers
26-
|
27-
9 | except (ImportError, TypeError):
28-
10 | pass
29-
11 | except (*retriable_exceptions,):
30-
| ^^^^^^^^^^^^^^^^^^^^^^^^ B013
31-
12 | pass
32-
13 | except(ValueError,):
33-
|
34-
= help: Replace with `except retriable_exceptions`
35-
36-
Safe fix
37-
8 8 | pass
38-
9 9 | except (ImportError, TypeError):
39-
10 10 | pass
40-
11 |-except (*retriable_exceptions,):
41-
11 |+except retriable_exceptions:
42-
12 12 | pass
43-
13 13 | except(ValueError,):
44-
14 14 | pass
45-
4625
B013.py:13:7: B013 [*] A length-one tuple literal is redundant in exception handlers
4726
|
4827
11 | except (*retriable_exceptions,):
@@ -60,5 +39,5 @@ B013.py:13:7: B013 [*] A length-one tuple literal is redundant in exception hand
6039
13 |-except(ValueError,):
6140
13 |+except ValueError:
6241
14 14 | pass
63-
64-
42+
15 15 |
43+
16 16 | list_exceptions = [FileExistsError, FileNotFoundError]

0 commit comments

Comments
 (0)