Skip to content

Commit a37d719

Browse files
ambvpablogsal
andauthored
[3.13] gh-129958: Properly disallow newlines in format specs in single-quoted f-strings (GH-130063) (GH-132692)
(cherry picked from commit 2f8b08d) Co-authored-by: Pablo Galindo Salgado <[email protected]>
1 parent ca2e1a1 commit a37d719

File tree

4 files changed

+39
-31
lines changed

4 files changed

+39
-31
lines changed

Lib/test/test_fstring.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,6 +1784,31 @@ def test_gh129093(self):
17841784
self.assertEqual(f'{f'{1!=2=}'=}', "f'{1!=2=}'='1!=2=True'")
17851785
self.assertEqual(f'{f'{1 != 2=}'=}', "f'{1 != 2=}'='1 != 2=True'")
17861786

1787+
def test_newlines_in_format_specifiers(self):
1788+
cases = [
1789+
"""f'{1:d\n}'""",
1790+
"""f'__{
1791+
1:d
1792+
}__'""",
1793+
'''f"{value:.
1794+
{'2f'}}"''',
1795+
'''f"{value:
1796+
{'.2f'}f}"''',
1797+
'''f"{value:
1798+
#{'x'}}"''',
1799+
]
1800+
self.assertAllRaise(SyntaxError, "f-string: newlines are not allowed in format specifiers", cases)
1801+
1802+
valid_cases = [
1803+
"""f'''__{
1804+
1:d
1805+
}__'''""",
1806+
"""f'''{1:d\n}'''""",
1807+
]
1808+
1809+
for case in valid_cases:
1810+
compile(case, "<string>", "exec")
1811+
17871812

17881813
if __name__ == '__main__':
17891814
unittest.main()

Lib/test/test_tokenize.py

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -603,22 +603,6 @@ def test_string(self):
603603
OP '}' (6, 0) (6, 1)
604604
FSTRING_MIDDLE '__' (6, 1) (6, 3)
605605
FSTRING_END "'''" (6, 3) (6, 6)
606-
""")
607-
self.check_tokenize("""\
608-
f'__{
609-
x:d
610-
}__'""", """\
611-
FSTRING_START "f'" (1, 0) (1, 2)
612-
FSTRING_MIDDLE '__' (1, 2) (1, 4)
613-
OP '{' (1, 4) (1, 5)
614-
NL '\\n' (1, 5) (1, 6)
615-
NAME 'x' (2, 4) (2, 5)
616-
OP ':' (2, 5) (2, 6)
617-
FSTRING_MIDDLE 'd' (2, 6) (2, 7)
618-
NL '\\n' (2, 7) (2, 8)
619-
OP '}' (3, 0) (3, 1)
620-
FSTRING_MIDDLE '__' (3, 1) (3, 3)
621-
FSTRING_END "'" (3, 3) (3, 4)
622606
""")
623607

624608
self.check_tokenize("""\
@@ -2468,21 +2452,6 @@ def test_string(self):
24682452
RBRACE '}' (6, 0) (6, 1)
24692453
FSTRING_MIDDLE '__' (6, 1) (6, 3)
24702454
FSTRING_END "'''" (6, 3) (6, 6)
2471-
""")
2472-
2473-
self.check_tokenize("""\
2474-
f'__{
2475-
x:d
2476-
}__'""", """\
2477-
FSTRING_START "f'" (1, 0) (1, 2)
2478-
FSTRING_MIDDLE '__' (1, 2) (1, 4)
2479-
LBRACE '{' (1, 4) (1, 5)
2480-
NAME 'x' (2, 4) (2, 5)
2481-
COLON ':' (2, 5) (2, 6)
2482-
FSTRING_MIDDLE 'd' (2, 6) (2, 7)
2483-
RBRACE '}' (3, 0) (3, 1)
2484-
FSTRING_MIDDLE '__' (3, 1) (3, 3)
2485-
FSTRING_END "'" (3, 3) (3, 4)
24862455
""")
24872456

24882457
def test_function(self):
@@ -3038,6 +3007,10 @@ def get_tokens(string):
30383007
"'''sdfsdf''",
30393008
"("*1000+"a"+")"*1000,
30403009
"]",
3010+
"""\
3011+
f'__{
3012+
x:d
3013+
}__'""",
30413014
]:
30423015
with self.subTest(case=case):
30433016
self.assertRaises(tokenize.TokenError, get_tokens, case)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a bug that was allowing newlines inconsitently in format specifiers for
2+
single-quoted f-strings. Patch by Pablo Galindo.

Parser/lexer/lexer.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,6 +1347,14 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct
13471347
// it means that the format spec ends here and we should
13481348
// return to the regular mode.
13491349
if (in_format_spec && c == '\n') {
1350+
if (current_tok->f_string_quote_size == 1) {
1351+
return MAKE_TOKEN(
1352+
_PyTokenizer_syntaxerror(
1353+
tok,
1354+
"f-string: newlines are not allowed in format specifiers for single quoted f-strings"
1355+
)
1356+
);
1357+
}
13501358
tok_backup(tok, c);
13511359
TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE;
13521360
current_tok->in_format_spec = 0;

0 commit comments

Comments
 (0)