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:
Roman Miroshnychenko 2017-04-02 23:38:50 +03:00 committed by Dean Moldovan
parent 37ef74c584
commit 83a8a977a7
3 changed files with 23 additions and 0 deletions

View File

@ -597,6 +597,9 @@ public:
/// Clear the held Python error state (the C++ `what()` message remains intact)
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:
PyObject *type, *value, *trace;
};

View File

@ -86,6 +86,20 @@ void throws_logic_error() {
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 {
PythonCallInDestructor(const py::dict &d) : d(d) {}
~PythonCallInDestructor() { d["good"] = true; }
@ -140,6 +154,7 @@ test_initializer custom_exceptions([](py::module &m) {
m.def("throws5", &throws5);
m.def("throws5_1", &throws5_1);
m.def("throws_logic_error", &throws_logic_error);
m.def("exception_matches", &exception_matches);
m.def("throw_already_set", [](bool err) {
if (err)

View File

@ -21,6 +21,11 @@ def test_python_call_in_catch():
assert d["good"] is True
def test_exception_matches():
from pybind11_tests import exception_matches
exception_matches()
def test_custom(msg):
from pybind11_tests import (MyException, MyException5, MyException5_1,
throws1, throws2, throws3, throws4, throws5, throws5_1,