| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -460,12 +460,46 @@ Querying the error indicator | |||
| 460 | 460 | } | |
| 461 | 461 | ||
| 462 | 462 | ||
| 463 | - .. c:function:: void PyErr_GetExcInfo(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback) | ||
| 463 | + .. c:function:: PyObject* PyErr_GetHandledException(void) | ||
| 464 | + | ||
| 465 | + Retrieve the active exception instance, as would be returned by :func:`sys.exception`. | ||
| 466 | + This refers to an exception that was *already caught*, not to an exception that was | ||
| 467 | + freshly raised. Returns a new reference to the exception or ``NULL``. | ||
| 468 | + Does not modify the interpreter's exception state. | ||
| 469 | + | ||
| 470 | + .. note:: | ||
| 471 | + | ||
| 472 | + This function is not normally used by code that wants to handle exceptions. | ||
| 473 | + Rather, it can be used when code needs to save and restore the exception | ||
| 474 | + state temporarily. Use :c:func:`PyErr_SetHandledException` to restore or | ||
| 475 | + clear the exception state. | ||
| 476 | + | ||
| 477 | + .. versionadded:: 3.11 | ||
| 464 | 478 | ||
| 465 | - Retrieve the exception info, as known from ``sys.exc_info()``. This refers | ||
| 479 | + .. c:function:: void PyErr_SetHandledException(PyObject *exc) | ||
| 480 | + | ||
| 481 | + Set the active exception, as known from ``sys.exception()``. This refers | ||
| 466 | 482 | to an exception that was *already caught*, not to an exception that was | |
| 467 | - freshly raised. Returns new references for the three objects, any of which | ||
| 468 | - may be ``NULL``. Does not modify the exception info state. | ||
| 483 | + freshly raised. | ||
| 484 | + To clear the exception state, pass ``NULL``. | ||
| 485 | + | ||
| 486 | + .. note:: | ||
| 487 | + | ||
| 488 | + This function is not normally used by code that wants to handle exceptions. | ||
| 489 | + Rather, it can be used when code needs to save and restore the exception | ||
| 490 | + state temporarily. Use :c:func:`PyErr_GetHandledException` to get the exception | ||
| 491 | + state. | ||
| 492 | + | ||
| 493 | + .. versionadded:: 3.11 | ||
| 494 | + | ||
| 495 | + .. c:function:: void PyErr_GetExcInfo(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback) | ||
| 496 | + | ||
| 497 | + Retrieve the old-style representation of the exception info, as known from | ||
| 498 | + :func:`sys.exc_info`. This refers to an exception that was *already caught*, | ||
| 499 | + not to an exception that was freshly raised. Returns new references for the | ||
| 500 | + three objects, any of which may be ``NULL``. Does not modify the exception | ||
| 501 | + info state. This function is kept for backwards compatibility. Prefer using | ||
| 502 | + :c:func:`PyErr_GetHandledException`. | ||
| 469 | 503 | ||
| 470 | 504 | .. note:: | |
| 471 | 505 | ||
@@ -483,6 +517,8 @@ Querying the error indicator | |||
| 483 | 517 | to an exception that was *already caught*, not to an exception that was | |
| 484 | 518 | freshly raised. This function steals the references of the arguments. | |
| 485 | 519 | To clear the exception state, pass ``NULL`` for all three arguments. | |
| 520 | + This function is kept for backwards compatibility. Prefer using | ||
| 521 | + :c:func:`PyErr_SetHandledException`. | ||
| 486 | 522 | ||
| 487 | 523 | .. note:: | |
| 488 | 524 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -381,19 +381,12 @@ always available. | |||
| 381 | 381 | ||
| 382 | 382 | .. function:: exception() | |
| 383 | 383 | ||
| 384 | - This function returns the exception instance that is currently being | ||
| 385 | - handled. This exception is specific both to the current thread and | ||
| 386 | - to the current stack frame. If the current stack frame is not handling | ||
| 387 | - an exception, the exception is taken from the calling stack frame, or its | ||
| 388 | - caller, and so on until a stack frame is found that is handling an | ||
| 389 | - exception. Here, "handling an exception" is defined as "executing an | ||
| 390 | - except clause." For any stack frame, only the exception being currently | ||
| 391 | - handled is accessible. | ||
| 384 | + This function, when called while an exception handler is executing (such as | ||
| 385 | + an ``except`` or ``except*`` clause), returns the exception instance that | ||
| 386 | + was caught by this handler. When exception handlers are nested within one | ||
| 387 | + another, only the exception handled by the innermost handler is accessible. | ||
| 392 | 388 | ||
| 393 | - .. index:: object: traceback | ||
| 394 | - | ||
| 395 | - If no exception is being handled anywhere on the stack, ``None`` is | ||
| 396 | - returned. | ||
| 389 | + If no exception handler is executing, this function returns ``None``. | ||
| 397 | 390 | ||
| 398 | 391 | .. versionadded:: 3.11 | |
| 399 | 392 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1161,6 +1161,14 @@ New Features | |||
| 1161 | 1161 | :c:func:`PyFrame_GetBuiltins`, :c:func:`PyFrame_GetGenerator`, | |
| 1162 | 1162 | :c:func:`PyFrame_GetGlobals`, :c:func:`PyFrame_GetLasti`. | |
| 1163 | 1163 | ||
| 1164 | + * Added two new functions to get and set the active exception instance: | ||
| 1165 | + :c:func:`PyErr_GetHandledException` and :c:func:`PyErr_SetHandledException`. | ||
| 1166 | + These are alternatives to :c:func:`PyErr_SetExcInfo()` and | ||
| 1167 | + :c:func:`PyErr_GetExcInfo()` which work with the legacy 3-tuple | ||
| 1168 | + representation of exceptions. | ||
| 1169 | + (Contributed by Irit Katriel in :issue:`46343`.) | ||
| 1170 | + | ||
| 1171 | + | ||
| 1164 | 1172 | Porting to Python 3.11 | |
| 1165 | 1173 | ---------------------- | |
| 1166 | 1174 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -91,6 +91,8 @@ typedef PyOSErrorObject PyWindowsErrorObject; | |||
| 91 | 91 | ||
| 92 | 92 | PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *); | |
| 93 | 93 | PyAPI_FUNC(_PyErr_StackItem*) _PyErr_GetTopmostException(PyThreadState *tstate); | |
| 94 | + PyAPI_FUNC(PyObject*) _PyErr_GetHandledException(PyThreadState *); | ||
| 95 | + PyAPI_FUNC(void) _PyErr_SetHandledException(PyThreadState *, PyObject *); | ||
| 94 | 96 | PyAPI_FUNC(void) _PyErr_GetExcInfo(PyThreadState *, PyObject **, PyObject **, PyObject **); | |
| 95 | 97 | ||
| 96 | 98 | /* Context manipulation (PEP 3134) */ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,6 +18,10 @@ PyAPI_FUNC(PyObject *) PyErr_Occurred(void); | |||
| 18 | 18 | PyAPI_FUNC(void) PyErr_Clear(void); | |
| 19 | 19 | PyAPI_FUNC(void) PyErr_Fetch(PyObject **, PyObject **, PyObject **); | |
| 20 | 20 | PyAPI_FUNC(void) PyErr_Restore(PyObject *, PyObject *, PyObject *); | |
| 21 | + #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030b0000 | ||
| 22 | + PyAPI_FUNC(PyObject*) PyErr_GetHandledException(void); | ||
| 23 | + PyAPI_FUNC(void) PyErr_SetHandledException(PyObject *); | ||
| 24 | + #endif | ||
| 21 | 25 | #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 | |
| 22 | 26 | PyAPI_FUNC(void) PyErr_GetExcInfo(PyObject **, PyObject **, PyObject **); | |
| 23 | 27 | PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -88,6 +88,28 @@ def test_no_FatalError_infinite_loop(self): | |||
| 88 | 88 | def test_memoryview_from_NULL_pointer(self): | |
| 89 | 89 | self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer) | |
| 90 | 90 | ||
| 91 | + def test_exception(self): | ||
| 92 | + raised_exception = ValueError("5") | ||
| 93 | + new_exc = TypeError("TEST") | ||
| 94 | + try: | ||
| 95 | + raise raised_exception | ||
| 96 | + except ValueError as e: | ||
| 97 | + orig_sys_exception = sys.exception() | ||
| 98 | + orig_exception = _testcapi.set_exception(new_exc) | ||
| 99 | + new_sys_exception = sys.exception() | ||
| 100 | + new_exception = _testcapi.set_exception(orig_exception) | ||
| 101 | + reset_sys_exception = sys.exception() | ||
| 102 | + | ||
| 103 | + self.assertEqual(orig_exception, e) | ||
| 104 | + | ||
| 105 | + self.assertEqual(orig_exception, raised_exception) | ||
| 106 | + self.assertEqual(orig_sys_exception, orig_exception) | ||
| 107 | + self.assertEqual(reset_sys_exception, orig_exception) | ||
| 108 | + self.assertEqual(new_exception, new_exc) | ||
| 109 | + self.assertEqual(new_sys_exception, new_exception) | ||
| 110 | + else: | ||
| 111 | + self.fail("Exception not raised") | ||
| 112 | + | ||
| 91 | 113 | def test_exc_info(self): | |
| 92 | 114 | raised_exception = ValueError("5") | |
| 93 | 115 | new_exc = TypeError("TEST") | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,5 @@ | |||
| 1 | + Added :c:func:`PyErr_GetHandledException` and | ||
| 2 | + :c:func:`PyErr_SetHandledException` as simpler alternatives to | ||
| 3 | + :c:func:`PyErr_GetExcInfo` and :c:func:`PyErr_SetExcInfo`. | ||
| 4 | + | ||
| 5 | + They are included in the stable ABI. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2253,3 +2253,8 @@ function PyMemoryView_FromBuffer | |||
| 2253 | 2253 | ||
| 2254 | 2254 | data Py_Version | |
| 2255 | 2255 | added 3.11 | |
| 2256 | + function PyErr_GetHandledException | ||
| 2257 | + added 3.11 | ||
| 2258 | + function PyErr_SetHandledException | ||
| 2259 | + added 3.11 | ||
| 2260 | + | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments