Skip to content

Conversation

@danparizher
Copy link
Contributor

@danparizher danparizher commented Oct 24, 2025

Summary

Fixes #21033 (RUF027) to suppress f-string suggestions for strings containing backslashes in interpolation expressions when targeting Python versions below 3.12, preventing syntax errors.

Problem Analysis

RUF027 was suggesting f-string conversions for strings with backslashes in interpolation expressions (e.g., "{'\\n'}"), but f-strings with backslashes in interpolations are only valid syntax in Python 3.12+. This caused syntax errors when the fix was applied to code targeting older Python versions.

The issue occurred because the should_be_fstring function was checking for backslashes anywhere in the string literal, rather than specifically within the interpolation expressions where the syntax restriction applies.

Approach

Added a version check in the should_be_fstring function to suppress RUF027 for strings containing backslashes within interpolation expressions when the target Python version is below 3.12. This ensures:

  • For Python < 3.12: RUF027 is suppressed for strings with backslashes in interpolations (e.g., "{'\\n'}{x}")
  • For Python ≥ 3.12: RUF027 works normally for strings with backslashes in interpolations

@github-actions
Copy link
Contributor

github-actions bot commented Oct 24, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@dscorbett
Copy link

Backslashes in f-strings aren’t the problem.

>>> f"\n"
'\n'

The problem is backslashes in f-string interpolations.

>>> f"{'\n'}"
  File "<stdin>", line 1
    f"{'\n'}"
             ^
SyntaxError: f-string expression part cannot include a backslash

Updated the RUF027 rule to only skip f-string suggestions for Python < 3.12 when backslashes appear in interpolations, not in the entire string. Adjusted test cases and snapshots to reflect this refined behavior.
@danparizher danparizher changed the title [ruff] Suppress strings with backslashes before Python 3.12 (RUF027) [ruff] Suppress strings with backslashes in interpolations before Python 3.12 (RUF027) Oct 25, 2025
@ntBre
Copy link
Contributor

ntBre commented Oct 27, 2025

I just worked on two issues for our syntax error related to this: #20867 and #20949. I think the fix here is similar to the incorrect code I had originally in the parser, which turned out to be too naive in the presence of nested interpolations. To summarize the two issues, code like this is valid on 3.11:

>>> f"{1:\"d\"}"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Invalid format specifier '"d"' for object of type 'int'

Note the ValueError, not an f-string syntax error. It looks like the code here would flag this because it's within the interpolation but not within the interpolation expression.

In contrast, code like this is still invalid on 3.11 because it's in the expression part of a nested interpolation:

>>> f'{1: abcd "{'aa'}" }'
  File "<stdin>", line 1
    f'{1: abcd "{'aa'}" }'
                  ^^
SyntaxError: f-string: expecting '}'

But the interpolations iterator doesn't recurse into nested interpolations, so the fix is also not as easy as only checking the expression part (that's what I got wrong in #20867).

It might be fair to be more conservative here since it's almost definitely easier to implement, but I wanted to mention this since it was relevant.

literal: &ast::StringLiteral,
locator: &Locator,
semantic: &SemanticModel,
checker: &Checker,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we could drop the locator and semantic arguments if we're passing the Checker they both come from. Alternatively, we could pass only the target_version, which is the only additional field we're accessing now.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should add a variant of this test where we use a Python version before 3.12. This is still showing a diagnostic being emitted.

@ntBre ntBre added bug Something isn't working fixes Related to suggested fixes for violations labels Oct 27, 2025
Updates the MissingFStringSyntax rule to correctly skip diagnostics for f-string interpolations containing backslashes when targeting Python 3.11, matching Python's behavior. Adds a dedicated test and snapshot to verify the change.
@danparizher danparizher requested a review from ntBre October 27, 2025 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working fixes Related to suggested fixes for violations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RUF027 creates invalid f-string interpolations with backslashes before Python 3.12

3 participants