mirror of
https://github.com/pybind/pybind11.git
synced 2025-02-17 22:20:41 +00:00
[smart_holder] Change throw_if_uninitialized_or_disowned_holder()
to also show C++ type name. (#4977)
* Change `throw_if_uninitialized_or_disowned_holder()` to also show C++ type name. * Fix pre-commit errors.
This commit is contained in:
parent
feed8b15b5
commit
d2ac3f5c70
@ -505,7 +505,7 @@ struct smart_holder_type_caster_load {
|
|||||||
}
|
}
|
||||||
if (void_ptr == nullptr) {
|
if (void_ptr == nullptr) {
|
||||||
if (have_holder()) {
|
if (have_holder()) {
|
||||||
throw_if_uninitialized_or_disowned_holder();
|
throw_if_uninitialized_or_disowned_holder(typeid(T));
|
||||||
void_ptr = holder().template as_raw_ptr_unowned<void>();
|
void_ptr = holder().template as_raw_ptr_unowned<void>();
|
||||||
} else if (load_impl.loaded_v_h.vh != nullptr) {
|
} else if (load_impl.loaded_v_h.vh != nullptr) {
|
||||||
void_ptr = load_impl.loaded_v_h.value_ptr();
|
void_ptr = load_impl.loaded_v_h.value_ptr();
|
||||||
@ -548,7 +548,7 @@ struct smart_holder_type_caster_load {
|
|||||||
if (!have_holder()) {
|
if (!have_holder()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
throw_if_uninitialized_or_disowned_holder();
|
throw_if_uninitialized_or_disowned_holder(typeid(T));
|
||||||
holder_type &hld = holder();
|
holder_type &hld = holder();
|
||||||
hld.ensure_is_not_disowned("loaded_as_shared_ptr");
|
hld.ensure_is_not_disowned("loaded_as_shared_ptr");
|
||||||
if (hld.vptr_is_using_noop_deleter) {
|
if (hld.vptr_is_using_noop_deleter) {
|
||||||
@ -612,7 +612,7 @@ struct smart_holder_type_caster_load {
|
|||||||
if (!have_holder()) {
|
if (!have_holder()) {
|
||||||
return unique_with_deleter<T, D>(nullptr, std::unique_ptr<D>());
|
return unique_with_deleter<T, D>(nullptr, std::unique_ptr<D>());
|
||||||
}
|
}
|
||||||
throw_if_uninitialized_or_disowned_holder();
|
throw_if_uninitialized_or_disowned_holder(typeid(T));
|
||||||
throw_if_instance_is_currently_owned_by_shared_ptr();
|
throw_if_instance_is_currently_owned_by_shared_ptr();
|
||||||
holder().ensure_is_not_disowned(context);
|
holder().ensure_is_not_disowned(context);
|
||||||
holder().template ensure_compatible_rtti_uqp_del<T, D>(context);
|
holder().template ensure_compatible_rtti_uqp_del<T, D>(context);
|
||||||
@ -694,17 +694,22 @@ private:
|
|||||||
holder_type &holder() const { return load_impl.loaded_v_h.holder<holder_type>(); }
|
holder_type &holder() const { return load_impl.loaded_v_h.holder<holder_type>(); }
|
||||||
|
|
||||||
// have_holder() must be true or this function will fail.
|
// have_holder() must be true or this function will fail.
|
||||||
void throw_if_uninitialized_or_disowned_holder() const {
|
void throw_if_uninitialized_or_disowned_holder(const char *typeid_name) const {
|
||||||
|
static const std::string missing_value_msg = "Missing value for wrapped C++ type `";
|
||||||
if (!holder().is_populated) {
|
if (!holder().is_populated) {
|
||||||
pybind11_fail("Missing value for wrapped C++ type:"
|
throw value_error(missing_value_msg + clean_type_id(typeid_name)
|
||||||
" Python instance is uninitialized.");
|
+ "`: Python instance is uninitialized.");
|
||||||
}
|
}
|
||||||
if (!holder().has_pointee()) {
|
if (!holder().has_pointee()) {
|
||||||
throw value_error("Missing value for wrapped C++ type:"
|
throw value_error(missing_value_msg + clean_type_id(typeid_name)
|
||||||
" Python instance was disowned.");
|
+ "`: Python instance was disowned.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void throw_if_uninitialized_or_disowned_holder(const std::type_info &type_info) const {
|
||||||
|
throw_if_uninitialized_or_disowned_holder(type_info.name());
|
||||||
|
}
|
||||||
|
|
||||||
// have_holder() must be true or this function will fail.
|
// have_holder() must be true or this function will fail.
|
||||||
void throw_if_instance_is_currently_owned_by_shared_ptr() const {
|
void throw_if_instance_is_currently_owned_by_shared_ptr() const {
|
||||||
auto vptr_gd_ptr = std::get_deleter<pybindit::memory::guarded_delete>(holder().vptr);
|
auto vptr_gd_ptr = std::get_deleter<pybindit::memory::guarded_delete>(holder().vptr);
|
||||||
|
@ -109,7 +109,9 @@ def test_pass_unique_ptr_disowns(pass_f, rtrn_f, expected):
|
|||||||
with pytest.raises(ValueError) as exc_info:
|
with pytest.raises(ValueError) as exc_info:
|
||||||
pass_f(obj)
|
pass_f(obj)
|
||||||
assert str(exc_info.value) == (
|
assert str(exc_info.value) == (
|
||||||
"Missing value for wrapped C++ type: Python instance was disowned."
|
"Missing value for wrapped C++ type"
|
||||||
|
+ " `pybind11_tests::class_sh_basic::atyp`:"
|
||||||
|
+ " Python instance was disowned."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,10 +20,7 @@ def is_disowned(callable_method):
|
|||||||
try:
|
try:
|
||||||
callable_method()
|
callable_method()
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
assert ( # noqa: PT017
|
assert "Python instance was disowned" in str(e) # noqa: PT017
|
||||||
str(e)
|
|
||||||
== "Missing value for wrapped C++ type: Python instance was disowned."
|
|
||||||
)
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -38,12 +38,8 @@ def test_get_vec_size_raw_shared(get_fn, vec_size_fn):
|
|||||||
def test_get_vec_size_unique(get_fn):
|
def test_get_vec_size_unique(get_fn):
|
||||||
obj = get_fn()
|
obj = get_fn()
|
||||||
assert m.vec_size_base0_unique_ptr(obj) == 5
|
assert m.vec_size_base0_unique_ptr(obj) == 5
|
||||||
with pytest.raises(ValueError) as exc_info:
|
with pytest.raises(ValueError, match="Python instance was disowned"):
|
||||||
m.vec_size_base0_unique_ptr(obj)
|
m.vec_size_base0_unique_ptr(obj)
|
||||||
assert (
|
|
||||||
str(exc_info.value)
|
|
||||||
== "Missing value for wrapped C++ type: Python instance was disowned."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_shared_vec_size_unique():
|
def test_get_shared_vec_size_unique():
|
||||||
|
@ -9,7 +9,7 @@ from pybind11_tests import class_sh_property as m
|
|||||||
|
|
||||||
@pytest.mark.xfail("env.PYPY", reason="gc after `del field` is apparently deferred")
|
@pytest.mark.xfail("env.PYPY", reason="gc after `del field` is apparently deferred")
|
||||||
@pytest.mark.parametrize("m_attr", ["m_valu_readonly", "m_valu_readwrite"])
|
@pytest.mark.parametrize("m_attr", ["m_valu_readonly", "m_valu_readwrite"])
|
||||||
def test_valu_getter(msg, m_attr):
|
def test_valu_getter(m_attr):
|
||||||
# Reduced from PyCLIF test:
|
# Reduced from PyCLIF test:
|
||||||
# https://github.com/google/clif/blob/c371a6d4b28d25d53a16e6d2a6d97305fb1be25a/clif/testing/python/nested_fields_test.py#L56
|
# https://github.com/google/clif/blob/c371a6d4b28d25d53a16e6d2a6d97305fb1be25a/clif/testing/python/nested_fields_test.py#L56
|
||||||
outer = m.Outer()
|
outer = m.Outer()
|
||||||
@ -17,15 +17,11 @@ def test_valu_getter(msg, m_attr):
|
|||||||
assert field.num == -99
|
assert field.num == -99
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(ValueError) as excinfo:
|
||||||
m.DisownOuter(outer)
|
m.DisownOuter(outer)
|
||||||
assert msg(excinfo.value) == "Cannot disown use_count != 1 (loaded_as_unique_ptr)."
|
assert str(excinfo.value) == "Cannot disown use_count != 1 (loaded_as_unique_ptr)."
|
||||||
del field
|
del field
|
||||||
m.DisownOuter(outer)
|
m.DisownOuter(outer)
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(ValueError, match="Python instance was disowned") as excinfo:
|
||||||
getattr(outer, m_attr)
|
getattr(outer, m_attr)
|
||||||
assert (
|
|
||||||
msg(excinfo.value)
|
|
||||||
== "Missing value for wrapped C++ type: Python instance was disowned."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_valu_setter():
|
def test_valu_setter():
|
||||||
@ -85,18 +81,14 @@ def test_ptr(field_type, num_default, outer_type, m_attr, r_kind):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("m_attr_readwrite", ["m_uqmp_readwrite", "m_uqcp_readwrite"])
|
@pytest.mark.parametrize("m_attr_readwrite", ["m_uqmp_readwrite", "m_uqcp_readwrite"])
|
||||||
def test_uqp(m_attr_readwrite, msg):
|
def test_uqp(m_attr_readwrite):
|
||||||
outer = m.Outer()
|
outer = m.Outer()
|
||||||
assert getattr(outer, m_attr_readwrite) is None
|
assert getattr(outer, m_attr_readwrite) is None
|
||||||
field_orig = m.Field()
|
field_orig = m.Field()
|
||||||
field_orig.num = 39
|
field_orig.num = 39
|
||||||
setattr(outer, m_attr_readwrite, field_orig)
|
setattr(outer, m_attr_readwrite, field_orig)
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(ValueError, match="Python instance was disowned"):
|
||||||
_ = field_orig.num
|
_ = field_orig.num
|
||||||
assert (
|
|
||||||
msg(excinfo.value)
|
|
||||||
== "Missing value for wrapped C++ type: Python instance was disowned."
|
|
||||||
)
|
|
||||||
field_retr1 = getattr(outer, m_attr_readwrite)
|
field_retr1 = getattr(outer, m_attr_readwrite)
|
||||||
assert getattr(outer, m_attr_readwrite) is None
|
assert getattr(outer, m_attr_readwrite) is None
|
||||||
assert field_retr1.num == 39
|
assert field_retr1.num == 39
|
||||||
|
@ -16,12 +16,8 @@ def test_pointee_and_ptr_owner(give_up_ownership_via):
|
|||||||
obj = m.pointee()
|
obj = m.pointee()
|
||||||
assert obj.get_int() == 213
|
assert obj.get_int() == 213
|
||||||
owner = m.ptr_owner(obj)
|
owner = m.ptr_owner(obj)
|
||||||
with pytest.raises(ValueError) as exc_info:
|
with pytest.raises(ValueError, match="Python instance was disowned"):
|
||||||
obj.get_int()
|
obj.get_int()
|
||||||
assert (
|
|
||||||
str(exc_info.value)
|
|
||||||
== "Missing value for wrapped C++ type: Python instance was disowned."
|
|
||||||
)
|
|
||||||
assert owner.is_owner()
|
assert owner.is_owner()
|
||||||
reclaimed = getattr(owner, give_up_ownership_via)()
|
reclaimed = getattr(owner, give_up_ownership_via)()
|
||||||
assert not owner.is_owner()
|
assert not owner.is_owner()
|
||||||
|
Loading…
Reference in New Issue
Block a user