diff --git a/Include/pythonrun.h b/Include/pythonrun.h index 41d82e89f84..154c7450cb9 100644 --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -12,7 +12,10 @@ PyAPI_FUNC(PyObject *) Py_CompileString(const char *, const char *, int); PyAPI_FUNC(void) PyErr_Print(void); PyAPI_FUNC(void) PyErr_PrintEx(int); PyAPI_FUNC(void) PyErr_Display(PyObject *, PyObject *, PyObject *); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030C0000 PyAPI_FUNC(void) PyErr_DisplayException(PyObject *); +#endif /* Stuff with no proper home (yet) */ diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 1c5d1ab82c8..399c59f8780 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -394,6 +394,8 @@ class PurePythonExceptionFormattingMixin: class CAPIExceptionFormattingMixin: + LEGACY = 0 + def get_exception(self, callable, slice_start=0, slice_end=-1): from _testcapi import exception_print try: @@ -401,11 +403,13 @@ class CAPIExceptionFormattingMixin: self.fail("No exception thrown.") except Exception as e: with captured_output("stderr") as tbstderr: - exception_print(e) + exception_print(e, self.LEGACY) return tbstderr.getvalue().splitlines()[slice_start:slice_end] callable_line = get_exception.__code__.co_firstlineno + 3 +class CAPIExceptionFormattingLegacyMixin(CAPIExceptionFormattingMixin): + LEGACY = 1 @requires_debug_ranges() class TracebackErrorLocationCaretTestBase: @@ -912,6 +916,16 @@ class CPythonTracebackErrorCaretTests( Same set of tests as above but with Python's internal traceback printing. """ +@cpython_only +@requires_debug_ranges() +class CPythonTracebackErrorCaretTests( + CAPIExceptionFormattingLegacyMixin, + TracebackErrorLocationCaretTestBase, + unittest.TestCase, +): + """ + Same set of tests as above but with Python's legacy internal traceback printing. + """ class TracebackFormatTests(unittest.TestCase): diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c index 1922ca3beb7..6099f7d20eb 100644 --- a/Modules/_testcapi/exceptions.c +++ b/Modules/_testcapi/exceptions.c @@ -40,12 +40,22 @@ static PyObject * exception_print(PyObject *self, PyObject *args) { PyObject *exc; + int legacy = 0; - if (!PyArg_ParseTuple(args, "O:exception_print", &exc)) { + if (!PyArg_ParseTuple(args, "O|i:exception_print", &exc, &legacy)) { return NULL; } - - PyErr_DisplayException(exc); + if (legacy) { + PyObject *tb = NULL; + if (PyExceptionInstance_Check(exc)) { + tb = PyException_GetTraceback(exc); + } + PyErr_Display((PyObject *) Py_TYPE(exc), exc, tb); + Py_XDECREF(tb); + } + else { + PyErr_DisplayException(exc); + } Py_RETURN_NONE; }