mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
Add a method to check Python exception types (#772)
This commit adds `error_already_set::matches()` convenience method to check if the exception trapped by `error_already_set` matches a given Python exception type. This will address #700 by providing a less verbose way to check exceptions.
This commit is contained in:
parent
37ef74c584
commit
83a8a977a7
@ -597,6 +597,9 @@ public:
|
|||||||
/// Clear the held Python error state (the C++ `what()` message remains intact)
|
/// Clear the held Python error state (the C++ `what()` message remains intact)
|
||||||
void clear() { restore(); PyErr_Clear(); }
|
void clear() { restore(); PyErr_Clear(); }
|
||||||
|
|
||||||
|
/// Check if the trapped exception matches a given Python exception class
|
||||||
|
bool matches(PyObject *ex) const { return PyErr_GivenExceptionMatches(ex, type); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PyObject *type, *value, *trace;
|
PyObject *type, *value, *trace;
|
||||||
};
|
};
|
||||||
|
@ -86,6 +86,20 @@ void throws_logic_error() {
|
|||||||
throw std::logic_error("this error should fall through to the standard handler");
|
throw std::logic_error("this error should fall through to the standard handler");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test error_already_set::matches() method
|
||||||
|
void exception_matches() {
|
||||||
|
py::dict foo;
|
||||||
|
try {
|
||||||
|
foo["bar"];
|
||||||
|
}
|
||||||
|
catch (py::error_already_set& ex) {
|
||||||
|
if (ex.matches(PyExc_KeyError))
|
||||||
|
ex.clear();
|
||||||
|
else
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct PythonCallInDestructor {
|
struct PythonCallInDestructor {
|
||||||
PythonCallInDestructor(const py::dict &d) : d(d) {}
|
PythonCallInDestructor(const py::dict &d) : d(d) {}
|
||||||
~PythonCallInDestructor() { d["good"] = true; }
|
~PythonCallInDestructor() { d["good"] = true; }
|
||||||
@ -140,6 +154,7 @@ test_initializer custom_exceptions([](py::module &m) {
|
|||||||
m.def("throws5", &throws5);
|
m.def("throws5", &throws5);
|
||||||
m.def("throws5_1", &throws5_1);
|
m.def("throws5_1", &throws5_1);
|
||||||
m.def("throws_logic_error", &throws_logic_error);
|
m.def("throws_logic_error", &throws_logic_error);
|
||||||
|
m.def("exception_matches", &exception_matches);
|
||||||
|
|
||||||
m.def("throw_already_set", [](bool err) {
|
m.def("throw_already_set", [](bool err) {
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -21,6 +21,11 @@ def test_python_call_in_catch():
|
|||||||
assert d["good"] is True
|
assert d["good"] is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_exception_matches():
|
||||||
|
from pybind11_tests import exception_matches
|
||||||
|
exception_matches()
|
||||||
|
|
||||||
|
|
||||||
def test_custom(msg):
|
def test_custom(msg):
|
||||||
from pybind11_tests import (MyException, MyException5, MyException5_1,
|
from pybind11_tests import (MyException, MyException5, MyException5_1,
|
||||||
throws1, throws2, throws3, throws4, throws5, throws5_1,
|
throws1, throws2, throws3, throws4, throws5, throws5_1,
|
||||||
|
Loading…
Reference in New Issue
Block a user