mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
[BUGFIX] Fixing pybind11::error_already_set.matches to also work with exception subclasses (#1715)
* Fixing order of arguments in call to PyErr_GivenExceptionMatches in pybind11::error_already_set.matches * Added tests on error_already_set::matches fix for exception base classes
This commit is contained in:
parent
a0b8f70df4
commit
97784dad3e
@ -344,7 +344,7 @@ public:
|
|||||||
/// Check if the currently trapped error type matches the given Python exception class (or a
|
/// Check if the currently trapped error type matches the given Python exception class (or a
|
||||||
/// subclass thereof). May also be passed a tuple to search for any exception class matches in
|
/// subclass thereof). May also be passed a tuple to search for any exception class matches in
|
||||||
/// the given tuple.
|
/// the given tuple.
|
||||||
bool matches(handle ex) const { return PyErr_GivenExceptionMatches(ex.ptr(), m_type.ptr()); }
|
bool matches(handle exc) const { return PyErr_GivenExceptionMatches(m_type.ptr(), exc.ptr()); }
|
||||||
|
|
||||||
const object& type() const { return m_type; }
|
const object& type() const { return m_type; }
|
||||||
const object& value() const { return m_value; }
|
const object& value() const { return m_value; }
|
||||||
|
@ -118,10 +118,38 @@ TEST_SUBMODULE(exceptions, m) {
|
|||||||
m.def("throws_logic_error", []() { throw std::logic_error("this error should fall through to the standard handler"); });
|
m.def("throws_logic_error", []() { throw std::logic_error("this error should fall through to the standard handler"); });
|
||||||
m.def("exception_matches", []() {
|
m.def("exception_matches", []() {
|
||||||
py::dict foo;
|
py::dict foo;
|
||||||
try { foo["bar"]; }
|
try {
|
||||||
|
// Assign to a py::object to force read access of nonexistent dict entry
|
||||||
|
py::object o = foo["bar"];
|
||||||
|
}
|
||||||
catch (py::error_already_set& ex) {
|
catch (py::error_already_set& ex) {
|
||||||
if (!ex.matches(PyExc_KeyError)) throw;
|
if (!ex.matches(PyExc_KeyError)) throw;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
m.def("exception_matches_base", []() {
|
||||||
|
py::dict foo;
|
||||||
|
try {
|
||||||
|
// Assign to a py::object to force read access of nonexistent dict entry
|
||||||
|
py::object o = foo["bar"];
|
||||||
|
}
|
||||||
|
catch (py::error_already_set &ex) {
|
||||||
|
if (!ex.matches(PyExc_Exception)) throw;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
m.def("modulenotfound_exception_matches_base", []() {
|
||||||
|
try {
|
||||||
|
// On Python >= 3.6, this raises a ModuleNotFoundError, a subclass of ImportError
|
||||||
|
py::module::import("nonexistent");
|
||||||
|
}
|
||||||
|
catch (py::error_already_set &ex) {
|
||||||
|
if (!ex.matches(PyExc_ImportError)) throw;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
m.def("throw_already_set", [](bool err) {
|
m.def("throw_already_set", [](bool err) {
|
||||||
|
@ -48,7 +48,9 @@ def test_python_call_in_catch():
|
|||||||
|
|
||||||
|
|
||||||
def test_exception_matches():
|
def test_exception_matches():
|
||||||
m.exception_matches()
|
assert m.exception_matches()
|
||||||
|
assert m.exception_matches_base()
|
||||||
|
assert m.modulenotfound_exception_matches_base()
|
||||||
|
|
||||||
|
|
||||||
def test_custom(msg):
|
def test_custom(msg):
|
||||||
|
Loading…
Reference in New Issue
Block a user