Skip to content

Commit aa64c46

Browse files
Issue #23781: Add private helper function _PyErr_ReplaceException() that
corresponds _PyErr_ChainExceptions() in Python 3 to help porting patches from Python 3.
1 parent d06c201 commit aa64c46

File tree

5 files changed

+27
-26
lines changed

5 files changed

+27
-26
lines changed

Include/pyerrors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ PyAPI_FUNC(void) PyErr_Restore(PyObject *, PyObject *, PyObject *);
9191
PyAPI_FUNC(int) PyErr_GivenExceptionMatches(PyObject *, PyObject *);
9292
PyAPI_FUNC(int) PyErr_ExceptionMatches(PyObject *);
9393
PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);
94+
PyAPI_FUNC(void) _PyErr_ReplaceException(PyObject *, PyObject *, PyObject *);
9495

9596
/* */
9697

Modules/_io/_iomodule.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -529,14 +529,8 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds)
529529
PyObject *exc, *val, *tb, *close_result;
530530
PyErr_Fetch(&exc, &val, &tb);
531531
close_result = PyObject_CallMethod(result, "close", NULL);
532-
if (close_result != NULL) {
533-
Py_DECREF(close_result);
534-
PyErr_Restore(exc, val, tb);
535-
} else {
536-
Py_XDECREF(exc);
537-
Py_XDECREF(val);
538-
Py_XDECREF(tb);
539-
}
532+
_PyErr_ReplaceException(exc, val, tb);
533+
Py_XDECREF(close_result);
540534
Py_DECREF(result);
541535
}
542536
Py_XDECREF(modeobj);

Modules/_io/bufferedio.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -483,15 +483,8 @@ buffered_close(buffered *self, PyObject *args)
483483
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
484484

485485
if (exc != NULL) {
486-
if (res != NULL) {
487-
Py_CLEAR(res);
488-
PyErr_Restore(exc, val, tb);
489-
}
490-
else {
491-
Py_DECREF(exc);
492-
Py_XDECREF(val);
493-
Py_XDECREF(tb);
494-
}
486+
_PyErr_ReplaceException(exc, val, tb);
487+
Py_CLEAR(res);
495488
}
496489

497490
end:

Modules/_io/textio.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2480,15 +2480,8 @@ textiowrapper_close(textio *self, PyObject *args)
24802480

24812481
res = PyObject_CallMethod(self->buffer, "close", NULL);
24822482
if (exc != NULL) {
2483-
if (res != NULL) {
2484-
Py_CLEAR(res);
2485-
PyErr_Restore(exc, val, tb);
2486-
}
2487-
else {
2488-
Py_DECREF(exc);
2489-
Py_XDECREF(val);
2490-
Py_XDECREF(tb);
2491-
}
2483+
_PyErr_ReplaceException(exc, val, tb);
2484+
Py_CLEAR(res);
24922485
}
24932486
return res;
24942487
}

Python/errors.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,26 @@ PyErr_Clear(void)
263263
PyErr_Restore(NULL, NULL, NULL);
264264
}
265265

266+
/* Restore previously fetched exception if an exception is not set,
267+
otherwise drop previously fetched exception.
268+
Like _PyErr_ChainExceptions() in Python 3, but doesn't set the context.
269+
*/
270+
void
271+
_PyErr_ReplaceException(PyObject *exc, PyObject *val, PyObject *tb)
272+
{
273+
if (exc == NULL)
274+
return;
275+
276+
if (PyErr_Occurred()) {
277+
Py_DECREF(exc);
278+
Py_XDECREF(val);
279+
Py_XDECREF(tb);
280+
}
281+
else {
282+
PyErr_Restore(exc, val, tb);
283+
}
284+
}
285+
266286
/* Convenience functions to set a type error exception and return 0 */
267287

268288
int

0 commit comments

Comments
 (0)