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] Needless else clause (RUF047) #15051

Merged
merged 5 commits into from
Jan 21, 2025
Merged

Conversation

InSyncWithFoo
Copy link
Contributor

Summary

Partially addresses #13929.

Test Plan

cargo nextest run and cargo insta test.

Copy link
Contributor

github-actions bot commented Dec 19, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

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

apache/airflow (+4 -0 violations, +0 -0 fixes)

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

+ providers/src/airflow/providers/google/cloud/operators/bigquery.py:1638:9: RUF047 [*] Empty `else` clause
+ providers/tests/fab/auth_manager/api_endpoints/test_asset_endpoint.py:38:5: RUF047 [*] Empty `else` clause
+ providers/tests/fab/auth_manager/api_endpoints/test_dag_run_endpoint.py:44:5: RUF047 [*] Empty `else` clause
+ tests/models/test_taskinstance.py:2388:17: RUF047 [*] Empty `else` clause

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

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

+ lnbits/core/crud.py:791:5: RUF047 [*] Empty `else` clause
+ lnbits/core/crud.py:800:5: RUF047 [*] Empty `else` clause

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
RUF047 6 6 0 0 0

@MichaReiser MichaReiser added rule Implementing or modifying a lint rule preview Related to preview mode features labels Dec 19, 2024
@MichaReiser MichaReiser self-assigned this Dec 19, 2024
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.

Thanks.

I refactored your rule to remove some duplication and simplified it to only detect single pass or ... statements. PIE790 detects bodies containing both a ... and a pass statement.

I further extended the test cases and there's one case where we fail to detect a useless else because of the comment and one case where we marked the else as useless when we should not. We have to take the indent of the comments into consideration. See

fn handle_own_line_comment_between_branches<'a>(
and
fn handle_own_line_comment_after_branch<'a>(

Maybe we can come up with a simpler heuristic for this specific case?

@InSyncWithFoo
Copy link
Contributor Author

InSyncWithFoo commented Dec 19, 2024

@MichaReiser If indentation is to be taken into consideration, should this be reported or not?

if test:
    _4_spaces()
  # 2 spaces
else:
    ...

What about this?

if test:
	_1_tab()  # These two lines would align if tabs are displayed as 1 character wide.
 # 1 space
else:
	...

# Same question, but for 2, 3, 4 spaces?

@MichaReiser
Copy link
Member

We should implement it so that it's consistent with the formatter. Your examples get formatted to

if test:
    _1_tab()  # These two lines would align if tabs are displayed as 1 character wide.
    # 1 space
else:
    ...

# Same question, but for 2, 3, 4 spaces?

if test:
    _4_spaces()
# 2 spaces
else:
    ...

@MichaReiser
Copy link
Member

@InSyncWithFoo do you plan to follow up on this PR?

@InSyncWithFoo
Copy link
Contributor Author

@MichaReiser Yes.

@InSyncWithFoo
Copy link
Contributor Author

InSyncWithFoo commented Jan 20, 2025

Took me long enough. I think I got most of it, save for this one:

if a:
	b()
else:
	...
	# comment

I have no idea how to detect that comment: it's not included within else_range. I thought about manual tokens processing, but then I wouldn't know when to stop, because there might not be a next statement at all. Iterating all comments is a lot more expensive than necessary, so that's not a good choice either.

@MichaReiser
Copy link
Member

I have no idea how to detect that comment: it's not included within else_range. I thought about manual tokens processing, but then I wouldn't know when to stop, because there might not be a next statement at all. Iterating all comments is a lot more expensive than necessary, so that's not a good choice either.

I would use the tokens and start at the end of the else_range and skip all tokens until it finds the first new line token. From there, keep taking all tokens until you find the first non-trivia token that isn't a comment. For all comments in that range, test if the indent of the comment is larger than the indent of the else header. If so -> it belongs to the else body. You can stop as soon as you've found the first comment that doesn't belong to the else body.

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.

Nice

@MichaReiser MichaReiser enabled auto-merge (squash) January 21, 2025 08:16
@MichaReiser MichaReiser merged commit c616650 into astral-sh:main Jan 21, 2025
20 checks passed
@InSyncWithFoo InSyncWithFoo deleted the RUF047 branch January 21, 2025 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
preview Related to preview mode features rule Implementing or modifying a lint rule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants