Skip to content

Commit de9998a

Browse files
committed
bpo-46091: Correctly calculate indentation levels for whitespace lines with continuation characters
1 parent f4095e5 commit de9998a

4 files changed

Lines changed: 51 additions & 14 deletions

File tree

Lib/test/test_ast.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,8 +1076,7 @@ def test_literal_eval_malformed_lineno(self):
10761076
ast.literal_eval(node)
10771077

10781078
def test_literal_eval_syntax_errors(self):
1079-
msg = "unexpected character after line continuation character"
1080-
with self.assertRaisesRegex(SyntaxError, msg):
1079+
with self.assertRaisesRegex(SyntaxError, "unexpected indent"):
10811080
ast.literal_eval(r'''
10821081
\
10831082
(\

Lib/test/test_syntax.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,27 @@ def test_empty_line_after_linecont(self):
15071507
\
15081508
15091509
pass
1510+
"""
1511+
try:
1512+
compile(s, '<string>', 'exec')
1513+
except SyntaxError:
1514+
self.fail("Empty line after a line continuation character is valid.")
1515+
1516+
# See issue-46091
1517+
s = r"""\
1518+
def fib(n):
1519+
\
1520+
'''Print a Fibonacci series up to n.'''
1521+
\
1522+
a, b = 0, 1
1523+
\
1524+
while a < n:
1525+
\
1526+
print(a, end=' ')
1527+
\
1528+
a, b = b, a+b
1529+
\
1530+
print()
15101531
"""
15111532
try:
15121533
compile(s, '<string>', 'exec')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Correctly calculate indentation levels for lines with whitespace character
2+
that are ended by line continuation characters. Patch by Pablo Galindo

Parser/tokenizer.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,6 +1347,24 @@ tok_decimal_tail(struct tok_state *tok)
13471347

13481348
/* Get next token, after space stripping etc. */
13491349

1350+
static inline int
1351+
tok_continuation_line(struct tok_state *tok) {
1352+
int c = tok_nextc(tok);
1353+
if (c != '\n') {
1354+
tok->done = E_LINECONT;
1355+
return -1;
1356+
}
1357+
c = tok_nextc(tok);
1358+
if (c == EOF) {
1359+
tok->done = E_EOF;
1360+
tok->cur = tok->inp;
1361+
return -1;
1362+
} else {
1363+
tok_backup(tok, c);
1364+
}
1365+
return c;
1366+
}
1367+
13501368
static int
13511369
tok_get(struct tok_state *tok, const char **p_start, const char **p_end)
13521370
{
@@ -1375,12 +1393,18 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end)
13751393
else if (c == '\014') {/* Control-L (formfeed) */
13761394
col = altcol = 0; /* For Emacs users */
13771395
}
1396+
else if (c == '\\') {
1397+
c = tok_continuation_line(tok);
1398+
if (c == -1) {
1399+
return ERRORTOKEN;
1400+
}
1401+
}
13781402
else {
13791403
break;
13801404
}
13811405
}
13821406
tok_backup(tok, c);
1383-
if (c == '#' || c == '\n' || c == '\\') {
1407+
if (c == '#' || c == '\n') {
13841408
/* Lines with only whitespace and/or comments
13851409
and/or a line continuation character
13861410
shouldn't affect the indentation and are
@@ -1964,19 +1988,10 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end)
19641988

19651989
/* Line continuation */
19661990
if (c == '\\') {
1967-
c = tok_nextc(tok);
1968-
if (c != '\n') {
1969-
tok->done = E_LINECONT;
1991+
c = tok_continuation_line(tok);
1992+
if (c == -1) {
19701993
return ERRORTOKEN;
19711994
}
1972-
c = tok_nextc(tok);
1973-
if (c == EOF) {
1974-
tok->done = E_EOF;
1975-
tok->cur = tok->inp;
1976-
return ERRORTOKEN;
1977-
} else {
1978-
tok_backup(tok, c);
1979-
}
19801995
tok->cont_line = 1;
19811996
goto again; /* Read next line */
19821997
}

0 commit comments

Comments
 (0)