Commit 77695702 authored by scoder's avatar scoder Committed by GitHub

Adapt to "exc_info" changes in CPython 3.11a4 (GH-4584)

Adapt to "exc_info" changes in CPython 3.11a4, where "->exc_type" and "->exc_traceback" are gone and now get inferred from "->exc_value".

Closes https://github.com/cython/cython/issues/4500
parent 9d038fb3
......@@ -601,6 +601,9 @@ static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *$local_tstate_cna
static CYTHON_INLINE
void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *exc_state) {
#if PY_VERSION_HEX >= 0x030B00a4
Py_CLEAR(exc_state->exc_value);
#else
PyObject *t, *v, *tb;
t = exc_state->exc_type;
v = exc_state->exc_value;
......@@ -613,6 +616,7 @@ void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *exc_state) {
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
#endif
}
#define __Pyx_Coroutine_AlreadyRunningError(gen) (__Pyx__Coroutine_AlreadyRunningError(gen), (PyObject*)NULL)
......@@ -718,14 +722,21 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
// - do not touch external frames and tracebacks
exc_state = &self->gi_exc_state;
if (exc_state->exc_type) {
if (exc_state->exc_value) {
#if CYTHON_COMPILING_IN_PYPY
// FIXME: what to do in PyPy?
#else
// Generators always return to their most recent caller, not
// necessarily their creator.
if (exc_state->exc_traceback) {
PyTracebackObject *tb = (PyTracebackObject *) exc_state->exc_traceback;
PyObject *exc_tb;
#if PY_VERSION_HEX >= 0x030B00a4
// owned reference!
exc_tb = PyException_GetTraceback(exc_state->exc_value);
#else
exc_tb = exc_state->exc_traceback;
#endif
if (exc_tb) {
PyTracebackObject *tb = (PyTracebackObject *) exc_tb;
PyFrameObject *f = tb->tb_frame;
assert(f->f_back == NULL);
......@@ -737,6 +748,9 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
Py_XINCREF(tstate->frame);
f->f_back = tstate->frame;
#endif
#if PY_VERSION_HEX >= 0x030B00a4
Py_DECREF(exc_tb);
#endif
}
#endif
}
......@@ -778,17 +792,28 @@ static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStr
// Don't keep the reference to f_back any longer than necessary. It
// may keep a chain of frames alive or it could create a reference
// cycle.
PyObject *exc_tb = exc_state->exc_traceback;
if (likely(exc_tb)) {
#if CYTHON_COMPILING_IN_PYPY
// FIXME: what to do in PyPy?
#else
PyObject *exc_tb;
#if PY_VERSION_HEX >= 0x030B00a4
if (!exc_state->exc_value) return;
// owned reference!
exc_tb = PyException_GetTraceback(exc_state->exc_value);
#else
exc_tb = exc_state->exc_traceback;
#endif
if (likely(exc_tb)) {
PyTracebackObject *tb = (PyTracebackObject *) exc_tb;
PyFrameObject *f = tb->tb_frame;
Py_CLEAR(f->f_back);
#endif
#if PY_VERSION_HEX >= 0x030B00a4
Py_DECREF(exc_tb);
#endif
}
#endif
}
static CYTHON_INLINE
......@@ -1133,9 +1158,13 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *self, PyObject *args) {
}
static CYTHON_INLINE int __Pyx_Coroutine_traverse_excstate(__Pyx_ExcInfoStruct *exc_state, visitproc visit, void *arg) {
#if PY_VERSION_HEX >= 0x030B00a4
Py_VISIT(exc_state->exc_value);
#else
Py_VISIT(exc_state->exc_type);
Py_VISIT(exc_state->exc_value);
Py_VISIT(exc_state->exc_traceback);
#endif
return 0;
}
......@@ -1432,9 +1461,13 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
gen->resume_label = 0;
gen->classobj = NULL;
gen->yieldfrom = NULL;
#if PY_VERSION_HEX >= 0x030B00a4
gen->gi_exc_state.exc_value = NULL;
#else
gen->gi_exc_state.exc_type = NULL;
gen->gi_exc_state.exc_value = NULL;
gen->gi_exc_state.exc_traceback = NULL;
#endif
#if CYTHON_USE_EXC_INFO_STACK
gen->gi_exc_state.previous_item = NULL;
#endif
......@@ -2171,7 +2204,7 @@ static void __Pyx__ReturnWithStopIteration(PyObject* value) {
#if CYTHON_FAST_THREAD_STATE
__Pyx_PyThreadState_assign
#if CYTHON_USE_EXC_INFO_STACK
if (!$local_tstate_cname->exc_info->exc_type)
if (!$local_tstate_cname->exc_info->exc_value)
#else
if (!$local_tstate_cname->exc_type)
#endif
......
......@@ -339,7 +339,7 @@ static _PyErr_StackItem *
__Pyx_PyErr_GetTopmostException(PyThreadState *tstate)
{
_PyErr_StackItem *exc_info = tstate->exc_info;
while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) &&
while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) &&
exc_info->previous_item != NULL)
{
exc_info = exc_info->previous_item;
......@@ -405,12 +405,21 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
#if CYTHON_USE_EXC_INFO_STACK
{
_PyErr_StackItem *exc_info = tstate->exc_info;
#if PY_VERSION_HEX >= 0x030B00a4
tmp_value = exc_info->exc_value;
exc_info->exc_value = local_value;
tmp_type = NULL;
tmp_tb = NULL;
Py_XDECREF(local_type);
Py_XDECREF(local_tb);
#else
tmp_type = exc_info->exc_type;
tmp_value = exc_info->exc_value;
tmp_tb = exc_info->exc_traceback;
exc_info->exc_type = local_type;
exc_info->exc_value = local_value;
exc_info->exc_traceback = local_tb;
#endif
}
#else
tmp_type = tstate->exc_type;
......@@ -452,33 +461,42 @@ static CYTHON_INLINE void __Pyx_ReraiseException(void) {
PyThreadState *tstate = PyThreadState_GET();
#if CYTHON_USE_EXC_INFO_STACK
_PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
type = exc_info->exc_type;
value = exc_info->exc_value;
#if PY_VERSION_HEX >= 0x030B00a4
if (unlikely(value == Py_None)) {
value = NULL;
} else if (value) {
Py_INCREF(value);
type = (PyObject*) Py_TYPE(value);
Py_INCREF(type);
tb = PyException_GetTraceback(value);
}
#else
type = exc_info->exc_type;
tb = exc_info->exc_traceback;
Py_XINCREF(type);
Py_XINCREF(value);
Py_XINCREF(tb);
#endif
#else
type = tstate->exc_type;
value = tstate->exc_value;
tb = tstate->exc_traceback;
Py_XINCREF(type);
Py_XINCREF(value);
Py_XINCREF(tb);
#endif
#else
PyErr_GetExcInfo(&type, &value, &tb);
#endif
if (!type || type == Py_None) {
#if !CYTHON_FAST_THREAD_STATE
if (unlikely(!type || type == Py_None)) {
Py_XDECREF(type);
Py_XDECREF(value);
Py_XDECREF(tb);
#endif
// message copied from Py3
PyErr_SetString(PyExc_RuntimeError,
"No active exception to reraise");
} else {
#if CYTHON_FAST_THREAD_STATE
Py_INCREF(type);
Py_XINCREF(value);
Py_XINCREF(tb);
#endif
PyErr_Restore(type, value, tb);
}
}
......@@ -504,24 +522,49 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
#if CYTHON_FAST_THREAD_STATE
static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
#if CYTHON_USE_EXC_INFO_STACK
#if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4
_PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
PyObject *exc_value = exc_info->exc_value;
if (exc_value == NULL || exc_value == Py_None) {
*value = NULL;
*type = NULL;
*tb = NULL;
} else {
*value = exc_value;
Py_INCREF(*value);
*type = (PyObject*) Py_TYPE(exc_value);
Py_INCREF(*type);
*tb = PyException_GetTraceback(exc_value);
}
#elif CYTHON_USE_EXC_INFO_STACK
_PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
*type = exc_info->exc_type;
*value = exc_info->exc_value;
*tb = exc_info->exc_traceback;
Py_XINCREF(*type);
Py_XINCREF(*value);
Py_XINCREF(*tb);
#else
*type = tstate->exc_type;
*value = tstate->exc_value;
*tb = tstate->exc_traceback;
#endif
Py_XINCREF(*type);
Py_XINCREF(*value);
Py_XINCREF(*tb);
#endif
}
static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) {
#if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4
_PyErr_StackItem *exc_info = tstate->exc_info;
PyObject *tmp_value = exc_info->exc_value;
exc_info->exc_value = value;
Py_XDECREF(tmp_value);
// TODO: avoid passing these at all
Py_XDECREF(type);
Py_XDECREF(tb);
#else
PyObject *tmp_type, *tmp_value, *tmp_tb;
#if CYTHON_USE_EXC_INFO_STACK
_PyErr_StackItem *exc_info = tstate->exc_info;
tmp_type = exc_info->exc_type;
......@@ -541,6 +584,7 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
#endif
}
#endif
......@@ -560,8 +604,22 @@ static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value,
#if CYTHON_FAST_THREAD_STATE
static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
PyObject *tmp_type, *tmp_value, *tmp_tb;
#if CYTHON_USE_EXC_INFO_STACK
#if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4
_PyErr_StackItem *exc_info = tstate->exc_info;
tmp_value = exc_info->exc_value;
exc_info->exc_value = *value;
if (tmp_value == NULL || tmp_value == Py_None) {
Py_XDECREF(tmp_value);
tmp_value = NULL;
tmp_type = NULL;
tmp_tb = NULL;
} else {
// TODO: avoid swapping these at all
tmp_type = (PyObject*) Py_TYPE(tmp_value);
Py_INCREF(tmp_type);
tmp_tb = PyException_GetTraceback(tmp_value);
}
#elif CYTHON_USE_EXC_INFO_STACK
_PyErr_StackItem *exc_info = tstate->exc_info;
tmp_type = exc_info->exc_type;
tmp_value = exc_info->exc_value;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment