full integration of (revised) pickle support
[SVN r14557]
This commit is contained in:
parent
3232c5be86
commit
e15ca5c642
1
Jamfile
1
Jamfile
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
24
include/boost/python/detail/api_placeholder.hpp
Normal file
24
include/boost/python/detail/api_placeholder.hpp
Normal 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
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 ;
|
||||
|
@ -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())
|
||||
)
|
||||
;
|
||||
}
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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())
|
||||
)
|
||||
;
|
||||
}
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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())
|
||||
)
|
||||
;
|
||||
}
|
||||
|
@ -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])
|
||||
|
Loading…
Reference in New Issue
Block a user