Skip to content

Commit

Permalink
[refurb] Handle non-finite decimals in `verbose-decimal-constructor…
Browse files Browse the repository at this point in the history
… (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 <[email protected]>
  • Loading branch information
dylwil3 and MichaReiser authored Dec 3, 2024
1 parent 5137fcc commit 91e2d9a
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 6 deletions.
14 changes: 14 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/refurb/FURB157.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,17 @@
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 ")
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
@@ -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
|
Expand Down Expand Up @@ -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 ")

0 comments on commit 91e2d9a

Please sign in to comment.