summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES1
-rw-r--r--pygments/lexers/python.py24
-rw-r--r--tests/snippets/pycon/broken_tb.txt97
3 files changed, 110 insertions, 12 deletions
diff --git a/CHANGES b/CHANGES
index e1013178..445dace8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -21,6 +21,7 @@ Version 2.15.0
on Python 3.10 and older (#2328).
- Fix some places where a locale-dependent encoding could unintentionally
be used instead of UTF-8 (#2326).
+- Fix Python traceback handling (#2226, #2329).
Version 2.14.0
--------------
diff --git a/pygments/lexers/python.py b/pygments/lexers/python.py
index 0a318a9e..6ba3d19e 100644
--- a/pygments/lexers/python.py
+++ b/pygments/lexers/python.py
@@ -679,15 +679,15 @@ class PythonConsoleLexer(Lexer):
insertions = []
curtb = ''
tbindex = 0
- tb = 0
+ in_tb = False
for match in line_re.finditer(text):
line = match.group()
if line.startswith('>>> ') or line.startswith('... '):
- tb = 0
+ in_tb = False
insertions.append((len(curcode),
[(0, Generic.Prompt, line[:4])]))
curcode += line[4:]
- elif line.rstrip() == '...' and not tb:
+ elif line.rstrip() == '...' and not in_tb:
# only a new >>> prompt can end an exception block
# otherwise an ellipsis in place of the traceback frames
# will be mishandled
@@ -700,20 +700,20 @@ class PythonConsoleLexer(Lexer):
insertions, pylexer.get_tokens_unprocessed(curcode))
curcode = ''
insertions = []
- if (line.startswith('Traceback (most recent call last):') or
- re.match(' File "[^"]+", line \\d+\\n$', line)):
- tb = 1
- curtb = line
- tbindex = match.start()
- elif line == 'KeyboardInterrupt\n':
- yield match.start(), Name.Class, line
- elif tb:
+ if in_tb:
curtb += line
if not (line.startswith(' ') or line.strip() == '...'):
- tb = 0
+ in_tb = False
for i, t, v in tblexer.get_tokens_unprocessed(curtb):
yield tbindex+i, t, v
curtb = ''
+ elif (line.startswith('Traceback (most recent call last):') or
+ re.match(' File "[^"]+", line \\d+\\n$', line)):
+ in_tb = True
+ curtb = line
+ tbindex = match.start()
+ elif line == 'KeyboardInterrupt\n':
+ yield match.start(), Name.Class, line
else:
yield match.start(), Generic.Output, line
if curcode:
diff --git a/tests/snippets/pycon/broken_tb.txt b/tests/snippets/pycon/broken_tb.txt
new file mode 100644
index 00000000..6cecf761
--- /dev/null
+++ b/tests/snippets/pycon/broken_tb.txt
@@ -0,0 +1,97 @@
+---input---
+>>> exec('"')
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "<string>", line 1
+ "
+ ^
+SyntaxError: EOL while scanning string literal
+
+>>> exec('"')
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "<string>", line 1, in <module>
+ "
+ ^
+SyntaxError: EOL while scanning string literal
+
+---tokens---
+'>>> ' Generic.Prompt
+'exec' Name
+'(' Punctuation
+"'" Literal.String.Single
+'"' Literal.String.Single
+"'" Literal.String.Single
+')' Punctuation
+'\n' Text.Whitespace
+
+'Traceback (most recent call last):\n' Generic.Traceback
+
+' File ' Text
+'"<stdin>"' Name.Builtin
+', line ' Text
+'1' Literal.Number
+', in ' Text
+'<module>' Name
+'\n' Text.Whitespace
+
+' File ' Text
+'"<string>"' Name.Builtin
+', line ' Text
+'1' Literal.Number
+'\n' Text.Whitespace
+
+' ' Text.Whitespace
+'"' Literal.String.Double
+'\n' Text.Whitespace
+
+' ' Text.Whitespace
+'^' Punctuation.Marker
+'\n' Text.Whitespace
+
+'SyntaxError' Generic.Error
+': ' Text
+'EOL while scanning string literal' Name
+'\n' Text.Whitespace
+
+'\n' Generic.Output
+
+'>>> ' Generic.Prompt
+'exec' Name
+'(' Punctuation
+"'" Literal.String.Single
+'"' Literal.String.Single
+"'" Literal.String.Single
+')' Punctuation
+'\n' Text.Whitespace
+
+'Traceback (most recent call last):\n' Generic.Traceback
+
+' File ' Text
+'"<stdin>"' Name.Builtin
+', line ' Text
+'1' Literal.Number
+', in ' Text
+'<module>' Name
+'\n' Text.Whitespace
+
+' File ' Text
+'"<string>"' Name.Builtin
+', line ' Text
+'1' Literal.Number
+', in ' Text
+'<module>' Name
+'\n' Text.Whitespace
+
+' ' Text.Whitespace
+'"' Literal.String.Double
+'\n' Text.Whitespace
+
+' ' Text.Whitespace
+'^' Punctuation.Marker
+'\n' Text.Whitespace
+
+'SyntaxError' Generic.Error
+': ' Text
+'EOL while scanning string literal' Name
+'\n' Text.Whitespace