Skip to content

Avoid emitting multi-line f-string elements before Python 3.12#24377

Merged
charliermarsh merged 1 commit into
mainfrom
charlie/formatter-multiline
Apr 5, 2026
Merged

Avoid emitting multi-line f-string elements before Python 3.12#24377
charliermarsh merged 1 commit into
mainfrom
charlie/formatter-multiline

Conversation

@charliermarsh

Copy link
Copy Markdown
Member

Summary

See: #24355 (comment). Prior to Python 3.12, we need to avoid emitting formatted expressions that span multiple lines in non-triple quoted f-strings.

@charliermarsh charliermarsh added bug Something isn't working formatter Related to the formatter labels Apr 2, 2026
@charliermarsh charliermarsh force-pushed the charlie/formatter-multiline branch from 1ac515a to 2af1535 Compare April 2, 2026 21:08
@astral-sh-bot

astral-sh-bot Bot commented Apr 2, 2026

Copy link
Copy Markdown

ruff-ecosystem results

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

```python
if f"aaaaaaaaaaa {[ttttteeeeeeeeest]} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is actually invalid on Python 3.11, but the input is already invalid in this case, so I think it's within the bounds of the formatter contract?

@charliermarsh charliermarsh marked this pull request as ready for review April 2, 2026 21:09
@MichaReiser

Copy link
Copy Markdown
Member

I'll review on Tuesday. What's the underlying issue here. Is it that the formatter sometimes formats an interpolation over multiple lines if the f-string contains another multiline interpolation?

@charliermarsh charliermarsh force-pushed the charlie/parser-multiline branch from 03d8338 to da1acf5 Compare April 3, 2026 14:00
@charliermarsh charliermarsh force-pushed the charlie/formatter-multiline branch from 2af1535 to 215c43d Compare April 3, 2026 14:00
@charliermarsh

Copy link
Copy Markdown
Member Author

Is it that the formatter sometimes formats an interpolation over multiple lines if the f-string contains another multiline interpolation?

Yeah that's right. So I'm unclear if we actually consider this a bug, because I think the code has to be syntactically invalid already in order for this to trigger? In other words, we're introducing another syntax error, but the code was already invalid in another interpolation.

@MichaReiser

Copy link
Copy Markdown
Member

Yeah. I guess it does make it worse. I was mainly curious to understand how rigorous we need to be (e.g. can a triple quoted f-string that's nested in a single quoted f-string contain newlines?)

@charliermarsh

Copy link
Copy Markdown
Member Author

Thinking about it more, I'm sort of inclined to just treat this as a wontfix. I don't know that it's worth the time / concern / complexity.

@dylwil3

dylwil3 commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

This warning in the formatter tests seems to implicitly say it's okay to have syntax errors if they were also present in the source:

let sub = SubDiagnostic::new(
SubDiagnosticSeverity::Warning,
"Only accept new syntax errors if they are also present in the input. \
The formatter should not introduce syntax errors.",

So I think wontfix makes sense. (Are we even technically adding a new syntax error? Or just making the existing one "worse"?)

@MichaReiser MichaReiser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm fine either way and agree that I don't consider this a bug, but not introducing more syntax errors seems preferable, and the added complexity is limited.

Thank you

@charliermarsh charliermarsh force-pushed the charlie/parser-multiline branch 3 times, most recently from 3144fb7 to d2cd4d1 Compare April 5, 2026 15:04
Base automatically changed from charlie/parser-multiline to main April 5, 2026 15:09
@charliermarsh charliermarsh force-pushed the charlie/formatter-multiline branch from 215c43d to a24edfe Compare April 5, 2026 15:10
@charliermarsh charliermarsh enabled auto-merge (squash) April 5, 2026 15:10
@charliermarsh charliermarsh merged commit 1fe1c5f into main Apr 5, 2026
42 checks passed
@charliermarsh charliermarsh deleted the charlie/formatter-multiline branch April 5, 2026 15:14
nicopauss pushed a commit to Intersec/lib-common that referenced this pull request Jun 4, 2026
##### [\`v0.15.10\`](https://github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#01510)

Released on 2026-04-09.

##### Preview features

- \[`flake8-logging`] Allow closures in except handlers (`LOG004`) ([#24464](astral-sh/ruff#24464))
- \[`flake8-self`] Make `SLF` diagnostics robust to non-self-named variables ([#24281](astral-sh/ruff#24281))
- \[`flake8-simplify`] Make the fix for `collapsible-if` safe in `preview` (`SIM102`) ([#24371](astral-sh/ruff#24371))

##### Bug fixes

- Avoid emitting multi-line f-string elements before Python 3.12 ([#24377](astral-sh/ruff#24377))
- Avoid syntax error from `E502` fixes in f-strings and t-strings ([#24410](astral-sh/ruff#24410))
- Strip form feeds from indent passed to `dedent_to` ([#24381](astral-sh/ruff#24381))
- \[`pyupgrade`] Fix panic caused by handling of octals (`UP012`) ([#24390](astral-sh/ruff#24390))
- Reject multi-line f-string elements before Python 3.12 ([#24355](astral-sh/ruff#24355))

##### Rule changes

- \[`ruff`] Treat f-string interpolation as potential side effect (`RUF019`) ([#24426](astral-sh/ruff#24426))

##### Server

- Add support for custom file extensions ([#24463](astral-sh/ruff#24463))

##### Documentation

- Document adding fixes in CONTRIBUTING.md ([#24393](astral-sh/ruff#24393))
- Fix JSON typo in settings example ([#24517](astral-sh/ruff#24517))

##### Contributors

- [@charliermarsh](https://github.com/charliermarsh)
- [@dylwil3](https://github.com/dylwil3)
- [@silverstein](https://github.com/silverstein)
- [@anishgirianish](https://github.com/anishgirianish)
- [@shizukushq](https://github.com/shizukushq)
- [@zanieb](https://github.com/zanieb)
- [@AlexWaygood](https://github.com/AlexWaygood)
##### [\`v0.15.9\`](https://github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#0159)

Released on 2026-04-02.

##### Preview features

- \[`pyflakes`] Flag annotated variable redeclarations as `F811` in preview mode ([#24244](astral-sh/ruff#24244))
- \[`ruff`] Allow dunder-named assignments in non-strict mode for `RUF067` ([#24089](astral-sh/ruff#24089))

##### Bug fixes

- \[`flake8-errmsg`] Avoid shadowing existing `msg` in fix for `EM101` ([#24363](astral-sh/ruff#24363))
- \[`flake8-simplify`] Ignore pre-initialization references in `SIM113` ([#24235](astral-sh/ruff#24235))
- \[`pycodestyle`] Fix `W391` fixes for consecutive empty notebook cells ([#24236](astral-sh/ruff#24236))
- \[`pyupgrade`] Fix `UP008` nested class matching ([#24273](astral-sh/ruff#24273))
- \[`pyupgrade`] Ignore strings with string-only escapes (`UP012`) ([#16058](astral-sh/ruff#16058))
- \[`ruff`] `RUF072`: skip formfeeds on dedent ([#24308](astral-sh/ruff#24308))
- \[`ruff`] Avoid re-using symbol in `RUF024` fix ([#24316](astral-sh/ruff#24316))
- \[`ruff`] Parenthesize expression in `RUF050` fix ([#24234](astral-sh/ruff#24234))
- Disallow starred expressions as values of starred expressions ([#24280](astral-sh/ruff#24280))

##### Rule changes

- \[`flake8-simplify`] Suppress `SIM105` for `except*` before Python 3.12 ([#23869](astral-sh/ruff#23869))
- \[`pyflakes`] Extend `F507` to flag `%`-format strings with zero placeholders ([#24215](astral-sh/ruff#24215))
- \[`pyupgrade`] `UP018` should detect more unnecessarily wrapped literals (UP018) ([#24093](astral-sh/ruff#24093))
- \[`pyupgrade`] Fix `UP008` callable scope handling to support lambdas ([#24274](astral-sh/ruff#24274))
- \[`ruff`] `RUF010`: Mark fix as unsafe when it deletes a comment ([#24270](astral-sh/ruff#24270))

##### Formatter

- Add `nested-string-quote-style` formatting option ([#24312](astral-sh/ruff#24312))

##### Documentation

- \[`flake8-bugbear`] Clarify RUF071 fix safety for non-path string comparisons ([#24149](astral-sh/ruff#24149))
- \[`flake8-type-checking`] Clarify import cycle wording for `TC001`/`TC002`/`TC003` ([#24322](astral-sh/ruff#24322))

##### Other changes

- Avoid rendering fix lines with trailing whitespace after `|` ([#24343](astral-sh/ruff#24343))

##### Contributors

- [@charliermarsh](https://github.com/charliermarsh)
- [@MichaReiser](https://github.com/MichaReiser)
- [@tranhoangtu-it](https://github.com/tranhoangtu-it)
- [@dylwil3](https://github.com/dylwil3)
- [@zsol](https://github.com/zsol)
- [@renovate](https://github.com/renovate)
- [@bitloi](https://github.com/bitloi)
- [@danparizher](https://github.com/danparizher)
- [@chinar-amrutkar](https://github.com/chinar-amrutkar)
- [@second-ed](https://github.com/second-ed)
- [@getehen](https://github.com/getehen)
- [@Redovo1](https://github.com/Redovo1)
- [@matthewlloyd](https://github.com/matthewlloyd)
- [@zanieb](https://github.com/zanieb)
- [@InSyncWithFoo](https://github.com/InSyncWithFoo)
- [@RenzoMXD](https://github.com/RenzoMXD)

Renovate-Branch: renovate/2024.6-ruff-0.15.x
Change-Id: Id4bd542d4f128b509284d9dcda312f2b39c29964
Priv-Id: 28ebcacdeffa50cec7a52eee59091a75ca5e9539
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working formatter Related to the formatter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants