Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ruff] Detect more strict-integer expressions (RUF046) #14833

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

InSyncWithFoo
Copy link
Contributor

Summary

Part 2 of the big change introduced in #14828 and the follow-up to #14832.

Test Plan

cargo nextest run and cargo insta test.

@InSyncWithFoo InSyncWithFoo changed the title [ruff] Do not simplify round() calls (RUF046) [ruff] Detect more strict-integer expressions (RUF046) Dec 8, 2024
Copy link
Contributor

github-actions bot commented Dec 8, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+2 -0 violations, +0 -0 fixes in 2 projects; 53 projects unchanged)

milvus-io/pymilvus (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview

+ pymilvus/orm/schema.py:827:53: RUF046 [*] Value being casted is already an integer

rotki/rotki (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview

+ rotkehlchen/tests/utils/ethereum.py:231:15: RUF046 [*] Value being casted is already an integer

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
RUF046 2 2 0 0 0

@MichaReiser
Copy link
Member

Hmm, I can't change the base branch if the target is from a fork. I'll wait reviewing this PR until the target is merged.

@MichaReiser
Copy link
Member

Would you mind writing a short summary of what you're changing in the PR description? It's hard to review code if the change is unclear.

Did you review through the ecosystem changes? It's unclear to me why we're no longer flagging

https://github.com/RasaHQ/rasa/blob/b8de3b231126747ff74b2782cb25cb22d2d898d7/rasa/shared/core/training_data/loading.py#L86

@InSyncWithFoo
Copy link
Contributor Author

@MichaReiser These changes are all expected, even if they don't seem correct at first sight. For example:

#                                                   vvvvvvvvvvvvv Not `int`.
def load_data_from_files(..., exclusion_percentage: Optional[int] = None) -> ...:
    ...
#                   vvvvvvvvvvvvvvvvvvvvvvvvvvvv This is classified as "Maybe" rather than "Likely".
    idx = int(round(exclusion_percentage / 100.0 * len(story_steps)))
#                   \______This thus might also not be `int`______/

However, I also agree that this is suboptimal. round() with no ndigits is indeed likely to produce an int. In any case, since #14832 and this have diverged, I can only work on improving this after the former is merged.

Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind updating your PR with a short summary outlining the change? It's otherwise very difficult to review the PR without even knowing what the intended behavior is.

@InSyncWithFoo
Copy link
Contributor Author

The goal of this PR is to correctly detect 1 & 1 and other kinds of expressions to be strict instances of int. Other cases can be found in RUF046.py.

To give an example, int(len(foo) // 2) would not be detected as a violation prior to this PR. It now is. Existing violations are also preserved.

There are, however, limitations. foo is not bar is classified as IsStrictlyInt::False, resulting in 1 + (foo is not bar) being IsStrictlyInt::Maybe, even though 1 + True is 2.

@MichaReiser
Copy link
Member

Thanks for the extra explanation. That's helpful.

I don't think the pattern is common enough to justify the increase in complexity. Unless we move some of the logic into typing::is_int where it can be used for other rules as well.

@InSyncWithFoo
Copy link
Contributor Author

InSyncWithFoo commented Dec 12, 2024

@MichaReiser On the other hand, it is:

That's without function calls, variables and such.

There's also \bint\(\s*\d+\s*/\s*\d+\s*\) with ~900 results, but I suppose that should be another rule.

@MichaReiser
Copy link
Member

I'm not suggesting that we should not improve the rule at all, but I'm wary of making rules unnecessarily complex by implementing too much ad hoc type inference. It results in inconsistent behavior between rules and makes Ruff harder to maintain.

Can we focus on the most important cases you outlined above: single numbers, mathematical expressions, and a few known function calls? It also makes me wonder if we could move some or most of the logic into typing::is_int (we can only move the "strict" part). The logic would then benefit all rules instead of just a few.

@InSyncWithFoo
Copy link
Contributor Author

InSyncWithFoo commented Dec 14, 2024

Can we focus on the most important cases you outlined above: single numbers, mathematical expressions, and a few known function calls?

But I'm already focused on such expressions. All three kinds you mention, yes. expr_is_strictly_int() just recurses into subexpressions, nothing more. I really don't think I can simplify it any further (save for the Expr::Compare branch?).

typing::is_int() attempts to infer the type of a binding, not an arbitrary expression. I could move expr_is_strictly_int() to somewhere inside typing, but that's about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants