Compare commits

...

4 Commits

Author SHA1 Message Date
Ed Catmur d880383d38
Merge 059362bcab into ab955f158c 2024-06-12 22:19:28 +00:00
pre-commit-ci[bot] 059362bcab [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2022-06-28 14:52:40 +00:00
Ed Catmur a8046ffe2d don't set nested exception if already set 2022-06-28 15:50:28 +01:00
Ed Catmur 1bd0eaae06 Expose exception cause as std::nested_exception 2022-06-28 15:19:00 +01:00
1 changed files with 22 additions and 2 deletions

View File

@ -716,6 +716,8 @@ struct error_fetch_and_normalize {
return (PyErr_GivenExceptionMatches(m_type.ptr(), exc.ptr()) != 0);
}
std::nested_exception get_cause_as_nested() const;
// Not protecting these for simplicity.
object m_type, m_value, m_trace;
@ -736,13 +738,17 @@ PYBIND11_NAMESPACE_END(detail)
/// thrown to propagate python-side errors back through C++ which can either be caught manually or
/// else falls back to the function dispatcher (which then raises the captured error back to
/// python).
class PYBIND11_EXPORT_EXCEPTION error_already_set : public std::exception {
class PYBIND11_EXPORT_EXCEPTION error_already_set : public std::exception,
public std::nested_exception {
public:
/// Fetches the current Python exception (using PyErr_Fetch()), which will clear the
/// current Python error indicator.
error_already_set()
: m_fetched_error{new detail::error_fetch_and_normalize("pybind11::error_already_set"),
m_fetched_error_deleter} {}
m_fetched_error_deleter} {
if (not nested_ptr())
static_cast<std::nested_exception &>(*this) = m_fetched_error->get_cause_as_nested();
}
/// The what() result is built lazily on demand.
/// WARNING: This member function needs to acquire the Python GIL. This can lead to
@ -2531,6 +2537,20 @@ bool object_api<D>::rich_compare(object_api const &other, int value) const {
return rv == 1;
}
inline std::nested_exception error_fetch_and_normalize::get_cause_as_nested() const {
auto cause = reinterpret_steal<object>(PyException_GetCause(m_value.ptr()));
if (not cause or cause.is_none())
return std::nested_exception();
auto typ = type::of(cause);
auto tb = reinterpret_steal<object>(PyException_GetTraceback(cause.ptr()));
PyErr_Restore(typ.release().ptr(), cause.release().ptr(), tb.release().ptr());
try {
throw error_already_set();
} catch (...) {
return std::nested_exception();
}
}
#define PYBIND11_MATH_OPERATOR_UNARY(op, fn) \
template <typename D> \
object object_api<D>::op() const { \