Skip to content

Conversation

@danparizher
Copy link
Contributor

Summary

Fixed FURB101 (read-whole-file) to handle annotated assignments. Previously, the rule would detect violations in code like contents: str = f.read() but fail to generate a fix. Now it correctly generates fixes that preserve type annotations (e.g., contents: str = Path("file.txt").read_text(encoding="utf-8")).

Fixes #21274

Problem Analysis

The FURB101 rule was only checking for Stmt::Assign statements when determining whether a fix could be applied. When encountering annotated assignments (Stmt::AnnAssign) like contents: str = f.read(), the rule would:

  1. Correctly detect the violation (the diagnostic was reported)
  2. Fail to generate a fix because:
    • The visit_expr method only matched Stmt::Assign, not Stmt::AnnAssign
    • The generate_fix function only accepted Stmt::Assign in its body validation
    • The replacement code generation didn't account for type annotations

This occurred because Python's AST represents annotated assignments as a different node type (StmtAnnAssign) with separate fields for the target, annotation, and value, unlike regular assignments which use a list of targets.

Approach

The fix extends the rule to handle both assignment types:

  1. Updated visit_expr method: Now matches both Stmt::Assign and Stmt::AnnAssign, extracting:

    • Variable name from the target expression
    • Type annotation code (when present) using the code generator
  2. Updated generate_fix function:

    • Added annotation: Option<String> parameter to accept annotation code
    • Updated body validation to accept both Stmt::Assign and Stmt::AnnAssign
    • Modified replacement code generation to preserve annotations: {var}: {annotation} = {binding}({filename_code}).{suggestion}
  3. Added test case: Added an annotated assignment test case to verify the fix works correctly.

The implementation maintains backward compatibility with regular assignments while adding support for annotated assignments, ensuring type annotations are preserved in the generated fixes.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 5, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

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

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

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

+ providers/amazon/src/airflow/providers/amazon/aws/hooks/base_aws.py:1005:18: FURB101 [*] `open` and `read` should be replaced by `Path(self.waiter_path).read_text()`
- providers/amazon/src/airflow/providers/amazon/aws/hooks/base_aws.py:1005:18: FURB101 `open` and `read` should be replaced by `Path(self.waiter_path).read_text()`

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

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

+ zerver/lib/export.py:1729:10: FURB101 [*] `open` and `read` should be replaced by `Path(input_path).read_bytes()`
- zerver/lib/export.py:1729:10: FURB101 `open` and `read` should be replaced by `Path(input_path).read_bytes()`
+ zerver/lib/import_realm.py:1214:10: FURB101 [*] `open` and `read` should be replaced by `Path(migration_status_filename).read_text()`
- zerver/lib/import_realm.py:1214:10: FURB101 `open` and `read` should be replaced by `Path(migration_status_filename).read_text()`
+ zerver/lib/import_realm.py:998:10: FURB101 [*] `open` and `read` should be replaced by `Path(records_filename).read_bytes()`
- zerver/lib/import_realm.py:998:10: FURB101 `open` and `read` should be replaced by `Path(records_filename).read_bytes()`
+ zerver/lib/management.py:282:18: FURB101 [*] `open` and `read` should be replaced by `Path(options["password_file"]).read_text()`
- zerver/lib/management.py:282:18: FURB101 `open` and `read` should be replaced by `Path(options["password_file"]).read_text()`
+ zerver/management/commands/send_custom_email.py:118:22: FURB101 [*] `open` and `read` should be replaced by `Path(options["json_file"]).read_text()`
- zerver/management/commands/send_custom_email.py:118:22: FURB101 `open` and `read` should be replaced by `Path(options["json_file"]).read_text()`
+ zerver/management/commands/send_custom_email.py:233:18: FURB101 [*] `open` and `read` should be replaced by `Path(options["json_file"]).read_text()`
- zerver/management/commands/send_custom_email.py:233:18: FURB101 `open` and `read` should be replaced by `Path(options["json_file"]).read_text()`

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
FURB101 14 0 0 14 0

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.

Annotations block the FURB101 fix

1 participant