Repository navigation
Alternate nested quotes inside format spec interpolations - #28259
Merged
MichaReiser merged 4 commits intoSep 7, 2026
Merged
Conversation
A replacement field inside a format spec belongs to the same string as the field enclosing it, but it was being treated as a further level of nesting. Before Python 3.12 that made the formatter preserve the inner quotes and reuse the outer quote character, which is a syntax error the parser rejects. Only entering another string literal is a further level of nesting, so keep the state unchanged for format spec fields.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
cargo hawk flags them as unnecessarily visible: both are only used inside the module that defines them.
Format-spec interpolations belong to the containing f-string or t-string. Advance the nesting depth when entering a string, and retain each interpolation’s own layout context without introducing format-spec markers. Regression: astral-sh#28218
Member
|
Thank you. I made a few smaller changes, mainly to avoid introducing more state. The implementation now has an explicit |
1 task
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #28218.
When Ruff formats an f-string, it normally alternates the inner quotes so they don't conflict with the outer ones. For example, a normal interpolation like
f'x {d["k"]} y'is formatted asf"x {d['k']} y".However, this didn't work correctly for interpolations inside a format spec. For example,
f'x {v:,.{d["n"]}f} y'was left with{d["n"]}using the same quote character as the outer f-string.Reusing the outer quote character inside an f-string is only valid starting with Python 3.12, thanks to PEP 701. With
target-version = "py311", this meant Ruff's formatter could produce code that its own checker would reject with:Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12)The issue was caused by how Ruff tracks nesting inside interpolated strings. A field inside a format spec was incorrectly treated as an additional nesting level, even though it's still part of the same f-string and doesn't introduce another string literal.
That incorrect nesting level caused the formatter to preserve the existing quotes for Python versions before 3.12. In this case, preserving them resulted in invalid Python 3.11 syntax.
The fix is to only increase the nesting level when entering another string literal. Entering a format spec does not count as deeper string nesting, so fields inside format specs now stay at the current nesting level.