https://github.com/python/cpython/commit/a37d719d37ba0f45d0e88f1f70ccd66f2a4f209e commit: a37d719d37ba0f45d0e88f1f70ccd66f2a4f209e branch: 3.13 author: Ćukasz Langa <luk...@langa.pl> committer: ambv <luk...@langa.pl> date: 2025-04-18T17:41:42+02:00 summary:
[3.13] gh-129958: Properly disallow newlines in format specs in single-quoted f-strings (GH-130063) (GH-132692) (cherry picked from commit 2f8b08da475152adea59b6bf98e2d0cb73dd8a59) Co-authored-by: Pablo Galindo Salgado <pablog...@gmail.com> files: A Misc/NEWS.d/next/Core and Builtins/2025-02-13-00-14-24.gh-issue-129958.Uj7lyY.rst M Lib/test/test_fstring.py M Lib/test/test_tokenize.py M Parser/lexer/lexer.c diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index f5111b38a45707..1ad16937b2b5ba 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -1784,6 +1784,31 @@ def test_gh129093(self): self.assertEqual(f'{f'{1!=2=}'=}', "f'{1!=2=}'='1!=2=True'") self.assertEqual(f'{f'{1 != 2=}'=}', "f'{1 != 2=}'='1 != 2=True'") + def test_newlines_in_format_specifiers(self): + cases = [ + """f'{1:d\n}'""", + """f'__{ + 1:d + }__'""", + '''f"{value:. + {'2f'}}"''', + '''f"{value: + {'.2f'}f}"''', + '''f"{value: + #{'x'}}"''', + ] + self.assertAllRaise(SyntaxError, "f-string: newlines are not allowed in format specifiers", cases) + + valid_cases = [ + """f'''__{ + 1:d + }__'''""", + """f'''{1:d\n}'''""", + ] + + for case in valid_cases: + compile(case, "<string>", "exec") + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index 940ea21754ea37..e9701eb130d3e3 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -603,22 +603,6 @@ def test_string(self): OP '}' (6, 0) (6, 1) FSTRING_MIDDLE '__' (6, 1) (6, 3) FSTRING_END "'''" (6, 3) (6, 6) - """) - self.check_tokenize("""\ -f'__{ - x:d -}__'""", """\ - FSTRING_START "f'" (1, 0) (1, 2) - FSTRING_MIDDLE '__' (1, 2) (1, 4) - OP '{' (1, 4) (1, 5) - NL '\\n' (1, 5) (1, 6) - NAME 'x' (2, 4) (2, 5) - OP ':' (2, 5) (2, 6) - FSTRING_MIDDLE 'd' (2, 6) (2, 7) - NL '\\n' (2, 7) (2, 8) - OP '}' (3, 0) (3, 1) - FSTRING_MIDDLE '__' (3, 1) (3, 3) - FSTRING_END "'" (3, 3) (3, 4) """) self.check_tokenize("""\ @@ -2468,21 +2452,6 @@ def test_string(self): RBRACE '}' (6, 0) (6, 1) FSTRING_MIDDLE '__' (6, 1) (6, 3) FSTRING_END "'''" (6, 3) (6, 6) - """) - - self.check_tokenize("""\ -f'__{ - x:d -}__'""", """\ - FSTRING_START "f'" (1, 0) (1, 2) - FSTRING_MIDDLE '__' (1, 2) (1, 4) - LBRACE '{' (1, 4) (1, 5) - NAME 'x' (2, 4) (2, 5) - COLON ':' (2, 5) (2, 6) - FSTRING_MIDDLE 'd' (2, 6) (2, 7) - RBRACE '}' (3, 0) (3, 1) - FSTRING_MIDDLE '__' (3, 1) (3, 3) - FSTRING_END "'" (3, 3) (3, 4) """) def test_function(self): @@ -3038,6 +3007,10 @@ def get_tokens(string): "'''sdfsdf''", "("*1000+"a"+")"*1000, "]", + """\ + f'__{ + x:d + }__'""", ]: with self.subTest(case=case): self.assertRaises(tokenize.TokenError, get_tokens, case) diff --git a/Misc/NEWS.d/next/Core and Builtins/2025-02-13-00-14-24.gh-issue-129958.Uj7lyY.rst b/Misc/NEWS.d/next/Core and Builtins/2025-02-13-00-14-24.gh-issue-129958.Uj7lyY.rst new file mode 100644 index 00000000000000..c0fa76c89e4c4e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2025-02-13-00-14-24.gh-issue-129958.Uj7lyY.rst @@ -0,0 +1,2 @@ +Fix a bug that was allowing newlines inconsitently in format specifiers for +single-quoted f-strings. Patch by Pablo Galindo. diff --git a/Parser/lexer/lexer.c b/Parser/lexer/lexer.c index 15e6332ee35718..e4b02aee51d3cf 100644 --- a/Parser/lexer/lexer.c +++ b/Parser/lexer/lexer.c @@ -1347,6 +1347,14 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct // it means that the format spec ends here and we should // return to the regular mode. if (in_format_spec && c == '\n') { + if (current_tok->f_string_quote_size == 1) { + return MAKE_TOKEN( + _PyTokenizer_syntaxerror( + tok, + "f-string: newlines are not allowed in format specifiers for single quoted f-strings" + ) + ); + } tok_backup(tok, c); TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; current_tok->in_format_spec = 0; _______________________________________________ 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