Skip to content

Commit

Permalink
Enable "factory sets error and returns nullptr"
Browse files Browse the repository at this point in the history
  • Loading branch information
Ralf W. Grosse-Kunstleve committed Sep 8, 2023
1 parent 33e5d26 commit e821d9b
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 0 deletions.
3 changes: 3 additions & 0 deletions include/pybind11/detail/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,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");
}
}
Expand Down
10 changes: 10 additions & 0 deletions tests/test_factory_constructors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,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
Expand Down
7 changes: 7 additions & 0 deletions tests/test_factory_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,10 @@ def __init__(self, bad):
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)

0 comments on commit e821d9b

Please sign in to comment.