From 0af4b23d9f5f6b77046a0fd1311d2e65b747dfaf Mon Sep 17 00:00:00 2001 From: Dylan <53534755+dylwil3@users.noreply.github.com> Date: Sun, 9 Feb 2025 10:16:28 -0600 Subject: [PATCH] [`ruff`] Skip type definitions for `missing-f-string-syntax` (`RUF027`) (#16054) As an f-string is never correct in a type definition context, we skip [missing-f-string-syntax (RUF027)](https://docs.astral.sh/ruff/rules/missing-f-string-syntax/#missing-f-string-syntax-ruf027) in this case. Closes #16037 --- .../ruff_linter/resources/test/fixtures/ruff/RUF027_0.py | 7 +++++++ .../src/rules/ruff/rules/missing_fstring_syntax.rs | 5 +++++ ...uff_linter__rules__ruff__tests__RUF027_RUF027_0.py.snap | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/crates/ruff_linter/resources/test/fixtures/ruff/RUF027_0.py b/crates/ruff_linter/resources/test/fixtures/ruff/RUF027_0.py index 4780348c12..e5bef3033f 100644 --- a/crates/ruff_linter/resources/test/fixtures/ruff/RUF027_0.py +++ b/crates/ruff_linter/resources/test/fixtures/ruff/RUF027_0.py @@ -72,3 +72,10 @@ def method_calls(): def format_specifiers(): a = 4 b = "{a:b} {a:^5}" + +# fstrings are never correct as type definitions +# so we should always skip those +def in_type_def(): + from typing import cast + a = 'int' + cast('f"{a}"','11') diff --git a/crates/ruff_linter/src/rules/ruff/rules/missing_fstring_syntax.rs b/crates/ruff_linter/src/rules/ruff/rules/missing_fstring_syntax.rs index 05c7cb54f4..73c77ccdba 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/missing_fstring_syntax.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/missing_fstring_syntax.rs @@ -73,6 +73,11 @@ impl AlwaysFixableViolation for MissingFStringSyntax { pub(crate) fn missing_fstring_syntax(checker: &Checker, literal: &ast::StringLiteral) { let semantic = checker.semantic(); + // fstrings are never correct as type definitions + if semantic.in_type_definition() { + return; + } + // we want to avoid statement expressions that are just a string literal. // there's no reason to have standalone f-strings and this lets us avoid docstrings too if let ast::Stmt::Expr(ast::StmtExpr { value, .. }) = semantic.current_statement() { diff --git a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF027_RUF027_0.py.snap b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF027_RUF027_0.py.snap index 2973ba2930..590ff57921 100644 --- a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF027_RUF027_0.py.snap +++ b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF027_RUF027_0.py.snap @@ -306,6 +306,8 @@ RUF027_0.py:74:9: RUF027 [*] Possible f-string without an `f` prefix 73 | a = 4 74 | b = "{a:b} {a:^5}" | ^^^^^^^^^^^^^^ RUF027 +75 | +76 | # fstrings are never correct as type definitions | = help: Add `f` prefix @@ -315,3 +317,6 @@ RUF027_0.py:74:9: RUF027 [*] Possible f-string without an `f` prefix 73 73 | a = 4 74 |- b = "{a:b} {a:^5}" 74 |+ b = f"{a:b} {a:^5}" +75 75 | +76 76 | # fstrings are never correct as type definitions +77 77 | # so we should always skip those