summaryrefslogtreecommitdiffstats
path: root/Python/errors.c
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2021-11-30 22:37:04 (GMT)
committerGitHub <noreply@github.com>2021-11-30 22:37:04 (GMT)
commit8a45ca542a65ea27e7acaa44a4c833a27830e796 (patch)
tree8cc5563159c3c11b88d0f9c9b9164ed21a9d9e7f /Python/errors.c
parentaf8c8caaf5e07c02202d736a31f6a2f7e27819b8 (diff)
downloadcpython-8a45ca542a65ea27e7acaa44a4c833a27830e796.zip
cpython-8a45ca542a65ea27e7acaa44a4c833a27830e796.tar.gz
cpython-8a45ca542a65ea27e7acaa44a4c833a27830e796.tar.bz2
bpo-45711: Change exc_info related APIs to derive type and traceback from the exception instance (GH-29780)
Diffstat (limited to 'Python/errors.c')
-rw-r--r--Python/errors.c74
1 files changed, 48 insertions, 26 deletions
diff --git a/Python/errors.c b/Python/errors.c
index 6e74d19..0a8b5a2 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -470,6 +470,33 @@ PyErr_Clear(void)
_PyErr_Clear(tstate);
}
+static PyObject*
+get_exc_type(PyObject *exc_value) /* returns a borrowed ref */
+{
+ if (exc_value == NULL || exc_value == Py_None) {
+ return Py_None;
+ }
+ else {
+ assert(PyExceptionInstance_Check(exc_value));
+ PyObject *type = PyExceptionInstance_Class(exc_value);
+ assert(type != NULL);
+ return type;
+ }
+}
+
+static PyObject*
+get_exc_traceback(PyObject *exc_value) /* returns a borrowed ref */
+{
+ if (exc_value == NULL || exc_value == Py_None) {
+ return Py_None;
+ }
+ else {
+ assert(PyExceptionInstance_Check(exc_value));
+ PyObject *tb = PyException_GetTraceback(exc_value);
+ Py_XDECREF(tb);
+ return tb ? tb : Py_None;
+ }
+}
void
_PyErr_GetExcInfo(PyThreadState *tstate,
@@ -477,18 +504,9 @@ _PyErr_GetExcInfo(PyThreadState *tstate,
{
_PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate);
+ *p_type = get_exc_type(exc_info->exc_value);
*p_value = exc_info->exc_value;
- *p_traceback = exc_info->exc_traceback;
-
- if (*p_value == NULL || *p_value == Py_None) {
- assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None);
- *p_type = Py_None;
- }
- else {
- assert(PyExceptionInstance_Check(*p_value));
- assert(exc_info->exc_type == PyExceptionInstance_Class(*p_value));
- *p_type = PyExceptionInstance_Class(*p_value);
- }
+ *p_traceback = get_exc_traceback(exc_info->exc_value);
Py_XINCREF(*p_type);
Py_XINCREF(*p_value);
@@ -504,7 +522,7 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
}
void
-PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback)
+PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback)
{
PyObject *oldtype, *oldvalue, *oldtraceback;
PyThreadState *tstate = _PyThreadState_GET();
@@ -513,9 +531,16 @@ PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback)
oldvalue = tstate->exc_info->exc_value;
oldtraceback = tstate->exc_info->exc_traceback;
- tstate->exc_info->exc_type = p_type;
- tstate->exc_info->exc_value = p_value;
- tstate->exc_info->exc_traceback = p_traceback;
+
+ tstate->exc_info->exc_type = get_exc_type(value);
+ Py_XINCREF(tstate->exc_info->exc_type);
+ tstate->exc_info->exc_value = value;
+ tstate->exc_info->exc_traceback = get_exc_traceback(value);
+ Py_XINCREF(tstate->exc_info->exc_traceback);
+
+ /* These args are no longer used, but we still need to steal a ref */
+ Py_XDECREF(type);
+ Py_XDECREF(traceback);
Py_XDECREF(oldtype);
Py_XDECREF(oldvalue);
@@ -527,22 +552,19 @@ PyObject*
_PyErr_StackItemToExcInfoTuple(_PyErr_StackItem *err_info)
{
PyObject *exc_value = err_info->exc_value;
- if (exc_value == NULL) {
- exc_value = Py_None;
- }
- assert(exc_value == Py_None || PyExceptionInstance_Check(exc_value));
+ assert(exc_value == NULL ||
+ exc_value == Py_None ||
+ PyExceptionInstance_Check(exc_value));
- PyObject *exc_type = PyExceptionInstance_Check(exc_value) ?
- PyExceptionInstance_Class(exc_value) :
- Py_None;
+ PyObject *exc_type = get_exc_type(exc_value);
+ PyObject *exc_traceback = get_exc_traceback(exc_value);
return Py_BuildValue(
"(OOO)",
- exc_type,
- exc_value,
- err_info->exc_traceback != NULL ?
- err_info->exc_traceback : Py_None);
+ exc_type ? exc_type : Py_None,
+ exc_value ? exc_value : Py_None,
+ exc_traceback ? exc_traceback : Py_None);
}