Skip to content

Commit 6b9f653

Browse files
committed
Add support for nested exceptions in custom exceptions
1 parent 06003e8 commit 6b9f653

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

include/pybind11/pybind11.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2535,7 +2535,9 @@ class exception : public object {
25352535
}
25362536

25372537
// Sets the current python exception to this exception object with the given message
2538-
void operator()(const char *message) { PyErr_SetString(m_ptr, message); }
2538+
void operator()(const char *message) {
2539+
detail::raise_err(m_ptr, message);
2540+
}
25392541
};
25402542

25412543
PYBIND11_NAMESPACE_BEGIN(detail)
@@ -2567,6 +2569,8 @@ register_exception_impl(handle scope, const char *name, handle base, bool isLoca
25672569
try {
25682570
std::rethrow_exception(p);
25692571
} catch (const CppException &e) {
2572+
detail::handle_nested_exception(e, p);
2573+
25702574
detail::get_exception_object<CppException>()(e.what());
25712575
}
25722576
});

tests/test_exceptions.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,14 @@ TEST_SUBMODULE(exceptions, m) {
305305
}
306306
});
307307

308+
m.def("throw_custom_nested_exception", []() {
309+
try {
310+
throw std::runtime_error("Inner Exception");
311+
} catch (const std::runtime_error &) {
312+
std::throw_with_nested(MyException5("Outer Exception"));
313+
}
314+
});
315+
308316
m.def("error_already_set_what", [](const py::object &exc_type, const py::object &exc_value) {
309317
PyErr_SetObject(exc_type.ptr(), exc_value.ptr());
310318
std::string what = py::error_already_set().what();

tests/test_exceptions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,13 @@ def test_throw_nested_exception():
248248
assert str(excinfo.value.__cause__) == "Inner Exception"
249249

250250

251+
def test_throw_custom_nested_exception():
252+
with pytest.raises(m.MyException5) as excinfo:
253+
m.throw_custom_nested_exception()
254+
assert str(excinfo.value) == "Outer Exception"
255+
assert str(excinfo.value.__cause__) == "Inner Exception"
256+
257+
251258
# This can often happen if you wrap a pybind11 class in a Python wrapper
252259
def test_invalid_repr():
253260
class MyRepr:

0 commit comments

Comments
 (0)