mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
Remove try_as_void_ptr_capsule
feature from smart_holder branch.
This manual removal was informed by reviews of these commits (newest to oldest): *d930de0bca
*114c0f2a3e
*1c10b097a7
*9d4b4dffce
*da058a2904
This commit is contained in:
parent
c4df281e9d
commit
bf79caafd9
@ -36,72 +36,6 @@ struct is_smart_holder_type<smart_holder> : std::true_type {};
|
||||
// SMART_HOLDER_WIP: Needs refactoring of existing pybind11 code.
|
||||
inline void register_instance(instance *self, void *valptr, const type_info *tinfo);
|
||||
inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo);
|
||||
extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *, PyObject *);
|
||||
|
||||
// Replace all occurrences of substrings in a string.
|
||||
inline void replace_all(std::string &str, const std::string &from, const std::string &to) {
|
||||
if (str.empty()) {
|
||||
return;
|
||||
}
|
||||
size_t pos = 0;
|
||||
while ((pos = str.find(from, pos)) != std::string::npos) {
|
||||
str.replace(pos, from.length(), to);
|
||||
pos += to.length();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool type_is_pybind11_class_(PyTypeObject *type_obj) {
|
||||
#if defined(PYPY_VERSION)
|
||||
auto &internals = get_internals();
|
||||
return bool(internals.registered_types_py.find(type_obj)
|
||||
!= internals.registered_types_py.end());
|
||||
#else
|
||||
return bool(type_obj->tp_new == pybind11_object_new);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool is_instance_method_of_type(PyTypeObject *type_obj, PyObject *attr_name) {
|
||||
PyObject *descr = _PyType_Lookup(type_obj, attr_name);
|
||||
return bool((descr != nullptr) && PyInstanceMethod_Check(descr));
|
||||
}
|
||||
|
||||
inline object try_get_as_capsule_method(PyObject *obj, PyObject *attr_name) {
|
||||
if (PyType_Check(obj)) {
|
||||
return object();
|
||||
}
|
||||
PyTypeObject *type_obj = Py_TYPE(obj);
|
||||
bool known_callable = false;
|
||||
if (type_is_pybind11_class_(type_obj)) {
|
||||
if (!is_instance_method_of_type(type_obj, attr_name)) {
|
||||
return object();
|
||||
}
|
||||
known_callable = true;
|
||||
}
|
||||
PyObject *method = PyObject_GetAttr(obj, attr_name);
|
||||
if (method == nullptr) {
|
||||
PyErr_Clear();
|
||||
return object();
|
||||
}
|
||||
if (!known_callable && PyCallable_Check(method) == 0) {
|
||||
Py_DECREF(method);
|
||||
return object();
|
||||
}
|
||||
return reinterpret_steal<object>(method);
|
||||
}
|
||||
|
||||
inline void *try_as_void_ptr_capsule_get_pointer(handle src, const char *typeid_name) {
|
||||
std::string suffix = clean_type_id(typeid_name);
|
||||
replace_all(suffix, "::", "_"); // Convert `a::b::c` to `a_b_c`.
|
||||
replace_all(suffix, "*", "");
|
||||
object as_capsule_method = try_get_as_capsule_method(src.ptr(), str("as_" + suffix).ptr());
|
||||
if (as_capsule_method) {
|
||||
object void_ptr_capsule = as_capsule_method();
|
||||
if (isinstance<capsule>(void_ptr_capsule)) {
|
||||
return reinterpret_borrow<capsule>(void_ptr_capsule).get_pointer();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The modified_type_caster_generic_load_impl could replace type_caster_generic::load_impl but not
|
||||
// vice versa. The main difference is that the original code only propagates a reference to the
|
||||
@ -176,15 +110,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool try_as_void_ptr_capsule(handle src) {
|
||||
unowned_void_ptr_from_void_ptr_capsule
|
||||
= try_as_void_ptr_capsule_get_pointer(src, cpptype->name());
|
||||
if (unowned_void_ptr_from_void_ptr_capsule != nullptr) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PYBIND11_NOINLINE static void *local_load(PyObject *src, const type_info *ti) {
|
||||
std::unique_ptr<modified_type_caster_generic_load_impl> loader(
|
||||
new modified_type_caster_generic_load_impl(ti));
|
||||
@ -337,16 +262,12 @@ public:
|
||||
loaded_v_h = value_and_holder();
|
||||
return true;
|
||||
}
|
||||
if (convert && cpptype && try_as_void_ptr_capsule(src)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const type_info *typeinfo = nullptr;
|
||||
const std::type_info *cpptype = nullptr;
|
||||
void *unowned_void_ptr_from_direct_conversion = nullptr;
|
||||
void *unowned_void_ptr_from_void_ptr_capsule = nullptr;
|
||||
const std::type_info *loaded_v_h_cpptype = nullptr;
|
||||
std::vector<void *(*) (void *)> implicit_casts;
|
||||
value_and_holder loaded_v_h;
|
||||
@ -499,10 +420,7 @@ struct smart_holder_type_caster_load {
|
||||
}
|
||||
|
||||
T *loaded_as_raw_ptr_unowned() const {
|
||||
void *void_ptr = load_impl.unowned_void_ptr_from_void_ptr_capsule;
|
||||
if (void_ptr == nullptr) {
|
||||
void_ptr = load_impl.unowned_void_ptr_from_direct_conversion;
|
||||
}
|
||||
void *void_ptr = load_impl.unowned_void_ptr_from_direct_conversion;
|
||||
if (void_ptr == nullptr) {
|
||||
if (have_holder()) {
|
||||
throw_if_uninitialized_or_disowned_holder(typeid(T));
|
||||
@ -531,13 +449,6 @@ struct smart_holder_type_caster_load {
|
||||
}
|
||||
|
||||
std::shared_ptr<T> loaded_as_shared_ptr(handle responsible_parent = nullptr) const {
|
||||
if (load_impl.unowned_void_ptr_from_void_ptr_capsule) {
|
||||
if (responsible_parent) {
|
||||
return make_shared_ptr_with_responsible_parent(responsible_parent);
|
||||
}
|
||||
throw cast_error("Unowned pointer from a void pointer capsule cannot be converted to a"
|
||||
" std::shared_ptr.");
|
||||
}
|
||||
if (load_impl.unowned_void_ptr_from_direct_conversion != nullptr) {
|
||||
if (responsible_parent) {
|
||||
return make_shared_ptr_with_responsible_parent(responsible_parent);
|
||||
@ -601,10 +512,6 @@ struct smart_holder_type_caster_load {
|
||||
|
||||
template <typename D>
|
||||
std::unique_ptr<T, D> loaded_as_unique_ptr(const char *context = "loaded_as_unique_ptr") {
|
||||
if (load_impl.unowned_void_ptr_from_void_ptr_capsule) {
|
||||
throw cast_error("Unowned pointer from a void pointer capsule cannot be converted to a"
|
||||
" std::unique_ptr.");
|
||||
}
|
||||
if (load_impl.unowned_void_ptr_from_direct_conversion != nullptr) {
|
||||
throw cast_error("Unowned pointer from direct conversion cannot be converted to a"
|
||||
" std::unique_ptr.");
|
||||
|
@ -137,7 +137,6 @@ set(PYBIND11_TEST_FILES
|
||||
test_class_sh_unique_ptr_custom_deleter
|
||||
test_class_sh_unique_ptr_member
|
||||
test_class_sh_virtual_py_cpp_mix
|
||||
test_class_sh_void_ptr_capsule
|
||||
test_classh_mock
|
||||
test_const_name
|
||||
test_constants_and_functions
|
||||
|
@ -1,127 +0,0 @@
|
||||
#include <pybind11/smart_holder.h>
|
||||
|
||||
#include "pybind11_tests.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace pybind11_tests {
|
||||
namespace class_sh_void_ptr_capsule {
|
||||
|
||||
struct Valid {};
|
||||
|
||||
struct NoConversion {};
|
||||
|
||||
struct NoCapsuleReturned {};
|
||||
|
||||
struct AsAnotherObject {};
|
||||
|
||||
// Create a void pointer capsule for test. The encapsulated object does not
|
||||
// matter for this test case.
|
||||
PyObject *create_test_void_ptr_capsule() {
|
||||
static int just_to_have_something_to_point_to = 0;
|
||||
return PyCapsule_New(static_cast<void *>(&just_to_have_something_to_point_to), "int", nullptr);
|
||||
}
|
||||
|
||||
int get_from_valid_capsule(const Valid *) { return 1; }
|
||||
|
||||
int get_from_shared_ptr_valid_capsule(const std::shared_ptr<Valid> &) { return 2; }
|
||||
|
||||
int get_from_unique_ptr_valid_capsule(std::unique_ptr<Valid>) { return 3; }
|
||||
|
||||
int get_from_no_conversion_capsule(const NoConversion *) { return 4; }
|
||||
|
||||
int get_from_no_capsule_returned(const NoCapsuleReturned *) { return 5; }
|
||||
|
||||
// https://github.com/pybind/pybind11/issues/3788
|
||||
struct TypeWithGetattr {
|
||||
TypeWithGetattr() = default;
|
||||
int get_42() const { return 42; }
|
||||
};
|
||||
|
||||
// https://github.com/pybind/pybind11/issues/3804
|
||||
struct Base1 {
|
||||
int a1{};
|
||||
};
|
||||
struct Base2 {
|
||||
int a2{};
|
||||
};
|
||||
|
||||
struct Base12 : Base1, Base2 {
|
||||
int foo() const { return 0; }
|
||||
};
|
||||
|
||||
struct Derived1 : Base12 {
|
||||
int bar() const { return 1; }
|
||||
};
|
||||
|
||||
struct Derived2 : Base12 {
|
||||
int bar() const { return 2; }
|
||||
};
|
||||
|
||||
struct UnspecBase {
|
||||
virtual ~UnspecBase() = default;
|
||||
virtual int Get() const { return 100; }
|
||||
};
|
||||
|
||||
int PassUnspecBase(const UnspecBase &sb) { return sb.Get() + 30; }
|
||||
|
||||
struct UnspecDerived : UnspecBase {
|
||||
int Get() const override { return 200; }
|
||||
};
|
||||
|
||||
} // namespace class_sh_void_ptr_capsule
|
||||
} // namespace pybind11_tests
|
||||
|
||||
using namespace pybind11_tests::class_sh_void_ptr_capsule;
|
||||
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Valid)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(TypeWithGetattr)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Base1)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Base2)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Base12)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Derived1)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Derived2)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(UnspecBase)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(UnspecDerived)
|
||||
|
||||
TEST_SUBMODULE(class_sh_void_ptr_capsule, m) {
|
||||
py::classh<Valid>(m, "Valid");
|
||||
|
||||
m.def("get_from_valid_capsule", &get_from_valid_capsule);
|
||||
m.def("get_from_shared_ptr_valid_capsule", &get_from_shared_ptr_valid_capsule);
|
||||
m.def("get_from_unique_ptr_valid_capsule", &get_from_unique_ptr_valid_capsule);
|
||||
m.def("get_from_no_conversion_capsule", &get_from_no_conversion_capsule);
|
||||
m.def("get_from_no_capsule_returned", &get_from_no_capsule_returned);
|
||||
m.def("create_test_void_ptr_capsule", []() {
|
||||
PyObject *capsule = create_test_void_ptr_capsule();
|
||||
return pybind11::reinterpret_steal<py::capsule>(capsule);
|
||||
});
|
||||
|
||||
py::classh<TypeWithGetattr>(m, "TypeWithGetattr")
|
||||
.def(py::init<>())
|
||||
.def("get_42", &TypeWithGetattr::get_42)
|
||||
.def("__getattr__",
|
||||
[](TypeWithGetattr &, const std::string &key) { return "GetAttr: " + key; });
|
||||
|
||||
py::classh<Base1>(m, "Base1");
|
||||
py::classh<Base2>(m, "Base2");
|
||||
|
||||
py::classh<Base12, Base1, Base2>(m, "Base12")
|
||||
.def(py::init<>())
|
||||
.def("foo", &Base12::foo)
|
||||
.def("__getattr__",
|
||||
[](Base12 &, const std::string &key) { return "Base GetAttr: " + key; });
|
||||
|
||||
py::classh<Derived1, Base12>(m, "Derived1").def(py::init<>()).def("bar", &Derived1::bar);
|
||||
|
||||
py::classh<Derived2, Base12>(m, "Derived2").def(py::init<>()).def("bar", &Derived2::bar);
|
||||
|
||||
py::classh<UnspecBase>(m, "UnspecBase");
|
||||
m.def("PassUnspecBase", PassUnspecBase);
|
||||
py::classh<UnspecDerived>(m, "UnspecDerived") // UnspecBase NOT specified as base here.
|
||||
.def(py::init<>())
|
||||
.def("as_pybind11_tests_class_sh_void_ptr_capsule_UnspecBase", [](UnspecDerived *self) {
|
||||
return py::reinterpret_steal<py::object>(
|
||||
PyCapsule_New(static_cast<void *>(self), nullptr, nullptr));
|
||||
});
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from pybind11_tests import class_sh_void_ptr_capsule as m
|
||||
|
||||
|
||||
class Valid:
|
||||
def __init__(self):
|
||||
self.capsule_generated = False
|
||||
|
||||
def as_pybind11_tests_class_sh_void_ptr_capsule_Valid(self):
|
||||
self.capsule_generated = True
|
||||
return m.create_test_void_ptr_capsule()
|
||||
|
||||
|
||||
class NoConversion:
|
||||
def __init__(self):
|
||||
self.capsule_generated = False
|
||||
|
||||
|
||||
class NoCapsuleReturned:
|
||||
def __init__(self):
|
||||
self.capsule_generated = False
|
||||
|
||||
def as_pybind11_tests_class_sh_void_ptr_capsule_NoCapsuleReturned(
|
||||
self,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
class AsAnotherObject:
|
||||
def __init__(self):
|
||||
self.capsule_generated = False
|
||||
|
||||
def as_pybind11_tests_class_sh_void_ptr_capsule_Valid(self):
|
||||
self.capsule_generated = True
|
||||
return m.create_test_void_ptr_capsule()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("ctor", "caller", "expected"),
|
||||
[
|
||||
(Valid, m.get_from_valid_capsule, 1),
|
||||
(AsAnotherObject, m.get_from_valid_capsule, 1),
|
||||
],
|
||||
)
|
||||
def test_valid_as_void_ptr_capsule_function(ctor, caller, expected):
|
||||
obj = ctor()
|
||||
assert caller(obj) == expected
|
||||
assert obj.capsule_generated
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("ctor", "caller"),
|
||||
[
|
||||
(NoConversion, m.get_from_no_conversion_capsule),
|
||||
(NoCapsuleReturned, m.get_from_no_capsule_returned),
|
||||
],
|
||||
)
|
||||
def test_invalid_as_void_ptr_capsule_function(ctor, caller):
|
||||
obj = ctor()
|
||||
with pytest.raises(TypeError):
|
||||
caller(obj)
|
||||
assert not obj.capsule_generated
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("ctor", "caller", "pointer_type", "capsule_generated"),
|
||||
[
|
||||
(AsAnotherObject, m.get_from_shared_ptr_valid_capsule, "shared_ptr", True),
|
||||
(AsAnotherObject, m.get_from_unique_ptr_valid_capsule, "unique_ptr", True),
|
||||
],
|
||||
)
|
||||
def test_as_void_ptr_capsule_unsupported(ctor, caller, pointer_type, capsule_generated):
|
||||
obj = ctor()
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
caller(obj)
|
||||
assert pointer_type in str(excinfo.value)
|
||||
assert obj.capsule_generated == capsule_generated
|
||||
|
||||
|
||||
def test_type_with_getattr():
|
||||
obj = m.TypeWithGetattr()
|
||||
assert obj.get_42() == 42
|
||||
assert obj.something == "GetAttr: something"
|
||||
|
||||
|
||||
def test_multiple_inheritance_getattr():
|
||||
d1 = m.Derived1()
|
||||
assert d1.foo() == 0
|
||||
assert d1.bar() == 1
|
||||
assert d1.prop1 == "Base GetAttr: prop1"
|
||||
|
||||
d2 = m.Derived2()
|
||||
assert d2.foo() == 0
|
||||
assert d2.bar() == 2
|
||||
assert d2.prop2 == "Base GetAttr: prop2"
|
||||
|
||||
|
||||
def test_pass_unspecified_base():
|
||||
assert m.PassUnspecBase(m.UnspecDerived()) == 230
|
Loading…
Reference in New Issue
Block a user