From fe3abeda9f93a3255dbde87fa977954b5c880f0f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 18 May 2006 15:49:41 +0000 Subject: [PATCH] much more informative pickle error messages if pickling is not enabled [SVN r34004] --- src/object/class.cpp | 5 ++++- src/object/pickle_support.cpp | 17 +++++++++++++++++ test/pickle1.cpp | 5 +++++ test/pickle1.py | 5 +++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/object/class.cpp b/src/object/class.cpp index efc492c6..7faf1830 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -530,6 +530,10 @@ namespace objects if (scope().ptr() != Py_None) scope().attr(name) = result; + // For pickle. Will lead to informative error messages if pickling + // is not enabled. + result.attr("__reduce__") = object(make_instance_reduce_function()); + return result; } } @@ -627,7 +631,6 @@ namespace objects void class_base::enable_pickling_(bool getstate_manages_dict) { - setattr("__reduce__", object(make_instance_reduce_function())); setattr("__safe_for_unpickling__", object(true)); if (getstate_manages_dict) diff --git a/src/object/pickle_support.cpp b/src/object/pickle_support.cpp index 897ee633..1c574552 100644 --- a/src/object/pickle_support.cpp +++ b/src/object/pickle_support.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace boost { namespace python { @@ -19,6 +20,22 @@ namespace { object instance_class(instance_obj.attr("__class__")); result.append(instance_class); object none; + if (!getattr(instance_obj, "__safe_for_unpickling__", none)) + { + str type_name(getattr(instance_class, "__name__")); + str module_name(getattr(instance_class, "__module__", "")); + if (module_name) + module_name += "."; + + PyErr_SetObject( + PyExc_RuntimeError, + ( "Pickling of \"%s\" instances is not enabled" + " (http://www.boost.org/libs/python/doc/v2/pickle.html)" + % (module_name+type_name)).ptr() + ); + + throw_error_already_set(); + } object getinitargs = getattr(instance_obj, "__getinitargs__", none); tuple initargs; if (getinitargs.ptr() != none.ptr()) { diff --git a/test/pickle1.cpp b/test/pickle1.cpp index bcdb2633..c1f8c805 100644 --- a/test/pickle1.cpp +++ b/test/pickle1.cpp @@ -45,6 +45,8 @@ namespace { } }; + // To support test of "pickling not enabled" error message. + struct noop {}; } BOOST_PYTHON_MODULE(pickle1_ext) @@ -54,4 +56,7 @@ BOOST_PYTHON_MODULE(pickle1_ext) .def("greet", &world::greet) .def_pickle(world_pickle_suite()) ; + + // To support test of "pickling not enabled" error message. + class_("noop"); } diff --git a/test/pickle1.py b/test/pickle1.py index bb66b31b..8369768d 100644 --- a/test/pickle1.py +++ b/test/pickle1.py @@ -18,6 +18,11 @@ r'''>>> import pickle1_ext Hello from California! >>> print wl.greet() Hello from California! + + >>> noop = pickle1_ext.noop() + >>> try: pickle.dumps(noop) + ... except RuntimeError, e: print str(e)[:55] + Pickling of "pickle1_ext.noop" instances is not enabled ''' def run(args = None):