diff options
Diffstat (limited to '3rdparty/pybind11/tests/test_pickling.cpp')
| -rw-r--r-- | 3rdparty/pybind11/tests/test_pickling.cpp | 130 | 
1 files changed, 130 insertions, 0 deletions
diff --git a/3rdparty/pybind11/tests/test_pickling.cpp b/3rdparty/pybind11/tests/test_pickling.cpp new file mode 100644 index 00000000..9dc63bda --- /dev/null +++ b/3rdparty/pybind11/tests/test_pickling.cpp @@ -0,0 +1,130 @@ +/* +    tests/test_pickling.cpp -- pickle support + +    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> + +    All rights reserved. Use of this source code is governed by a +    BSD-style license that can be found in the LICENSE file. +*/ + +#include "pybind11_tests.h" + +TEST_SUBMODULE(pickling, m) { +    // test_roundtrip +    class Pickleable { +    public: +        Pickleable(const std::string &value) : m_value(value) { } +        const std::string &value() const { return m_value; } + +        void setExtra1(int extra1) { m_extra1 = extra1; } +        void setExtra2(int extra2) { m_extra2 = extra2; } +        int extra1() const { return m_extra1; } +        int extra2() const { return m_extra2; } +    private: +        std::string m_value; +        int m_extra1 = 0; +        int m_extra2 = 0; +    }; + +    class PickleableNew : public Pickleable { +    public: +        using Pickleable::Pickleable; +    }; + +    py::class_<Pickleable>(m, "Pickleable") +        .def(py::init<std::string>()) +        .def("value", &Pickleable::value) +        .def("extra1", &Pickleable::extra1) +        .def("extra2", &Pickleable::extra2) +        .def("setExtra1", &Pickleable::setExtra1) +        .def("setExtra2", &Pickleable::setExtra2) +        // For details on the methods below, refer to +        // http://docs.python.org/3/library/pickle.html#pickling-class-instances +        .def("__getstate__", [](const Pickleable &p) { +            /* Return a tuple that fully encodes the state of the object */ +            return py::make_tuple(p.value(), p.extra1(), p.extra2()); +        }) +        .def("__setstate__", [](Pickleable &p, py::tuple t) { +            if (t.size() != 3) +                throw std::runtime_error("Invalid state!"); +            /* Invoke the constructor (need to use in-place version) */ +            new (&p) Pickleable(t[0].cast<std::string>()); + +            /* Assign any additional state */ +            p.setExtra1(t[1].cast<int>()); +            p.setExtra2(t[2].cast<int>()); +        }); + +    py::class_<PickleableNew, Pickleable>(m, "PickleableNew") +        .def(py::init<std::string>()) +        .def(py::pickle( +            [](const PickleableNew &p) { +                return py::make_tuple(p.value(), p.extra1(), p.extra2()); +            }, +            [](py::tuple t) { +                if (t.size() != 3) +                    throw std::runtime_error("Invalid state!"); +                auto p = PickleableNew(t[0].cast<std::string>()); + +                p.setExtra1(t[1].cast<int>()); +                p.setExtra2(t[2].cast<int>()); +                return p; +            } +        )); + +#if !defined(PYPY_VERSION) +    // test_roundtrip_with_dict +    class PickleableWithDict { +    public: +        PickleableWithDict(const std::string &value) : value(value) { } + +        std::string value; +        int extra; +    }; + +    class PickleableWithDictNew : public PickleableWithDict { +    public: +        using PickleableWithDict::PickleableWithDict; +    }; + +    py::class_<PickleableWithDict>(m, "PickleableWithDict", py::dynamic_attr()) +        .def(py::init<std::string>()) +        .def_readwrite("value", &PickleableWithDict::value) +        .def_readwrite("extra", &PickleableWithDict::extra) +        .def("__getstate__", [](py::object self) { +            /* Also include __dict__ in state */ +            return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__")); +        }) +        .def("__setstate__", [](py::object self, py::tuple t) { +            if (t.size() != 3) +                throw std::runtime_error("Invalid state!"); +            /* Cast and construct */ +            auto& p = self.cast<PickleableWithDict&>(); +            new (&p) PickleableWithDict(t[0].cast<std::string>()); + +            /* Assign C++ state */ +            p.extra = t[1].cast<int>(); + +            /* Assign Python state */ +            self.attr("__dict__") = t[2]; +        }); + +    py::class_<PickleableWithDictNew, PickleableWithDict>(m, "PickleableWithDictNew") +        .def(py::init<std::string>()) +        .def(py::pickle( +            [](py::object self) { +                return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__")); +            }, +            [](const py::tuple &t) { +                if (t.size() != 3) +                    throw std::runtime_error("Invalid state!"); + +                auto cpp_state = PickleableWithDictNew(t[0].cast<std::string>()); +                cpp_state.extra = t[1].cast<int>(); + +                auto py_state = t[2].cast<py::dict>(); +                return std::make_pair(cpp_state, py_state); +            } +        )); +#endif +}  | 
