mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-07 21:25:08 +00:00
[ruff
] Do not simplify round()
calls (RUF046
) (#14832)
## Summary Part 1 of the big change introduced in #14828. This temporarily causes all fixes for `round(...)` to be considered unsafe, but they will eventually be enhanced. ## Test Plan `cargo nextest run` and `cargo insta test`.
This commit is contained in:
parent
68eb0a2511
commit
c62ba48ad4
4 changed files with 569 additions and 374 deletions
|
@ -1,9 +1,12 @@
|
|||
import math
|
||||
|
||||
|
||||
inferred_int = 1
|
||||
inferred_float = 1.
|
||||
|
||||
|
||||
### Safely fixable
|
||||
|
||||
# Arguments are not checked
|
||||
int(id())
|
||||
int(len([]))
|
||||
int(ord(foo))
|
||||
|
@ -17,6 +20,15 @@ int(math.lcm())
|
|||
int(math.isqrt())
|
||||
int(math.perm())
|
||||
|
||||
int(round(1, 0))
|
||||
int(round(1, 10))
|
||||
|
||||
int(round(1))
|
||||
int(round(1, None))
|
||||
|
||||
int(round(1.))
|
||||
int(round(1., None))
|
||||
|
||||
|
||||
### Unsafe
|
||||
|
||||
|
@ -24,27 +36,35 @@ int(math.ceil())
|
|||
int(math.floor())
|
||||
int(math.trunc())
|
||||
|
||||
int(round(inferred_int, 0))
|
||||
int(round(inferred_int, 10))
|
||||
|
||||
### `round()`
|
||||
int(round(inferred_int))
|
||||
int(round(inferred_int, None))
|
||||
|
||||
## Errors
|
||||
int(round(0))
|
||||
int(round(0, 0))
|
||||
int(round(0, None))
|
||||
int(round(inferred_float))
|
||||
int(round(inferred_float, None))
|
||||
|
||||
int(round(0.1))
|
||||
int(round(0.1, None))
|
||||
int(round(unknown))
|
||||
int(round(unknown, None))
|
||||
|
||||
# Argument type is not checked
|
||||
foo = type("Foo", (), {"__round__": lambda self: 4.2})()
|
||||
|
||||
int(round(foo))
|
||||
int(round(foo, 0))
|
||||
int(round(foo, None))
|
||||
### No errors
|
||||
|
||||
int(round(1, unknown))
|
||||
int(round(1., unknown))
|
||||
|
||||
int(round(1., 0))
|
||||
int(round(inferred_float, 0))
|
||||
|
||||
int(round(inferred_int, unknown))
|
||||
int(round(inferred_float, unknown))
|
||||
|
||||
int(round(unknown, 0))
|
||||
int(round(unknown, unknown))
|
||||
|
||||
## No errors
|
||||
int(round(0, 3.14))
|
||||
int(round(0, non_literal))
|
||||
int(round(inferred_int, 3.14))
|
||||
|
||||
int(round(0, 0), base)
|
||||
int(round(0, 0, extra=keyword))
|
||||
int(round(0.1, 0))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::checkers::ast::Checker;
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||
use ruff_python_ast::{Arguments, Expr, ExprCall, ExprName, ExprNumberLiteral, Number};
|
||||
use ruff_python_ast::{Arguments, Expr, ExprCall, ExprNumberLiteral, Number};
|
||||
use ruff_python_semantic::analyze::typing;
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_text_size::TextRange;
|
||||
|
@ -74,7 +74,7 @@ pub(crate) fn unnecessary_cast_to_int(checker: &mut Checker, call: &ExprCall) {
|
|||
|
||||
// Depends on `ndigits` and `number.__round__`
|
||||
["" | "builtins", "round"] => {
|
||||
if let Some(fix) = replace_with_shortened_round_call(checker, outer_range, arguments) {
|
||||
if let Some(fix) = replace_with_round(checker, outer_range, inner_range, arguments) {
|
||||
fix
|
||||
} else {
|
||||
return;
|
||||
|
@ -89,9 +89,9 @@ pub(crate) fn unnecessary_cast_to_int(checker: &mut Checker, call: &ExprCall) {
|
|||
_ => return,
|
||||
};
|
||||
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(UnnecessaryCastToInt, call.range).with_fix(fix));
|
||||
let diagnostic = Diagnostic::new(UnnecessaryCastToInt, call.range);
|
||||
|
||||
checker.diagnostics.push(diagnostic.with_fix(fix));
|
||||
}
|
||||
|
||||
fn single_argument_to_int_call<'a>(
|
||||
|
@ -117,12 +117,29 @@ fn single_argument_to_int_call<'a>(
|
|||
Some(argument)
|
||||
}
|
||||
|
||||
/// Returns an [`Edit`] when the call is of any of the forms:
|
||||
/// * `round(integer)`, `round(integer, 0)`, `round(integer, None)`
|
||||
/// * `round(whatever)`, `round(whatever, None)`
|
||||
fn replace_with_shortened_round_call(
|
||||
/// The type of the first argument to `round()`
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum Rounded {
|
||||
InferredInt,
|
||||
InferredFloat,
|
||||
LiteralInt,
|
||||
LiteralFloat,
|
||||
Other,
|
||||
}
|
||||
|
||||
/// The type of the second argument to `round()`
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum Ndigits {
|
||||
NotGiven,
|
||||
LiteralInt,
|
||||
LiteralNone,
|
||||
Other,
|
||||
}
|
||||
|
||||
fn replace_with_round(
|
||||
checker: &Checker,
|
||||
outer_range: TextRange,
|
||||
inner_range: TextRange,
|
||||
arguments: &Arguments,
|
||||
) -> Option<Fix> {
|
||||
if arguments.len() > 2 {
|
||||
|
@ -132,48 +149,56 @@ fn replace_with_shortened_round_call(
|
|||
let number = arguments.find_argument("number", 0)?;
|
||||
let ndigits = arguments.find_argument("ndigits", 1);
|
||||
|
||||
let number_is_int = match number {
|
||||
Expr::Name(name) => is_int(checker.semantic(), name),
|
||||
Expr::NumberLiteral(ExprNumberLiteral { value, .. }) => matches!(value, Number::Int(..)),
|
||||
_ => false,
|
||||
let number_kind = match number {
|
||||
Expr::Name(name) => {
|
||||
let semantic = checker.semantic();
|
||||
|
||||
match semantic.only_binding(name).map(|id| semantic.binding(id)) {
|
||||
Some(binding) if typing::is_int(binding, semantic) => Rounded::InferredInt,
|
||||
Some(binding) if typing::is_float(binding, semantic) => Rounded::InferredFloat,
|
||||
_ => Rounded::Other,
|
||||
}
|
||||
}
|
||||
|
||||
Expr::NumberLiteral(ExprNumberLiteral { value, .. }) => match value {
|
||||
Number::Int(..) => Rounded::LiteralInt,
|
||||
Number::Float(..) => Rounded::LiteralFloat,
|
||||
Number::Complex { .. } => Rounded::Other,
|
||||
},
|
||||
|
||||
_ => Rounded::Other,
|
||||
};
|
||||
|
||||
match ndigits {
|
||||
Some(Expr::NumberLiteral(ExprNumberLiteral { value, .. }))
|
||||
if is_literal_zero(value) && number_is_int => {}
|
||||
Some(Expr::NoneLiteral(_)) | None => {}
|
||||
let ndigits_kind = match ndigits {
|
||||
None => Ndigits::NotGiven,
|
||||
Some(Expr::NoneLiteral(_)) => Ndigits::LiteralNone,
|
||||
|
||||
Some(Expr::NumberLiteral(ExprNumberLiteral {
|
||||
value: Number::Int(..),
|
||||
..
|
||||
})) => Ndigits::LiteralInt,
|
||||
|
||||
_ => Ndigits::Other,
|
||||
};
|
||||
|
||||
let applicability = match (number_kind, ndigits_kind) {
|
||||
(Rounded::LiteralInt, Ndigits::LiteralInt)
|
||||
| (Rounded::LiteralInt | Rounded::LiteralFloat, Ndigits::NotGiven | Ndigits::LiteralNone) => {
|
||||
Applicability::Safe
|
||||
}
|
||||
|
||||
(Rounded::InferredInt, Ndigits::LiteralInt)
|
||||
| (
|
||||
Rounded::InferredInt | Rounded::InferredFloat | Rounded::Other,
|
||||
Ndigits::NotGiven | Ndigits::LiteralNone,
|
||||
) => Applicability::Unsafe,
|
||||
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let number_expr = checker.locator().slice(number);
|
||||
let new_content = format!("round({number_expr})");
|
||||
let edit = replace_with_inner(checker, outer_range, inner_range);
|
||||
|
||||
let applicability = if number_is_int {
|
||||
Applicability::Safe
|
||||
} else {
|
||||
Applicability::Unsafe
|
||||
};
|
||||
|
||||
Some(Fix::applicable_edit(
|
||||
Edit::range_replacement(new_content, outer_range),
|
||||
applicability,
|
||||
))
|
||||
}
|
||||
|
||||
fn is_int(semantic: &SemanticModel, name: &ExprName) -> bool {
|
||||
let Some(binding) = semantic.only_binding(name).map(|id| semantic.binding(id)) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
typing::is_int(binding, semantic)
|
||||
}
|
||||
|
||||
fn is_literal_zero(value: &Number) -> bool {
|
||||
let Number::Int(int) = value else {
|
||||
return false;
|
||||
};
|
||||
|
||||
matches!(int.as_u8(), Some(0))
|
||||
Some(Fix::applicable_edit(edit, applicability))
|
||||
}
|
||||
|
||||
fn replace_with_inner(checker: &Checker, outer_range: TextRange, inner_range: TextRange) -> Edit {
|
||||
|
|
|
@ -2,429 +2,566 @@
|
|||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
RUF046.py:7:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
6 | # Arguments are not checked
|
||||
7 | int(id())
|
||||
| ^^^^^^^^^ RUF046
|
||||
8 | int(len([]))
|
||||
9 | int(ord(foo))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
4 4 | ### Safely fixable
|
||||
5 5 |
|
||||
6 6 | # Arguments are not checked
|
||||
7 |-int(id())
|
||||
7 |+id()
|
||||
8 8 | int(len([]))
|
||||
9 9 | int(ord(foo))
|
||||
10 10 | int(hash(foo, bar))
|
||||
|
||||
RUF046.py:8:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
6 | # Arguments are not checked
|
||||
7 | int(id())
|
||||
8 | int(len([]))
|
||||
| ^^^^^^^^^^^^ RUF046
|
||||
9 | int(ord(foo))
|
||||
10 | int(hash(foo, bar))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
5 5 |
|
||||
6 6 | # Arguments are not checked
|
||||
7 7 | int(id())
|
||||
8 |-int(len([]))
|
||||
8 |+len([])
|
||||
9 9 | int(ord(foo))
|
||||
10 10 | int(hash(foo, bar))
|
||||
11 11 | int(int(''))
|
||||
|
||||
RUF046.py:9:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
7 | int(id())
|
||||
8 | int(len([]))
|
||||
9 | int(ord(foo))
|
||||
| ^^^^^^^^^^^^^ RUF046
|
||||
10 | int(hash(foo, bar))
|
||||
11 | int(int(''))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
6 6 | # Arguments are not checked
|
||||
7 7 | int(id())
|
||||
8 8 | int(len([]))
|
||||
9 |-int(ord(foo))
|
||||
9 |+ord(foo)
|
||||
10 10 | int(hash(foo, bar))
|
||||
11 11 | int(int(''))
|
||||
12 12 |
|
||||
|
||||
RUF046.py:10:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
8 | int(len([]))
|
||||
9 | int(ord(foo))
|
||||
10 | int(hash(foo, bar))
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
11 | int(int(''))
|
||||
8 | ### Safely fixable
|
||||
9 |
|
||||
10 | int(id())
|
||||
| ^^^^^^^^^ RUF046
|
||||
11 | int(len([]))
|
||||
12 | int(ord(foo))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
7 7 | int(id())
|
||||
8 8 | int(len([]))
|
||||
9 9 | int(ord(foo))
|
||||
10 |-int(hash(foo, bar))
|
||||
10 |+hash(foo, bar)
|
||||
11 11 | int(int(''))
|
||||
12 12 |
|
||||
13 13 | int(math.comb())
|
||||
7 7 |
|
||||
8 8 | ### Safely fixable
|
||||
9 9 |
|
||||
10 |-int(id())
|
||||
10 |+id()
|
||||
11 11 | int(len([]))
|
||||
12 12 | int(ord(foo))
|
||||
13 13 | int(hash(foo, bar))
|
||||
|
||||
RUF046.py:11:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
9 | int(ord(foo))
|
||||
10 | int(hash(foo, bar))
|
||||
11 | int(int(''))
|
||||
10 | int(id())
|
||||
11 | int(len([]))
|
||||
| ^^^^^^^^^^^^ RUF046
|
||||
12 |
|
||||
13 | int(math.comb())
|
||||
12 | int(ord(foo))
|
||||
13 | int(hash(foo, bar))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
8 8 | int(len([]))
|
||||
9 9 | int(ord(foo))
|
||||
10 10 | int(hash(foo, bar))
|
||||
11 |-int(int(''))
|
||||
11 |+int('')
|
||||
12 12 |
|
||||
13 13 | int(math.comb())
|
||||
14 14 | int(math.factorial())
|
||||
8 8 | ### Safely fixable
|
||||
9 9 |
|
||||
10 10 | int(id())
|
||||
11 |-int(len([]))
|
||||
11 |+len([])
|
||||
12 12 | int(ord(foo))
|
||||
13 13 | int(hash(foo, bar))
|
||||
14 14 | int(int(''))
|
||||
|
||||
RUF046.py:12:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
10 | int(id())
|
||||
11 | int(len([]))
|
||||
12 | int(ord(foo))
|
||||
| ^^^^^^^^^^^^^ RUF046
|
||||
13 | int(hash(foo, bar))
|
||||
14 | int(int(''))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
9 9 |
|
||||
10 10 | int(id())
|
||||
11 11 | int(len([]))
|
||||
12 |-int(ord(foo))
|
||||
12 |+ord(foo)
|
||||
13 13 | int(hash(foo, bar))
|
||||
14 14 | int(int(''))
|
||||
15 15 |
|
||||
|
||||
RUF046.py:13:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
11 | int(int(''))
|
||||
12 |
|
||||
13 | int(math.comb())
|
||||
| ^^^^^^^^^^^^^^^^ RUF046
|
||||
14 | int(math.factorial())
|
||||
15 | int(math.gcd())
|
||||
11 | int(len([]))
|
||||
12 | int(ord(foo))
|
||||
13 | int(hash(foo, bar))
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
14 | int(int(''))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
10 10 | int(hash(foo, bar))
|
||||
11 11 | int(int(''))
|
||||
12 12 |
|
||||
13 |-int(math.comb())
|
||||
13 |+math.comb()
|
||||
14 14 | int(math.factorial())
|
||||
15 15 | int(math.gcd())
|
||||
16 16 | int(math.lcm())
|
||||
10 10 | int(id())
|
||||
11 11 | int(len([]))
|
||||
12 12 | int(ord(foo))
|
||||
13 |-int(hash(foo, bar))
|
||||
13 |+hash(foo, bar)
|
||||
14 14 | int(int(''))
|
||||
15 15 |
|
||||
16 16 | int(math.comb())
|
||||
|
||||
RUF046.py:14:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
13 | int(math.comb())
|
||||
14 | int(math.factorial())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
15 | int(math.gcd())
|
||||
16 | int(math.lcm())
|
||||
12 | int(ord(foo))
|
||||
13 | int(hash(foo, bar))
|
||||
14 | int(int(''))
|
||||
| ^^^^^^^^^^^^ RUF046
|
||||
15 |
|
||||
16 | int(math.comb())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
11 11 | int(int(''))
|
||||
12 12 |
|
||||
13 13 | int(math.comb())
|
||||
14 |-int(math.factorial())
|
||||
14 |+math.factorial()
|
||||
15 15 | int(math.gcd())
|
||||
16 16 | int(math.lcm())
|
||||
17 17 | int(math.isqrt())
|
||||
|
||||
RUF046.py:15:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
13 | int(math.comb())
|
||||
14 | int(math.factorial())
|
||||
15 | int(math.gcd())
|
||||
| ^^^^^^^^^^^^^^^ RUF046
|
||||
16 | int(math.lcm())
|
||||
17 | int(math.isqrt())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
12 12 |
|
||||
13 13 | int(math.comb())
|
||||
14 14 | int(math.factorial())
|
||||
15 |-int(math.gcd())
|
||||
15 |+math.gcd()
|
||||
16 16 | int(math.lcm())
|
||||
17 17 | int(math.isqrt())
|
||||
18 18 | int(math.perm())
|
||||
11 11 | int(len([]))
|
||||
12 12 | int(ord(foo))
|
||||
13 13 | int(hash(foo, bar))
|
||||
14 |-int(int(''))
|
||||
14 |+int('')
|
||||
15 15 |
|
||||
16 16 | int(math.comb())
|
||||
17 17 | int(math.factorial())
|
||||
|
||||
RUF046.py:16:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
14 | int(math.factorial())
|
||||
15 | int(math.gcd())
|
||||
16 | int(math.lcm())
|
||||
| ^^^^^^^^^^^^^^^ RUF046
|
||||
17 | int(math.isqrt())
|
||||
18 | int(math.perm())
|
||||
14 | int(int(''))
|
||||
15 |
|
||||
16 | int(math.comb())
|
||||
| ^^^^^^^^^^^^^^^^ RUF046
|
||||
17 | int(math.factorial())
|
||||
18 | int(math.gcd())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
13 13 | int(math.comb())
|
||||
14 14 | int(math.factorial())
|
||||
15 15 | int(math.gcd())
|
||||
16 |-int(math.lcm())
|
||||
16 |+math.lcm()
|
||||
17 17 | int(math.isqrt())
|
||||
18 18 | int(math.perm())
|
||||
19 19 |
|
||||
13 13 | int(hash(foo, bar))
|
||||
14 14 | int(int(''))
|
||||
15 15 |
|
||||
16 |-int(math.comb())
|
||||
16 |+math.comb()
|
||||
17 17 | int(math.factorial())
|
||||
18 18 | int(math.gcd())
|
||||
19 19 | int(math.lcm())
|
||||
|
||||
RUF046.py:17:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
15 | int(math.gcd())
|
||||
16 | int(math.lcm())
|
||||
17 | int(math.isqrt())
|
||||
| ^^^^^^^^^^^^^^^^^ RUF046
|
||||
18 | int(math.perm())
|
||||
16 | int(math.comb())
|
||||
17 | int(math.factorial())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
18 | int(math.gcd())
|
||||
19 | int(math.lcm())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
14 14 | int(math.factorial())
|
||||
15 15 | int(math.gcd())
|
||||
16 16 | int(math.lcm())
|
||||
17 |-int(math.isqrt())
|
||||
17 |+math.isqrt()
|
||||
18 18 | int(math.perm())
|
||||
19 19 |
|
||||
20 20 |
|
||||
14 14 | int(int(''))
|
||||
15 15 |
|
||||
16 16 | int(math.comb())
|
||||
17 |-int(math.factorial())
|
||||
17 |+math.factorial()
|
||||
18 18 | int(math.gcd())
|
||||
19 19 | int(math.lcm())
|
||||
20 20 | int(math.isqrt())
|
||||
|
||||
RUF046.py:18:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
16 | int(math.lcm())
|
||||
17 | int(math.isqrt())
|
||||
18 | int(math.perm())
|
||||
| ^^^^^^^^^^^^^^^^ RUF046
|
||||
16 | int(math.comb())
|
||||
17 | int(math.factorial())
|
||||
18 | int(math.gcd())
|
||||
| ^^^^^^^^^^^^^^^ RUF046
|
||||
19 | int(math.lcm())
|
||||
20 | int(math.isqrt())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
15 15 | int(math.gcd())
|
||||
16 16 | int(math.lcm())
|
||||
17 17 | int(math.isqrt())
|
||||
18 |-int(math.perm())
|
||||
18 |+math.perm()
|
||||
19 19 |
|
||||
20 20 |
|
||||
21 21 | ### Unsafe
|
||||
15 15 |
|
||||
16 16 | int(math.comb())
|
||||
17 17 | int(math.factorial())
|
||||
18 |-int(math.gcd())
|
||||
18 |+math.gcd()
|
||||
19 19 | int(math.lcm())
|
||||
20 20 | int(math.isqrt())
|
||||
21 21 | int(math.perm())
|
||||
|
||||
RUF046.py:19:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
17 | int(math.factorial())
|
||||
18 | int(math.gcd())
|
||||
19 | int(math.lcm())
|
||||
| ^^^^^^^^^^^^^^^ RUF046
|
||||
20 | int(math.isqrt())
|
||||
21 | int(math.perm())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
16 16 | int(math.comb())
|
||||
17 17 | int(math.factorial())
|
||||
18 18 | int(math.gcd())
|
||||
19 |-int(math.lcm())
|
||||
19 |+math.lcm()
|
||||
20 20 | int(math.isqrt())
|
||||
21 21 | int(math.perm())
|
||||
22 22 |
|
||||
|
||||
RUF046.py:20:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
18 | int(math.gcd())
|
||||
19 | int(math.lcm())
|
||||
20 | int(math.isqrt())
|
||||
| ^^^^^^^^^^^^^^^^^ RUF046
|
||||
21 | int(math.perm())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
17 17 | int(math.factorial())
|
||||
18 18 | int(math.gcd())
|
||||
19 19 | int(math.lcm())
|
||||
20 |-int(math.isqrt())
|
||||
20 |+math.isqrt()
|
||||
21 21 | int(math.perm())
|
||||
22 22 |
|
||||
23 23 | int(round(1, 0))
|
||||
|
||||
RUF046.py:21:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
19 | int(math.lcm())
|
||||
20 | int(math.isqrt())
|
||||
21 | int(math.perm())
|
||||
| ^^^^^^^^^^^^^^^^ RUF046
|
||||
22 |
|
||||
23 | int(round(1, 0))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
18 18 | int(math.gcd())
|
||||
19 19 | int(math.lcm())
|
||||
20 20 | int(math.isqrt())
|
||||
21 |-int(math.perm())
|
||||
21 |+math.perm()
|
||||
22 22 |
|
||||
23 23 | int(round(1, 0))
|
||||
24 24 | int(round(1, 10))
|
||||
|
||||
RUF046.py:23:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
21 | ### Unsafe
|
||||
21 | int(math.perm())
|
||||
22 |
|
||||
23 | int(math.ceil())
|
||||
23 | int(round(1, 0))
|
||||
| ^^^^^^^^^^^^^^^^ RUF046
|
||||
24 | int(math.floor())
|
||||
25 | int(math.trunc())
|
||||
24 | int(round(1, 10))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
20 20 |
|
||||
21 21 | ### Unsafe
|
||||
ℹ Safe fix
|
||||
20 20 | int(math.isqrt())
|
||||
21 21 | int(math.perm())
|
||||
22 22 |
|
||||
23 |-int(math.ceil())
|
||||
23 |+math.ceil()
|
||||
24 24 | int(math.floor())
|
||||
25 25 | int(math.trunc())
|
||||
26 26 |
|
||||
23 |-int(round(1, 0))
|
||||
23 |+round(1, 0)
|
||||
24 24 | int(round(1, 10))
|
||||
25 25 |
|
||||
26 26 | int(round(1))
|
||||
|
||||
RUF046.py:24:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
23 | int(math.ceil())
|
||||
24 | int(math.floor())
|
||||
23 | int(round(1, 0))
|
||||
24 | int(round(1, 10))
|
||||
| ^^^^^^^^^^^^^^^^^ RUF046
|
||||
25 | int(math.trunc())
|
||||
25 |
|
||||
26 | int(round(1))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
21 21 | ### Unsafe
|
||||
ℹ Safe fix
|
||||
21 21 | int(math.perm())
|
||||
22 22 |
|
||||
23 23 | int(math.ceil())
|
||||
24 |-int(math.floor())
|
||||
24 |+math.floor()
|
||||
25 25 | int(math.trunc())
|
||||
26 26 |
|
||||
27 27 |
|
||||
23 23 | int(round(1, 0))
|
||||
24 |-int(round(1, 10))
|
||||
24 |+round(1, 10)
|
||||
25 25 |
|
||||
26 26 | int(round(1))
|
||||
27 27 | int(round(1, None))
|
||||
|
||||
RUF046.py:25:1: RUF046 [*] Value being casted is already an integer
|
||||
RUF046.py:26:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
23 | int(math.ceil())
|
||||
24 | int(math.floor())
|
||||
25 | int(math.trunc())
|
||||
| ^^^^^^^^^^^^^^^^^ RUF046
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
22 22 |
|
||||
23 23 | int(math.ceil())
|
||||
24 24 | int(math.floor())
|
||||
25 |-int(math.trunc())
|
||||
25 |+math.trunc()
|
||||
26 26 |
|
||||
27 27 |
|
||||
28 28 | ### `round()`
|
||||
|
||||
RUF046.py:31:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
30 | ## Errors
|
||||
31 | int(round(0))
|
||||
24 | int(round(1, 10))
|
||||
25 |
|
||||
26 | int(round(1))
|
||||
| ^^^^^^^^^^^^^ RUF046
|
||||
32 | int(round(0, 0))
|
||||
33 | int(round(0, None))
|
||||
27 | int(round(1, None))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
28 28 | ### `round()`
|
||||
29 29 |
|
||||
30 30 | ## Errors
|
||||
31 |-int(round(0))
|
||||
31 |+round(0)
|
||||
32 32 | int(round(0, 0))
|
||||
33 33 | int(round(0, None))
|
||||
34 34 |
|
||||
23 23 | int(round(1, 0))
|
||||
24 24 | int(round(1, 10))
|
||||
25 25 |
|
||||
26 |-int(round(1))
|
||||
26 |+round(1)
|
||||
27 27 | int(round(1, None))
|
||||
28 28 |
|
||||
29 29 | int(round(1.))
|
||||
|
||||
RUF046.py:32:1: RUF046 [*] Value being casted is already an integer
|
||||
RUF046.py:27:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
30 | ## Errors
|
||||
31 | int(round(0))
|
||||
32 | int(round(0, 0))
|
||||
| ^^^^^^^^^^^^^^^^ RUF046
|
||||
33 | int(round(0, None))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
29 29 |
|
||||
30 30 | ## Errors
|
||||
31 31 | int(round(0))
|
||||
32 |-int(round(0, 0))
|
||||
32 |+round(0)
|
||||
33 33 | int(round(0, None))
|
||||
34 34 |
|
||||
35 35 | int(round(0.1))
|
||||
|
||||
RUF046.py:33:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
31 | int(round(0))
|
||||
32 | int(round(0, 0))
|
||||
33 | int(round(0, None))
|
||||
26 | int(round(1))
|
||||
27 | int(round(1, None))
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
34 |
|
||||
35 | int(round(0.1))
|
||||
28 |
|
||||
29 | int(round(1.))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
30 30 | ## Errors
|
||||
31 31 | int(round(0))
|
||||
32 32 | int(round(0, 0))
|
||||
33 |-int(round(0, None))
|
||||
33 |+round(0)
|
||||
34 34 |
|
||||
35 35 | int(round(0.1))
|
||||
36 36 | int(round(0.1, None))
|
||||
24 24 | int(round(1, 10))
|
||||
25 25 |
|
||||
26 26 | int(round(1))
|
||||
27 |-int(round(1, None))
|
||||
27 |+round(1, None)
|
||||
28 28 |
|
||||
29 29 | int(round(1.))
|
||||
30 30 | int(round(1., None))
|
||||
|
||||
RUF046.py:29:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
27 | int(round(1, None))
|
||||
28 |
|
||||
29 | int(round(1.))
|
||||
| ^^^^^^^^^^^^^^ RUF046
|
||||
30 | int(round(1., None))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
26 26 | int(round(1))
|
||||
27 27 | int(round(1, None))
|
||||
28 28 |
|
||||
29 |-int(round(1.))
|
||||
29 |+round(1.)
|
||||
30 30 | int(round(1., None))
|
||||
31 31 |
|
||||
32 32 |
|
||||
|
||||
RUF046.py:30:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
29 | int(round(1.))
|
||||
30 | int(round(1., None))
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Safe fix
|
||||
27 27 | int(round(1, None))
|
||||
28 28 |
|
||||
29 29 | int(round(1.))
|
||||
30 |-int(round(1., None))
|
||||
30 |+round(1., None)
|
||||
31 31 |
|
||||
32 32 |
|
||||
33 33 | ### Unsafe
|
||||
|
||||
RUF046.py:35:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
33 | int(round(0, None))
|
||||
33 | ### Unsafe
|
||||
34 |
|
||||
35 | int(round(0.1))
|
||||
| ^^^^^^^^^^^^^^^ RUF046
|
||||
36 | int(round(0.1, None))
|
||||
35 | int(math.ceil())
|
||||
| ^^^^^^^^^^^^^^^^ RUF046
|
||||
36 | int(math.floor())
|
||||
37 | int(math.trunc())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
32 32 | int(round(0, 0))
|
||||
33 33 | int(round(0, None))
|
||||
32 32 |
|
||||
33 33 | ### Unsafe
|
||||
34 34 |
|
||||
35 |-int(round(0.1))
|
||||
35 |+round(0.1)
|
||||
36 36 | int(round(0.1, None))
|
||||
37 37 |
|
||||
38 38 | # Argument type is not checked
|
||||
35 |-int(math.ceil())
|
||||
35 |+math.ceil()
|
||||
36 36 | int(math.floor())
|
||||
37 37 | int(math.trunc())
|
||||
38 38 |
|
||||
|
||||
RUF046.py:36:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
35 | int(round(0.1))
|
||||
36 | int(round(0.1, None))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
37 |
|
||||
38 | # Argument type is not checked
|
||||
35 | int(math.ceil())
|
||||
36 | int(math.floor())
|
||||
| ^^^^^^^^^^^^^^^^^ RUF046
|
||||
37 | int(math.trunc())
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
33 33 | int(round(0, None))
|
||||
33 33 | ### Unsafe
|
||||
34 34 |
|
||||
35 35 | int(round(0.1))
|
||||
36 |-int(round(0.1, None))
|
||||
36 |+round(0.1)
|
||||
37 37 |
|
||||
38 38 | # Argument type is not checked
|
||||
39 39 | foo = type("Foo", (), {"__round__": lambda self: 4.2})()
|
||||
35 35 | int(math.ceil())
|
||||
36 |-int(math.floor())
|
||||
36 |+math.floor()
|
||||
37 37 | int(math.trunc())
|
||||
38 38 |
|
||||
39 39 | int(round(inferred_int, 0))
|
||||
|
||||
RUF046.py:41:1: RUF046 [*] Value being casted is already an integer
|
||||
RUF046.py:37:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
39 | foo = type("Foo", (), {"__round__": lambda self: 4.2})()
|
||||
40 |
|
||||
41 | int(round(foo))
|
||||
| ^^^^^^^^^^^^^^^ RUF046
|
||||
42 | int(round(foo, 0))
|
||||
43 | int(round(foo, None))
|
||||
35 | int(math.ceil())
|
||||
36 | int(math.floor())
|
||||
37 | int(math.trunc())
|
||||
| ^^^^^^^^^^^^^^^^^ RUF046
|
||||
38 |
|
||||
39 | int(round(inferred_int, 0))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
38 38 | # Argument type is not checked
|
||||
39 39 | foo = type("Foo", (), {"__round__": lambda self: 4.2})()
|
||||
40 40 |
|
||||
41 |-int(round(foo))
|
||||
41 |+round(foo)
|
||||
42 42 | int(round(foo, 0))
|
||||
43 43 | int(round(foo, None))
|
||||
34 34 |
|
||||
35 35 | int(math.ceil())
|
||||
36 36 | int(math.floor())
|
||||
37 |-int(math.trunc())
|
||||
37 |+math.trunc()
|
||||
38 38 |
|
||||
39 39 | int(round(inferred_int, 0))
|
||||
40 40 | int(round(inferred_int, 10))
|
||||
|
||||
RUF046.py:39:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
37 | int(math.trunc())
|
||||
38 |
|
||||
39 | int(round(inferred_int, 0))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
40 | int(round(inferred_int, 10))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
36 36 | int(math.floor())
|
||||
37 37 | int(math.trunc())
|
||||
38 38 |
|
||||
39 |-int(round(inferred_int, 0))
|
||||
39 |+round(inferred_int, 0)
|
||||
40 40 | int(round(inferred_int, 10))
|
||||
41 41 |
|
||||
42 42 | int(round(inferred_int))
|
||||
|
||||
RUF046.py:40:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
39 | int(round(inferred_int, 0))
|
||||
40 | int(round(inferred_int, 10))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
41 |
|
||||
42 | int(round(inferred_int))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
37 37 | int(math.trunc())
|
||||
38 38 |
|
||||
39 39 | int(round(inferred_int, 0))
|
||||
40 |-int(round(inferred_int, 10))
|
||||
40 |+round(inferred_int, 10)
|
||||
41 41 |
|
||||
42 42 | int(round(inferred_int))
|
||||
43 43 | int(round(inferred_int, None))
|
||||
|
||||
RUF046.py:42:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
40 | int(round(inferred_int, 10))
|
||||
41 |
|
||||
42 | int(round(inferred_int))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
43 | int(round(inferred_int, None))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
39 39 | int(round(inferred_int, 0))
|
||||
40 40 | int(round(inferred_int, 10))
|
||||
41 41 |
|
||||
42 |-int(round(inferred_int))
|
||||
42 |+round(inferred_int)
|
||||
43 43 | int(round(inferred_int, None))
|
||||
44 44 |
|
||||
45 45 | int(round(inferred_float))
|
||||
|
||||
RUF046.py:43:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
41 | int(round(foo))
|
||||
42 | int(round(foo, 0))
|
||||
43 | int(round(foo, None))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
42 | int(round(inferred_int))
|
||||
43 | int(round(inferred_int, None))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
44 |
|
||||
45 | ## No errors
|
||||
45 | int(round(inferred_float))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
40 40 |
|
||||
41 41 | int(round(foo))
|
||||
42 42 | int(round(foo, 0))
|
||||
43 |-int(round(foo, None))
|
||||
43 |+round(foo)
|
||||
40 40 | int(round(inferred_int, 10))
|
||||
41 41 |
|
||||
42 42 | int(round(inferred_int))
|
||||
43 |-int(round(inferred_int, None))
|
||||
43 |+round(inferred_int, None)
|
||||
44 44 |
|
||||
45 45 | ## No errors
|
||||
46 46 | int(round(0, 3.14))
|
||||
45 45 | int(round(inferred_float))
|
||||
46 46 | int(round(inferred_float, None))
|
||||
|
||||
RUF046.py:45:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
43 | int(round(inferred_int, None))
|
||||
44 |
|
||||
45 | int(round(inferred_float))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
46 | int(round(inferred_float, None))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
42 42 | int(round(inferred_int))
|
||||
43 43 | int(round(inferred_int, None))
|
||||
44 44 |
|
||||
45 |-int(round(inferred_float))
|
||||
45 |+round(inferred_float)
|
||||
46 46 | int(round(inferred_float, None))
|
||||
47 47 |
|
||||
48 48 | int(round(unknown))
|
||||
|
||||
RUF046.py:46:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
45 | int(round(inferred_float))
|
||||
46 | int(round(inferred_float, None))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
47 |
|
||||
48 | int(round(unknown))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
43 43 | int(round(inferred_int, None))
|
||||
44 44 |
|
||||
45 45 | int(round(inferred_float))
|
||||
46 |-int(round(inferred_float, None))
|
||||
46 |+round(inferred_float, None)
|
||||
47 47 |
|
||||
48 48 | int(round(unknown))
|
||||
49 49 | int(round(unknown, None))
|
||||
|
||||
RUF046.py:48:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
46 | int(round(inferred_float, None))
|
||||
47 |
|
||||
48 | int(round(unknown))
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
49 | int(round(unknown, None))
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
45 45 | int(round(inferred_float))
|
||||
46 46 | int(round(inferred_float, None))
|
||||
47 47 |
|
||||
48 |-int(round(unknown))
|
||||
48 |+round(unknown)
|
||||
49 49 | int(round(unknown, None))
|
||||
50 50 |
|
||||
51 51 |
|
||||
|
||||
RUF046.py:49:1: RUF046 [*] Value being casted is already an integer
|
||||
|
|
||||
48 | int(round(unknown))
|
||||
49 | int(round(unknown, None))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF046
|
||||
|
|
||||
= help: Remove unnecessary conversion to `int`
|
||||
|
||||
ℹ Unsafe fix
|
||||
46 46 | int(round(inferred_float, None))
|
||||
47 47 |
|
||||
48 48 | int(round(unknown))
|
||||
49 |-int(round(unknown, None))
|
||||
49 |+round(unknown, None)
|
||||
50 50 |
|
||||
51 51 |
|
||||
52 52 | ### No errors
|
||||
|
|
|
@ -665,6 +665,14 @@ impl BuiltinTypeChecker for IntChecker {
|
|||
const EXPR_TYPE: PythonType = PythonType::Number(NumberLike::Integer);
|
||||
}
|
||||
|
||||
struct FloatChecker;
|
||||
|
||||
impl BuiltinTypeChecker for FloatChecker {
|
||||
const BUILTIN_TYPE_NAME: &'static str = "float";
|
||||
const TYPING_NAME: Option<&'static str> = None;
|
||||
const EXPR_TYPE: PythonType = PythonType::Number(NumberLike::Float);
|
||||
}
|
||||
|
||||
pub struct IoBaseChecker;
|
||||
|
||||
impl TypeChecker for IoBaseChecker {
|
||||
|
@ -850,6 +858,11 @@ pub fn is_int(binding: &Binding, semantic: &SemanticModel) -> bool {
|
|||
check_type::<IntChecker>(binding, semantic)
|
||||
}
|
||||
|
||||
/// Test whether the given binding can be considered an instance of `float`.
|
||||
pub fn is_float(binding: &Binding, semantic: &SemanticModel) -> bool {
|
||||
check_type::<FloatChecker>(binding, semantic)
|
||||
}
|
||||
|
||||
/// Test whether the given binding can be considered a set.
|
||||
///
|
||||
/// For this, we check what value might be associated with it through it's initialization and
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue