gh-129958: Properly disallow newlines in format specs in single-quoted f-strings (GH-130063)

This commit is contained in:
Pablo Galindo Salgado 2025-04-18 13:30:04 +01:00 committed by GitHub
parent e01e582902
commit 2f8b08da47
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 39 additions and 31 deletions

View file

@ -1795,6 +1795,31 @@ print(f'''{{
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()

View file

@ -605,22 +605,6 @@ f'''__{
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 @@ f'''__{
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 @@ async def f():
"'''sdfsdf''",
"("*1000+"a"+")"*1000,
"]",
"""\
f'__{
x:d
}__'""",
]:
with self.subTest(case=case):
self.assertRaises(tokenize.TokenError, get_tokens, case)

View file

@ -0,0 +1,2 @@
Fix a bug that was allowing newlines inconsitently in format specifiers for
single-quoted f-strings. Patch by Pablo Galindo.

View file

@ -1341,6 +1341,14 @@ f_string_middle:
// 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;