https://github.com/python/cpython/commit/2f8b08da475152adea59b6bf98e2d0cb73dd8a59
commit: 2f8b08da475152adea59b6bf98e2d0cb73dd8a59
branch: main
author: Pablo Galindo Salgado <[email protected]>
committer: ambv <[email protected]>
date: 2025-04-18T14:30:04+02:00
summary:
gh-129958: Properly disallow newlines in format specs in single-quoted
f-strings (GH-130063)
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 5974024c170cef..e75e7db378cef1 100644
--- a/Lib/test/test_fstring.py
+++ b/Lib/test/test_fstring.py
@@ -1795,6 +1795,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 4e05a38394cdc1..2d41a5e5ac0697 100644
--- a/Lib/test/test_tokenize.py
+++ b/Lib/test/test_tokenize.py
@@ -605,22 +605,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("""\
@@ -2471,21 +2455,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):
@@ -3041,6 +3010,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 45604b197f43f2..5e68e5d035c545 100644
--- a/Parser/lexer/lexer.c
+++ b/Parser/lexer/lexer.c
@@ -1341,6 +1341,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 -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]