mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-110721: Use the traceback module for PyErr_Display() and fallback to the C implementation (#110702)
This commit is contained in:
parent
8c6c14b91b
commit
e7331365b4
7 changed files with 146 additions and 837 deletions
|
@ -963,7 +963,9 @@ class CPythonTracebackLegacyErrorCaretTests(
|
|||
Same set of tests as above but with Python's legacy internal traceback printing.
|
||||
"""
|
||||
|
||||
class TracebackFormatTests(unittest.TestCase):
|
||||
|
||||
class TracebackFormatMixin:
|
||||
DEBUG_RANGES = True
|
||||
|
||||
def some_exception(self):
|
||||
raise KeyError('blah')
|
||||
|
@ -1137,6 +1139,8 @@ class TracebackFormatTests(unittest.TestCase):
|
|||
)
|
||||
expected = (tb_line + result_g).splitlines()
|
||||
actual = stderr_g.getvalue().splitlines()
|
||||
if not self.DEBUG_RANGES:
|
||||
expected = [line for line in expected if not set(line.strip()) == {"^"}]
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
# Check 2 different repetitive sections
|
||||
|
@ -1173,6 +1177,8 @@ class TracebackFormatTests(unittest.TestCase):
|
|||
)
|
||||
expected = (result_h + result_g).splitlines()
|
||||
actual = stderr_h.getvalue().splitlines()
|
||||
if not self.DEBUG_RANGES:
|
||||
expected = [line for line in expected if not set(line.strip()) == {"^"}]
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
# Check the boundary conditions. First, test just below the cutoff.
|
||||
|
@ -1199,11 +1205,13 @@ class TracebackFormatTests(unittest.TestCase):
|
|||
)
|
||||
tb_line = (
|
||||
'Traceback (most recent call last):\n'
|
||||
f' File "{__file__}", line {lineno_g+77}, in _check_recursive_traceback_display\n'
|
||||
f' File "{__file__}", line {lineno_g+81}, in _check_recursive_traceback_display\n'
|
||||
' g(traceback._RECURSIVE_CUTOFF)\n'
|
||||
)
|
||||
expected = (tb_line + result_g).splitlines()
|
||||
actual = stderr_g.getvalue().splitlines()
|
||||
if not self.DEBUG_RANGES:
|
||||
expected = [line for line in expected if not set(line.strip()) == {"^"}]
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
# Second, test just above the cutoff.
|
||||
|
@ -1231,24 +1239,24 @@ class TracebackFormatTests(unittest.TestCase):
|
|||
)
|
||||
tb_line = (
|
||||
'Traceback (most recent call last):\n'
|
||||
f' File "{__file__}", line {lineno_g+108}, in _check_recursive_traceback_display\n'
|
||||
f' File "{__file__}", line {lineno_g+114}, in _check_recursive_traceback_display\n'
|
||||
' g(traceback._RECURSIVE_CUTOFF + 1)\n'
|
||||
)
|
||||
expected = (tb_line + result_g).splitlines()
|
||||
actual = stderr_g.getvalue().splitlines()
|
||||
if not self.DEBUG_RANGES:
|
||||
expected = [line for line in expected if not set(line.strip()) == {"^"}]
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@requires_debug_ranges()
|
||||
def test_recursive_traceback_python(self):
|
||||
self._check_recursive_traceback_display(traceback.print_exc)
|
||||
|
||||
@cpython_only
|
||||
@requires_debug_ranges()
|
||||
def test_recursive_traceback_cpython_internal(self):
|
||||
from _testcapi import exception_print
|
||||
def render_exc():
|
||||
exception_print(sys.exception())
|
||||
self._check_recursive_traceback_display(render_exc)
|
||||
def test_recursive_traceback(self):
|
||||
if self.DEBUG_RANGES:
|
||||
self._check_recursive_traceback_display(traceback.print_exc)
|
||||
else:
|
||||
from _testcapi import exception_print
|
||||
def render_exc():
|
||||
exception_print(sys.exception())
|
||||
self._check_recursive_traceback_display(render_exc)
|
||||
|
||||
def test_format_stack(self):
|
||||
def fmt():
|
||||
|
@ -1321,7 +1329,8 @@ class TracebackFormatTests(unittest.TestCase):
|
|||
def test_print_exception_bad_type_capi(self):
|
||||
from _testcapi import exception_print
|
||||
with captured_output("stderr") as stderr:
|
||||
exception_print(42)
|
||||
with support.catch_unraisable_exception():
|
||||
exception_print(42)
|
||||
self.assertEqual(
|
||||
stderr.getvalue(),
|
||||
('TypeError: print_exception(): '
|
||||
|
@ -1345,6 +1354,24 @@ context_message = (
|
|||
boundaries = re.compile(
|
||||
'(%s|%s)' % (re.escape(cause_message), re.escape(context_message)))
|
||||
|
||||
class TestTracebackFormat(unittest.TestCase, TracebackFormatMixin):
|
||||
pass
|
||||
|
||||
@cpython_only
|
||||
class TestFallbackTracebackFormat(unittest.TestCase, TracebackFormatMixin):
|
||||
DEBUG_RANGES = False
|
||||
def setUp(self) -> None:
|
||||
self.original_unraisable_hook = sys.unraisablehook
|
||||
sys.unraisablehook = lambda *args: None
|
||||
self.original_hook = traceback._print_exception_bltin
|
||||
traceback._print_exception_bltin = lambda *args: 1/0
|
||||
return super().setUp()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
traceback._print_exception_bltin = self.original_hook
|
||||
sys.unraisablehook = self.original_unraisable_hook
|
||||
return super().tearDown()
|
||||
|
||||
class BaseExceptionReportingTests:
|
||||
|
||||
def get_exception(self, exception_or_callable):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue