[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