summaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Utility/Exceptions.c
diff options
context:
space:
mode:
authornik-bes <[email protected]>2025-05-19 07:20:13 +0300
committernik-bes <[email protected]>2025-05-19 07:36:02 +0300
commit317b7368e24941ff76499f500579fd9b10f6656e (patch)
treeabbcbaea595e7d2e9f23cf59a408b3082fe4340d /contrib/tools/cython/Cython/Utility/Exceptions.c
parent6b666a52d40308ab9b3532cd8d3008b9f37cfffb (diff)
Update Cython to 3.0.10.
commit_hash:b43c96b868cd36d636192fd2c6024d9f0d2fb6f8
Diffstat (limited to 'contrib/tools/cython/Cython/Utility/Exceptions.c')
-rw-r--r--contrib/tools/cython/Cython/Utility/Exceptions.c413
1 files changed, 355 insertions, 58 deletions
diff --git a/contrib/tools/cython/Cython/Utility/Exceptions.c b/contrib/tools/cython/Cython/Utility/Exceptions.c
index 8117b92d4b7..daf6578eb96 100644
--- a/contrib/tools/cython/Cython/Utility/Exceptions.c
+++ b/contrib/tools/cython/Cython/Utility/Exceptions.c
@@ -7,42 +7,82 @@
/////////////// AssertionsEnabled.init ///////////////
-__Pyx_init_assertions_enabled();
-/////////////// AssertionsEnabled.proto ///////////////
+if (likely(__Pyx_init_assertions_enabled() == 0)); else
+// error propagation code is appended automatically
-#define __Pyx_init_assertions_enabled()
+/////////////// AssertionsEnabled.proto ///////////////
#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag)
- #define __pyx_assertions_enabled() (1)
-#elif PY_VERSION_HEX < 0x03080000 || CYTHON_COMPILING_IN_PYPY || defined(Py_LIMITED_API)
- #define __pyx_assertions_enabled() (!Py_OptimizeFlag)
-#elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030900A6
- // Py3.8+ has PyConfig from PEP 587, but only Py3.9 added read access to it.
- // Py_OptimizeFlag is deprecated in Py3.12+
+ #define __Pyx_init_assertions_enabled() (0)
+ #define __pyx_assertions_enabled() (1)
+#elif CYTHON_COMPILING_IN_LIMITED_API || (CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030C0000)
+ // Py_OptimizeFlag is deprecated in Py3.12+ and not available in the Limited API.
static int __pyx_assertions_enabled_flag;
#define __pyx_assertions_enabled() (__pyx_assertions_enabled_flag)
- #undef __Pyx_init_assertions_enabled
- static void __Pyx_init_assertions_enabled(void) {
- __pyx_assertions_enabled_flag = ! _PyInterpreterState_GetConfig(__Pyx_PyThreadState_Current->interp)->optimization_level;
+ static int __Pyx_init_assertions_enabled(void) {
+ PyObject *builtins, *debug, *debug_str;
+ int flag;
+ builtins = PyEval_GetBuiltins();
+ if (!builtins) goto bad;
+ debug_str = PyUnicode_FromStringAndSize("__debug__", 9);
+ if (!debug_str) goto bad;
+ debug = PyObject_GetItem(builtins, debug_str);
+ Py_DECREF(debug_str);
+ if (!debug) goto bad;
+ flag = PyObject_IsTrue(debug);
+ Py_DECREF(debug);
+ if (flag == -1) goto bad;
+ __pyx_assertions_enabled_flag = flag;
+ return 0;
+ bad:
+ __pyx_assertions_enabled_flag = 1;
+ // We (rarely) may not have an exception set, but the calling code will call PyErr_Occurred() either way.
+ return -1;
}
#else
- #define __pyx_assertions_enabled() (!Py_OptimizeFlag)
+ #define __Pyx_init_assertions_enabled() (0)
+ #define __pyx_assertions_enabled() (!Py_OptimizeFlag)
#endif
+/////////////// ErrOccurredWithGIL.proto ///////////////
+static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */
+
+/////////////// ErrOccurredWithGIL ///////////////
+static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) {
+ int err;
+ #ifdef WITH_THREAD
+ PyGILState_STATE _save = PyGILState_Ensure();
+ #endif
+ err = !!PyErr_Occurred();
+ #ifdef WITH_THREAD
+ PyGILState_Release(_save);
+ #endif
+ return err;
+}
+
+
/////////////// PyThreadStateGet.proto ///////////////
//@substitute: naming
#if CYTHON_FAST_THREAD_STATE
#define __Pyx_PyThreadState_declare PyThreadState *$local_tstate_cname;
#define __Pyx_PyThreadState_assign $local_tstate_cname = __Pyx_PyThreadState_Current;
-#define __Pyx_PyErr_Occurred() $local_tstate_cname->curexc_type
+#if PY_VERSION_HEX >= 0x030C00A6
+#define __Pyx_PyErr_Occurred() ($local_tstate_cname->current_exception != NULL)
+#define __Pyx_PyErr_CurrentExceptionType() ($local_tstate_cname->current_exception ? (PyObject*) Py_TYPE($local_tstate_cname->current_exception) : (PyObject*) NULL)
+#else
+#define __Pyx_PyErr_Occurred() ($local_tstate_cname->curexc_type != NULL)
+#define __Pyx_PyErr_CurrentExceptionType() ($local_tstate_cname->curexc_type)
+#endif
#else
+// !CYTHON_FAST_THREAD_STATE
#define __Pyx_PyThreadState_declare
#define __Pyx_PyThreadState_assign
-#define __Pyx_PyErr_Occurred() PyErr_Occurred()
+#define __Pyx_PyErr_Occurred() (PyErr_Occurred() != NULL)
+#define __Pyx_PyErr_CurrentExceptionType() PyErr_Occurred()
#endif
@@ -75,12 +115,30 @@ static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple
}
static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err) {
- PyObject *exc_type = tstate->curexc_type;
+ int result;
+ PyObject *exc_type;
+#if PY_VERSION_HEX >= 0x030C00A6
+ PyObject *current_exception = tstate->current_exception;
+ if (unlikely(!current_exception)) return 0;
+ exc_type = (PyObject*) Py_TYPE(current_exception);
+ if (exc_type == err) return 1;
+#else
+ exc_type = tstate->curexc_type;
if (exc_type == err) return 1;
if (unlikely(!exc_type)) return 0;
- if (unlikely(PyTuple_Check(err)))
- return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err);
- return __Pyx_PyErr_GivenExceptionMatches(exc_type, err);
+#endif
+ #if CYTHON_AVOID_BORROWED_REFS
+ Py_INCREF(exc_type);
+ #endif
+ if (unlikely(PyTuple_Check(err))) {
+ result = __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err);
+ } else {
+ result = __Pyx_PyErr_GivenExceptionMatches(exc_type, err);
+ }
+ #if CYTHON_AVOID_BORROWED_REFS
+ Py_DECREF(exc_type);
+ #endif
+ return result;
}
#endif
@@ -97,7 +155,7 @@ static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tsta
static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); /*proto*/
static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); /*proto*/
-#if CYTHON_COMPILING_IN_CPYTHON
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A6
#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL))
#else
#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc)
@@ -118,6 +176,22 @@ static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject
#if CYTHON_FAST_THREAD_STATE
static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) {
+#if PY_VERSION_HEX >= 0x030C00A6
+ PyObject *tmp_value;
+ assert(type == NULL || (value != NULL && type == (PyObject*) Py_TYPE(value)));
+ if (value) {
+ #if CYTHON_COMPILING_IN_CPYTHON
+ if (unlikely(((PyBaseExceptionObject*) value)->traceback != tb))
+ #endif
+ // If this fails, we may lose the traceback but still set the expected exception below.
+ PyException_SetTraceback(value, tb);
+ }
+ tmp_value = tstate->current_exception;
+ tstate->current_exception = value;
+ Py_XDECREF(tmp_value);
+ Py_XDECREF(type);
+ Py_XDECREF(tb);
+#else
PyObject *tmp_type, *tmp_value, *tmp_tb;
tmp_type = tstate->curexc_type;
tmp_value = tstate->curexc_value;
@@ -128,15 +202,35 @@ static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObjec
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
+#endif
}
static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
+#if PY_VERSION_HEX >= 0x030C00A6
+ PyObject* exc_value;
+ exc_value = tstate->current_exception;
+ tstate->current_exception = 0;
+ *value = exc_value;
+ *type = NULL;
+ *tb = NULL;
+ if (exc_value) {
+ *type = (PyObject*) Py_TYPE(exc_value);
+ Py_INCREF(*type);
+ #if CYTHON_COMPILING_IN_CPYTHON
+ *tb = ((PyBaseExceptionObject*) exc_value)->traceback;
+ Py_XINCREF(*tb);
+ #else
+ *tb = PyException_GetTraceback(exc_value);
+ #endif
+ }
+#else
*type = tstate->curexc_type;
*value = tstate->curexc_value;
*tb = tstate->curexc_traceback;
tstate->curexc_type = 0;
tstate->curexc_value = 0;
tstate->curexc_traceback = 0;
+#endif
}
#endif
@@ -153,9 +247,9 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
// has changed quite a lot between the two versions.
#if PY_MAJOR_VERSION < 3
-static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
- CYTHON_UNUSED PyObject *cause) {
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
__Pyx_PyThreadState_declare
+ CYTHON_UNUSED_VAR(cause);
/* 'cause' is only used in Py3 */
Py_XINCREF(type);
if (!value || value == Py_None)
@@ -310,7 +404,10 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
PyErr_SetObject(type, value);
if (tb) {
-#if CYTHON_FAST_THREAD_STATE
+ #if PY_VERSION_HEX >= 0x030C00A6
+ // If this fails, we just get a different exception, so ignore the return value.
+ PyException_SetTraceback(value, tb);
+ #elif CYTHON_FAST_THREAD_STATE
PyThreadState *tstate = __Pyx_PyThreadState_Current;
PyObject* tmp_tb = tstate->curexc_traceback;
if (tb != tmp_tb) {
@@ -336,19 +433,19 @@ bad:
/////////////// GetTopmostException.proto ///////////////
-#if CYTHON_USE_EXC_INFO_STACK
+#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE
static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate);
#endif
/////////////// GetTopmostException ///////////////
-#if CYTHON_USE_EXC_INFO_STACK
+#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE
// Copied from errors.c in CPython.
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;
@@ -377,31 +474,46 @@ static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
#endif
{
- PyObject *local_type, *local_value, *local_tb;
+ PyObject *local_type = NULL, *local_value, *local_tb = NULL;
#if CYTHON_FAST_THREAD_STATE
PyObject *tmp_type, *tmp_value, *tmp_tb;
+ #if PY_VERSION_HEX >= 0x030C00A6
+ local_value = tstate->current_exception;
+ tstate->current_exception = 0;
+ if (likely(local_value)) {
+ local_type = (PyObject*) Py_TYPE(local_value);
+ Py_INCREF(local_type);
+ local_tb = PyException_GetTraceback(local_value);
+ }
+ #else
local_type = tstate->curexc_type;
local_value = tstate->curexc_value;
local_tb = tstate->curexc_traceback;
tstate->curexc_type = 0;
tstate->curexc_value = 0;
tstate->curexc_traceback = 0;
+ #endif
#else
PyErr_Fetch(&local_type, &local_value, &local_tb);
#endif
+
PyErr_NormalizeException(&local_type, &local_value, &local_tb);
-#if CYTHON_FAST_THREAD_STATE
+#if CYTHON_FAST_THREAD_STATE && PY_VERSION_HEX >= 0x030C00A6
+ if (unlikely(tstate->current_exception))
+#elif CYTHON_FAST_THREAD_STATE
if (unlikely(tstate->curexc_type))
#else
if (unlikely(PyErr_Occurred()))
#endif
goto bad;
+
#if PY_MAJOR_VERSION >= 3
if (local_tb) {
if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
goto bad;
}
#endif
+
// traceback may be NULL for freshly raised exceptions
Py_XINCREF(local_tb);
// exception state may be temporarily empty in parallel loops (race condition)
@@ -410,16 +522,26 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
*type = local_type;
*value = local_value;
*tb = local_tb;
+
#if CYTHON_FAST_THREAD_STATE
#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;
@@ -437,7 +559,9 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
#else
PyErr_SetExcInfo(local_type, local_value, local_tb);
#endif
+
return 0;
+
bad:
*type = 0;
*value = 0;
@@ -459,35 +583,44 @@ static CYTHON_INLINE void __Pyx_ReraiseException(void) {
PyObject *type = NULL, *value = NULL, *tb = NULL;
#if CYTHON_FAST_THREAD_STATE
PyThreadState *tstate = PyThreadState_GET();
- #if CYTHON_USE_EXC_INFO_STACK
+ #if 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;
+ #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;
- #endif
+ 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);
}
}
@@ -513,24 +646,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;
- #else
+ 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;
@@ -550,6 +708,7 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
+ #endif
}
#endif
@@ -569,8 +728,27 @@ 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);
+ #if CYTHON_COMPILING_IN_CPYTHON
+ tmp_tb = ((PyBaseExceptionObject*) tmp_value)->traceback;
+ Py_XINCREF(tmp_tb);
+ #else
+ tmp_tb = PyException_GetTraceback(tmp_value);
+ #endif
+ }
+ #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;
@@ -579,7 +757,7 @@ static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject *
exc_info->exc_type = *type;
exc_info->exc_value = *value;
exc_info->exc_traceback = *tb;
- #else
+ #else
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
@@ -587,7 +765,7 @@ static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject *
tstate->exc_type = *type;
tstate->exc_value = *value;
tstate->exc_traceback = *tb;
- #endif
+ #endif
*type = tmp_type;
*value = tmp_value;
@@ -616,9 +794,9 @@ static void __Pyx_WriteUnraisable(const char *name, int clineno,
//@requires: PyErrFetchRestore
//@requires: PyThreadStateGet
-static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
- CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename,
- int full_traceback, CYTHON_UNUSED int nogil) {
+static void __Pyx_WriteUnraisable(const char *name, int clineno,
+ int lineno, const char *filename,
+ int full_traceback, int nogil) {
PyObject *old_exc, *old_val, *old_tb;
PyObject *ctx;
__Pyx_PyThreadState_declare
@@ -626,9 +804,14 @@ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
PyGILState_STATE state;
if (nogil)
state = PyGILState_Ensure();
- /* initalize to suppress warning */
+ /* arbitrary, to suppress warning */
else state = (PyGILState_STATE)0;
#endif
+ CYTHON_UNUSED_VAR(clineno);
+ CYTHON_UNUSED_VAR(lineno);
+ CYTHON_UNUSED_VAR(filename);
+ CYTHON_MAYBE_UNUSED_VAR(nogil);
+
__Pyx_PyThreadState_assign
__Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
if (full_traceback) {
@@ -665,19 +848,21 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line);/*proto*/
#endif
/////////////// CLineInTraceback ///////////////
-//@requires: ObjectHandling.c::PyObjectGetAttrStr
+//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: ObjectHandling.c::PyDictVersioning
//@requires: PyErrFetchRestore
//@substitute: naming
#ifndef CYTHON_CLINE_IN_TRACEBACK
-static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_line) {
+static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) {
PyObject *use_cline;
PyObject *ptype, *pvalue, *ptraceback;
#if CYTHON_COMPILING_IN_CPYTHON
PyObject **cython_runtime_dict;
#endif
+ CYTHON_MAYBE_UNUSED_VAR(tstate);
+
if (unlikely(!${cython_runtime_cname})) {
// Very early error where the runtime module is not set up yet.
return c_line;
@@ -694,7 +879,7 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li
} else
#endif
{
- PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(${cython_runtime_cname}, PYIDENT("cline_in_traceback"));
+ PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStrNoError(${cython_runtime_cname}, PYIDENT("cline_in_traceback"));
if (use_cline_obj) {
use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True;
Py_DECREF(use_cline_obj);
@@ -729,13 +914,123 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"
-#if PY_VERSION_HEX >= 0x030b00a6
+#if PY_VERSION_HEX >= 0x030b00a6 && !CYTHON_COMPILING_IN_LIMITED_API
#ifndef Py_BUILD_CORE
#define Py_BUILD_CORE 1
#endif
#include "internal/pycore_frame.h"
#endif
+#if CYTHON_COMPILING_IN_LIMITED_API
+static PyObject *__Pyx_PyCode_Replace_For_AddTraceback(PyObject *code, PyObject *scratch_dict,
+ PyObject *firstlineno, PyObject *name) {
+ PyObject *replace = NULL;
+ if (unlikely(PyDict_SetItemString(scratch_dict, "co_firstlineno", firstlineno))) return NULL;
+ if (unlikely(PyDict_SetItemString(scratch_dict, "co_name", name))) return NULL;
+
+ replace = PyObject_GetAttrString(code, "replace");
+ if (likely(replace)) {
+ PyObject *result;
+ result = PyObject_Call(replace, $empty_tuple, scratch_dict);
+ Py_DECREF(replace);
+ return result;
+ }
+ PyErr_Clear();
+
+ #if __PYX_LIMITED_VERSION_HEX < 0x030780000
+ // If we're here, we're probably on Python <=3.7 which doesn't have code.replace.
+ // In this we take a lazy interpreted route (without regard to performance
+ // since it's fairly old and this is mostly just to get something working)
+ {
+ PyObject *compiled = NULL, *result = NULL;
+ if (unlikely(PyDict_SetItemString(scratch_dict, "code", code))) return NULL;
+ if (unlikely(PyDict_SetItemString(scratch_dict, "type", (PyObject*)(&PyType_Type)))) return NULL;
+ compiled = Py_CompileString(
+ "out = type(code)(\n"
+ " code.co_argcount, code.co_kwonlyargcount, code.co_nlocals, code.co_stacksize,\n"
+ " code.co_flags, code.co_code, code.co_consts, code.co_names,\n"
+ " code.co_varnames, code.co_filename, co_name, co_firstlineno,\n"
+ " code.co_lnotab)\n", "<dummy>", Py_file_input);
+ if (!compiled) return NULL;
+ result = PyEval_EvalCode(compiled, scratch_dict, scratch_dict);
+ Py_DECREF(compiled);
+ if (!result) PyErr_Print();
+ Py_DECREF(result);
+ result = PyDict_GetItemString(scratch_dict, "out");
+ if (result) Py_INCREF(result);
+ return result;
+ }
+ #else
+ return NULL;
+ #endif
+}
+
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+ int py_line, const char *filename) {
+ PyObject *code_object = NULL, *py_py_line = NULL, *py_funcname = NULL, *dict = NULL;
+ PyObject *replace = NULL, *getframe = NULL, *frame = NULL;
+ PyObject *exc_type, *exc_value, *exc_traceback;
+ int success = 0;
+ if (c_line) {
+ // Avoid "unused" warning as long as we don't use this.
+ (void) $cfilenm_cname;
+ (void) __Pyx_CLineForTraceback(__Pyx_PyThreadState_Current, c_line);
+ }
+
+ // DW - this is a horrendous hack, but I'm quite proud of it. Essentially
+ // we need to generate a frame with the right line number/filename/funcname.
+ // We do this by compiling a small bit of code that uses sys._getframe to get a
+ // frame, and then customizing the details of the code to match.
+ // We then run the code object and use the generated frame to set the traceback.
+
+ PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
+
+ code_object = Py_CompileString("_getframe()", filename, Py_eval_input);
+ if (unlikely(!code_object)) goto bad;
+ py_py_line = PyLong_FromLong(py_line);
+ if (unlikely(!py_py_line)) goto bad;
+ py_funcname = PyUnicode_FromString(funcname);
+ if (unlikely(!py_funcname)) goto bad;
+ dict = PyDict_New();
+ if (unlikely(!dict)) goto bad;
+ {
+ PyObject *old_code_object = code_object;
+ code_object = __Pyx_PyCode_Replace_For_AddTraceback(code_object, dict, py_py_line, py_funcname);
+ Py_DECREF(old_code_object);
+ }
+ if (unlikely(!code_object)) goto bad;
+
+ // Note that getframe is borrowed
+ getframe = PySys_GetObject("_getframe");
+ if (unlikely(!getframe)) goto bad;
+ // reuse dict as globals (nothing conflicts, and it saves an allocation)
+ if (unlikely(PyDict_SetItemString(dict, "_getframe", getframe))) goto bad;
+
+ frame = PyEval_EvalCode(code_object, dict, dict);
+ if (unlikely(!frame) || frame == Py_None) goto bad;
+ success = 1;
+
+ bad:
+ PyErr_Restore(exc_type, exc_value, exc_traceback);
+ Py_XDECREF(code_object);
+ Py_XDECREF(py_py_line);
+ Py_XDECREF(py_funcname);
+ Py_XDECREF(dict);
+ Py_XDECREF(replace);
+
+ if (success) {
+ // Unfortunately an easy way to check the type of frame isn't in the
+ // limited API. The check against None should cover the most
+ // likely wrong answer though.
+ PyTraceBack_Here(
+ // Python < 0x03090000 didn't expose PyFrameObject
+ // but they all expose struct _frame as an opaque type
+ (struct _frame*)frame);
+ }
+
+ Py_XDECREF(frame);
+}
+#else
static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
const char *funcname, int c_line,
int py_line, const char *filename) {
@@ -768,6 +1063,7 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
#if PY_MAJOR_VERSION < 3
py_code = __Pyx_PyCode_New(
0, /*int argcount,*/
+ 0, /*int posonlyargcount,*/
0, /*int kwonlyargcount,*/
0, /*int nlocals,*/
0, /*int stacksize,*/
@@ -787,7 +1083,7 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
#else
py_code = PyCode_NewEmpty(filename, funcname, py_line);
#endif
- Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline
+ Py_XDECREF(py_funcname); /* XDECREF since it's only set on Py3 if cline */
return py_code;
bad:
Py_XDECREF(py_funcname);
@@ -838,3 +1134,4 @@ bad:
Py_XDECREF(py_code);
Py_XDECREF(py_frame);
}
+#endif