mirror of
https://github.com/boostorg/python.git
synced 2026-01-23 17:52:17 +00:00
class_::enable_pickling() in publicized interface; tested with everything incl. VC6 and 7.0
[SVN r22254]
This commit is contained in:
@@ -281,6 +281,7 @@ namespace boost { namespace python
|
||||
// pickle support
|
||||
template <typename PickleSuite>
|
||||
self& def_pickle(PickleSuite const&);
|
||||
self& enable_pickling();
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
@@ -709,6 +710,23 @@ class_& def_pickle(PickleSuite const&);
|
||||
checks.</dt>
|
||||
</dl>
|
||||
<br>
|
||||
<pre>
|
||||
class_& enable_pickling();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> n/a</dt>
|
||||
|
||||
<dt><b>Effects:</b> Defines the <code>__reduce__</code> method and
|
||||
the <code>__safe_for_unpickling__</code> attribute.
|
||||
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
|
||||
<dt><b>Rationale:</b> Light-weight alternative to
|
||||
<code>def_pickle()</code>. Enables implementation of
|
||||
<a href="pickle.html">pickle support</a> from Python.</dt>
|
||||
</dl>
|
||||
<br>
|
||||
|
||||
|
||||
<h3><a name="bases-spec"></a>Class template
|
||||
|
||||
@@ -281,13 +281,51 @@ is not empty.
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<h2>Light-weight alternative: pickle support implemented in Python</h2>
|
||||
|
||||
© Copyright Ralf W. Grosse-Kunstleve 20012-2002. Permission to copy,
|
||||
<h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>
|
||||
|
||||
The <tt>pickle4.cpp</tt> example demonstrates an alternative technique
|
||||
for implementing pickle support. First we direct Boost.Python via
|
||||
the <tt>class_::enable_pickling()</tt> member function to define only
|
||||
the basic attributes required for pickling:
|
||||
|
||||
<pre>
|
||||
class_<world>("world", args<const std::string&>())
|
||||
// ...
|
||||
.enable_pickling()
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
This enables the standard Python pickle interface as described
|
||||
in the Python documentation. By "injecting" a
|
||||
<tt>__getinitargs__</tt> method into the definition of the wrapped
|
||||
class we make all instances pickleable:
|
||||
|
||||
<pre>
|
||||
# import the wrapped world class
|
||||
from pickle4_ext import world
|
||||
|
||||
# definition of __getinitargs__
|
||||
def world_getinitargs(self):
|
||||
return (self.get_country(),)
|
||||
|
||||
# now inject __getinitargs__ (Python is a dynamic language!)
|
||||
world.__getinitargs__ = world_getinitargs
|
||||
</pre>
|
||||
|
||||
See also the
|
||||
<a href="../tutorial/doc/extending_wrapped_objects_in_python.html"
|
||||
>tutorial section</a> on injecting additional methods from Python.
|
||||
|
||||
<hr>
|
||||
|
||||
© Copyright Ralf W. Grosse-Kunstleve 2001-2004. Permission to copy,
|
||||
use, modify, sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided "as
|
||||
is" without express or implied warranty, and with no claim as to its
|
||||
suitability for any purpose.
|
||||
|
||||
<p>
|
||||
Updated: Aug 2002.
|
||||
Updated: Feb 2004.
|
||||
</div>
|
||||
|
||||
@@ -415,6 +415,12 @@ class class_ : public objects::class_base
|
||||
return *this;
|
||||
}
|
||||
|
||||
self& enable_pickling()
|
||||
{
|
||||
this->base::enable_pickling_(false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
self& staticmethod(char const* name)
|
||||
{
|
||||
this->make_method_static(name);
|
||||
|
||||
@@ -32,7 +32,7 @@ struct BOOST_PYTHON_DECL class_base : python::api::object
|
||||
|
||||
// Implementation detail. Hiding this in the private section would
|
||||
// require use of template friend declarations.
|
||||
void enable_pickling(bool getstate_manages_dict);
|
||||
void enable_pickling_(bool getstate_manages_dict);
|
||||
|
||||
protected:
|
||||
void add_property(char const* name, object const& fget);
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace detail {
|
||||
inaccessible* (*setstate_fn)(),
|
||||
bool)
|
||||
{
|
||||
cl.enable_pickling(false);
|
||||
cl.enable_pickling_(false);
|
||||
cl.def("__getinitargs__", getinitargs_fn);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace detail {
|
||||
void (*setstate_fn)(Tsetstate, Ttuple),
|
||||
bool getstate_manages_dict)
|
||||
{
|
||||
cl.enable_pickling(getstate_manages_dict);
|
||||
cl.enable_pickling_(getstate_manages_dict);
|
||||
cl.def("__getstate__", getstate_fn);
|
||||
cl.def("__setstate__", setstate_fn);
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace detail {
|
||||
void (*setstate_fn)(Tsetstate, Ttuple),
|
||||
bool getstate_manages_dict)
|
||||
{
|
||||
cl.enable_pickling(getstate_manages_dict);
|
||||
cl.enable_pickling_(getstate_manages_dict);
|
||||
cl.def("__getinitargs__", getinitargs_fn);
|
||||
cl.def("__getstate__", getstate_fn);
|
||||
cl.def("__setstate__", setstate_fn);
|
||||
|
||||
@@ -599,7 +599,7 @@ namespace objects
|
||||
this->setattr("__init__", object(f));
|
||||
}
|
||||
|
||||
void class_base::enable_pickling(bool getstate_manages_dict)
|
||||
void class_base::enable_pickling_(bool getstate_manages_dict)
|
||||
{
|
||||
setattr("__reduce__", object(make_instance_reduce_function()));
|
||||
setattr("__safe_for_unpickling__", object(true));
|
||||
|
||||
@@ -151,6 +151,7 @@ bpl-test crossmod_exception
|
||||
[ bpl-test pickle1 ]
|
||||
[ bpl-test pickle2 ]
|
||||
[ bpl-test pickle3 ]
|
||||
[ bpl-test pickle4 ]
|
||||
|
||||
[ bpl-test nested ]
|
||||
|
||||
|
||||
41
test/pickle4.cpp
Normal file
41
test/pickle4.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Example by Ralf W. Grosse-Kunstleve
|
||||
|
||||
/*
|
||||
This example shows how to enable pickling without using the
|
||||
pickle_suite. The pickling interface (__getinitargs__) is
|
||||
implemented in Python.
|
||||
|
||||
For more information refer to boost/libs/python/doc/pickle.html.
|
||||
*/
|
||||
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.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; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(pickle4_ext)
|
||||
{
|
||||
using namespace boost::python;
|
||||
class_<world>("world", init<const std::string&>())
|
||||
.enable_pickling()
|
||||
.def("greet", &world::greet)
|
||||
.def("get_country", &world::get_country)
|
||||
;
|
||||
}
|
||||
36
test/pickle4.py
Normal file
36
test/pickle4.py
Normal file
@@ -0,0 +1,36 @@
|
||||
r'''>>> import pickle4_ext
|
||||
>>> import pickle
|
||||
>>> def world_getinitargs(self):
|
||||
... return (self.get_country(),)
|
||||
>>> pickle4_ext.world.__getinitargs__ = world_getinitargs
|
||||
>>> pickle4_ext.world.__module__
|
||||
'pickle4_ext'
|
||||
>>> pickle4_ext.world.__safe_for_unpickling__
|
||||
1
|
||||
>>> pickle4_ext.world.__name__
|
||||
'world'
|
||||
>>> pickle4_ext.world('Hello').__reduce__()
|
||||
(<class 'pickle4_ext.world'>, ('Hello',))
|
||||
>>> wd = pickle4_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):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
status = run()[0]
|
||||
if (status == 0): print "Done."
|
||||
sys.exit(status)
|
||||
Reference in New Issue
Block a user