[`refurb`] Handle non-finite decimals in `verbose-decimal-constructor (FURB157)` (#14596)

This PR extends the Decimal parsing used in [verbose-decimal-constructor
(FURB157)](https://docs.astral.sh/ruff/rules/verbose-decimal-constructor/)
to better handle non-finite `Decimal` objects, avoiding some false
negatives.

Closes #14587

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
Dylan 2024-12-02 18:13:20 -06:00 committed by GitHub
parent 5137fcc9c8
commit 91e2d9a139
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 219 additions and 6 deletions

View File

@ -42,3 +42,17 @@ Decimal("-0") # Ok
Decimal("_") # Ok
Decimal(" ") # Ok
Decimal("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") # Ok
# Non-finite variants
# https://github.com/astral-sh/ruff/issues/14587
Decimal(float(" nan ")) # Decimal(" nan ")
Decimal(float(" +nan ")) # Decimal(" +nan ")
# In this one case, " -nan ", the fix has to be
# `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
Decimal(float(" -nan ")) # Decimal(" nan ")
Decimal(float(" inf ")) # Decimal(" inf ")
Decimal(float(" +inf ")) # Decimal(" +inf ")
Decimal(float(" -inf ")) # Decimal(" -inf ")
Decimal(float(" infinity ")) # Decimal(" infinity ")
Decimal(float(" +infinity ")) # Decimal(" +infinity ")
Decimal(float(" -infinity ")) # Decimal(" -infinity ")

View File

@ -152,14 +152,34 @@ pub(crate) fn verbose_decimal_constructor(checker: &mut Checker, call: &ast::Exp
let Some(float) = float.as_string_literal_expr() else {
return;
};
if !matches!(
float.value.to_str().to_lowercase().as_str(),
"inf" | "-inf" | "infinity" | "-infinity" | "nan"
) {
let trimmed = float.value.to_str().trim();
let mut matches_non_finite_keyword = false;
for non_finite_keyword in [
"inf",
"+inf",
"-inf",
"infinity",
"+infinity",
"-infinity",
"nan",
"+nan",
"-nan",
] {
if trimmed.eq_ignore_ascii_case(non_finite_keyword) {
matches_non_finite_keyword = true;
break;
}
}
if !matches_non_finite_keyword {
return;
}
let replacement = checker.locator().slice(float).to_string();
let mut replacement = checker.locator().slice(float).to_string();
// `Decimal(float("-nan")) == Decimal("nan")`
if trimmed.eq_ignore_ascii_case("-nan") {
replacement.remove(replacement.find('-').unwrap());
}
let mut diagnostic = Diagnostic::new(
VerboseDecimalConstructor {
replacement: replacement.clone(),

View File

@ -1,6 +1,5 @@
---
source: crates/ruff_linter/src/rules/refurb/mod.rs
snapshot_kind: text
---
FURB157.py:5:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
@ -207,3 +206,183 @@ FURB157.py:24:9: FURB157 [*] Verbose expression in `Decimal` constructor
25 25 |
26 26 | # Ok
27 27 | Decimal("2e-4")
FURB157.py:48:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
46 | # Non-finite variants
47 | # https://github.com/astral-sh/ruff/issues/14587
48 | Decimal(float(" nan ")) # Decimal(" nan ")
| ^^^^^^^^^^^^^^ FURB157
49 | Decimal(float(" +nan ")) # Decimal(" +nan ")
50 | # In this one case, " -nan ", the fix has to be
|
= help: Replace with `" nan "`
Safe fix
45 45 |
46 46 | # Non-finite variants
47 47 | # https://github.com/astral-sh/ruff/issues/14587
48 |-Decimal(float(" nan ")) # Decimal(" nan ")
48 |+Decimal(" nan ") # Decimal(" nan ")
49 49 | Decimal(float(" +nan ")) # Decimal(" +nan ")
50 50 | # In this one case, " -nan ", the fix has to be
51 51 | # `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
FURB157.py:49:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
47 | # https://github.com/astral-sh/ruff/issues/14587
48 | Decimal(float(" nan ")) # Decimal(" nan ")
49 | Decimal(float(" +nan ")) # Decimal(" +nan ")
| ^^^^^^^^^^^^^^^ FURB157
50 | # In this one case, " -nan ", the fix has to be
51 | # `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
|
= help: Replace with `" +nan "`
Safe fix
46 46 | # Non-finite variants
47 47 | # https://github.com/astral-sh/ruff/issues/14587
48 48 | Decimal(float(" nan ")) # Decimal(" nan ")
49 |-Decimal(float(" +nan ")) # Decimal(" +nan ")
49 |+Decimal(" +nan ") # Decimal(" +nan ")
50 50 | # In this one case, " -nan ", the fix has to be
51 51 | # `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
52 52 | Decimal(float(" -nan ")) # Decimal(" nan ")
FURB157.py:52:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
50 | # In this one case, " -nan ", the fix has to be
51 | # `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
52 | Decimal(float(" -nan ")) # Decimal(" nan ")
| ^^^^^^^^^^^^^^^ FURB157
53 | Decimal(float(" inf ")) # Decimal(" inf ")
54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
|
= help: Replace with `" nan "`
Safe fix
49 49 | Decimal(float(" +nan ")) # Decimal(" +nan ")
50 50 | # In this one case, " -nan ", the fix has to be
51 51 | # `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
52 |-Decimal(float(" -nan ")) # Decimal(" nan ")
52 |+Decimal(" nan ") # Decimal(" nan ")
53 53 | Decimal(float(" inf ")) # Decimal(" inf ")
54 54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
55 55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
FURB157.py:53:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
51 | # `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
52 | Decimal(float(" -nan ")) # Decimal(" nan ")
53 | Decimal(float(" inf ")) # Decimal(" inf ")
| ^^^^^^^^^^^^^^ FURB157
54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
|
= help: Replace with `" inf "`
Safe fix
50 50 | # In this one case, " -nan ", the fix has to be
51 51 | # `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
52 52 | Decimal(float(" -nan ")) # Decimal(" nan ")
53 |-Decimal(float(" inf ")) # Decimal(" inf ")
53 |+Decimal(" inf ") # Decimal(" inf ")
54 54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
55 55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
56 56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
FURB157.py:54:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
52 | Decimal(float(" -nan ")) # Decimal(" nan ")
53 | Decimal(float(" inf ")) # Decimal(" inf ")
54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
| ^^^^^^^^^^^^^^^ FURB157
55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
|
= help: Replace with `" +inf "`
Safe fix
51 51 | # `Decimal(" nan ")`` because `Decimal("-nan") != Decimal(float("-nan"))`
52 52 | Decimal(float(" -nan ")) # Decimal(" nan ")
53 53 | Decimal(float(" inf ")) # Decimal(" inf ")
54 |-Decimal(float(" +inf ")) # Decimal(" +inf ")
54 |+Decimal(" +inf ") # Decimal(" +inf ")
55 55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
56 56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
57 57 | Decimal(float(" +infinity ")) # Decimal(" +infinity ")
FURB157.py:55:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
53 | Decimal(float(" inf ")) # Decimal(" inf ")
54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
| ^^^^^^^^^^^^^^^ FURB157
56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
57 | Decimal(float(" +infinity ")) # Decimal(" +infinity ")
|
= help: Replace with `" -inf "`
Safe fix
52 52 | Decimal(float(" -nan ")) # Decimal(" nan ")
53 53 | Decimal(float(" inf ")) # Decimal(" inf ")
54 54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
55 |-Decimal(float(" -inf ")) # Decimal(" -inf ")
55 |+Decimal(" -inf ") # Decimal(" -inf ")
56 56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
57 57 | Decimal(float(" +infinity ")) # Decimal(" +infinity ")
58 58 | Decimal(float(" -infinity ")) # Decimal(" -infinity ")
FURB157.py:56:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
| ^^^^^^^^^^^^^^^^^^^ FURB157
57 | Decimal(float(" +infinity ")) # Decimal(" +infinity ")
58 | Decimal(float(" -infinity ")) # Decimal(" -infinity ")
|
= help: Replace with `" infinity "`
Safe fix
53 53 | Decimal(float(" inf ")) # Decimal(" inf ")
54 54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
55 55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
56 |-Decimal(float(" infinity ")) # Decimal(" infinity ")
56 |+Decimal(" infinity ") # Decimal(" infinity ")
57 57 | Decimal(float(" +infinity ")) # Decimal(" +infinity ")
58 58 | Decimal(float(" -infinity ")) # Decimal(" -infinity ")
FURB157.py:57:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
57 | Decimal(float(" +infinity ")) # Decimal(" +infinity ")
| ^^^^^^^^^^^^^^^^^^^^ FURB157
58 | Decimal(float(" -infinity ")) # Decimal(" -infinity ")
|
= help: Replace with `" +infinity "`
Safe fix
54 54 | Decimal(float(" +inf ")) # Decimal(" +inf ")
55 55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
56 56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
57 |-Decimal(float(" +infinity ")) # Decimal(" +infinity ")
57 |+Decimal(" +infinity ") # Decimal(" +infinity ")
58 58 | Decimal(float(" -infinity ")) # Decimal(" -infinity ")
FURB157.py:58:9: FURB157 [*] Verbose expression in `Decimal` constructor
|
56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
57 | Decimal(float(" +infinity ")) # Decimal(" +infinity ")
58 | Decimal(float(" -infinity ")) # Decimal(" -infinity ")
| ^^^^^^^^^^^^^^^^^^^^ FURB157
|
= help: Replace with `" -infinity "`
Safe fix
55 55 | Decimal(float(" -inf ")) # Decimal(" -inf ")
56 56 | Decimal(float(" infinity ")) # Decimal(" infinity ")
57 57 | Decimal(float(" +infinity ")) # Decimal(" +infinity ")
58 |-Decimal(float(" -infinity ")) # Decimal(" -infinity ")
58 |+Decimal(" -infinity ") # Decimal(" -infinity ")