fix: better exception and error handling for capsules (#3825)

* Make capsule errors better match python
This commit is contained in:
Aaron Gokaslan 2022-03-25 10:55:13 -04:00 committed by GitHub
parent 47079b9e7b
commit 146695a904
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 14 deletions

View File

@ -1288,7 +1288,8 @@ public:
static pybind11::dtype dtype() { static pybind11::dtype dtype() {
list shape; list shape;
array_info<T>::append_extents(shape); array_info<T>::append_extents(shape);
return pybind11::dtype::from_args(pybind11::make_tuple(base_descr::dtype(), shape)); return pybind11::dtype::from_args(
pybind11::make_tuple(base_descr::dtype(), std::move(shape)));
} }
}; };

View File

@ -1574,7 +1574,7 @@ public:
void (*destructor)(PyObject *) = nullptr) void (*destructor)(PyObject *) = nullptr)
: object(PyCapsule_New(const_cast<void *>(value), name, destructor), stolen_t{}) { : object(PyCapsule_New(const_cast<void *>(value), name, destructor), stolen_t{}) {
if (!m_ptr) { if (!m_ptr) {
pybind11_fail("Could not allocate capsule object!"); throw error_already_set();
} }
} }
@ -1582,34 +1582,42 @@ public:
capsule(const void *value, void (*destruct)(PyObject *)) capsule(const void *value, void (*destruct)(PyObject *))
: object(PyCapsule_New(const_cast<void *>(value), nullptr, destruct), stolen_t{}) { : object(PyCapsule_New(const_cast<void *>(value), nullptr, destruct), stolen_t{}) {
if (!m_ptr) { if (!m_ptr) {
pybind11_fail("Could not allocate capsule object!"); throw error_already_set();
} }
} }
capsule(const void *value, void (*destructor)(void *)) { capsule(const void *value, void (*destructor)(void *)) {
m_ptr = PyCapsule_New(const_cast<void *>(value), nullptr, [](PyObject *o) { m_ptr = PyCapsule_New(const_cast<void *>(value), nullptr, [](PyObject *o) {
auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o)); auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o));
if (destructor == nullptr) {
if (PyErr_Occurred()) {
throw error_already_set();
}
pybind11_fail("Unable to get capsule context");
}
void *ptr = PyCapsule_GetPointer(o, nullptr); void *ptr = PyCapsule_GetPointer(o, nullptr);
if (ptr == nullptr) {
throw error_already_set();
}
destructor(ptr); destructor(ptr);
}); });
if (!m_ptr) { if (!m_ptr || PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) {
pybind11_fail("Could not allocate capsule object!"); throw error_already_set();
}
if (PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) {
pybind11_fail("Could not set capsule context!");
} }
} }
explicit capsule(void (*destructor)()) { explicit capsule(void (*destructor)()) {
m_ptr = PyCapsule_New(reinterpret_cast<void *>(destructor), nullptr, [](PyObject *o) { m_ptr = PyCapsule_New(reinterpret_cast<void *>(destructor), nullptr, [](PyObject *o) {
auto destructor = reinterpret_cast<void (*)()>(PyCapsule_GetPointer(o, nullptr)); auto destructor = reinterpret_cast<void (*)()>(PyCapsule_GetPointer(o, nullptr));
if (destructor == nullptr) {
throw error_already_set();
}
destructor(); destructor();
}); });
if (!m_ptr) { if (!m_ptr) {
pybind11_fail("Could not allocate capsule object!"); throw error_already_set();
} }
} }
@ -1624,8 +1632,7 @@ public:
const auto *name = this->name(); const auto *name = this->name();
T *result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, name)); T *result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, name));
if (!result) { if (!result) {
PyErr_Clear(); throw error_already_set();
pybind11_fail("Unable to extract capsule contents!");
} }
return result; return result;
} }
@ -1633,8 +1640,7 @@ public:
/// Replaces a capsule's pointer *without* calling the destructor on the existing one. /// Replaces a capsule's pointer *without* calling the destructor on the existing one.
void set_pointer(const void *value) { void set_pointer(const void *value) {
if (PyCapsule_SetPointer(m_ptr, const_cast<void *>(value)) != 0) { if (PyCapsule_SetPointer(m_ptr, const_cast<void *>(value)) != 0) {
PyErr_Clear(); throw error_already_set();
pybind11_fail("Could not set capsule pointer");
} }
} }