mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-129958: Properly disallow newlines in format specs in single-quoted f-strings (GH-130063)
This commit is contained in:
parent
e01e582902
commit
2f8b08da47
4 changed files with 39 additions and 31 deletions
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix a bug that was allowing newlines inconsitently in format specifiers for
|
||||
single-quoted f-strings. Patch by Pablo Galindo.
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue