Skip to content

gh-132661: Disallow Template/str concatenation after PEP 750 spec update #135996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 27 commits into
base: main
Choose a base branch
from

Conversation

davepeck
Copy link
Contributor

@davepeck davepeck commented Jun 26, 2025

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

Copy link
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

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

Thank you!

@lysnikolaou
Copy link
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 davepeck marked this pull request as ready for review July 8, 2025 23:27
@davepeck
Copy link
Contributor Author

davepeck commented Jul 8, 2025

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

Copy link
Member

@sobolevn sobolevn left a 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 :)

Copy link
Member

@lysnikolaou lysnikolaou left a 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.

Comment on lines 1890 to 1894
// Cannot mix strings/f-strings and t-strings
if ((unicode_string_found || f_string_found) && t_string_found) {
RAISE_SYNTAX_ERROR("cannot mix str and Template literals");
return NULL;
}
Copy link
Member

Choose a reason for hiding this comment

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

This is not the way to do this. Instead, we should be doing this at the parser level. Right now we're doing this:

atom[expr_ty]:
    | NAME
    | 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
    | 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
    | 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
    | &(STRING|FSTRING_START|TSTRING_START) strings  # This'll change
    | NUMBER
    | &'(' (tuple | group | genexp)
    | &'[' (list | listcomp)
    | &'{' (dict | set | dictcomp | setcomp)
    | '...' { _PyAST_Constant(Py_Ellipsis, NULL, EXTRA) }

strings[expr_ty] (memo): a[asdl_expr_seq*]=(fstring|string|tstring)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }

Instead, we should be doing something like:

atom[expr_ty]:
    | NAME
    | 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
    | 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
    | 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
    | &(STRING|FSTRING_START) strings  # We now have two alternatives
    | &TSTRING_START tstrings
    | NUMBER
    | &'(' (tuple | group | genexp)
    | &'[' (list | listcomp)
    | &'{' (dict | set | dictcomp | setcomp)
    | '...' { _PyAST_Constant(Py_Ellipsis, NULL, EXTRA) }

tstrings[expr_ty] (memo): a[asdl_expr_seq*]=tstring+ { <new action here> }
strings[expr_ty] (memo): a[asdl_expr_seq*]=(fstring|string)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }

Notice how instead of intermixing the three rules in one sequence, we can now only mix strings and fstrings, but tstrings can only be concatenated with other tstrings. The new action should probably be _build_concatenated_template_str renamed with a _PyPegen prefix, but I'm not sure whether that'll work unchanged, it might need some editing. Also, some of the invalid_* rules might need changing.

Copy link
Contributor Author

@davepeck davepeck Jul 9, 2025

Choose a reason for hiding this comment

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

Sure thing, will do.

I just wasn't sure we wanted the extra complexity in the grammar.

Copy link
Contributor Author

@davepeck davepeck Jul 10, 2025

Choose a reason for hiding this comment

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

@lysnikolaou Would you be okay with something more along the lines of:

strings[expr_ty] (memo):
    | invalid_string_tstring_concat
    | a[asdl_expr_seq*]=(fstring|string)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }
    | a[asdl_expr_seq*]=tstring+ { _PyPegen_concatenate_tstrings(p, a, EXTRA) }

...

invalid_string_tstring_concat:
    | (fstring|string)+ a[expr_ty]=tstring { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot mix t-strings with strings or f-strings") }
    | tstring+ a[expr_ty]=(fstring|string) { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot mix t-strings with strings or f-strings") }

or do we prefer separating strings from tstrings (and I guess having two different invalid rules)

Copy link
Member

Choose a reason for hiding this comment

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

Sure, this looks even better. Can we use RAISE_SYNTAX_ERROR_KNOWN_RANGE instead of KNOWN_LOCATION so that the error is a bit clearer?

Copy link
Member

Choose a reason for hiding this comment

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

Also, is this ready for another review or should I wait for a ping from you?

Copy link
Contributor Author

@davepeck davepeck Jul 10, 2025

Choose a reason for hiding this comment

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

Can we use RAISE_SYNTAX_ERROR_KNOWN_RANGE

Ah, yeah, that'd be nicer; will do. I guess the "ideal" range would include exactly two neighboring literals that conflict.

Also, is this ready for another review or should I wait for a ping from you?

Not yet, I'll ping you. Thanks! (Still have more to tease apart in action_helpers.c and also need to tackle ast_unparse.)

@bedevere-app
Copy link

bedevere-app bot commented Jul 9, 2025

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

davepeck and others added 10 commits July 9, 2025 12:20
Co-authored-by: sobolevn <mail@sobolevn.me>
…e-132661.34ftJl.rst

Co-authored-by: sobolevn <mail@sobolevn.me>
Squashed commit of the following:

commit 0941a3088578c1a8002e58ea6e11527bedf0e81e
Author: Dave <davepeck@gmail.com>
Date:   Thu Jul 10 01:49:24 2025 +0000

    Maybe cleaner?

commit e5a69c851a0f43a4e84325051a37de20282dd810
Author: Dave <davepeck@gmail.com>
Date:   Wed Jul 9 23:17:58 2025 +0000

    In progress: update grammar
@pablogsal
Copy link
Member

Screenshot 2025-07-10 at 16 31 27

The universe is at peace :)

@davepeck
Copy link
Contributor Author

davepeck commented Jul 10, 2025

The universe is at peace :)

Getting closer:
Screenshot 2025-07-10 at 9 20 46 AM

I will not rest until it is perfectly at peace, even I if have to commit uncompilable atrocities. :-P

@davepeck
Copy link
Contributor Author

davepeck commented Jul 10, 2025

@lysnikolaou

Okay, I think this is ready! Updated the grammar and actions; fixed up ast_unparse.c.

Two questions:

  1. I suppose we could break _build_concatenated_str() in action_helpers.c into two separate routines. But given how much duplicated logic there would be around flattening/concatenating/re-folding, I decided to leave it untouched. Let me know if you'd like me to tease this apart further.

  2. Because t-string/non-t-string concat errors are handled in the grammar, but bytes/nonbytes are handled in action_helpers.c, t"foo" b"bar" results in the syntax error "cannot mix t-strings with strings or f-strings". Are we okay with that?

(PS: dear Bedevere: I have made the requested changes; please review again)

@bedevere-app
Copy link

bedevere-app bot commented Jul 10, 2025

Thanks for making the requested changes!

@lysnikolaou, @JelleZijlstra: please review the changes made to this pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy