Skip to content

Commit

Permalink
generalization of nb::chain_error
Browse files Browse the repository at this point in the history
  • Loading branch information
wjakob committed Jun 16, 2023
1 parent a7ddeb1 commit beb6999
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 11 deletions.
5 changes: 3 additions & 2 deletions docs/api_core.rst
Expand Up @@ -1217,8 +1217,9 @@ the reference section on :ref:`class binding <class_binding>`.
Raise a Python error of type ``type`` using the format string ``fmt``
interpreted by ``PyErr_FormatV``.

This newly created error is chained on top of an already existing error
status that must be set before calling the function.
If a Python error state was already set prior to calling this method, then
the new error is *chained* on top of the existing one. Otherwise, the
function creates a new error without initializing its ``__cause__`` field.

.. cpp:function:: void raise_from(python_error &e, handle type, const char * fmt, ...)

Expand Down
2 changes: 1 addition & 1 deletion include/nanobind/nb_error.h
Expand Up @@ -148,6 +148,6 @@ class exception : public object {
};

NB_CORE void chain_error(handle type, const char *fmt, ...) noexcept;
NB_CORE void raise_from(python_error &e, handle type, const char *fmt, ...);
[[noreturn]] NB_CORE void raise_from(python_error &e, handle type, const char *fmt, ...);

NAMESPACE_END(NB_NAMESPACE)
20 changes: 12 additions & 8 deletions src/error.cpp
Expand Up @@ -253,20 +253,21 @@ NAMESPACE_END(detail)
static void chain_error_v(handle type, const char *fmt, va_list args) noexcept {
#if PY_VERSION_HEX >= 0x030C0000
PyObject *value = PyErr_GetRaisedException();
check(value, "nanobind::detail::raise_from(): error status is not set!");
#else
PyObject *tp = nullptr, *value = nullptr, *traceback = nullptr;

PyErr_Fetch(&tp, &value, &traceback);
check(tp, "nanobind::detail::raise_from(): error status is not set!");

PyErr_NormalizeException(&tp, &value, &traceback);
if (traceback) {
PyException_SetTraceback(value, traceback);
Py_DECREF(traceback);
}
if (tp) {
PyErr_NormalizeException(&tp, &value, &traceback);
if (traceback) {
PyException_SetTraceback(value, traceback);
Py_DECREF(traceback);
}

Py_DECREF(tp);
Py_DECREF(tp);
tp = traceback = nullptr;
}
#endif

#if !defined(PYPY_VERSION)
Expand All @@ -278,6 +279,9 @@ static void chain_error_v(handle type, const char *fmt, va_list args) noexcept {
Py_DECREF(exc_str);
#endif

if (!value)
return;

PyObject *value_2 = nullptr;
#if PY_VERSION_HEX >= 0x030C0000
value_2 = PyErr_GetRaisedException();
Expand Down

0 comments on commit beb6999

Please sign in to comment.