mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 23:22:01 +00:00
Merge branch 'pybind:master' into master
This commit is contained in:
commit
c79813bfd6
@ -478,6 +478,11 @@ PYBIND11_NOINLINE std::string error_string() {
|
|||||||
|
|
||||||
error_scope scope; // Preserve error state
|
error_scope scope; // Preserve error state
|
||||||
|
|
||||||
|
PyErr_NormalizeException(&scope.type, &scope.value, &scope.trace);
|
||||||
|
if (scope.trace != nullptr) {
|
||||||
|
PyException_SetTraceback(scope.value, scope.trace);
|
||||||
|
}
|
||||||
|
|
||||||
std::string errorString;
|
std::string errorString;
|
||||||
if (scope.type) {
|
if (scope.type) {
|
||||||
errorString += handle(scope.type).attr("__name__").cast<std::string>();
|
errorString += handle(scope.type).attr("__name__").cast<std::string>();
|
||||||
@ -487,12 +492,6 @@ PYBIND11_NOINLINE std::string error_string() {
|
|||||||
errorString += (std::string) str(scope.value);
|
errorString += (std::string) str(scope.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyErr_NormalizeException(&scope.type, &scope.value, &scope.trace);
|
|
||||||
|
|
||||||
if (scope.trace != nullptr) {
|
|
||||||
PyException_SetTraceback(scope.value, scope.trace);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(PYPY_VERSION)
|
#if !defined(PYPY_VERSION)
|
||||||
if (scope.trace) {
|
if (scope.trace) {
|
||||||
auto *trace = (PyTracebackObject *) scope.trace;
|
auto *trace = (PyTracebackObject *) scope.trace;
|
||||||
|
@ -299,4 +299,12 @@ TEST_SUBMODULE(exceptions, m) {
|
|||||||
std::throw_with_nested(std::runtime_error("Outer Exception"));
|
std::throw_with_nested(std::runtime_error("Outer Exception"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m.def("error_already_set_what", [](const py::object &exc_type, const py::object &exc_value) {
|
||||||
|
PyErr_SetObject(exc_type.ptr(), exc_value.ptr());
|
||||||
|
std::string what = py::error_already_set().what();
|
||||||
|
bool py_err_set_after_what = (PyErr_Occurred() != nullptr);
|
||||||
|
PyErr_Clear();
|
||||||
|
return py::make_tuple(std::move(what), py_err_set_after_what);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -270,3 +270,53 @@ def test_local_translator(msg):
|
|||||||
m.throws_local_simple_error()
|
m.throws_local_simple_error()
|
||||||
assert not isinstance(excinfo.value, cm.LocalSimpleException)
|
assert not isinstance(excinfo.value, cm.LocalSimpleException)
|
||||||
assert msg(excinfo.value) == "this mod"
|
assert msg(excinfo.value) == "this mod"
|
||||||
|
|
||||||
|
|
||||||
|
class FlakyException(Exception):
|
||||||
|
def __init__(self, failure_point):
|
||||||
|
if failure_point == "failure_point_init":
|
||||||
|
raise ValueError("triggered_failure_point_init")
|
||||||
|
self.failure_point = failure_point
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.failure_point == "failure_point_str":
|
||||||
|
raise ValueError("triggered_failure_point_str")
|
||||||
|
return "FlakyException.__str__"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"exc_type, exc_value, expected_what",
|
||||||
|
(
|
||||||
|
(ValueError, "plain_str", "ValueError: plain_str"),
|
||||||
|
(ValueError, ("tuple_elem",), "ValueError: tuple_elem"),
|
||||||
|
(FlakyException, ("happy",), "FlakyException: FlakyException.__str__"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_error_already_set_what_with_happy_exceptions(
|
||||||
|
exc_type, exc_value, expected_what
|
||||||
|
):
|
||||||
|
what, py_err_set_after_what = m.error_already_set_what(exc_type, exc_value)
|
||||||
|
assert not py_err_set_after_what
|
||||||
|
assert what == expected_what
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.PYPY", reason="PyErr_NormalizeException Segmentation fault")
|
||||||
|
def test_flaky_exception_failure_point_init():
|
||||||
|
what, py_err_set_after_what = m.error_already_set_what(
|
||||||
|
FlakyException, ("failure_point_init",)
|
||||||
|
)
|
||||||
|
assert not py_err_set_after_what
|
||||||
|
lines = what.splitlines()
|
||||||
|
# PyErr_NormalizeException replaces the original FlakyException with ValueError:
|
||||||
|
assert lines[:3] == ["ValueError: triggered_failure_point_init", "", "At:"]
|
||||||
|
# Checking the first two lines of the traceback as formatted in error_string():
|
||||||
|
assert "test_exceptions.py(" in lines[3]
|
||||||
|
assert lines[3].endswith("): __init__")
|
||||||
|
assert lines[4].endswith("): test_flaky_exception_failure_point_init")
|
||||||
|
|
||||||
|
|
||||||
|
def test_flaky_exception_failure_point_str():
|
||||||
|
# The error_already_set ctor fails due to a ValueError in error_string():
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
m.error_already_set_what(FlakyException, ("failure_point_str",))
|
||||||
|
assert str(excinfo.value) == "triggered_failure_point_str"
|
||||||
|
@ -162,7 +162,7 @@ static int data_i = 42;
|
|||||||
TEST_SUBMODULE(numpy_array, sm) {
|
TEST_SUBMODULE(numpy_array, sm) {
|
||||||
try {
|
try {
|
||||||
py::module_::import("numpy");
|
py::module_::import("numpy");
|
||||||
} catch (...) {
|
} catch (const py::error_already_set &) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ struct B {};
|
|||||||
TEST_SUBMODULE(numpy_dtypes, m) {
|
TEST_SUBMODULE(numpy_dtypes, m) {
|
||||||
try {
|
try {
|
||||||
py::module_::import("numpy");
|
py::module_::import("numpy");
|
||||||
} catch (...) {
|
} catch (const py::error_already_set &) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ double my_func(int x, float y, double z) {
|
|||||||
TEST_SUBMODULE(numpy_vectorize, m) {
|
TEST_SUBMODULE(numpy_vectorize, m) {
|
||||||
try {
|
try {
|
||||||
py::module_::import("numpy");
|
py::module_::import("numpy");
|
||||||
} catch (...) {
|
} catch (const py::error_already_set &) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user