Skip to content

Commit

Permalink
[pylint] Also reports case np.nan/case math.nan (PLW0177) (#1…
Browse files Browse the repository at this point in the history
…6378)

## Summary

Resolves #16374.

`PLW0177` now also reports the pattern of a case branch if it is an
attribute access whose qualified name is that of either `np.nan` or
`math.nan`.

As the rule is in preview, the changes are not preview-gated.

## Test Plan

`cargo nextest run` and `cargo insta test`.
  • Loading branch information
InSyncWithFoo authored Feb 26, 2025
1 parent b89d61b commit 671494a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@
if x == builtins.float("nan"):
pass

# https://github.com/astral-sh/ruff/issues/16374
match number:
# Errors
case np.nan: ...
case math.nan: ...

# No errors
case np.nan(): ...
case math.nan(): ...
case float('nan'): ...
case npy_nan: ...

# OK
if math.isnan(x):
pass
Expand Down
9 changes: 9 additions & 0 deletions crates/ruff_linter/src/checkers/ast/analyze/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,15 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
pylint::rules::useless_exception_statement(checker, expr);
}
}
Stmt::Match(ast::StmtMatch {
subject: _,
cases,
range: _,
}) => {
if checker.enabled(Rule::NanComparison) {
pylint::rules::nan_comparison_match(checker, cases);
}
}
_ => {}
}
}
16 changes: 15 additions & 1 deletion crates/ruff_linter/src/rules/pylint/rules/nan_comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,21 @@ impl Violation for NanComparison {

/// PLW0177
pub(crate) fn nan_comparison(checker: &Checker, left: &Expr, comparators: &[Expr]) {
for expr in std::iter::once(left).chain(comparators) {
nan_comparison_impl(checker, std::iter::once(left).chain(comparators));
}

/// PLW0177
pub(crate) fn nan_comparison_match(checker: &Checker, cases: &[ast::MatchCase]) {
nan_comparison_impl(
checker,
cases
.iter()
.filter_map(|case| case.pattern.as_match_value().map(|pattern| &*pattern.value)),
);
}

fn nan_comparison_impl<'a>(checker: &Checker, comparators: impl Iterator<Item = &'a Expr>) {
for expr in comparators {
if let Some(qualified_name) = checker.semantic().resolve_qualified_name(expr) {
match qualified_name.segments() {
["numpy", "nan" | "NAN" | "NaN"] => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
source: crates/ruff_linter/src/rules/pylint/mod.rs
snapshot_kind: text
---
nan_comparison.py:11:9: PLW0177 Comparing against a NaN value; use `math.isnan` instead
|
Expand Down Expand Up @@ -89,3 +88,22 @@ nan_comparison.py:53:9: PLW0177 Comparing against a NaN value; use `math.isnan`
| ^^^^^^^^^^^^^^^^^^^^^ PLW0177
54 | pass
|

nan_comparison.py:59:10: PLW0177 Comparing against a NaN value; use `np.isnan` instead
|
57 | match number:
58 | # Errors
59 | case np.nan: ...
| ^^^^^^ PLW0177
60 | case math.nan: ...
|

nan_comparison.py:60:10: PLW0177 Comparing against a NaN value; use `math.isnan` instead
|
58 | # Errors
59 | case np.nan: ...
60 | case math.nan: ...
| ^^^^^^^^ PLW0177
61 |
62 | # No errors
|

0 comments on commit 671494a

Please sign in to comment.