2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-22 17:32:55 +00:00

added: pickle safety measures; bug fix: use bound_function::create()

[SVN r9399]
This commit is contained in:
Ralf W. Grosse-Kunstleve
2001-03-03 12:55:53 +00:00
parent 1d4427c056
commit b06d9e50eb
3 changed files with 87 additions and 10 deletions

View File

@@ -1,3 +1,6 @@
// Revision History:
// Mar 03 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve)
#ifndef CLASS_WRAPPER_DWA101000_H_
# define CLASS_WRAPPER_DWA101000_H_
@@ -24,6 +27,13 @@ class class_builder
~class_builder()
{}
inline void dict_defines_state() {
add(ref(BOOST_PYTHON_CONVERSION::to_python(1)), "__dict_defines_state__");
}
inline void getstate_manages_dict() {
add(ref(BOOST_PYTHON_CONVERSION::to_python(1)), "__getstate_manages_dict__");
}
// define constructors
template <class signature>

View File

@@ -5,6 +5,10 @@
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// Mar 03 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve)
// Mar 03 01 bug fix: use bound_function::create() (instead of new bound_function)
#include <boost/python/classes.hpp>
#include <boost/python/detail/functions.hpp>
@@ -67,8 +71,7 @@ namespace {
ref global_class_reduce()
{
static ref result(detail::new_wrapped_function(class_reduce));
return result;
return ref(detail::new_wrapped_function(class_reduce));
}
@@ -93,17 +96,41 @@ namespace {
ref getstate(PyObject_GetAttrString(obj, const_cast<char*>("__getstate__")),
ref::null_ok);
PyErr_Clear();
ref dict(PyObject_GetAttrString(obj, const_cast<char*>("__dict__")), ref::null_ok);
PyErr_Clear();
if (getstate.get() != 0)
{
if (dict.get() != 0 && dictionary(dict).size() > 0)
{
ref getstate_manages_dict(PyObject_GetAttrString(instance_class.get(), const_cast<char*>("__getstate_manages_dict__")), ref::null_ok);
PyErr_Clear();
if (getstate_manages_dict.get() == 0)
{
PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__getstate_manages_dict__ not set)");
throw error_already_set();
}
}
ref state = ref(PyEval_CallObject(getstate.get(), NULL));
return tuple(instance_class, initargs, state);
}
ref state(PyObject_GetAttrString(obj, const_cast<char*>("__dict__")), ref::null_ok);
PyErr_Clear();
if (state.get() != 0 && dictionary(state).size() > 0)
if (getinitargs.get() == 0)
{
return tuple(instance_class, initargs, state);
ref dict_defines_state(PyObject_GetAttrString(instance_class.get(), const_cast<char*>("__dict_defines_state__")), ref::null_ok);
PyErr_Clear();
if (dict_defines_state.get() == 0)
{
PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__dict_defines_state__ not set)");
throw error_already_set();
}
}
if (dict.get() != 0 && dictionary(dict).size() > 0)
{
return tuple(instance_class, initargs, dict);
}
return tuple(instance_class, initargs);
@@ -111,8 +138,7 @@ namespace {
ref global_instance_reduce()
{
static ref result(detail::new_wrapped_function(instance_reduce));
return result;
return ref(detail::new_wrapped_function(instance_reduce));
}
}
@@ -177,7 +203,7 @@ namespace detail {
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
{
ref target(as_object(this), ref::increment_count);
return new bound_function(target, global_class_reduce());
return bound_function::create(target, global_class_reduce());
}
ref local_attribute = m_name_space.get_item(string(name).reference());
@@ -348,7 +374,7 @@ PyObject* instance::getattr(const char* name, bool use_special_function)
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
{
return new detail::bound_function(ref(this, ref::increment_count), global_instance_reduce());
return detail::bound_function::create(ref(this, ref::increment_count), global_instance_reduce());
}
ref local_attribute = m_name_space.get_item(string(name).reference());

View File

@@ -239,6 +239,47 @@ Pickling tests:
Hello from California! 42
Hello from California! 0
Pickle safety measures:
>>> r=Rational(3, 4)
>>> r
Rational(3, 4)
>>> try: s=pickle.dumps(r)
... except RuntimeError, err: print err[0]
...
Incomplete pickle support (__dict_defines_state__ not set)
>>> class myrational(Rational):
... __dict_defines_state__ = 1 # this is a lie but good enough for testing.
...
>>> r=myrational(3, 4)
>>> r
Rational(3, 4)
>>> s=pickle.dumps(r)
>>> class myworld(world):
... def __init__(self):
... world.__init__(self, 'anywhere')
... self.x = 1
...
>>> w = myworld()
>>> w.greet()
'Hello from anywhere!'
>>> w.__dict__
{'x': 1}
>>> try: s=pickle.dumps(w)
... except RuntimeError, err: print err[0]
...
Incomplete pickle support (__getstate_manages_dict__ not set)
>>> class myunsafeworld(myworld):
... __getstate_manages_dict__ = 1 # this is a lie but good enough for testing.
...
>>> w = myunsafeworld()
>>> w.greet()
'Hello from anywhere!'
>>> w.__dict__
{'x': 1}
>>> s=pickle.dumps(w)
Special member attributes. Tests courtesy of Barry Scott <barry@scottb.demon.co.uk>
>>> class DerivedFromFoo(Foo):