Skip to content

Commit e15ca5c

Browse files
author
Ralf W. Grosse-Kunstleve
committed
full integration of (revised) pickle support
[SVN r14557]
1 parent 3232c5b commit e15ca5c

File tree

13 files changed

+93
-34
lines changed

13 files changed

+93
-34
lines changed

Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dll bpl
2727
src/object/function.cpp
2828
src/object/inheritance.cpp
2929
src/object/life_support.cpp
30+
src/object/pickle_support.cpp
3031
src/errors.cpp
3132
src/module.cpp
3233
src/converter/builtin_converters.cpp

include/boost/python/class.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
# include <boost/python/data_members.hpp>
2626
# include <boost/utility.hpp>
2727
# include <boost/python/detail/operator_id.hpp>
28+
# include <boost/python/object/pickle_support.hpp>
2829

2930
namespace boost { namespace python {
3031

@@ -195,6 +196,19 @@ class class_ : public objects::class_base
195196

196197
self& setattr(char const* name, handle<> const&);
197198

199+
// Pickle support
200+
template <typename PickleGroupType>
201+
self& def_pickle(PickleGroupType)
202+
{
203+
detail::pickle_group_finalize<PickleGroupType>::register_(
204+
*this,
205+
&PickleGroupType::getinitargs,
206+
&PickleGroupType::getstate,
207+
&PickleGroupType::setstate,
208+
PickleGroupType::getstate_manages_dict());
209+
return *this;
210+
}
211+
198212
private: // types
199213
typedef objects::class_id class_id;
200214

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef BOOST_PYTHON_API_PLACE_HOLDER_HPP
2+
#define BOOST_PYTHON_API_PLACE_HOLDER_HPP
3+
4+
namespace boost { namespace python {
5+
6+
inline long len(object const& obj)
7+
{
8+
long result = PyObject_Length(obj.ptr());
9+
if (PyErr_Occurred()) throw_error_already_set();
10+
return result;
11+
}
12+
13+
inline object getattr(object const& a0, const char* a1, object const& a2)
14+
{
15+
handle<> result(allow_null(PyObject_GetAttrString(
16+
a0.ptr(), const_cast<char*>(a1))));
17+
if (!PyErr_Occurred()) return object(result);
18+
PyErr_Clear();
19+
return a2;
20+
}
21+
22+
}} // namespace boost::python
23+
24+
#endif // BOOST_PYTHON_API_PLACE_HOLDER_HPP

include/boost/python/object/class.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct BOOST_PYTHON_DECL class_base : private noncopyable
3939
void add_property(char const* name, handle<> const& fget);
4040
void add_property(char const* name, handle<> const& fget, handle<> const& fset);
4141
void setattr(char const* name, handle<> const&);
42+
void enable_pickling(bool getstate_manages_dict);
4243
private:
4344
type_handle m_object;
4445
};

include/boost/python/object/pickle_support.hpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@ handle<> make_instance_reduce_function();
1616
namespace error_messages {
1717

1818
template <class T>
19-
struct missing_pickle_support_function_or_incorrect_signature {};
19+
struct missing_pickle_group_function_or_incorrect_signature {};
2020

2121
}
2222

23-
namespace detail { struct pickle_support_registration; }
23+
namespace detail { struct pickle_group_registration; }
2424

25-
struct pickle_support_base
25+
struct pickle_group
2626
{
2727
private:
2828
struct inaccessible {};
29-
friend struct detail::pickle_support_registration;
29+
friend struct detail::pickle_group_registration;
3030
public:
3131
static inaccessible* getinitargs() { return 0; }
3232
static inaccessible* getstate() { return 0; }
@@ -36,9 +36,9 @@ struct pickle_support_base
3636

3737
namespace detail {
3838

39-
struct pickle_support_registration
39+
struct pickle_group_registration
4040
{
41-
typedef pickle_support_base::inaccessible inaccessible;
41+
typedef pickle_group::inaccessible inaccessible;
4242

4343
template <class Class_, class Tgetinitargs>
4444
static
@@ -50,7 +50,7 @@ namespace detail {
5050
inaccessible* (*setstate_fn)(),
5151
bool)
5252
{
53-
cl.enable_pickle_support(false);
53+
cl.enable_pickling(false);
5454
cl.def("__getinitargs__", getinitargs_fn);
5555
}
5656

@@ -64,7 +64,7 @@ namespace detail {
6464
void (*setstate_fn)(Tsetstate, object),
6565
bool getstate_manages_dict)
6666
{
67-
cl.enable_pickle_support(getstate_manages_dict);
67+
cl.enable_pickling(getstate_manages_dict);
6868
cl.def("__getstate__", getstate_fn);
6969
cl.def("__setstate__", setstate_fn);
7070
}
@@ -80,7 +80,7 @@ namespace detail {
8080
void (*setstate_fn)(Tsetstate, object),
8181
bool getstate_manages_dict)
8282
{
83-
cl.enable_pickle_support(getstate_manages_dict);
83+
cl.enable_pickling(getstate_manages_dict);
8484
cl.def("__getinitargs__", getinitargs_fn);
8585
cl.def("__getstate__", getstate_fn);
8686
cl.def("__setstate__", setstate_fn);
@@ -94,15 +94,15 @@ namespace detail {
9494
...)
9595
{
9696
typedef typename
97-
error_messages::missing_pickle_support_function_or_incorrect_signature<
97+
error_messages::missing_pickle_group_function_or_incorrect_signature<
9898
Class_>::error_type error_type;
9999
}
100100
};
101101

102-
template <typename UserPickleSupportType>
103-
struct pickle_support_finalize
104-
: UserPickleSupportType,
105-
pickle_support_registration
102+
template <typename UserPickleGroupType>
103+
struct pickle_group_finalize
104+
: UserPickleGroupType,
105+
pickle_group_registration
106106
{};
107107

108108
} // namespace detail

src/object/class.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <boost/python/converter/registry.hpp>
77
#include <boost/python/object/class.hpp>
88
#include <boost/python/object/find_instance.hpp>
9+
#include <boost/python/object/pickle_support.hpp>
910
#include <boost/python/detail/map_entry.hpp>
1011
#include <boost/python/object.hpp>
1112
#include <boost/detail/binary_search.hpp>
@@ -304,6 +305,16 @@ namespace objects
304305
throw_error_already_set();
305306
}
306307

308+
void class_base::enable_pickling(bool getstate_manages_dict)
309+
{
310+
setattr("__reduce__", make_instance_reduce_function());
311+
handle<> one(PyInt_FromLong(1));
312+
setattr("__safe_for_unpickling__", one);
313+
if (getstate_manages_dict) {
314+
setattr("__getstate_manages_dict__", one);
315+
}
316+
}
317+
307318
BOOST_PYTHON_DECL type_handle registered_class_object(class_id id)
308319
{
309320
return objects::query_class(id);

test/Jamfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ;
8282

8383
bpl-test extract ;
8484

85+
bpl-test pickle1 ;
86+
bpl-test pickle2 ;
87+
bpl-test pickle3 ;
88+
8589
if $(TEST_BIENSTMAN_NON_BUGS)
8690
{
8791
bpl-test bienstman4 ;

test/pickle1.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace {
3232
std::string get_country() const { return country; }
3333
};
3434

35-
struct world_pickle_support : boost::python::pickle_support_base
35+
struct world_pickle_group : boost::python::pickle_group
3636
{
3737
static
3838
boost::python::tuple
@@ -54,7 +54,7 @@ BOOST_PYTHON_MODULE_INIT(pickle1_ext)
5454
.add(class_<world>("world")
5555
.def_init(args<const std::string&>())
5656
.def("greet", &world::greet)
57-
.pickle_support(world_pickle_support())
57+
.def_pickle(world_pickle_group())
5858
)
5959
;
6060
}

test/pickle1.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@
1818
'''
1919

2020
def run(args = None):
21+
import sys
22+
import doctest
23+
2124
if args is not None:
22-
import sys
2325
sys.argv = args
24-
import doctest, pickle1
25-
return doctest.testmod(pickle1)
26-
26+
return doctest.testmod(sys.modules.get(__name__))
27+
2728
if __name__ == '__main__':
29+
print "running..."
2830
import sys
2931
sys.exit(run()[0])
30-

test/pickle2.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace { // Avoid cluttering the global namespace.
4747
int secret_number;
4848
};
4949

50-
struct world_pickle_support : boost::python::pickle_support_base
50+
struct world_pickle_group : boost::python::pickle_group
5151
{
5252
static
5353
boost::python::tuple
@@ -95,7 +95,7 @@ BOOST_PYTHON_MODULE_INIT(pickle2_ext)
9595
.def("greet", &world::greet)
9696
.def("get_secret_number", &world::get_secret_number)
9797
.def("set_secret_number", &world::set_secret_number)
98-
.pickle_support(world_pickle_support())
98+
.def_pickle(world_pickle_group())
9999
)
100100
;
101101
}

0 commit comments

Comments
 (0)