Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,11 @@ def foo5():
foo.bar # Attribute (raise)
object().__class__ # Attribute (raise)
"foo" + "bar" # BinOp (raise)


def foo6():
x["item"] # Subscript (raise)
obj.attr["key"] # Subscript (raise)
get_dict()["key"] # Subscript on call result (raise)
x[0] # Subscript with int key (raise)
_ = x["item"] # OK: result intentionally ignored
5 changes: 5 additions & 0 deletions crates/ruff_linter/src/preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,8 @@ pub(crate) const fn is_trailing_pragma_in_line_length_enabled(preview: PreviewMo
pub(crate) const fn is_collapsible_if_fix_safe_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/issues/23932
pub(crate) const fn is_b018_subscript_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}
2 changes: 2 additions & 0 deletions crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ mod tests {
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_9.py"))]
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_B008.py"))]
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_1.pyi"))]
#[test_case(Rule::UselessExpression, Path::new("B018.py"))]
#[test_case(Rule::UselessExpression, Path::new("B018.ipynb"))]
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(
"preview__{}_{}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use ruff_text_size::Ranged;

use crate::Violation;
use crate::checkers::ast::Checker;
use crate::preview::is_b018_subscript_enabled;

use crate::rules::flake8_bugbear::helpers::at_last_top_level_expression_in_cell;

Expand Down Expand Up @@ -35,9 +36,10 @@ use crate::rules::flake8_bugbear::helpers::at_last_top_level_expression_in_cell;
/// This rule ignores expression types that are commonly used for their side
/// effects, such as function calls.
///
/// However, if a seemingly useless expression (like an attribute access) is
/// needed to trigger a side effect, consider assigning it to an anonymous
/// variable, to indicate that the return value is intentionally ignored.
/// However, if a seemingly useless expression (like an attribute access or a
/// subscript) is needed to trigger a side effect, consider assigning it to an
/// anonymous variable, to indicate that the return value is intentionally
/// ignored.
///
/// For example, given:
/// ```python
Expand Down Expand Up @@ -67,6 +69,10 @@ impl Violation for UselessExpression {
"Found useless attribute access. Either assign it to a variable or remove it."
.to_string()
}
Kind::Subscript => {
"Found useless subscript access. Either assign it to a variable or remove it."
.to_string()
}
}
}
}
Expand Down Expand Up @@ -108,6 +114,16 @@ pub(crate) fn useless_expression(checker: &Checker, value: &Expr) {
value.range(),
);
}
// Flag subscripts as useless expressions, even if they're attached to calls or other
// expressions.
if is_b018_subscript_enabled(checker.settings()) && value.is_subscript_expr() {
checker.report_diagnostic(
UselessExpression {
kind: Kind::Subscript,
},
value.range(),
);
}
return;
}

Expand All @@ -123,4 +139,5 @@ pub(crate) fn useless_expression(checker: &Checker, value: &Expr) {
enum Kind {
Expression,
Attribute,
Subscript,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
---
B018 Found useless expression. Either assign it to a variable or remove it.
--> B018.ipynb:5:1
|
3 | x
4 | # Only skip the last expression
5 | x # B018
| ^
6 | x
7 | # Nested expressions isn't relevant
|

B018 Found useless expression. Either assign it to a variable or remove it.
--> B018.ipynb:9:5
|
7 | # Nested expressions isn't relevant
8 | if True:
9 | x
| ^
10 | # Semicolons shouldn't affect the output
11 | x;
|

B018 Found useless expression. Either assign it to a variable or remove it.
--> B018.ipynb:13:1
|
11 | x;
12 | # Semicolons with multiple expressions
13 | x; x
| ^
14 | # Comments, newlines and whitespace
15 | x # comment
|
Loading