Blame external/pybind11/tests/pybind11_tests.cpp

Packit 534379
/*
Packit 534379
    tests/pybind11_tests.cpp -- pybind example plugin
Packit 534379
Packit 534379
    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
Packit 534379
Packit 534379
    All rights reserved. Use of this source code is governed by a
Packit 534379
    BSD-style license that can be found in the LICENSE file.
Packit 534379
*/
Packit 534379
Packit 534379
#include "pybind11_tests.h"
Packit 534379
#include "constructor_stats.h"
Packit 534379
Packit 534379
#include <functional>
Packit 534379
#include <list>
Packit 534379
Packit 534379
/*
Packit 534379
For testing purposes, we define a static global variable here in a function that each individual
Packit 534379
test .cpp calls with its initialization lambda.  It's convenient here because we can just not
Packit 534379
compile some test files to disable/ignore some of the test code.
Packit 534379
Packit 534379
It is NOT recommended as a way to use pybind11 in practice, however: the initialization order will
Packit 534379
be essentially random, which is okay for our test scripts (there are no dependencies between the
Packit 534379
individual pybind11 test .cpp files), but most likely not what you want when using pybind11
Packit 534379
productively.
Packit 534379
Packit 534379
Instead, see the "How can I reduce the build time?" question in the "Frequently asked questions"
Packit 534379
section of the documentation for good practice on splitting binding code over multiple files.
Packit 534379
*/
Packit 534379
std::list<std::function<void(py::module &)>> &initializers() {
Packit 534379
    static std::list<std::function<void(py::module &)>> inits;
Packit 534379
    return inits;
Packit 534379
}
Packit 534379
Packit 534379
test_initializer::test_initializer(Initializer init) {
Packit 534379
    initializers().push_back(init);
Packit 534379
}
Packit 534379
Packit 534379
test_initializer::test_initializer(const char *submodule_name, Initializer init) {
Packit 534379
    initializers().push_back([=](py::module &parent) {
Packit 534379
        auto m = parent.def_submodule(submodule_name);
Packit 534379
        init(m);
Packit 534379
    });
Packit 534379
}
Packit 534379
Packit 534379
void bind_ConstructorStats(py::module &m) {
Packit 534379
    py::class_<ConstructorStats>(m, "ConstructorStats")
Packit 534379
        .def("alive", &ConstructorStats::alive)
Packit 534379
        .def("values", &ConstructorStats::values)
Packit 534379
        .def_readwrite("default_constructions", &ConstructorStats::default_constructions)
Packit 534379
        .def_readwrite("copy_assignments", &ConstructorStats::copy_assignments)
Packit 534379
        .def_readwrite("move_assignments", &ConstructorStats::move_assignments)
Packit 534379
        .def_readwrite("copy_constructions", &ConstructorStats::copy_constructions)
Packit 534379
        .def_readwrite("move_constructions", &ConstructorStats::move_constructions)
Packit 534379
        .def_static("get", (ConstructorStats &(*)(py::object)) &ConstructorStats::get, py::return_value_policy::reference_internal)
Packit 534379
Packit 534379
        // Not exactly ConstructorStats, but related: expose the internal pybind number of registered instances
Packit 534379
        // to allow instance cleanup checks (invokes a GC first)
Packit 534379
        .def_static("detail_reg_inst", []() {
Packit 534379
            ConstructorStats::gc();
Packit 534379
            return py::detail::get_internals().registered_instances.size();
Packit 534379
        })
Packit 534379
        ;
Packit 534379
}
Packit 534379
Packit 534379
PYBIND11_MODULE(pybind11_tests, m) {
Packit 534379
    m.doc() = "pybind11 test module";
Packit 534379
Packit 534379
    bind_ConstructorStats(m);
Packit 534379
Packit 534379
#if !defined(NDEBUG)
Packit 534379
    m.attr("debug_enabled") = true;
Packit 534379
#else
Packit 534379
    m.attr("debug_enabled") = false;
Packit 534379
#endif
Packit 534379
Packit 534379
    py::class_<UserType>(m, "UserType", "A `py::class_` type for testing")
Packit 534379
        .def(py::init<>())
Packit 534379
        .def(py::init<int>())
Packit 534379
        .def("get_value", &UserType::value, "Get value using a method")
Packit 534379
        .def("set_value", &UserType::set, "Set value using a method")
Packit 534379
        .def_property("value", &UserType::value, &UserType::set, "Get/set value using a property")
Packit 534379
        .def("__repr__", [](const UserType& u) { return "UserType({})"_s.format(u.value()); });
Packit 534379
Packit 534379
    py::class_<IncType, UserType>(m, "IncType")
Packit 534379
        .def(py::init<>())
Packit 534379
        .def(py::init<int>())
Packit 534379
        .def("__repr__", [](const IncType& u) { return "IncType({})"_s.format(u.value()); });
Packit 534379
Packit 534379
    for (const auto &initializer : initializers())
Packit 534379
        initializer(m);
Packit 534379
Packit 534379
    if (!py::hasattr(m, "have_eigen")) m.attr("have_eigen") = false;
Packit 534379
}