[C++-sig] Re: [Boost-python-cvs] CVS: boost/libs/python/test pickle1.cpp,NONE,1.1 pickle1.py,NONE,1.1 pickle2.cpp,NONE,1.1 pickle2.py,NONE,1.1 pickle3.cpp,NONE,1.1 pickle3.py,NONE,1.1
David Abrahams
david.abrahams at rcn.com
Sun Jul 21 13:23:22 CEST 2002
Hi Ralf,
This is cool!
Can we discuss different names for "pickle_support_base" please?
I'm in favor of "pickler". Thus, world_pickle_support is-a
boost::python::pickler. I realize it's also an unpickler, so if you don't
like that I'd like to at least find a way to drop "_base" from any public
names.
-Dave
----- Original Message -----
From: "Ralf W. Grosse-Kunstleve" <rwgk at users.sourceforge.net>
To: <boost-python-cvs at lists.sourceforge.net>
Sent: Sunday, July 21, 2002 3:48 AM
Subject: [Boost-python-cvs] CVS: boost/libs/python/test
pickle1.cpp,NONE,1.1 pickle1.py,NONE,1.1 pickle2.cpp,NONE,1.1
pickle2.py,NONE,1.1 pickle3.cpp,NONE,1.1 pickle3.py,NONE,1.1
> Update of /cvsroot/boost/boost/libs/python/test
> In directory usw-pr-cvs1:/tmp/cvs-serv31578/test
>
> Added Files:
> pickle1.cpp pickle1.py pickle2.cpp pickle2.py pickle3.cpp
> pickle3.py
> Log Message:
> additional files for pickle support; no modification of any existing
files
>
> --- NEW FILE: pickle1.cpp ---
> // Example by Ralf W. Grosse-Kunstleve
>
> /*
> This example shows how to make an Extension Class "pickleable".
>
> The world class below can be fully restored by passing the
> appropriate argument to the constructor. Therefore it is sufficient
> to define the pickle interface method __getinitargs__.
>
> For more information refer to boost/libs/python/doc/pickle.html.
> */
>
> #include <boost/python/module.hpp>
> #include <boost/python/class.hpp>
> #include <boost/python/list.hpp>
> #include <boost/python/tuple.hpp>
>
> #include <string>
>
> namespace {
>
> // A friendly class.
> class world
> {
> private:
> std::string country;
> public:
> world(const std::string& country) {
> this->country = country;
> }
> std::string greet() const { return "Hello from " + country + "!"; }
> std::string get_country() const { return country; }
> };
>
> struct world_pickle_support : boost::python::pickle_support_base
> {
> static
> boost::python::tuple
> getinitargs(const world& w)
> {
> using namespace boost::python;
> list result;
> result.append(object(w.get_country()));
> return tuple(result);
> }
> };
>
> }
>
> BOOST_PYTHON_MODULE_INIT(pickle1_ext)
> {
> using namespace boost::python;
> module("pickle1_ext")
> .add(class_<world>("world")
> .def_init(args<const std::string&>())
> .def("greet", &world::greet)
> .pickle_support(world_pickle_support())
> )
> ;
> }
>
> --- NEW FILE: pickle1.py ---
> r'''>>> import pickle1_ext
> >>> import pickle
> >>> pickle1_ext.world.__module__
> 'pickle1_ext'
> >>> pickle1_ext.world.__safe_for_unpickling__
> 1
> >>> pickle1_ext.world.__name__
> 'world'
> >>> pickle1_ext.world('Hello').__reduce__()
> (<class 'pickle1_ext.world'>, ('Hello',))
> >>> wd = pickle1_ext.world('California')
> >>> pstr = pickle.dumps(wd)
> >>> wl = pickle.loads(pstr)
> >>> print wd.greet()
> Hello from California!
> >>> print wl.greet()
> Hello from California!
> '''
>
> def run(args = None):
> if args is not None:
> import sys
> sys.argv = args
> import doctest, pickle1
> return doctest.testmod(pickle1)
>
> if __name__ == '__main__':
> import sys
> sys.exit(run()[0])
>
>
> --- NEW FILE: pickle2.cpp ---
> // Example by Ralf W. Grosse-Kunstleve
>
> /*
> This example shows how to make an Extension Class "pickleable".
>
> The world class below contains member data (secret_number) that
> cannot be restored by any of the constructors. Therefore it is
> necessary to provide the __getstate__/__setstate__ pair of pickle
> interface methods.
>
> For simplicity, the __dict__ is not included in the result of
> __getstate__. This is not generally recommended, but a valid
> approach if it is anticipated that the object's __dict__ will
> always be empty. Note that safety guards are provided to catch
> the cases where this assumption is not true.
>
> pickle3.cpp shows how to include the object's __dict__ in the
> result of __getstate__.
>
> For more information refer to boost/libs/python/doc/pickle.html.
> */
>
> #include <string>
>
> #include <boost/python/module.hpp>
> #include <boost/python/class.hpp>
> #include <boost/python/list.hpp>
> #include <boost/python/tuple.hpp>
> #include <boost/python/extract.hpp>
> #include <boost/python/detail/api_placeholder.hpp>
>
> namespace { // Avoid cluttering the global namespace.
>
> // A friendly class.
> class world
> {
> public:
> world(const std::string& country) : secret_number(0) {
> this->country = country;
> }
> std::string greet() const { return "Hello from " + country + "!"; }
> std::string get_country() const { return country; }
> void set_secret_number(int number) { secret_number = number; }
> int get_secret_number() const { return secret_number; }
> private:
> std::string country;
> int secret_number;
> };
>
> struct world_pickle_support : boost::python::pickle_support_base
> {
> static
> boost::python::tuple
> getinitargs(const world& w)
> {
> using namespace boost::python;
> list result;
> result.append(object(w.get_country()));
> return tuple(result);
> }
>
> static
> boost::python::tuple
> getstate(const world& w)
> {
> using namespace boost::python;
> list result;
> result.append(object(w.get_secret_number()));
> return tuple(result);
> }
>
> static
> void
> setstate(world& w, boost::python::object state)
> {
> using namespace boost::python;
> extract<tuple> state_proxy(state);
> if (!state_proxy.check() || len(state_proxy()) != 1) {
> PyErr_SetString(PyExc_ValueError,
> "Unexpected argument in call to __setstate__.");
> throw_error_already_set();
> }
> long number = extract<long>(state_proxy()[0])();
> if (number != 42) w.set_secret_number(number);
> }
> };
>
> }
>
> BOOST_PYTHON_MODULE_INIT(pickle2_ext)
> {
> boost::python::module("pickle2_ext")
> .add(boost::python::class_<world>("world")
> .def_init(boost::python::args<const std::string&>())
> .def("greet", &world::greet)
> .def("get_secret_number", &world::get_secret_number)
> .def("set_secret_number", &world::set_secret_number)
> .pickle_support(world_pickle_support())
> )
> ;
> }
>
> --- NEW FILE: pickle2.py ---
> r'''>>> import pickle2_ext
> >>> import pickle
> >>> pickle2_ext.world.__module__
> 'pickle2_ext'
> >>> pickle2_ext.world.__safe_for_unpickling__
> 1
> >>> pickle2_ext.world.__name__
> 'world'
> >>> pickle2_ext.world('Hello').__reduce__()
> (<class 'pickle2_ext.world'>, ('Hello',), (0,))
> >>> for number in (24, 42):
> ... wd = pickle2_ext.world('California')
> ... wd.set_secret_number(number)
> ... pstr = pickle.dumps(wd)
> ... wl = pickle.loads(pstr)
> ... print wd.greet(), wd.get_secret_number()
> ... print wl.greet(), wl.get_secret_number()
> Hello from California! 24
> Hello from California! 24
> Hello from California! 42
> Hello from California! 0
>
> # Now show that the __dict__ is not taken care of.
> >>> wd = pickle2_ext.world('California')
> >>> wd.x = 1
> >>> wd.__dict__
> {'x': 1}
> >>> try: pstr = pickle.dumps(wd)
> ... except RuntimeError, err: print err[0]
> ...
> Incomplete pickle support (__getstate_manages_dict__ not set)
> '''
>
> def run(args = None):
> if args is not None:
> import sys
> sys.argv = args
> import doctest, pickle2
> return doctest.testmod(pickle2)
>
> if __name__ == '__main__':
> import sys
> sys.exit(run()[0])
>
>
> --- NEW FILE: pickle3.cpp ---
> // Example by Ralf W. Grosse-Kunstleve
>
> /*
> This example shows how to make an Extension Class "pickleable".
>
> The world class below contains member data (secret_number) that
> cannot be restored by any of the constructors. Therefore it is
> necessary to provide the __getstate__/__setstate__ pair of pickle
> interface methods.
>
> The object's __dict__ is included in the result of __getstate__.
> This requires more code (compare with pickle2.cpp), but is
> unavoidable if the object's __dict__ is not always empty.
>
> For more information refer to boost/libs/python/doc/pickle.html.
> */
>
> #include <string>
>
> #include <boost/python/module.hpp>
> #include <boost/python/class.hpp>
> #include <boost/python/list.hpp>
> #include <boost/python/tuple.hpp>
> #include <boost/python/dict.hpp>
> #include <boost/python/extract.hpp>
> #include <boost/python/detail/api_placeholder.hpp>
>
> namespace { // Avoid cluttering the global namespace.
>
> // A friendly class.
> class world
> {
> public:
> world(const std::string& country) : secret_number(0) {
> this->country = country;
> }
> std::string greet() const { return "Hello from " + country + "!"; }
> std::string get_country() const { return country; }
> void set_secret_number(int number) { secret_number = number; }
> int get_secret_number() const { return secret_number; }
> private:
> std::string country;
> int secret_number;
> };
>
> struct world_pickle_support : boost::python::pickle_support_base
> {
> static
> boost::python::tuple
> getinitargs(const world& w)
> {
> using namespace boost::python;
> list result;
> result.append(object(w.get_country()));
> return tuple(result);
> }
>
> static
> boost::python::tuple
> getstate(boost::python::object w_obj)
> {
> using namespace boost::python;
> world const& w = extract<world const&>(w_obj)();
> list result;
> // store the object's __dict__
> result.append(w_obj.attr("__dict__"));
> // store the internal state of the C++ object
> result.append(object(w.get_secret_number()));
> return tuple(result);
> }
>
> static
> void
> setstate(boost::python::object w_obj, boost::python::object state)
> {
> using namespace boost::python;
> world& w = extract<world&>(w_obj)();
> extract<tuple> state_proxy(state);
> if (!state_proxy.check() || len(state_proxy()) != 2) {
> PyErr_SetString(PyExc_ValueError,
> "Unexpected argument in call to __setstate__.");
> throw_error_already_set();
> }
> // restore the object's __dict__
> w_obj.attr("__dict__").attr("update")(object(state_proxy()[0]));
> // restore the internal state of the C++ object
> long number = extract<long>(state_proxy()[1])();
> if (number != 42) w.set_secret_number(number);
> }
>
> static bool getstate_manages_dict() { return true; }
> };
>
> }
>
> BOOST_PYTHON_MODULE_INIT(pickle3_ext)
> {
> boost::python::module("pickle3_ext")
> .add(boost::python::class_<world>("world")
> .def_init(boost::python::args<const std::string&>())
> .def("greet", &world::greet)
> .def("get_secret_number", &world::get_secret_number)
> .def("set_secret_number", &world::set_secret_number)
> .pickle_support(world_pickle_support())
> )
> ;
> }
>
> --- NEW FILE: pickle3.py ---
> r'''>>> import pickle3_ext
> >>> import pickle
> >>> pickle3_ext.world.__module__
> 'pickle3_ext'
> >>> pickle3_ext.world.__safe_for_unpickling__
> 1
> >>> pickle3_ext.world.__getstate_manages_dict__
> 1
> >>> pickle3_ext.world.__name__
> 'world'
> >>> pickle3_ext.world('Hello').__reduce__()
> (<class 'pickle3_ext.world'>, ('Hello',), ({}, 0))
> >>> for number in (24, 42):
> ... wd = pickle3_ext.world('California')
> ... wd.set_secret_number(number)
> ... wd.x = 2 * number
> ... wd.y = 'y' * number
> ... wd.z = 3. * number
> ... pstr = pickle.dumps(wd)
> ... wl = pickle.loads(pstr)
> ... print wd.greet(), wd.get_secret_number(), wd.x, wd.y, wd.z
> ... print wl.greet(), wl.get_secret_number(), wl.x, wl.y, wl.z
> Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0
> Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0
> Hello from California! 42 84
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0
> Hello from California! 0 84
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0
> '''
>
> def run(args = None):
> if args is not None:
> import sys
> sys.argv = args
> import doctest, pickle3
> return doctest.testmod(pickle3)
>
> if __name__ == '__main__':
> import sys
> sys.exit(run()[0])
>
>
>
> -------------------------------------------------------
> This sf.net email is sponsored by:ThinkGeek
> Welcome to geek heaven.
> http://thinkgeek.com/sf
> _______________________________________________
> Boost-python-cvs mailing list
> Boost-python-cvs at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/boost-python-cvs
More information about the Cplusplus-sig
mailing list