Skip to content

Commit

Permalink
Adjust to behavior change due to pybind/pybind11#4586 (smart_holder b…
Browse files Browse the repository at this point in the history
…ranch).

The behavior change made it possible to exercise the `reference_internal` vs `copy` behavior more thoroughly, which then led to a surprise discovery. See SURPRISE comment in tests/test_class_sh_property_stl.py
  • Loading branch information
Ralf W. Grosse-Kunstleve committed Mar 24, 2023
1 parent f80b55b commit 1bcd8e8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 12 deletions.
7 changes: 7 additions & 0 deletions tests/test_class_sh_property_stl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "pybind11_tests.h"

#include <cstddef>
#include <vector>

namespace test_class_sh_property_stl {
Expand All @@ -20,6 +21,11 @@ struct FieldHolder {
struct VectorFieldHolder {
std::vector<FieldHolder> vec_fld_hld;
VectorFieldHolder() { vec_fld_hld.push_back(FieldHolder{Field{300}}); }
void reset_at(std::size_t index, int wrapped_int) {
if (index < vec_fld_hld.size()) {
vec_fld_hld[index].fld.wrapped_int = wrapped_int;
}
}
};

} // namespace test_class_sh_property_stl
Expand All @@ -37,6 +43,7 @@ TEST_SUBMODULE(class_sh_property_stl, m) {

py::classh<VectorFieldHolder>(m, "VectorFieldHolder")
.def(py::init<>())
.def("reset_at", &VectorFieldHolder::reset_at)
.def_readwrite("vec_fld_hld_ref", &VectorFieldHolder::vec_fld_hld)
.def_readwrite("vec_fld_hld_cpy",
&VectorFieldHolder::vec_fld_hld,
Expand Down
38 changes: 26 additions & 12 deletions tests/test_class_sh_property_stl.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
import pytest

from pybind11_tests import class_sh_property_stl as m


def test_vec_fld_hld_ref():
vfh = m.VectorFieldHolder()
vfh0 = vfh.vec_fld_hld_ref[0]
with pytest.raises(RuntimeError) as exc_info:
vfh0.fld
assert str(exc_info.value) == "Non-owning holder (loaded_as_shared_ptr)."
def test_cpy_after_ref():
h = m.VectorFieldHolder()
c1 = h.vec_fld_hld_cpy
c2 = h.vec_fld_hld_cpy
assert repr(c2) != repr(c1)
r1 = h.vec_fld_hld_ref
assert repr(r1) != repr(c2)
assert repr(r1) != repr(c1)
r2 = h.vec_fld_hld_ref
assert repr(r2) == repr(r1)
c3 = h.vec_fld_hld_cpy
assert repr(c3) == repr(r1) # SURPRISE!


def test_persistent_holder():
h = m.VectorFieldHolder()
c0 = h.vec_fld_hld_cpy[0] # Must be first. See test_cpy_after_ref().
r0 = h.vec_fld_hld_ref[0] # Must be second.
assert c0.fld.wrapped_int == 300
assert r0.fld.wrapped_int == 300
h.reset_at(0, 400)
assert c0.fld.wrapped_int == 300
assert r0.fld.wrapped_int == 400


def test_vec_fld_hld_cpy():
vfh = m.VectorFieldHolder()
vfh0 = vfh.vec_fld_hld_cpy[0]
assert vfh0.fld.wrapped_int == 300
def test_temporary_holder_keep_alive():
r0 = m.VectorFieldHolder().vec_fld_hld_ref[0]
assert r0.fld.wrapped_int == 300

0 comments on commit 1bcd8e8

Please sign in to comment.