diff options
-rw-r--r-- | Lib/test/test_traceback.py | 10 | ||||
-rw-r--r-- | Lib/traceback.py | 14 |
2 files changed, 14 insertions, 10 deletions
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 7361d091cf..c703cedb05 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -58,13 +58,13 @@ class TracebackCases(unittest.TestCase): SyntaxError) self.assertIn("^", err[2]) # third line has caret self.assertEqual(err[2].count('\n'), 1) # and no additional newline - self.assertEqual(err[1].find("+"), err[2].find("^")) # in the right place + self.assertEqual(err[1].find("+") + 1, err[2].find("^")) # in the right place err = self.get_exception_format(self.syntax_error_with_caret_non_ascii, SyntaxError) self.assertIn("^", err[2]) # third line has caret self.assertEqual(err[2].count('\n'), 1) # and no additional newline - self.assertEqual(err[1].find("+"), err[2].find("^")) # in the right place + self.assertEqual(err[1].find("+") + 1, err[2].find("^")) # in the right place def test_nocaret(self): exc = SyntaxError("error", ("x.py", 23, None, "bad syntax")) @@ -78,7 +78,7 @@ class TracebackCases(unittest.TestCase): self.assertEqual(len(err), 4) self.assertEqual(err[1].strip(), "print(2)") self.assertIn("^", err[2]) - self.assertEqual(err[1].find(")"), err[2].find("^")) + self.assertEqual(err[1].find(")") + 1, err[2].find("^")) err = self.get_exception_format(self.syntax_error_bad_indentation2, IndentationError) @@ -656,7 +656,7 @@ class BaseExceptionReportingTests: self.assertIn('inner_raise() # Marker', blocks[2]) self.check_zero_div(blocks[2]) - @support.skip_if_new_parser("Pegen is arguably better here, so no need to fix this") + @unittest.skipIf(support.use_old_parser(), "Pegen is arguably better here, so no need to fix this") def test_syntax_error_offset_at_eol(self): # See #10186. def e(): @@ -666,7 +666,7 @@ class BaseExceptionReportingTests: def e(): exec("x = 5 | 4 |") msg = self.get_report(e).splitlines() - self.assertEqual(msg[-2], ' ^') + self.assertEqual(msg[-2], ' ^') def test_message_none(self): # A message that looks like "None" should not be treated specially diff --git a/Lib/traceback.py b/Lib/traceback.py index bf34bbab8a..7d5561769f 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -569,9 +569,12 @@ class TracebackException: if not issubclass(self.exc_type, SyntaxError): yield _format_final_exc_line(stype, self._str) - return + else: + yield from self._format_syntax_error(stype) - # It was a syntax error; show exactly where the problem was found. + def _format_syntax_error(self, stype): + """Format SyntaxError exceptions (internal helper).""" + # Show exactly where the problem was found. filename = self.filename or "<string>" lineno = str(self.lineno) or '?' yield ' File "{}", line {}\n'.format(filename, lineno) @@ -580,12 +583,13 @@ class TracebackException: offset = self.offset if badline is not None: yield ' {}\n'.format(badline.strip()) - if offset is not None: + if offset is not None and offset >= 1: caretspace = badline.rstrip('\n') - offset = min(len(caretspace), offset) - 1 + # Convert to 0-based offset, and clip to text length + offset = min(len(caretspace), offset - 1) caretspace = caretspace[:offset].lstrip() # non-space whitespace (likes tabs) must be kept for alignment - caretspace = ((c.isspace() and c or ' ') for c in caretspace) + caretspace = ((c if c.isspace() else ' ') for c in caretspace) yield ' {}^\n'.format(''.join(caretspace)) msg = self.msg or "<no detail available>" yield "{}: {}\n".format(stype, msg) |