https://github.com/python/cpython/commit/b451516aa69df357af829c6a9f773fb51862b5b8 commit: b451516aa69df357af829c6a9f773fb51862b5b8 branch: main author: sobolevn <m...@sobolevn.me> committer: sobolevn <m...@sobolevn.me> date: 2025-04-30T19:20:44+03:00 summary:
gh-133197: Improve error message for `ft""` and `bt""` cases (#133202) files: M Lib/test/test_syntax.py M Parser/lexer/lexer.c diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 55492350d00714..7ef4b735fcb805 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1877,6 +1877,22 @@ Traceback (most recent call last): SyntaxError: cannot assign to f-string expression here. Maybe you meant '==' instead of '='? +>>> ft'abc' +Traceback (most recent call last): +SyntaxError: can't use 'f' and 't' string prefixes together + +>>> tf"{x=}" +Traceback (most recent call last): +SyntaxError: can't use 'f' and 't' string prefixes together + +>>> tb'' +Traceback (most recent call last): +SyntaxError: can't use 'b' and 't' string prefixes together + +>>> bt"text" +Traceback (most recent call last): +SyntaxError: can't use 'b' and 't' string prefixes together + >>> t'{x}' = 42 Traceback (most recent call last): SyntaxError: cannot assign to t-string expression here. Maybe you meant '==' instead of '='? diff --git a/Parser/lexer/lexer.c b/Parser/lexer/lexer.c index ca01cab9937a85..98adf7447c5626 100644 --- a/Parser/lexer/lexer.c +++ b/Parser/lexer/lexer.c @@ -648,7 +648,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t /* Process the various legal combinations of b"", r"", u"", and f"". */ int saw_b = 0, saw_r = 0, saw_u = 0, saw_f = 0, saw_t = 0; while (1) { - if (!(saw_b || saw_u || saw_f || saw_t) && (c == 'b' || c == 'B')) + if (!(saw_b || saw_u || saw_f) && (c == 'b' || c == 'B')) saw_b = 1; /* Since this is a backwards compatibility support literal we don't want to support it in arbitrary order like byte literals. */ @@ -660,10 +660,10 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t else if (!(saw_r || saw_u) && (c == 'r' || c == 'R')) { saw_r = 1; } - else if (!(saw_f || saw_b || saw_u || saw_t) && (c == 'f' || c == 'F')) { + else if (!(saw_f || saw_b || saw_u) && (c == 'f' || c == 'F')) { saw_f = 1; } - else if (!(saw_t || saw_b || saw_u || saw_f) && (c == 't' || c == 'T')) { + else if (!(saw_t || saw_u) && (c == 't' || c == 'T')) { saw_t = 1; } else { @@ -671,6 +671,20 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t } c = tok_nextc(tok); if (c == '"' || c == '\'') { + if (saw_b && saw_t) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror_known_range( + tok, (int)(tok->start + 1 - tok->line_start), + (int)(tok->cur - tok->line_start), + "can't use 'b' and 't' string prefixes together")); + } + if (saw_f && saw_t) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror_known_range( + tok, (int)(tok->start + 1 - tok->line_start), + (int)(tok->cur - tok->line_start), + "can't use 'f' and 't' string prefixes together")); + } + + // Handle valid f or t string creation: if (saw_f || saw_t) { goto f_string_quote; } _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com