Skip to content

Conversation

naslundx
Copy link
Contributor

@naslundx naslundx commented Mar 3, 2025

Summary

Introducing a new rule based on discussions in #15732 and #15729 that checks for unnecessary in with empty collections.

I called it in_empty_collection and gave the rule number PLR6202 but of course open for suggestions/clarifications.

Technically fixable (can be replaced by boolean or, if in an if-statement, removed entirely) and can implement that as well if it makes sense.

Rule is in preview group. (Tried following https://docs.astral.sh/ruff/contributing/#example-adding-a-new-lint-rule as best I could)

Test Plan

Tried locally against sample code. Added unit test, and created snapshot.

Copy link
Contributor

github-actions bot commented Mar 3, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

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

zulip/zulip (+2 -0 violations, +0 -0 fixes)

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

+ tools/lib/provision.py:153:28: RUF060 Unnecessary membership test on empty collection
+ tools/lib/provision.py:153:73: RUF060 Unnecessary membership test on empty collection

pytest-dev/pytest (+3 -0 violations, +0 -0 fixes)

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

+ testing/test_assertrewrite.py:630:20: RUF060 Unnecessary membership test on empty collection
+ testing/test_assertrewrite.py:630:32: RUF060 Unnecessary membership test on empty collection
+ testing/test_assertrewrite.py:637:39: RUF060 Unnecessary membership test on empty collection

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
RUF060 5 5 0 0 0

@ntBre ntBre added the rule Implementing or modifying a lint rule label Mar 3, 2025
@naslundx naslundx force-pushed the add-rule-in-empty-collection branch 2 times, most recently from 5c4b0a1 to b122182 Compare March 3, 2025 20:24
@MichaReiser
Copy link
Member

@dylwil3 would you mind taking a look at this? I think you've most context on the change as you've been involved in both linked issues

Copy link
Collaborator

@dylwil3 dylwil3 left a comment

Choose a reason for hiding this comment

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

Thanks @naslundx , this looks nice! One thing is that my comment in the linked issue was that we should open a separate issue to decide whether this should be a rule, but we never actually did that.

So would you be willing to propose this as a rule in a new issue, and link this PR to it? Then we can see what folks think and do some design/decision-making there.

If we do decide to go ahead with this rule, then we'll also probably have to move it to a RUF rule, otherwise there will be a clash when pylint adds an R6202.

@naslundx
Copy link
Contributor Author

naslundx commented Mar 8, 2025

Thanks @dylwil3 ! Created an issue here and to reach a decision #16569

Will let the PR rest until then.

@@ -0,0 +1,19 @@
# Errors
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you also detect something like this?

a=[]
b= 7
if b in a:
    pass

I think is possible or?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With the current implementation, no. If there are mechanisms implemented to allow for this, please point me in the right direction!

Copy link
Collaborator

Choose a reason for hiding this comment

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

Something like this may be possible when the symbol is defined in the same file, but it would be a bit tricky to do reliably especially when there is complicated control flow. I think we can look into extending the rule to cover this case later, but for now I think we should stick with catching literals.

@naslundx naslundx force-pushed the add-rule-in-empty-collection branch from b122182 to 37779a5 Compare May 4, 2025 18:40
Copy link
Collaborator

@dylwil3 dylwil3 left a comment

Choose a reason for hiding this comment

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

Thanks for this! Would you mind adding a few more containers and tests for them?

func,
arguments,
range: _,
}) => semantic.match_builtin_expr(func, "set") && arguments.is_empty(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

We certainly at least want list, tuple, and dict here as well, but maybe we also want:

  • a match arm for strings, bytes literals, and f-strings of length zero?
  • the remaining builtin functions that create empty containers, which I think are: bytearray, bytes, frozenset, and str

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, that makes a lot of sense! The f-string was a bit tricky to figure out but I think I got it right.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updates are in a new commit

@naslundx naslundx force-pushed the add-rule-in-empty-collection branch from 953b74a to e4a4e8f Compare May 5, 2025 14:21
@naslundx
Copy link
Contributor Author

naslundx commented May 5, 2025

we'll also probably have to move it to a RUF rule, otherwise there will be a clash when pylint adds an R6202.

Lmk if I should change the code @dylwil3

@dylwil3
Copy link
Collaborator

dylwil3 commented May 5, 2025

Lmk if I should change the code @dylwil3

Yes thank you for the reminder! Looks like you're lucky number RUF060

Copy link
Collaborator

@dylwil3 dylwil3 left a comment

Choose a reason for hiding this comment

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

Almost there! One nit and then we'll need to move the rule to RUF060. Thanks for bearing with me!

Comment on lines 57 to 60
Expr::FString(s) => match s.as_single_part_fstring() {
Some(FString { elements, .. }) => elements.is_empty(),
_ => false,
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this won't catch implicit concatenation like "a" in f"" "", so maybe:

Suggested change
Expr::FString(s) => match s.as_single_part_fstring() {
Some(FString { elements, .. }) => elements.is_empty(),
_ => false,
},
Expr::FString(s) => s
.value
.elements()
.all(|elt| elt.as_literal().is_some_and(|elt| elt.is_empty())),

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

@naslundx naslundx force-pushed the add-rule-in-empty-collection branch from e4a4e8f to b29590c Compare May 6, 2025 07:44
@naslundx naslundx force-pushed the add-rule-in-empty-collection branch from b29590c to f66df9d Compare May 6, 2025 07:49
@naslundx
Copy link
Contributor Author

naslundx commented May 6, 2025

Change rule number to RUF060 ✔️

Copy link
Collaborator

@dylwil3 dylwil3 left a comment

Choose a reason for hiding this comment

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

This is a great contribution, and I was really impressed with how comfortable you got with the codebase so quickly! Thank you!

@dylwil3 dylwil3 enabled auto-merge (squash) May 6, 2025 13:51
@dylwil3 dylwil3 merged commit 76b6d53 into astral-sh:main May 6, 2025
33 checks passed
Glyphack pushed a commit to Glyphack/ruff that referenced this pull request May 6, 2025
## Summary

Introducing a new rule based on discussions in astral-sh#15732 and astral-sh#15729 that
checks for unnecessary in with empty collections.

I called it in_empty_collection and gave the rule number RUF060.

Rule is in preview group.
@naslundx
Copy link
Contributor Author

naslundx commented May 7, 2025

Thanks a lot @dylwil3 !
I think there is still some room for improvement on this rule, I'll take another look when I find some time. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rule Implementing or modifying a lint rule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants