Skip to content

Commit fe42aac

Browse files
committed
Python console: make traceback handling more robust
Fixes #2329 Fixes #2226
1 parent c9ca87f commit fe42aac

3 files changed

Lines changed: 110 additions & 12 deletions

File tree

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Version 2.15.0
2121
on Python 3.10 and older (#2328).
2222
- Fix some places where a locale-dependent encoding could unintentionally
2323
be used instead of UTF-8 (#2326).
24+
- Fix Python traceback handling (#2226, #2329).
2425

2526
Version 2.14.0
2627
--------------

pygments/lexers/python.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -679,15 +679,15 @@ def get_tokens_unprocessed(self, text):
679679
insertions = []
680680
curtb = ''
681681
tbindex = 0
682-
tb = 0
682+
in_tb = False
683683
for match in line_re.finditer(text):
684684
line = match.group()
685685
if line.startswith('>>> ') or line.startswith('... '):
686-
tb = 0
686+
in_tb = False
687687
insertions.append((len(curcode),
688688
[(0, Generic.Prompt, line[:4])]))
689689
curcode += line[4:]
690-
elif line.rstrip() == '...' and not tb:
690+
elif line.rstrip() == '...' and not in_tb:
691691
# only a new >>> prompt can end an exception block
692692
# otherwise an ellipsis in place of the traceback frames
693693
# will be mishandled
@@ -700,20 +700,20 @@ def get_tokens_unprocessed(self, text):
700700
insertions, pylexer.get_tokens_unprocessed(curcode))
701701
curcode = ''
702702
insertions = []
703-
if (line.startswith('Traceback (most recent call last):') or
704-
re.match(' File "[^"]+", line \\d+\\n$', line)):
705-
tb = 1
706-
curtb = line
707-
tbindex = match.start()
708-
elif line == 'KeyboardInterrupt\n':
709-
yield match.start(), Name.Class, line
710-
elif tb:
703+
if in_tb:
711704
curtb += line
712705
if not (line.startswith(' ') or line.strip() == '...'):
713-
tb = 0
706+
in_tb = False
714707
for i, t, v in tblexer.get_tokens_unprocessed(curtb):
715708
yield tbindex+i, t, v
716709
curtb = ''
710+
elif (line.startswith('Traceback (most recent call last):') or
711+
re.match(' File "[^"]+", line \\d+\\n$', line)):
712+
in_tb = True
713+
curtb = line
714+
tbindex = match.start()
715+
elif line == 'KeyboardInterrupt\n':
716+
yield match.start(), Name.Class, line
717717
else:
718718
yield match.start(), Generic.Output, line
719719
if curcode:

tests/snippets/pycon/broken_tb.txt

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
---input---
2+
>>> exec('"')
3+
Traceback (most recent call last):
4+
File "<stdin>", line 1, in <module>
5+
File "<string>", line 1
6+
"
7+
^
8+
SyntaxError: EOL while scanning string literal
9+
10+
>>> exec('"')
11+
Traceback (most recent call last):
12+
File "<stdin>", line 1, in <module>
13+
File "<string>", line 1, in <module>
14+
"
15+
^
16+
SyntaxError: EOL while scanning string literal
17+
18+
---tokens---
19+
'>>> ' Generic.Prompt
20+
'exec' Name
21+
'(' Punctuation
22+
"'" Literal.String.Single
23+
'"' Literal.String.Single
24+
"'" Literal.String.Single
25+
')' Punctuation
26+
'\n' Text.Whitespace
27+
28+
'Traceback (most recent call last):\n' Generic.Traceback
29+
30+
' File ' Text
31+
'"<stdin>"' Name.Builtin
32+
', line ' Text
33+
'1' Literal.Number
34+
', in ' Text
35+
'<module>' Name
36+
'\n' Text.Whitespace
37+
38+
' File ' Text
39+
'"<string>"' Name.Builtin
40+
', line ' Text
41+
'1' Literal.Number
42+
'\n' Text.Whitespace
43+
44+
' ' Text.Whitespace
45+
'"' Literal.String.Double
46+
'\n' Text.Whitespace
47+
48+
' ' Text.Whitespace
49+
'^' Punctuation.Marker
50+
'\n' Text.Whitespace
51+
52+
'SyntaxError' Generic.Error
53+
': ' Text
54+
'EOL while scanning string literal' Name
55+
'\n' Text.Whitespace
56+
57+
'\n' Generic.Output
58+
59+
'>>> ' Generic.Prompt
60+
'exec' Name
61+
'(' Punctuation
62+
"'" Literal.String.Single
63+
'"' Literal.String.Single
64+
"'" Literal.String.Single
65+
')' Punctuation
66+
'\n' Text.Whitespace
67+
68+
'Traceback (most recent call last):\n' Generic.Traceback
69+
70+
' File ' Text
71+
'"<stdin>"' Name.Builtin
72+
', line ' Text
73+
'1' Literal.Number
74+
', in ' Text
75+
'<module>' Name
76+
'\n' Text.Whitespace
77+
78+
' File ' Text
79+
'"<string>"' Name.Builtin
80+
', line ' Text
81+
'1' Literal.Number
82+
', in ' Text
83+
'<module>' Name
84+
'\n' Text.Whitespace
85+
86+
' ' Text.Whitespace
87+
'"' Literal.String.Double
88+
'\n' Text.Whitespace
89+
90+
' ' Text.Whitespace
91+
'^' Punctuation.Marker
92+
'\n' Text.Whitespace
93+
94+
'SyntaxError' Generic.Error
95+
': ' Text
96+
'EOL while scanning string literal' Name
97+
'\n' Text.Whitespace

0 commit comments

Comments
 (0)