mirror of
https://github.com/boostorg/python.git
synced 2026-01-21 17:12:22 +00:00
Pickling support
[SVN r8248]
This commit is contained in:
@@ -1,3 +1,15 @@
|
||||
2000-11-17 15:04
|
||||
Added pickling support + tests thanks to "Ralf W. Grosse-Kunstleve"
|
||||
<rwgk@cci.lbl.gov>
|
||||
|
||||
Added a specialization of Callback<const char*> to prevent unsafe usage.
|
||||
|
||||
Fixed Ullrich's operator_dispatcher refcount bug
|
||||
|
||||
Removed const char* return values from virtual functions in tests; that
|
||||
usage was unsafe.
|
||||
|
||||
|
||||
2000-11-15 12:01
|
||||
Fixed Ullrich's refcount bug
|
||||
|
||||
|
||||
93
subclass.cpp
93
subclass.cpp
@@ -12,6 +12,7 @@
|
||||
#include <cstddef>
|
||||
#include "callback.h"
|
||||
#include <cstring>
|
||||
#include "module.h"
|
||||
|
||||
namespace py {
|
||||
|
||||
@@ -55,6 +56,64 @@ namespace {
|
||||
Py_XDECREF(v);
|
||||
Py_XDECREF(tb);
|
||||
}
|
||||
|
||||
//
|
||||
// pickle support courtesy of "Ralf W. Grosse-Kunstleve" <rwgk@cci.lbl.gov>
|
||||
//
|
||||
PyObject* class_reduce(PyObject* klass)
|
||||
{
|
||||
return PyObject_GetAttrString(klass, "__name__");
|
||||
}
|
||||
|
||||
Ptr global_class_reduce()
|
||||
{
|
||||
static Ptr result(py::new_wrapped_function(class_reduce));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Tuple instance_reduce(PyObject* instance)
|
||||
{
|
||||
Ptr instance_class(PyObject_GetAttrString(instance, "__class__"));
|
||||
|
||||
Ptr getinitargs(PyObject_GetAttrString(instance, "__getinitargs__"),
|
||||
Ptr::null_ok);
|
||||
PyErr_Clear();
|
||||
Ptr initargs;
|
||||
if (getinitargs.get() != 0)
|
||||
{
|
||||
initargs = Ptr(PyEval_CallObject(getinitargs.get(), NULL));
|
||||
initargs = Ptr(PySequence_Tuple(initargs.get()));
|
||||
}
|
||||
else
|
||||
{
|
||||
initargs = Ptr(PyTuple_New(0));
|
||||
}
|
||||
|
||||
Ptr getstate(PyObject_GetAttrString(instance, "__getstate__"),
|
||||
Ptr::null_ok);
|
||||
PyErr_Clear();
|
||||
if (getstate.get() != 0)
|
||||
{
|
||||
Ptr state = Ptr(PyEval_CallObject(getstate.get(), NULL));
|
||||
return Tuple(instance_class, initargs, state);
|
||||
}
|
||||
|
||||
Ptr state(PyObject_GetAttrString(instance, "__dict__"), Ptr::null_ok);
|
||||
PyErr_Clear();
|
||||
if (state.get() != 0)
|
||||
{
|
||||
return Tuple(instance_class, initargs, state);
|
||||
}
|
||||
|
||||
return Tuple(instance_class, initargs);
|
||||
}
|
||||
|
||||
Ptr global_instance_reduce()
|
||||
{
|
||||
static Ptr result(py::new_wrapped_function(instance_reduce));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +146,7 @@ namespace detail {
|
||||
m_bases = new_bases;
|
||||
}
|
||||
|
||||
PyObject* ClassBase::getattr(const char* name) const
|
||||
PyObject* ClassBase::getattr(const char* name)
|
||||
{
|
||||
if (!PY_CSTD_::strcmp(name, "__dict__"))
|
||||
{
|
||||
@@ -109,6 +168,17 @@ namespace detail {
|
||||
Py_INCREF(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// pickle support courtesy of "Ralf W. Grosse-Kunstleve" <rwgk@cci.lbl.gov>
|
||||
if (!PY_CSTD_::strcmp(name, "__safe_for_unpickling__"))
|
||||
{
|
||||
return PyInt_FromLong(1);
|
||||
}
|
||||
if (!PY_CSTD_::strcmp(name, "__reduce__"))
|
||||
{
|
||||
Ptr target(as_object(this), Ptr::new_ref);
|
||||
return new BoundFunction(target, global_class_reduce());
|
||||
}
|
||||
|
||||
Ptr local_attribute = m_name_space.get_item(String(name).reference());
|
||||
|
||||
@@ -275,6 +345,11 @@ PyObject* Instance::getattr(const char* name, bool use_special_function)
|
||||
Py_INCREF(this->ob_type);
|
||||
return as_object(this->ob_type);
|
||||
}
|
||||
|
||||
if (!PY_CSTD_::strcmp(name, "__reduce__"))
|
||||
{
|
||||
return new BoundFunction(Ptr(this, Ptr::new_ref), global_instance_reduce());
|
||||
}
|
||||
|
||||
Ptr local_attribute = m_name_space.get_item(String(name).reference());
|
||||
|
||||
@@ -767,21 +842,7 @@ namespace {
|
||||
void add_current_module_name(Dict& name_space)
|
||||
{
|
||||
static String module_key("__module__", String::interned);
|
||||
static String name_key("__name__", String::interned);
|
||||
|
||||
Ptr existing_value = name_space.get_item(module_key);
|
||||
if (existing_value.get() == 0)
|
||||
{
|
||||
PyObject* globals = PyEval_GetGlobals();
|
||||
if (globals != 0) // Why don't we throw in this case? Who knows? This is
|
||||
{ // what Python does for class objects!
|
||||
PyObject* module_name = PyDict_GetItem(globals, name_key.get());
|
||||
if (module_name != 0)
|
||||
{
|
||||
name_space[module_key] = Ptr(module_name, Ptr::borrowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
name_space.set_item(module_key, Module::name());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace detail {
|
||||
Dict& dict();
|
||||
|
||||
// Standard Python functions.
|
||||
PyObject* getattr(const char* name) const;
|
||||
PyObject* getattr(const char* name);
|
||||
int setattr(const char* name, PyObject* value);
|
||||
PyObject* repr() const;
|
||||
void add_base(Ptr base);
|
||||
|
||||
@@ -206,6 +206,39 @@ Polymorphism also works:
|
||||
>>> baz.get_foo_value(polymorphic_foo)
|
||||
1000
|
||||
|
||||
Pickling tests:
|
||||
|
||||
>>> world.__module__
|
||||
'demo'
|
||||
>>> world.__safe_for_unpickling__
|
||||
1
|
||||
>>> world.__reduce__()
|
||||
'world'
|
||||
>>> reduced = world('Hello').__reduce__()
|
||||
>>> reduced[0] == world
|
||||
1
|
||||
>>> reduced[1:]
|
||||
(('Hello',), (0,))
|
||||
>>> import StringIO
|
||||
>>> import cPickle
|
||||
>>> pickle = cPickle
|
||||
>>> for number in (24, 42):
|
||||
... wd = world('California')
|
||||
... wd.set_secret_number(number)
|
||||
... # Dump it out and read it back in.
|
||||
... f = StringIO.StringIO()
|
||||
... pickle.dump(wd, f)
|
||||
... f = StringIO.StringIO(f.getvalue())
|
||||
... wl = pickle.load(f)
|
||||
... #
|
||||
... 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
|
||||
|
||||
Special member attributes. Tests courtesy of Barry Scott <barry@scottb.demon.co.uk>
|
||||
|
||||
>>> class DerivedFromFoo(Foo):
|
||||
|
||||
Reference in New Issue
Block a user