GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-132661: Disallow `Template`/`str` concatenation after PEP 750 spec update by davepeck · Pull Request #135996 · python/cpython

Conversation

@davepeck

@davepeck davepeck commented Jun 26, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Following the steering council decision and corresponding update to PEP750, we are removing support for both implicit and explicit Template/str concatenation.

  • Issue: Implement PEP 750 – Template Strings #132661

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

gpshead and efimov-mikhail reacted with rocket emoji
All reactions
  • 🚀 2 reactions
davepeck added 2 commits June 26, 2025 17:46
@davepeck
Disallow explicit concat between Template and str
5d5e187
@davepeck
First pass at removing implicit Template/str concat
1cc778f
@bedevere-app bedevere-app Bot mentioned this pull request Jun 26, 2025
Implement PEP 750 – Template Strings #132661
Closed
sobolevn
sobolevn reviewed Jun 26, 2025
View reviewed changes

@sobolevn sobolevn left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Thank you!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Parser/action_helpers.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/unicodeobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_tstring.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@davepeck
Merge branch 'main' into pep750-concat-update
7ea498c
@lysnikolaou

lysnikolaou commented Jun 30, 2025

Copy link
Copy Markdown
Member

Happy to do this with your input, or happy to hand it off to you!

Happy to help out / review this PR if you wanna take a stab at it. Feel free to reach out if you have any specific questions.

davepeck reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@dylwil3 dylwil3 mentioned this pull request Jul 4, 2025
Add t-string fixtures for rules that do not need to be modified astral-sh/ruff#19146
Merged
davepeck added 8 commits July 8, 2025 12:50
@davepeck
Merge branch 'main' into pep750-concat-update
d08c8b8
@davepeck
Remove extraneous newline
c662041
@davepeck
Add expected exception messages to tests
b17b7c9
@davepeck
Remove _ast_unparse t/f implicit concat helper code
a0c1bb6
@davepeck
Merge branch 'main' into pep750-concat-update
23988e8
@davepeck
Add a parallel comment
d7eadec
@davepeck
Add news blurb for PR.
cb1ad63
@davepeck
One day, I may develop RST muscle memory.
741eaf2
Today was, alas, not that day.
@davepeck
davepeck marked this pull request as ready for review July 8, 2025 23:27
@davepeck
davepeck requested review from Eclips4, JelleZijlstra, isidentical, lysnikolaou, pablogsal and tomasr8 as code owners July 8, 2025 23:27
@bedevere-app bedevere-app Bot added the awaiting review label Jul 8, 2025
@davepeck

davepeck commented Jul 8, 2025

Copy link
Copy Markdown
Contributor Author

@lysnikolaou Think this is ready. The only question for me is whether we want to go further with _PyPegen_concatenate_strings().

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@davepeck
Merge branch 'main' into pep750-concat-update
8aeb512
JelleZijlstra
JelleZijlstra approved these changes Jul 9, 2025
View reviewed changes
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting review labels Jul 9, 2025
sobolevn
sobolevn reviewed Jul 9, 2025
View reviewed changes

@sobolevn sobolevn left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Thank you! Several small nitpicks :)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

davepeck reacted with heart emoji
All reactions
  • ❤️ 1 reaction
Comment thread Lib/test/test_tstring.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_tstring.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_tstring.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Misc/NEWS.d/next/Core_and_Builtins/2025-07-08-23-22-08.gh-issue-132661.34ftJl.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/templateobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

lysnikolaou
lysnikolaou requested changes Jul 9, 2025
View reviewed changes

@lysnikolaou lysnikolaou left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Thanks @davepeck for working on this! Looks great in general. Left a few unimportant comments and one more significant one about how to implement this in the parser. Also, we'll need to change ast_unparse.c around https://github.com/python/cpython/blob/main/Python/ast_unparse.c#L715.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

davepeck reacted with heart emoji
All reactions
  • ❤️ 1 reaction
Comment thread Lib/test/test_tstring.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/templateobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Parser/action_helpers.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@davepeck
Fix exception assert message checks
6ea3af3
@efimov-mikhail

efimov-mikhail commented Jul 16, 2025

Copy link
Copy Markdown
Member

LGTM

davepeck reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lysnikolaou

lysnikolaou commented Jul 17, 2025

Copy link
Copy Markdown
Member

