mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-28 08:02:00 +00:00
Backport of https://github.com/google/pywrapcc/pull/30064
This is a very simple change in support of the PyCLIF-pybind11 integration work: Merely an extra `if` to pre-empt `TypeError: pybind11::init(): factory function returned nullptr`. This allows the factory function to set a custom Python error instead. Manually written factory functions could `throw error_already_set()` directly, but in the context of PyCLIF that is very difficult (compared to this very simple PR), because the factory function can be completely unaware of pybind11.
This commit is contained in:
parent
8c7b8dd0ae
commit
bb02ebc654
@ -38,6 +38,9 @@ PYBIND11_NAMESPACE_BEGIN(initimpl)
|
||||
|
||||
inline void no_nullptr(void *ptr) {
|
||||
if (!ptr) {
|
||||
if (PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
throw type_error("pybind11::init(): factory function returned nullptr");
|
||||
}
|
||||
}
|
||||
|
@ -412,6 +412,16 @@ TEST_SUBMODULE(factory_constructors, m) {
|
||||
"__init__", [](NoisyAlloc &a, int i, const std::string &) { new (&a) NoisyAlloc(i); });
|
||||
});
|
||||
|
||||
struct FactoryErrorAlreadySet {};
|
||||
py::class_<FactoryErrorAlreadySet>(m, "FactoryErrorAlreadySet")
|
||||
.def(py::init([](bool set_error) -> FactoryErrorAlreadySet * {
|
||||
if (!set_error) {
|
||||
return new FactoryErrorAlreadySet();
|
||||
}
|
||||
py::set_error(PyExc_ValueError, "factory sets error and returns nullptr");
|
||||
return nullptr;
|
||||
}));
|
||||
|
||||
// static_assert testing (the following def's should all fail with appropriate compilation
|
||||
// errors):
|
||||
#if 0
|
||||
|
@ -514,3 +514,10 @@ def test_invalid_self():
|
||||
str(excinfo.value)
|
||||
== "__init__(self, ...) called with invalid or missing `self` argument"
|
||||
)
|
||||
|
||||
|
||||
def test_factory_error_already_set():
|
||||
obj = m.FactoryErrorAlreadySet(False)
|
||||
assert isinstance(obj, m.FactoryErrorAlreadySet)
|
||||
with pytest.raises(ValueError, match="factory sets error and returns nullptr"):
|
||||
m.FactoryErrorAlreadySet(True)
|
||||
|
Loading…
Reference in New Issue
Block a user