[pylint] Also reports case np.nan/case math.nan (PLW0177) (#16378)

## 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`.
This commit is contained in:
InSync 2025-02-27 01:50:21 +07:00 committed by GitHub
parent b89d61bd05
commit 671494a620
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 55 additions and 2 deletions

View file

@ -53,6 +53,18 @@ import builtins
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

View file

@ -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);
}
}
_ => {}
}
}

View file

@ -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"] => {

View file

@ -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
|
@ -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
|