full integration of (revised) pickle support

[SVN r14557]
This commit is contained in:
Ralf W. Grosse-Kunstleve 2002-07-22 06:54:39 +00:00
parent 3232c5be86
commit e15ca5c642
13 changed files with 96 additions and 37 deletions

View File

@ -27,6 +27,7 @@ dll bpl
src/object/function.cpp
src/object/inheritance.cpp
src/object/life_support.cpp
src/object/pickle_support.cpp
src/errors.cpp
src/module.cpp
src/converter/builtin_converters.cpp

View File

@ -25,6 +25,7 @@
# include <boost/python/data_members.hpp>
# include <boost/utility.hpp>
# include <boost/python/detail/operator_id.hpp>
# include <boost/python/object/pickle_support.hpp>
namespace boost { namespace python {
@ -195,6 +196,19 @@ class class_ : public objects::class_base
self& setattr(char const* name, handle<> const&);
// Pickle support
template <typename PickleGroupType>
self& def_pickle(PickleGroupType)
{
detail::pickle_group_finalize<PickleGroupType>::register_(
*this,
&PickleGroupType::getinitargs,
&PickleGroupType::getstate,
&PickleGroupType::setstate,
PickleGroupType::getstate_manages_dict());
return *this;
}
private: // types
typedef objects::class_id class_id;

View File

@ -0,0 +1,24 @@
#ifndef BOOST_PYTHON_API_PLACE_HOLDER_HPP
#define BOOST_PYTHON_API_PLACE_HOLDER_HPP
namespace boost { namespace python {
inline long len(object const& obj)
{
long result = PyObject_Length(obj.ptr());
if (PyErr_Occurred()) throw_error_already_set();
return result;
}
inline object getattr(object const& a0, const char* a1, object const& a2)
{
handle<> result(allow_null(PyObject_GetAttrString(
a0.ptr(), const_cast<char*>(a1))));
if (!PyErr_Occurred()) return object(result);
PyErr_Clear();
return a2;
}
}} // namespace boost::python
#endif // BOOST_PYTHON_API_PLACE_HOLDER_HPP

View File

@ -39,6 +39,7 @@ struct BOOST_PYTHON_DECL class_base : private noncopyable
void add_property(char const* name, handle<> const& fget);
void add_property(char const* name, handle<> const& fget, handle<> const& fset);
void setattr(char const* name, handle<> const&);
void enable_pickling(bool getstate_manages_dict);
private:
type_handle m_object;
};

View File

@ -16,17 +16,17 @@ handle<> make_instance_reduce_function();
namespace error_messages {
template <class T>
struct missing_pickle_support_function_or_incorrect_signature {};
struct missing_pickle_group_function_or_incorrect_signature {};
}
namespace detail { struct pickle_support_registration; }
namespace detail { struct pickle_group_registration; }
struct pickle_support_base
struct pickle_group
{
private:
struct inaccessible {};
friend struct detail::pickle_support_registration;
friend struct detail::pickle_group_registration;
public:
static inaccessible* getinitargs() { return 0; }
static inaccessible* getstate() { return 0; }
@ -36,9 +36,9 @@ struct pickle_support_base
namespace detail {
struct pickle_support_registration
struct pickle_group_registration
{
typedef pickle_support_base::inaccessible inaccessible;
typedef pickle_group::inaccessible inaccessible;
template <class Class_, class Tgetinitargs>
static
@ -50,7 +50,7 @@ namespace detail {
inaccessible* (*setstate_fn)(),
bool)
{
cl.enable_pickle_support(false);
cl.enable_pickling(false);
cl.def("__getinitargs__", getinitargs_fn);
}
@ -64,7 +64,7 @@ namespace detail {
void (*setstate_fn)(Tsetstate, object),
bool getstate_manages_dict)
{
cl.enable_pickle_support(getstate_manages_dict);
cl.enable_pickling(getstate_manages_dict);
cl.def("__getstate__", getstate_fn);
cl.def("__setstate__", setstate_fn);
}
@ -80,7 +80,7 @@ namespace detail {
void (*setstate_fn)(Tsetstate, object),
bool getstate_manages_dict)
{
cl.enable_pickle_support(getstate_manages_dict);
cl.enable_pickling(getstate_manages_dict);
cl.def("__getinitargs__", getinitargs_fn);
cl.def("__getstate__", getstate_fn);
cl.def("__setstate__", setstate_fn);
@ -94,15 +94,15 @@ namespace detail {
...)
{
typedef typename
error_messages::missing_pickle_support_function_or_incorrect_signature<
error_messages::missing_pickle_group_function_or_incorrect_signature<
Class_>::error_type error_type;
}
};
template <typename UserPickleSupportType>
struct pickle_support_finalize
: UserPickleSupportType,
pickle_support_registration
template <typename UserPickleGroupType>
struct pickle_group_finalize
: UserPickleGroupType,
pickle_group_registration
{};
} // namespace detail

View File

@ -6,6 +6,7 @@
#include <boost/python/converter/registry.hpp>
#include <boost/python/object/class.hpp>
#include <boost/python/object/find_instance.hpp>
#include <boost/python/object/pickle_support.hpp>
#include <boost/python/detail/map_entry.hpp>
#include <boost/python/object.hpp>
#include <boost/detail/binary_search.hpp>
@ -304,6 +305,16 @@ namespace objects
throw_error_already_set();
}
void class_base::enable_pickling(bool getstate_manages_dict)
{
setattr("__reduce__", make_instance_reduce_function());
handle<> one(PyInt_FromLong(1));
setattr("__safe_for_unpickling__", one);
if (getstate_manages_dict) {
setattr("__getstate_manages_dict__", one);
}
}
BOOST_PYTHON_DECL type_handle registered_class_object(class_id id)
{
return objects::query_class(id);

View File

@ -82,6 +82,10 @@ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ;
bpl-test extract ;
bpl-test pickle1 ;
bpl-test pickle2 ;
bpl-test pickle3 ;
if $(TEST_BIENSTMAN_NON_BUGS)
{
bpl-test bienstman4 ;

View File

@ -32,7 +32,7 @@ namespace {
std::string get_country() const { return country; }
};
struct world_pickle_support : boost::python::pickle_support_base
struct world_pickle_group : boost::python::pickle_group
{
static
boost::python::tuple
@ -54,7 +54,7 @@ BOOST_PYTHON_MODULE_INIT(pickle1_ext)
.add(class_<world>("world")
.def_init(args<const std::string&>())
.def("greet", &world::greet)
.pickle_support(world_pickle_support())
.def_pickle(world_pickle_group())
)
;
}

View File

@ -18,13 +18,14 @@ r'''>>> import pickle1_ext
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, pickle1
return doctest.testmod(pickle1)
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
sys.exit(run()[0])

View File

@ -47,7 +47,7 @@ namespace { // Avoid cluttering the global namespace.
int secret_number;
};
struct world_pickle_support : boost::python::pickle_support_base
struct world_pickle_group : boost::python::pickle_group
{
static
boost::python::tuple
@ -95,7 +95,7 @@ BOOST_PYTHON_MODULE_INIT(pickle2_ext)
.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())
.def_pickle(world_pickle_group())
)
;
}

View File

@ -32,13 +32,14 @@ r'''>>> import pickle2_ext
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, pickle2
return doctest.testmod(pickle2)
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
sys.exit(run()[0])

View File

@ -43,7 +43,7 @@ namespace { // Avoid cluttering the global namespace.
int secret_number;
};
struct world_pickle_support : boost::python::pickle_support_base
struct world_pickle_group : boost::python::pickle_group
{
static
boost::python::tuple
@ -101,7 +101,7 @@ BOOST_PYTHON_MODULE_INIT(pickle3_ext)
.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())
.def_pickle(world_pickle_group())
)
;
}

View File

@ -27,12 +27,14 @@ r'''>>> import pickle3_ext
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, pickle3
return doctest.testmod(pickle3)
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
sys.exit(run()[0])