Looks great and aaalmost there. I have one last thing I missed during my previous reviews.

If I remember correctly, https://github.com/python/cpython/blob/main/Python/codegen.c#L4084-L4093 can be removed as well, because it's only there to handle FormattedValues, which cannot happen anymore.

After that, it's gonna be good to go, promise!

davepeck reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@davepeck
Remove no-longer used path in codegen.c
5037f89
@davepeck
davepeck requested review from iritkatriel and markshannon as code owners July 17, 2025 15:59
@davepeck

davepeck commented Jul 17, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

If I remember correctly, https://github.com/python/cpython/blob/main/Python/codegen.c#L4084-L4093 can be removed as well, because it's only there to handle FormattedValues, which cannot happen anymore.

@lysnikolaou Ah, yes -- thank you. Removed now; tests continue to pass.

(If we prefer, I can replace VISIT() in the else block with a direct ADDOP_LOAD_CONST(). I'd probably add an assert(value->kind == Constant_kind) there, too.)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

lysnikolaou
lysnikolaou approved these changes Jul 21, 2025
View reviewed changes

@lysnikolaou lysnikolaou left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Looks good to me! Thanks @davepeck! Great work.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

davepeck reacted with heart emoji efimov-mikhail reacted with rocket emoji
All reactions
  • ❤️ 1 reaction
  • 🚀 1 reaction
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting change review labels Jul 21, 2025
@lysnikolaou lysnikolaou added the needs backport to 3.14 bugs and security fixes label Jul 21, 2025
@lysnikolaou
lysnikolaou merged commit c5e77af into python:main Jul 21, 2025
@miss-islington-app

miss-islington-app Bot commented Jul 21, 2025

Copy link
Copy Markdown

Thanks @davepeck for the PR, and @lysnikolaou for merging it 🌮🎉.. I'm working now to backport this PR to: 3.14.
🐍🍒⛏🤖

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lysnikolaou
lysnikolaou deleted the pep750-concat-update branch July 21, 2025 06:44
@bedevere-app bedevere-app Bot removed the awaiting merge label Jul 21, 2025
@miss-islington-app

miss-islington-app Bot commented Jul 21, 2025

Copy link
Copy Markdown

Sorry, @davepeck and @lysnikolaou, I could not cleanly backport this to 3.14 due to a conflict.
Please backport using cherry_picker on command line.

cherry_picker c5e77af131aa0c8832a9ee50c4410731254e4209 3.14
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@miss-islington-app miss-islington-app Bot assigned lysnikolaou Jul 21, 2025
@lysnikolaou

lysnikolaou commented Jul 21, 2025

Copy link
Copy Markdown
Member

I can handle tha backport.

davepeck reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

lysnikolaou added a commit to lysnikolaou/cpython that referenced this pull request Jul 21, 2025
@davepeck @sobolevn @lysnikolaou
pythongh-132661: Disallow Template/str concatenation after PEP 75…
9ef8d31
…0 spec update (python#135996)

Co-authored-by: sobolevn <[email protected]>
Co-authored-by: Lysandros Nikolaou <[email protected]>
(cherry picked from commit c5e77af)
lysnikolaou added a commit that referenced this pull request Jul 21, 2025
@lysnikolaou @davepeck @sobolevn
[3.14] gh-132661: Disallow Template/str concatenation after PEP 7…
af8d1f5
…50 spec update (#135996) (#136901)

Co-authored-by: Dave Peck <[email protected]>
Co-authored-by: sobolevn <[email protected]>
@dylwil3 dylwil3 mentioned this pull request Jul 25, 2025
Disallow implicit concatenation of t-strings and other string types astral-sh/ruff#19485
Merged
dylwil3 added a commit to astral-sh/ruff that referenced this pull request Jul 27, 2025
@dylwil3
Disallow implicit concatenation of t-strings and other string types (#…
008bbfd
…19485)

As of [this cpython PR](python/cpython#135996),
it is not allowed to concatenate t-strings with non-t-strings,
implicitly or explicitly. Expressions such as `"foo" t"{bar}"` are now
syntax errors.

This PR updates some AST nodes and parsing to reflect this change.

The structural change is that `TStringPart` is no longer needed, since,
as in the case of `BytesStringLiteral`, the only possibilities are that
we have a single `TString` or a vector of such (representing an implicit
concatenation of t-strings). This removes a level of nesting from many
AST expressions (which is what all the snapshot changes reflect), and
simplifies some logic in the implementation of visitors, for example.

The other change of note is in the parser. When we meet an implicit
concatenation of string-like literals, we now count the number of
t-string literals. If these do not exhaust the total number of
implicitly concatenated pieces, then we emit a syntax error. To recover
from this syntax error, we encode any t-string pieces as _invalid_
string literals (which means we flag them as invalid, record their
range, and record the value as `""`). Note that if at least one of the
pieces is an f-string we prefer to parse the entire string as an
f-string; otherwise we parse it as a string.

This logic is exactly the same as how we currently treat
`BytesStringLiteral` parsing and error recovery - and carries with it
the same pros and cons.

Finally, note that I have not implemented any changes in the
implementation of the formatter. As far as I can tell, none are needed.
I did change a few of the fixtures so that we are always concatenating
t-strings with t-strings.
taegyunkim pushed a commit to taegyunkim/cpython that referenced this pull request Aug 4, 2025
@davepeck @sobolevn
@lysnikolaou @taegyunkim
pythongh-132661: Disallow Template/str concatenation after PEP 75…
7f6e070
…0 spec update (python#135996)

Co-authored-by: sobolevn <[email protected]>
Co-authored-by: Lysandros Nikolaou <[email protected]>
@serhiy-storchaka

serhiy-storchaka commented Aug 14, 2025

Copy link
Copy Markdown
Member

Reminder about backporting. @davepeck @lysnikolaou

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@encukou

encukou commented Aug 15, 2025

Copy link
Copy Markdown
Member

GH-136901 is a backport of this pull request to the 3.14 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@encukou encukou removed the needs backport to 3.14 bugs and security fixes label Aug 15, 2025
Agent-Hellboy pushed a commit to Agent-Hellboy/cpython that referenced this pull request Aug 19, 2025
@davepeck @sobolevn
@lysnikolaou @Agent-Hellboy
pythongh-132661: Disallow Template/str concatenation after PEP 75…
b23afac
…0 spec update (python#135996)

Co-authored-by: sobolevn <[email protected]>
Co-authored-by: Lysandros Nikolaou <[email protected]>
kumaraditya303 pushed a commit to miss-islington/cpython that referenced this pull request Sep 9, 2025
@lysnikolaou @davepeck
@sobolevn @kumaraditya303
[3.14] pythongh-132661: Disallow Template/str concatenation after…
73305f0
… PEP 750 spec update (python#135996) (python#136901)

Co-authored-by: Dave Peck <[email protected]>
Co-authored-by: sobolevn <[email protected]>
KotlinIsland pushed a commit to KotlinIsland/basedpython that referenced this pull request May 1, 2026
@dylwil3
Add t-string fixtures for rules that do not need to be modified (#19146)
d96deab
I used a script to attempt to identify those rules with the following
property: changing f-strings to t-strings in the corresponding fixture
altered the number of lint errors emitted. In other words, those rules
for which f-strings and t-strings are not treated the same in the
current implementation.

This PR documents the subset of such rules where this is fine and no
changes need to be made to the implementation of the rule. Mostly these
are the rules where it is relevant that an f-string evaluates to type
`str` at runtime whereas t-strings do not.

In theory many of these fixtures are not super necessary - it's unlikely
t-strings would be used for most of these. However, the internal
handling of t-strings is tightly coupled with that of f-strings, and may
become even more so as we implement the upcoming changes due to
python/cpython#135996 . So I'd like to keep
these around as regression tests.

Note: The `flake8-bandit` fixtures were already added during the
original t-string implementation.

| Rule(s) | Reason |
| --- | --- |
| [`unused-method-argument`
(`ARG002`)](https://docs.astral.sh/ruff/rules/unused-method-argument/#unused-method-argument-arg002)
| f-strings exempted for msg in `NotImplementedError` not relevant for
t-strings |
| [`logging-f-string`
(`G004`)](https://docs.astral.sh/ruff/rules/logging-f-string/#logging-f-string-g004)
| t-strings cannot be used here |
| [`f-string-in-get-text-func-call`
(`INT001`)](https://docs.astral.sh/ruff/rules/f-string-in-get-text-func-call/#f-string-in-get-text-func-call-int001)
| rule justified by eager evaluation of interpolations |
| [`flake8-bandit`](https://docs.astral.sh/ruff/rules/#flake8-bandit-s)|
rules justified by eager evaluation of interpolations |
| [`single-string-slots`
(`PLC0205`)](https://docs.astral.sh/ruff/rules/single-string-slots/#single-string-slots-plc0205)
| t-strings cannot be slots in general |
| [`unnecessary-encode-utf8`
(`UP012`)](https://docs.astral.sh/ruff/rules/unnecessary-encode-utf8/#unnecessary-encode-utf8-up012)
| cannot encode t-strings |
| [`no-self-use`
(`PLR6301`)](https://docs.astral.sh/ruff/rules/no-self-use/#no-self-use-plr6301)
| f-strings exempted for msg in NotImplementedError not relevant for
t-strings |
| [`pytest-raises-too-broad`
(`PT011`)](https://docs.astral.sh/ruff/rules/pytest-raises-too-broad/) /
[`pytest-fail-without-message`
(`PT016`)](https://docs.astral.sh/ruff/rules/pytest-fail-without-message/#pytest-fail-without-message-pt016)
/ [`pytest-warns-too-broad`
(`PT030`)](https://docs.astral.sh/ruff/rules/pytest-warns-too-broad/#pytest-warns-too-broad-pt030)
| t-strings cannot be empty or used as messages |
| [`assert-on-string-literal`
(`PLW0129`)](https://docs.astral.sh/ruff/rules/assert-on-string-literal/#assert-on-string-literal-plw0129)
| t-strings are not strings and cannot be empty |
| [`native-literals`
(`UP018`)](https://docs.astral.sh/ruff/rules/native-literals/#native-literals-up018)
| t-strings are not native literals |
KotlinIsland pushed a commit to KotlinIsland/basedpython that referenced this pull request May 1, 2026
@dylwil3
Disallow implicit concatenation of t-strings and other string types (…
c6f0b4a
…#19485)

As of [this cpython PR](python/cpython#135996),
it is not allowed to concatenate t-strings with non-t-strings,
implicitly or explicitly. Expressions such as `"foo" t"{bar}"` are now
syntax errors.

This PR updates some AST nodes and parsing to reflect this change.

The structural change is that `TStringPart` is no longer needed, since,
as in the case of `BytesStringLiteral`, the only possibilities are that
we have a single `TString` or a vector of such (representing an implicit
concatenation of t-strings). This removes a level of nesting from many
AST expressions (which is what all the snapshot changes reflect), and
simplifies some logic in the implementation of visitors, for example.

The other change of note is in the parser. When we meet an implicit
concatenation of string-like literals, we now count the number of
t-string literals. If these do not exhaust the total number of
implicitly concatenated pieces, then we emit a syntax error. To recover
from this syntax error, we encode any t-string pieces as _invalid_
string literals (which means we flag them as invalid, record their
range, and record the value as `""`). Note that if at least one of the
pieces is an f-string we prefer to parse the entire string as an
f-string; otherwise we parse it as a string.

This logic is exactly the same as how we currently treat
`BytesStringLiteral` parsing and error recovery - and carries with it
the same pros and cons.

Finally, note that I have not implemented any changes in the
implementation of the formatter. As far as I can tell, none are needed.
I did change a few of the fixtures so that we are always concatenating
t-strings with t-strings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@sobolevn sobolevn sobolevn left review comments
@efimov-mikhail efimov-mikhail efimov-mikhail left review comments
@lysnikolaou lysnikolaou lysnikolaou approved these changes
@Eclips4 Eclips4 Awaiting requested review from Eclips4 Eclips4 is a code owner
@tomasr8 tomasr8 Awaiting requested review from tomasr8 tomasr8 is a code owner
@isidentical isidentical Awaiting requested review from isidentical isidentical is a code owner
@pablogsal pablogsal Awaiting requested review from pablogsal pablogsal is a code owner
@JelleZijlstra JelleZijlstra Awaiting requested review from JelleZijlstra JelleZijlstra is a code owner
@markshannon markshannon Awaiting requested review from markshannon markshannon is a code owner
@iritkatriel iritkatriel Awaiting requested review from iritkatriel iritkatriel is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@lysnikolaou lysnikolaou

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

8 participants

@davepeck @lysnikolaou @pablogsal @efimov-mikhail @serhiy-storchaka @encukou @JelleZijlstra @sobolevn
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.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.