From 52f4be8946198685264fedac9d554a503b201bb9 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Sat, 3 Sep 2016 14:54:22 -0400 Subject: [PATCH] Make test initialization self-registering Adding or removing tests is a little bit cumbersome currently: the test needs to be added to CMakeLists.txt, the init function needs to be predeclared in pybind11_tests.cpp, then called in the plugin initialization. While this isn't a big deal for tests that are being committed, it's more of a hassle when working on some new feature or test code for which I temporarily only care about building and linking the test being worked on rather than the entire test suite. This commit changes tests to self-register their initialization by having each test initialize a local object (which stores the initialization function in a static variable). This makes changing the set of tests being build easy: one only needs to add or comment out test names in tests/CMakeLists.txt. A couple other minor changes that go along with this: - test_eigen.cpp is now included in the test list, then removed if eigen isn't available. This lets you disable the eigen tests by commenting it out, just like all the other tests, but keeps the build working without eigen eigen isn't available. (Also, if it's commented out, we don't even bother looking for and reporting the building with/without eigen status message). - pytest is now invoked with all the built test names (with .cpp changed to .py) so that it doesn't try to run tests that weren't built. --- tests/CMakeLists.txt | 24 ++++++---- tests/pybind11_tests.cpp | 63 ++++---------------------- tests/pybind11_tests.h | 8 ++++ tests/test_buffers.cpp | 4 +- tests/test_callbacks.cpp | 4 +- tests/test_constants_and_functions.cpp | 4 +- tests/test_eigen.cpp | 6 ++- tests/test_enum.cpp | 4 +- tests/test_eval.cpp | 4 +- tests/test_exceptions.cpp | 4 +- tests/test_inheritance.cpp | 4 +- tests/test_issues.cpp | 3 ++ tests/test_keep_alive.cpp | 4 +- tests/test_kwargs_and_defaults.cpp | 4 +- tests/test_methods_and_attributes.cpp | 4 +- tests/test_modules.cpp | 4 +- tests/test_numpy_dtypes.cpp | 4 +- tests/test_numpy_vectorize.cpp | 4 +- tests/test_opaque_types.cpp | 4 +- tests/test_operator_overloading.cpp | 4 +- tests/test_pickling.cpp | 4 +- tests/test_python_types.cpp | 4 +- tests/test_sequences_and_iterators.cpp | 4 +- tests/test_smart_ptr.cpp | 4 +- tests/test_stl_binders.cpp | 4 +- tests/test_virtual_functions.cpp | 4 +- 26 files changed, 83 insertions(+), 105 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5841d82e..0efefaae 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,6 +7,7 @@ set(PYBIND11_TEST_FILES test_buffers.cpp test_callbacks.cpp test_constants_and_functions.cpp + test_eigen.cpp test_enum.cpp test_eval.cpp test_exceptions.cpp @@ -28,14 +29,21 @@ set(PYBIND11_TEST_FILES test_virtual_functions.cpp ) -# Check if Eigen is available -find_package(Eigen3 QUIET) +string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}") -if(EIGEN3_FOUND) - list(APPEND PYBIND11_TEST_FILES test_eigen.cpp) - message(STATUS "Building tests with Eigen v${EIGEN3_VERSION}") -else() - message(STATUS "Building tests WITHOUT Eigen") +# Check if Eigen is available; if not, remove from PYBIND11_TEST_FILES (but +# keep it in PYBIND11_PYTEST_FILES, so that we get the "eigen is not installed" +# skip message). +list(FIND PYBIND11_TEST_FILES test_eigen.cpp PYBIND11_TEST_FILES_EIGEN_I) +if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1) + find_package(Eigen3 QUIET) + + if(EIGEN3_FOUND) + message(STATUS "Building tests with Eigen v${EIGEN3_VERSION}") + else() + list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_EIGEN_I}) + message(STATUS "Building tests WITHOUT Eigen") + endif() endif() # Create the binding library @@ -74,5 +82,5 @@ if(NOT PYBIND11_PYTEST_FOUND) endif() # A single command to compile and run the tests -add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest -rws +add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest -rws ${PYBIND11_PYTEST_FILES} DEPENDS pybind11_tests WORKING_DIRECTORY ${testdir}) diff --git a/tests/pybind11_tests.cpp b/tests/pybind11_tests.cpp index 525f379e..f3f557a2 100644 --- a/tests/pybind11_tests.cpp +++ b/tests/pybind11_tests.cpp @@ -10,32 +10,14 @@ #include "pybind11_tests.h" #include "constructor_stats.h" -void init_ex_methods_and_attributes(py::module &); -void init_ex_python_types(py::module &); -void init_ex_operator_overloading(py::module &); -void init_ex_constants_and_functions(py::module &); -void init_ex_callbacks(py::module &); -void init_ex_sequences_and_iterators(py::module &); -void init_ex_buffers(py::module &); -void init_ex_smart_ptr(py::module &); -void init_ex_modules(py::module &); -void init_ex_numpy_vectorize(py::module &); -void init_ex_arg_keywords_and_defaults(py::module &); -void init_ex_virtual_functions(py::module &); -void init_ex_keep_alive(py::module &); -void init_ex_opaque_types(py::module &); -void init_ex_pickling(py::module &); -void init_ex_inheritance(py::module &); -void init_ex_stl_binder_vector(py::module &); -void init_ex_eval(py::module &); -void init_ex_custom_exceptions(py::module &); -void init_ex_numpy_dtypes(py::module &); -void init_ex_enum(py::module &); -void init_issues(py::module &); +std::list> &initializers() { + static std::list> inits; + return inits; +} -#if defined(PYBIND11_TEST_EIGEN) - void init_eigen(py::module &); -#endif +test_initializer::test_initializer(std::function initializer) { + initializers().push_back(std::move(initializer)); +} void bind_ConstructorStats(py::module &m) { py::class_(m, "ConstructorStats") @@ -54,35 +36,10 @@ PYBIND11_PLUGIN(pybind11_tests) { bind_ConstructorStats(m); - init_ex_methods_and_attributes(m); - init_ex_python_types(m); - init_ex_operator_overloading(m); - init_ex_constants_and_functions(m); - init_ex_callbacks(m); - init_ex_sequences_and_iterators(m); - init_ex_buffers(m); - init_ex_smart_ptr(m); - init_ex_modules(m); - init_ex_numpy_vectorize(m); - init_ex_arg_keywords_and_defaults(m); - init_ex_virtual_functions(m); - init_ex_keep_alive(m); - init_ex_opaque_types(m); - init_ex_pickling(m); - init_ex_inheritance(m); - init_ex_stl_binder_vector(m); - init_ex_eval(m); - init_ex_custom_exceptions(m); - init_ex_numpy_dtypes(m); - init_ex_enum(m); - init_issues(m); + for (const auto &initializer : initializers()) + initializer(m); -#if defined(PYBIND11_TEST_EIGEN) - init_eigen(m); - m.attr("have_eigen") = py::cast(true); -#else - m.attr("have_eigen") = py::cast(false); -#endif + if (!m.attr("have_eigen")) m.attr("have_eigen") = py::cast(false); return m.ptr(); } diff --git a/tests/pybind11_tests.h b/tests/pybind11_tests.h index ab8fff79..8af3154e 100644 --- a/tests/pybind11_tests.h +++ b/tests/pybind11_tests.h @@ -1,7 +1,15 @@ +#pragma once #include #include +#include +#include using std::cout; using std::endl; namespace py = pybind11; + +class test_initializer { +public: + test_initializer(std::function initializer); +}; diff --git a/tests/test_buffers.cpp b/tests/test_buffers.cpp index 5a4dc67d..c3a7a9e0 100644 --- a/tests/test_buffers.cpp +++ b/tests/test_buffers.cpp @@ -74,7 +74,7 @@ private: float *m_data; }; -void init_ex_buffers(py::module &m) { +test_initializer buffers([](py::module &m) { py::class_ mtx(m, "Matrix"); mtx.def(py::init()) @@ -114,4 +114,4 @@ void init_ex_buffers(py::module &m) { ); }) ; -} +}); diff --git a/tests/test_callbacks.cpp b/tests/test_callbacks.cpp index 270ff5cc..31d0740c 100644 --- a/tests/test_callbacks.cpp +++ b/tests/test_callbacks.cpp @@ -71,7 +71,7 @@ struct Payload { } }; -void init_ex_callbacks(py::module &m) { +test_initializer callbacks([](py::module &m) { m.def("test_callback1", &test_callback1); m.def("test_callback2", &test_callback2); m.def("test_callback3", &test_callback3); @@ -95,4 +95,4 @@ void init_ex_callbacks(py::module &m) { m.def("test_dummy_function", &test_dummy_function); // Export the payload constructor statistics for testing purposes: m.def("payload_cstats", &ConstructorStats::get); -} +}); diff --git a/tests/test_constants_and_functions.cpp b/tests/test_constants_and_functions.cpp index 03f41779..29a27965 100644 --- a/tests/test_constants_and_functions.cpp +++ b/tests/test_constants_and_functions.cpp @@ -38,7 +38,7 @@ std::string print_bytes(py::bytes bytes) { return ret; } -void init_ex_constants_and_functions(py::module &m) { +test_initializer constants_and_functions([](py::module &m) { m.attr("some_constant") = py::int_(14); m.def("test_function", &test_function1); @@ -52,4 +52,4 @@ void init_ex_constants_and_functions(py::module &m) { m.def("return_bytes", &return_bytes); m.def("print_bytes", &print_bytes); -} +}); diff --git a/tests/test_eigen.cpp b/tests/test_eigen.cpp index 42bb969f..518cfecc 100644 --- a/tests/test_eigen.cpp +++ b/tests/test_eigen.cpp @@ -32,7 +32,7 @@ typedef Eigen::Matrix Ma MatrixXfRowMajor double_mat_rm(const MatrixXfRowMajor& x) { return 2.0f * x; } -void init_eigen(py::module &m) { +test_initializer eigen([](py::module &m) { typedef Eigen::Matrix FixedMatrixR; typedef Eigen::Matrix FixedMatrixC; typedef Eigen::Matrix DenseMatrixR; @@ -40,6 +40,8 @@ void init_eigen(py::module &m) { typedef Eigen::SparseMatrix SparseMatrixR; typedef Eigen::SparseMatrix SparseMatrixC; + m.attr("have_eigen") = py::cast(true); + // Non-symmetric matrix with zero elements Eigen::MatrixXf mat(5, 6); mat << 0, 3, 0, 0, 0, 11, 22, 0, 0, 0, 17, 11, 7, 5, 0, 1, 0, 11, 0, @@ -129,4 +131,4 @@ void init_eigen(py::module &m) { m.def("sparse_passthrough_c", [](const SparseMatrixC &m) -> SparseMatrixC { return m; }); -} +}); diff --git a/tests/test_enum.cpp b/tests/test_enum.cpp index e4b2594c..6ed0a6aa 100644 --- a/tests/test_enum.cpp +++ b/tests/test_enum.cpp @@ -35,7 +35,7 @@ std::string test_scoped_enum(ScopedEnum z) { return "ScopedEnum::" + std::string(z == ScopedEnum::Two ? "Two" : "Three"); } -void init_ex_enum(py::module &m) { +test_initializer enums([](py::module &m) { m.def("test_scoped_enum", &test_scoped_enum); py::enum_(m, "UnscopedEnum") @@ -54,4 +54,4 @@ void init_ex_enum(py::module &m) { .value("EFirstMode", ClassWithUnscopedEnum::EFirstMode) .value("ESecondMode", ClassWithUnscopedEnum::ESecondMode) .export_values(); -} +}); diff --git a/tests/test_eval.cpp b/tests/test_eval.cpp index 6b16e7c7..45d811d7 100644 --- a/tests/test_eval.cpp +++ b/tests/test_eval.cpp @@ -11,7 +11,7 @@ #include #include "pybind11_tests.h" -void init_ex_eval(py::module & m) { +test_initializer eval([](py::module &m) { auto global = py::dict(py::module::import("__main__").attr("__dict__")); m.def("test_eval_statements", [global]() { @@ -77,4 +77,4 @@ void init_ex_eval(py::module & m) { } return false; }); -} +}); diff --git a/tests/test_exceptions.cpp b/tests/test_exceptions.cpp index 492308fa..534f23bf 100644 --- a/tests/test_exceptions.cpp +++ b/tests/test_exceptions.cpp @@ -66,7 +66,7 @@ void throws_logic_error() { throw std::logic_error("this error should fall through to the standard handler"); } -void init_ex_custom_exceptions(py::module &m) { +test_initializer custom_exceptions([](py::module &m) { // make a new custom exception and use it as a translation target static py::exception ex(m, "MyException"); py::register_exception_translator([](std::exception_ptr p) { @@ -104,5 +104,5 @@ void init_ex_custom_exceptions(py::module &m) { m.def("throws3", &throws3); m.def("throws4", &throws4); m.def("throws_logic_error", &throws_logic_error); -} +}); diff --git a/tests/test_inheritance.cpp b/tests/test_inheritance.cpp index 2997ccec..e1aad992 100644 --- a/tests/test_inheritance.cpp +++ b/tests/test_inheritance.cpp @@ -44,7 +44,7 @@ struct BaseClass { virtual ~BaseClass() {} }; struct DerivedClass1 : BaseClass { }; struct DerivedClass2 : BaseClass { }; -void init_ex_inheritance(py::module &m) { +test_initializer inheritance([](py::module &m) { py::class_ pet_class(m, "Pet"); pet_class .def(py::init()) @@ -69,4 +69,4 @@ void init_ex_inheritance(py::module &m) { m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); }); m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); }); m.def("return_none", []() -> BaseClass* { return nullptr; }); -} +}); diff --git a/tests/test_issues.cpp b/tests/test_issues.cpp index 5f680ebd..51013e55 100644 --- a/tests/test_issues.cpp +++ b/tests/test_issues.cpp @@ -173,3 +173,6 @@ void init_issues(py::module &m) { m2.def("get_NestB", [](const NestB &b) { return b.value; }); m2.def("get_NestC", [](const NestC &c) { return c.value; }); } + +// MSVC workaround: trying to use a lambda here crashes MSCV +test_initializer issues(&init_issues); diff --git a/tests/test_keep_alive.cpp b/tests/test_keep_alive.cpp index 25f852ea..a07670b6 100644 --- a/tests/test_keep_alive.cpp +++ b/tests/test_keep_alive.cpp @@ -25,7 +25,7 @@ public: Child *returnNullChild() { return nullptr; } }; -void init_ex_keep_alive(py::module &m) { +test_initializer keep_alive([](py::module &m) { py::class_(m, "Parent") .def(py::init<>()) .def("addChild", &Parent::addChild) @@ -37,4 +37,4 @@ void init_ex_keep_alive(py::module &m) { py::class_(m, "Child") .def(py::init<>()); -} +}); diff --git a/tests/test_kwargs_and_defaults.cpp b/tests/test_kwargs_and_defaults.cpp index 349b7ea9..0656cc59 100644 --- a/tests/test_kwargs_and_defaults.cpp +++ b/tests/test_kwargs_and_defaults.cpp @@ -39,7 +39,7 @@ struct KWClass { void foo(int, float) {} }; -void init_ex_arg_keywords_and_defaults(py::module &m) { +test_initializer arg_keywords_and_defaults([](py::module &m) { m.def("kw_func0", &kw_func); m.def("kw_func1", &kw_func, py::arg("x"), py::arg("y")); m.def("kw_func2", &kw_func, py::arg("x") = 100, py::arg("y") = 200); @@ -63,4 +63,4 @@ void init_ex_arg_keywords_and_defaults(py::module &m) { py::class_(m, "KWClass") .def("foo0", &KWClass::foo) .def("foo1", &KWClass::foo, "x"_a, "y"_a); -} +}); diff --git a/tests/test_methods_and_attributes.cpp b/tests/test_methods_and_attributes.cpp index 9317d780..8b0351e4 100644 --- a/tests/test_methods_and_attributes.cpp +++ b/tests/test_methods_and_attributes.cpp @@ -53,7 +53,7 @@ public: int value = 0; }; -void init_ex_methods_and_attributes(py::module &m) { +test_initializer methods_and_attributes([](py::module &m) { py::class_(m, "ExampleMandA") .def(py::init<>()) .def(py::init()) @@ -81,4 +81,4 @@ void init_ex_methods_and_attributes(py::module &m) { .def("__str__", &ExampleMandA::toString) .def_readwrite("value", &ExampleMandA::value) ; -} +}); diff --git a/tests/test_modules.cpp b/tests/test_modules.cpp index b77dacce..50c7d841 100644 --- a/tests/test_modules.cpp +++ b/tests/test_modules.cpp @@ -39,7 +39,7 @@ public: A a2{2}; }; -void init_ex_modules(py::module &m) { +test_initializer modules([](py::module &m) { py::module m_sub = m.def_submodule("submodule"); m_sub.def("submodule_func", &submodule_func); @@ -55,4 +55,4 @@ void init_ex_modules(py::module &m) { .def_readwrite("a2", &B::a2); m.attr("OD") = py::module::import("collections").attr("OrderedDict"); -} +}); diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index 7133a804..3041e55d 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -267,7 +267,7 @@ py::list test_dtype_methods() { return list; } -void init_ex_numpy_dtypes(py::module &m) { +test_initializer numpy_dtypes([](py::module &m) { try { py::module::import("numpy"); } catch (...) { @@ -297,6 +297,6 @@ void init_ex_numpy_dtypes(py::module &m) { m.def("test_array_ctors", &test_array_ctors); m.def("test_dtype_ctors", &test_dtype_ctors); m.def("test_dtype_methods", &test_dtype_methods); -} +}); #undef PYBIND11_PACKED diff --git a/tests/test_numpy_vectorize.cpp b/tests/test_numpy_vectorize.cpp index f05c655b..7b0c51ea 100644 --- a/tests/test_numpy_vectorize.cpp +++ b/tests/test_numpy_vectorize.cpp @@ -20,7 +20,7 @@ std::complex my_func3(std::complex c) { return c * std::complex(2.f); } -void init_ex_numpy_vectorize(py::module &m) { +test_initializer numpy_vectorize([](py::module &m) { // Vectorize all arguments of a function (though non-vector arguments are also allowed) m.def("vectorized_func", py::vectorize(my_func)); @@ -38,4 +38,4 @@ void init_ex_numpy_vectorize(py::module &m) { m.def("selective_func", [](py::array_t) { return "Int branch taken."; }); m.def("selective_func", [](py::array_t) { return "Float branch taken."; }); m.def("selective_func", [](py::array_t, py::array::c_style>) { return "Complex float branch taken."; }); -} +}); diff --git a/tests/test_opaque_types.cpp b/tests/test_opaque_types.cpp index 901f05e1..54f4dc7a 100644 --- a/tests/test_opaque_types.cpp +++ b/tests/test_opaque_types.cpp @@ -21,7 +21,7 @@ public: /* IMPORTANT: Disable internal pybind11 translation mechanisms for STL data structures */ PYBIND11_MAKE_OPAQUE(StringList); -void init_ex_opaque_types(py::module &m) { +test_initializer opaque_types([](py::module &m) { py::class_(m, "StringList") .def(py::init<>()) .def("pop_back", &StringList::pop_back) @@ -59,4 +59,4 @@ void init_ex_opaque_types(py::module &m) { result->push_back("some value"); return std::unique_ptr(result); }); -} +}); diff --git a/tests/test_operator_overloading.cpp b/tests/test_operator_overloading.cpp index b84a5b84..93aea801 100644 --- a/tests/test_operator_overloading.cpp +++ b/tests/test_operator_overloading.cpp @@ -52,7 +52,7 @@ private: float x, y; }; -void init_ex_operator_overloading(py::module &m) { +test_initializer operator_overloading([](py::module &m) { py::class_(m, "Vector2") .def(py::init()) .def(py::self + py::self) @@ -73,4 +73,4 @@ void init_ex_operator_overloading(py::module &m) { ; m.attr("Vector") = m.attr("Vector2"); -} +}); diff --git a/tests/test_pickling.cpp b/tests/test_pickling.cpp index 4a484525..4494c24d 100644 --- a/tests/test_pickling.cpp +++ b/tests/test_pickling.cpp @@ -24,7 +24,7 @@ private: int m_extra2 = 0; }; -void init_ex_pickling(py::module &m) { +test_initializer pickling([](py::module &m) { py::class_(m, "Pickleable") .def(py::init()) .def("value", &Pickleable::value) @@ -48,4 +48,4 @@ void init_ex_pickling(py::module &m) { p.setExtra1(t[1].cast()); p.setExtra2(t[2].cast()); }); -} +}); diff --git a/tests/test_python_types.cpp b/tests/test_python_types.cpp index 39e43eb6..8ec7e26a 100644 --- a/tests/test_python_types.cpp +++ b/tests/test_python_types.cpp @@ -167,7 +167,7 @@ public: int ExamplePythonTypes::value = 0; const int ExamplePythonTypes::value2 = 5; -void init_ex_python_types(py::module &m) { +test_initializer python_types([](py::module &m) { /* No constructor is explicitly defined below. An exception is raised when trying to construct it directly from Python */ py::class_(m, "ExamplePythonTypes", "Example 2 documentation") @@ -197,4 +197,4 @@ void init_ex_python_types(py::module &m) { .def_readwrite_static("value", &ExamplePythonTypes::value, "Static value member") .def_readonly_static("value2", &ExamplePythonTypes::value2, "Static value member (readonly)") ; -} +}); diff --git a/tests/test_sequences_and_iterators.cpp b/tests/test_sequences_and_iterators.cpp index 39e342ba..0a88cef6 100644 --- a/tests/test_sequences_and_iterators.cpp +++ b/tests/test_sequences_and_iterators.cpp @@ -168,7 +168,7 @@ bool operator==(const NonZeroIterator>& it, const NonZeroSentine return !(*it).first || !(*it).second; } -void init_ex_sequences_and_iterators(py::module &m) { +test_initializer sequences_and_iterators([](py::module &m) { py::class_ seq(m, "Sequence"); @@ -271,4 +271,4 @@ void init_ex_sequences_and_iterators(py::module &m) { On the actual Sequence object, the iterator would be constructed as follows: .def("__iter__", [](py::object s) { return PySequenceIterator(s.cast(), s); }) #endif -} +}); diff --git a/tests/test_smart_ptr.cpp b/tests/test_smart_ptr.cpp index 46c83b37..d4259694 100644 --- a/tests/test_smart_ptr.cpp +++ b/tests/test_smart_ptr.cpp @@ -105,7 +105,7 @@ void print_myobject3_2(std::shared_ptr obj) { std::cout << obj->toStr void print_myobject3_3(const std::shared_ptr &obj) { std::cout << obj->toString() << std::endl; } void print_myobject3_4(const std::shared_ptr *obj) { std::cout << (*obj)->toString() << std::endl; } -void init_ex_smart_ptr(py::module &m) { +test_initializer smart_ptr([](py::module &m) { py::class_> obj(m, "Object"); obj.def("getRefCount", &Object::getRefCount); @@ -147,4 +147,4 @@ void init_ex_smart_ptr(py::module &m) { // Expose constructor stats for the ref type m.def("cstats_ref", &ConstructorStats::get); -} +}); diff --git a/tests/test_stl_binders.cpp b/tests/test_stl_binders.cpp index da854fc4..a6ed6bf6 100644 --- a/tests/test_stl_binders.cpp +++ b/tests/test_stl_binders.cpp @@ -24,7 +24,7 @@ std::ostream & operator<<(std::ostream &s, El const&v) { return s; } -void init_ex_stl_binder_vector(py::module &m) { +test_initializer stl_binder_vector([](py::module &m) { py::class_(m, "El") .def(py::init()); @@ -34,4 +34,4 @@ void init_ex_stl_binder_vector(py::module &m) { py::bind_vector(m, "VectorEl"); py::bind_vector>(m, "VectorVectorEl"); -} +}); diff --git a/tests/test_virtual_functions.cpp b/tests/test_virtual_functions.cpp index f0f4702a..e591ba92 100644 --- a/tests/test_virtual_functions.cpp +++ b/tests/test_virtual_functions.cpp @@ -283,7 +283,7 @@ void initialize_inherited_virtuals(py::module &m) { }; -void init_ex_virtual_functions(py::module &m) { +test_initializer virtual_functions([](py::module &m) { /* Important: indicate the trampoline class PyExampleVirt using the third argument to py::class_. The second argument with the unique pointer is simply the default holder type used by pybind11. */ @@ -315,4 +315,4 @@ void init_ex_virtual_functions(py::module &m) { m.def("cstats_debug", &ConstructorStats::get); initialize_inherited_virtuals(m); -} +});