Skip to content

Commit

Permalink
[ruff] Detect more strict-integer expressions and move round() lo…
Browse files Browse the repository at this point in the history
…gic to new rule (`RUF046`, `RUF057`)
  • Loading branch information
InSyncWithFoo committed Dec 7, 2024
1 parent 8fdd880 commit 86e00a8
Show file tree
Hide file tree
Showing 12 changed files with 1,921 additions and 390 deletions.
110 changes: 91 additions & 19 deletions crates/ruff_linter/resources/test/fixtures/ruff/RUF046.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

### Safely fixable

# Arguments are not checked
int(id())
int(len([]))
int(ord(foo))
Expand All @@ -17,34 +16,107 @@
int(math.isqrt())
int(math.perm())

int(1)
int(v := 1)
int(~1)
int(-1)
int(+1)

int(1 + 1)
int(1 - 1)
int(1 * 1)
int(1 % 1)
int(1 ** 1)
int(1 << 1)
int(1 >> 1)
int(1 | 1)
int(1 ^ 1)
int(1 & 1)
int(1 // 1)

int(1 if ... else 2)

int(round(1))
int(round(1, None))
int(round(1, 0))


### Unsafe

int(math.ceil())
int(math.floor())
int(math.trunc())

int(1 and 0)
int(0 or -1)

async def f():
int(await f())

int(foo.bar)
int(bar([1][False]))

int(1 == 2 == 3)
int(foo == 1)
int(foo != 1)
int(foo < 1)
int(foo <= 1)
int(foo > 1)
int(foo >= 1)

int(v := {}[{}['']])

int(foo + 1)
int(foo - 1)
int(foo * 1)
int(foo @ 1)
int(foo / 1)
int(foo % 1)
int(foo ** 1)
int(foo << 1)
int(foo >> 1)
int(foo | 1)
int(foo ^ 1)
int(foo & 1)
int(foo // 1)

int(foo if ... else 4)

int(round())
int(round(ndigits=2))
int(round(3.4))
int(round(3.4, 0))
int(round(3.4, 2))
int(round(5, foo))


### No errors

int(3.14)
int(2.8j)

### `round()`
int(1 == 1)
int(1 != 1)
int(1 < 1)
int(1 <= 1)
int(1 > 1)
int(1 >= 1)
int(1 in 1)
int(1 not in 1)
int(1 is 1)
int(2 is not 3)
int(foo in 1)
int(foo not in 1)
int(foo is 1)
int(foo is not 1)

## Errors
int(round(0))
int(round(0, 0))
int(round(0, None))
int(v := 3.7)

int(round(0.1))
int(round(0.1, None))
int(not 109)

# Argument type is not checked
foo = type("Foo", (), {"__round__": lambda self: 4.2})()
int(1 / 1)
int(1 @ 1)

int(round(foo))
int(round(foo, 0))
int(round(foo, None))
int(1. if ... else .2)

## No errors
int(round(0, 3.14))
int(round(0, non_literal))
int(round(0, 0), base)
int(round(0, 0, extra=keyword))
int(round(0.1, 0))
int(round(5, 1))
35 changes: 35 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/ruff/RUF057.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
foo = 1
bar = 0
qux = 0.


### Errors

round(1, 0)
round(1, ndigits=0)
round(number=1, ndigits=0)

round(1, ndigits=None)
round(number=1, ndigits=None)

round(1., 0)
round(1., ndigits=0)
round(number=1., ndigits=0)

round(1., None)
round(1., ndigits=None)
round(number=1., ndigits=None)

round(foo, None)
round(foo, ndigits=None)
round(number=foo, ndigits=None)

### No errors

round(1, 1)
round(1, bar)
round(1., bar)
round(1., 0)
round(foo, bar)
round(0, 3.14)
round(0, 0, extra=keyword)
3 changes: 3 additions & 0 deletions crates/ruff_linter/src/checkers/ast/analyze/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
if checker.enabled(Rule::DotlessPathlibWithSuffix) {
flake8_use_pathlib::rules::dotless_pathlib_with_suffix(checker, call);
}
if checker.enabled(Rule::UnnecessaryRoundNdigits) {
ruff::rules::unnecessary_round_ndigits(checker, call);
}
}
Expr::Dict(dict) => {
if checker.any_enabled(&[
Expand Down
1 change: 1 addition & 0 deletions crates/ruff_linter/src/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Ruff, "048") => (RuleGroup::Preview, rules::ruff::rules::MapIntVersionParsing),
(Ruff, "052") => (RuleGroup::Preview, rules::ruff::rules::UsedDummyVariable),
(Ruff, "055") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryRegularExpression),
(Ruff, "057") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryRoundNdigits),
(Ruff, "100") => (RuleGroup::Stable, rules::ruff::rules::UnusedNOQA),
(Ruff, "101") => (RuleGroup::Stable, rules::ruff::rules::RedirectedNOQA),

Expand Down
2 changes: 2 additions & 0 deletions crates/ruff_linter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
//!
//! [Ruff]: https://github.com/astral-sh/ruff
extern crate core;

pub use locator::Locator;
pub use noqa::generate_noqa_edits;
#[cfg(feature = "clap")]
Expand Down
1 change: 1 addition & 0 deletions crates/ruff_linter/src/rules/ruff/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ mod tests {
#[test_case(Rule::UnnecessaryRegularExpression, Path::new("RUF055_0.py"))]
#[test_case(Rule::UnnecessaryRegularExpression, Path::new("RUF055_1.py"))]
#[test_case(Rule::UnnecessaryCastToInt, Path::new("RUF046.py"))]
#[test_case(Rule::UnnecessaryRoundNdigits, Path::new("RUF057.py"))]
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(
"preview__{}_{}",
Expand Down
2 changes: 2 additions & 0 deletions crates/ruff_linter/src/rules/ruff/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub(crate) use unnecessary_iterable_allocation_for_first_element::*;
pub(crate) use unnecessary_key_check::*;
pub(crate) use unnecessary_nested_literal::*;
pub(crate) use unnecessary_regular_expression::*;
pub(crate) use unnecessary_round_ndigits::*;
pub(crate) use unraw_re_pattern::*;
pub(crate) use unsafe_markup_use::*;
pub(crate) use unused_async::*;
Expand Down Expand Up @@ -84,6 +85,7 @@ mod unnecessary_iterable_allocation_for_first_element;
mod unnecessary_key_check;
mod unnecessary_nested_literal;
mod unnecessary_regular_expression;
mod unnecessary_round_ndigits;
mod unraw_re_pattern;
mod unsafe_markup_use;
mod unused_async;
Expand Down
Loading

0 comments on commit 86e00a8

Please sign in to comment.