mirror of
https://github.com/pybind/pybind11.git
synced 2026-04-19 22:39:09 +00:00
Add py::set_error(), use in updated py::exception<> documentation (#4772)
* Copy clang 17 compatibility fixes from PR #4762 to a separate PR. * static py::exception<> -> static py::handle * Add `py::set_error()` but also try the suggestion of @malfet (https://github.com/pytorch/pytorch/pull/106401#pullrequestreview-1559961407). * clang 17 compatibility fixes (#4767) * Copy clang 17 compatibility fixes from PR #4762 to a separate PR. * Add gcc:13 C++20 * Add silkeh/clang:16-bullseye C++20 * chore(deps): update pre-commit hooks (#4770) updates: - [github.com/psf/black: 23.3.0 → 23.7.0](https://github.com/psf/black/compare/23.3.0...23.7.0) - [github.com/astral-sh/ruff-pre-commit: v0.0.276 → v0.0.281](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.276...v0.0.281) - [github.com/asottile/blacken-docs: 1.14.0 → 1.15.0](https://github.com/asottile/blacken-docs/compare/1.14.0...1.15.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * docs: Remove upper bound on pybind11 in example pyproject.toml for setuptools (#4774) * docs: Remove upper bound on pybind11 in example pyproject.toml for setuptools * Update docs/compiling.rst --------- Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com> * Provide better type hints for a variety of generic types (#4259) * Provide better type hints for a variety of generic types * Makes better documentation * tuple, dict, list, set, function * Move to py::typing * style: pre-commit fixes * Update copyright line with correct year and actual author. The author information was copy-pasted from the git log output. --------- Co-authored-by: Ralf W. Grosse-Kunstleve <rwgk@google.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * Use `py::set_error()` everywhere possible (only one special case, in common.h). Overload `py::set_error(py::handle, py::handle)`. Change back to `static py::handle exc = ... .release();` Deprecate `py::exception<>::operator()` * Add `PYBIND11_WARNING_DISABLE` for INTEL and MSVC (and sort alphabetically). * `PYBIND11_WARNING_DISABLE_INTEL(10441)` does not work. For ICC only, falling back to the recommended `py::set_error()` to keep the testing simple. It is troublesome to add `--diag-disable=10441` specifically for test_exceptions.cpp, even that is non-ideal because it covers the entire file, not just the one line we need it for, and the value of exercising the trivial deprecated `operator()` on this one extra platform is practically zero. * Fix silly oversight. * NVHPC 23.5.0 generates deprecation warnings. They are currently not treated as errors, but falling back to using `py::set_error()` to not have to deal with that distraction. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Keto D. Zhang <keto.zhang@gmail.com> Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com> Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
This commit is contained in:
committed by
GitHub
parent
824dc27a01
commit
690a115d84
@@ -25,6 +25,10 @@ private:
|
||||
std::string message = "";
|
||||
};
|
||||
|
||||
class MyExceptionUseDeprecatedOperatorCall : public MyException {
|
||||
using MyException::MyException;
|
||||
};
|
||||
|
||||
// A type that should be translated to a standard Python exception
|
||||
class MyException2 : public std::exception {
|
||||
public:
|
||||
@@ -109,8 +113,8 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
m.def("throw_std_exception",
|
||||
[]() { throw std::runtime_error("This exception was intentionally thrown."); });
|
||||
|
||||
// make a new custom exception and use it as a translation target
|
||||
static py::exception<MyException> ex(m, "MyException");
|
||||
// PLEASE KEEP IN SYNC with docs/advanced/exceptions.rst
|
||||
static py::handle ex = py::exception<MyException>(m, "MyException").release();
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) {
|
||||
@@ -118,7 +122,32 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
}
|
||||
} catch (const MyException &e) {
|
||||
// Set MyException as the active python error
|
||||
ex(e.what());
|
||||
py::set_error(ex, e.what());
|
||||
}
|
||||
});
|
||||
|
||||
// Same as above, but using the deprecated `py::exception<>::operator()`
|
||||
// We want to be sure it still works, until it's removed.
|
||||
static const auto *const exd = new py::exception<MyExceptionUseDeprecatedOperatorCall>(
|
||||
m, "MyExceptionUseDeprecatedOperatorCall");
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const MyExceptionUseDeprecatedOperatorCall &e) {
|
||||
#if defined(__INTEL_COMPILER) || defined(__NVCOMPILER)
|
||||
// It is not worth the trouble dealing with warning suppressions for these compilers.
|
||||
// Falling back to the recommended approach to keep the test code simple.
|
||||
py::set_error(*exd, e.what());
|
||||
#else
|
||||
PYBIND11_WARNING_PUSH
|
||||
PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
|
||||
PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4996)
|
||||
(*exd)(e.what());
|
||||
PYBIND11_WARNING_POP
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
||||
@@ -132,7 +161,7 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
}
|
||||
} catch (const MyException2 &e) {
|
||||
// Translate this exception to a standard RuntimeError
|
||||
PyErr_SetString(PyExc_RuntimeError, e.what());
|
||||
py::set_error(PyExc_RuntimeError, e.what());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -162,11 +191,16 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const MyException6 &e) {
|
||||
PyErr_SetString(PyExc_RuntimeError, e.what());
|
||||
py::set_error(PyExc_RuntimeError, e.what());
|
||||
}
|
||||
});
|
||||
|
||||
m.def("throws1", []() { throw MyException("this error should go to a custom type"); });
|
||||
m.def("throws1",
|
||||
[]() { throw MyException("this error should go to py::exception<MyException>"); });
|
||||
m.def("throws1d", []() {
|
||||
throw MyExceptionUseDeprecatedOperatorCall(
|
||||
"this error should go to py::exception<MyExceptionUseDeprecatedOperatorCall>");
|
||||
});
|
||||
m.def("throws2",
|
||||
[]() { throw MyException2("this error should go to a standard Python exception"); });
|
||||
m.def("throws3", []() { throw MyException3("this error cannot be translated"); });
|
||||
@@ -222,7 +256,7 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
|
||||
m.def("throw_already_set", [](bool err) {
|
||||
if (err) {
|
||||
PyErr_SetString(PyExc_ValueError, "foo");
|
||||
py::set_error(PyExc_ValueError, "foo");
|
||||
}
|
||||
try {
|
||||
throw py::error_already_set();
|
||||
@@ -238,7 +272,7 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
}
|
||||
PyErr_Clear();
|
||||
if (err) {
|
||||
PyErr_SetString(PyExc_ValueError, "foo");
|
||||
py::set_error(PyExc_ValueError, "foo");
|
||||
}
|
||||
throw py::error_already_set();
|
||||
});
|
||||
@@ -247,7 +281,7 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
bool retval = false;
|
||||
try {
|
||||
PythonCallInDestructor set_dict_in_destructor(d);
|
||||
PyErr_SetString(PyExc_ValueError, "foo");
|
||||
py::set_error(PyExc_ValueError, "foo");
|
||||
throw py::error_already_set();
|
||||
} catch (const py::error_already_set &) {
|
||||
retval = true;
|
||||
@@ -282,14 +316,14 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
m.def("throw_should_be_translated_to_key_error", []() { throw shared_exception(); });
|
||||
|
||||
m.def("raise_from", []() {
|
||||
PyErr_SetString(PyExc_ValueError, "inner");
|
||||
py::set_error(PyExc_ValueError, "inner");
|
||||
py::raise_from(PyExc_ValueError, "outer");
|
||||
throw py::error_already_set();
|
||||
});
|
||||
|
||||
m.def("raise_from_already_set", []() {
|
||||
try {
|
||||
PyErr_SetString(PyExc_ValueError, "inner");
|
||||
py::set_error(PyExc_ValueError, "inner");
|
||||
throw py::error_already_set();
|
||||
} catch (py::error_already_set &e) {
|
||||
py::raise_from(e, PyExc_ValueError, "outer");
|
||||
@@ -306,7 +340,7 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
});
|
||||
|
||||
m.def("error_already_set_what", [](const py::object &exc_type, const py::object &exc_value) {
|
||||
PyErr_SetObject(exc_type.ptr(), exc_value.ptr());
|
||||
py::set_error(exc_type, exc_value);
|
||||
std::string what = py::error_already_set().what();
|
||||
bool py_err_set_after_what = (PyErr_Occurred() != nullptr);
|
||||
PyErr_Clear();
|
||||
@@ -321,7 +355,7 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
});
|
||||
|
||||
m.def("test_error_already_set_double_restore", [](bool dry_run) {
|
||||
PyErr_SetString(PyExc_ValueError, "Random error.");
|
||||
py::set_error(PyExc_ValueError, "Random error.");
|
||||
py::error_already_set e;
|
||||
e.restore();
|
||||
PyErr_Clear();
|
||||
|
||||
Reference in New Issue
Block a user