From cbebb6da1fa76bcbc1da0fc94855e193067483ca Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 22 Jan 2021 20:05:22 -0800 Subject: [PATCH] Tests for classh py::module_local() feature. --- include/pybind11/detail/classh_type_casters.h | 2 -- tests/classh_module_local_0.cpp | 27 +++++++++++++++ tests/classh_module_local_1.cpp | 33 +++++++++++++++++++ tests/classh_module_local_2.cpp | 33 +++++++++++++++++++ tests/test_classh_module_local.py | 27 +++++++++++++++ 5 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 tests/classh_module_local_0.cpp create mode 100644 tests/classh_module_local_1.cpp create mode 100644 tests/classh_module_local_2.cpp create mode 100644 tests/test_classh_module_local.py diff --git a/include/pybind11/detail/classh_type_casters.h b/include/pybind11/detail/classh_type_casters.h index 3c5033e53..267d46c01 100644 --- a/include/pybind11/detail/classh_type_casters.h +++ b/include/pybind11/detail/classh_type_casters.h @@ -84,7 +84,6 @@ public: } PYBIND11_NOINLINE static void *local_load(PyObject *src, const type_info *ti) { - pybind11_fail("classh_type_casters: local_load UNTESTED."); // Not thread safe. But the GIL needs to be held anyway in the context of this code. static modified_type_caster_generic_load_impl caster; caster = modified_type_caster_generic_load_impl(ti); @@ -111,7 +110,6 @@ public: void* void_ptr = foreign_typeinfo->module_local_load(src.ptr(), foreign_typeinfo); if (void_ptr != nullptr) { - pybind11_fail("classh_type_casters: try_load_foreign_module_local UNTESTED."); auto foreign_load_impl = static_cast(void_ptr); if (loaded_v_h_cpptype != nullptr) { pybind11_fail("classh_type_casters: try_load_foreign_module_local failure."); diff --git a/tests/classh_module_local_0.cpp b/tests/classh_module_local_0.cpp new file mode 100644 index 000000000..1e543c824 --- /dev/null +++ b/tests/classh_module_local_0.cpp @@ -0,0 +1,27 @@ +#include + +#include + +namespace pybind11_tests { +namespace classh_module_local { + +struct bottle { + std::string msg; +}; + +std::string get_msg(const bottle &b) { return b.msg; } + +bottle make_bottle() { return bottle(); } + +} // namespace classh_module_local +} // namespace pybind11_tests + +PYBIND11_CLASSH_TYPE_CASTERS(pybind11_tests::classh_module_local::bottle) + +PYBIND11_MODULE(classh_module_local_0, m) { + using namespace pybind11_tests::classh_module_local; + + m.def("get_msg", get_msg); + + m.def("make_bottle", make_bottle); +} diff --git a/tests/classh_module_local_1.cpp b/tests/classh_module_local_1.cpp new file mode 100644 index 000000000..456c863c1 --- /dev/null +++ b/tests/classh_module_local_1.cpp @@ -0,0 +1,33 @@ +// Identical to classh_module_local_2.cpp, except 2 replaced with 1. +#include + +#include + +namespace pybind11_tests { +namespace classh_module_local { + +struct bottle { + std::string msg; +}; + +std::string get_msg(const bottle &b) { return b.msg; } + +} // namespace classh_module_local +} // namespace pybind11_tests + +PYBIND11_CLASSH_TYPE_CASTERS(pybind11_tests::classh_module_local::bottle) + +PYBIND11_MODULE(classh_module_local_1, m) { + namespace py = pybind11; + using namespace pybind11_tests::classh_module_local; + + py::classh(m, "bottle", py::module_local()) + .def(py::init([](const std::string &msg) { + bottle obj; + obj.msg = msg; + return obj; + })) + .def("tag", [](const bottle &) { return 1; }); + + m.def("get_msg", get_msg); +} diff --git a/tests/classh_module_local_2.cpp b/tests/classh_module_local_2.cpp new file mode 100644 index 000000000..f9837e889 --- /dev/null +++ b/tests/classh_module_local_2.cpp @@ -0,0 +1,33 @@ +// Identical to classh_module_local_1.cpp, except 1 replaced with 2. +#include + +#include + +namespace pybind11_tests { +namespace classh_module_local { + +struct bottle { + std::string msg; +}; + +std::string get_msg(const bottle &b) { return b.msg; } + +} // namespace classh_module_local +} // namespace pybind11_tests + +PYBIND11_CLASSH_TYPE_CASTERS(pybind11_tests::classh_module_local::bottle) + +PYBIND11_MODULE(classh_module_local_2, m) { + namespace py = pybind11; + using namespace pybind11_tests::classh_module_local; + + py::classh(m, "bottle", py::module_local()) + .def(py::init([](const std::string &msg) { + bottle obj; + obj.msg = msg; + return obj; + })) + .def("tag", [](const bottle &) { return 2; }); + + m.def("get_msg", get_msg); +} diff --git a/tests/test_classh_module_local.py b/tests/test_classh_module_local.py new file mode 100644 index 000000000..b9e6b414c --- /dev/null +++ b/tests/test_classh_module_local.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +import pytest + +import classh_module_local_0 as m0 +import classh_module_local_1 as m1 +import classh_module_local_2 as m2 + + +def test_cross_module_get_msg(): + b1 = m1.bottle("A") + assert b1.tag() == 1 + b2 = m2.bottle("B") + assert b2.tag() == 2 + assert m1.get_msg(b1) == "A" + assert m2.get_msg(b2) == "B" + assert m1.get_msg(b2) == "B" + assert m2.get_msg(b1) == "A" + assert m0.get_msg(b1) == "A" + assert m0.get_msg(b2) == "B" + + +def test_m0_make_bottle(): + with pytest.raises(TypeError) as exc_info: + m0.make_bottle() + assert str(exc_info.value).startswith( + "Unable to convert function return value to a Python type!" + )