Fix broken pickling in Python 3 build

This commit is contained in:
rdb 2016-03-31 16:49:27 +02:00
parent ed9bed425f
commit 15b0ba45f9
4 changed files with 49 additions and 21 deletions

View File

@ -21,10 +21,14 @@ context between all objects written by that Pickler.
Unfortunately, cPickle cannot be supported, because it does not
support extensions of this nature. """
from types import *
from copy_reg import dispatch_table
import sys
from panda3d.core import BamWriter, BamReader
if sys.version_info >= (3, 0):
from copyreg import dispatch_table
else:
from copy_reg import dispatch_table
# A funny replacement for "import pickle" so we don't get confused
# with the local pickle.py.
pickle = __import__('pickle')
@ -60,7 +64,7 @@ class Pickler(pickle.Pickler):
# Check for a class with a custom metaclass; treat as regular class
try:
issc = issubclass(t, TypeType)
issc = issubclass(t, type)
except TypeError: # t is not a class (old Boost; see SF #502085)
issc = 0
if issc:
@ -91,12 +95,12 @@ class Pickler(pickle.Pickler):
(t.__name__, obj))
# Check for string returned by reduce(), meaning "save as global"
if type(rv) is StringType:
if type(rv) is str:
self.save_global(obj, rv)
return
# Assert that reduce() returned a tuple
if type(rv) is not TupleType:
if type(rv) is not tuple:
raise PicklingError("%s must return string or tuple" % reduce)
# Assert that it returned an appropriately sized tuple
@ -131,21 +135,20 @@ class Unpickler(pickle.Unpickler):
value = func(*args)
stack[-1] = value
pickle.Unpickler.dispatch[pickle.REDUCE] = load_reduce
#FIXME: how to replace in Python 3?
if sys.version_info < (3, 0):
pickle.Unpickler.dispatch[pickle.REDUCE] = load_reduce
# Shorthands
try:
from cStringIO import StringIO
except ImportError:
from io import StringIO
from io import BytesIO
def dump(obj, file, protocol=None):
Pickler(file, protocol).dump(obj)
def dumps(obj, protocol=None):
file = StringIO()
file = BytesIO()
Pickler(file, protocol).dump(obj)
return file.getvalue()
@ -153,5 +156,5 @@ def load(file):
return Unpickler(file).load()
def loads(str):
file = StringIO(str)
file = BytesIO(str)
return Unpickler(file).load()

View File

@ -4703,9 +4703,18 @@ write_function_instance(ostream &out, FunctionRemap *remap,
if (args_type == AT_single_arg) {
out << "#if PY_MAJOR_VERSION >= 3\n";
indent(out, indent_level)
<< param_name << "_str = PyUnicode_AsUTF8AndSize(arg, &"
<< param_name << "_len);\n";
// As a special hack to fix pickling in Python 3, if the method name
// starts with py_decode_, we take a bytes object instead of a str.
if (remap->_cppfunc->get_local_name().substr(0, 10) == "py_decode_") {
indent(out, indent_level) << "if (PyBytes_AsStringAndSize(arg, &"
<< param_name << "_str, &" << param_name << "_len) == -1) {\n";
indent(out, indent_level + 2) << param_name << "_str = NULL;\n";
indent(out, indent_level) << "}\n";
} else {
indent(out, indent_level)
<< param_name << "_str = PyUnicode_AsUTF8AndSize(arg, &"
<< param_name << "_len);\n";
}
out << "#else\n"; // NB. PyString_AsStringAndSize also accepts a PyUnicode.
indent(out, indent_level) << "if (PyString_AsStringAndSize(arg, &"
<< param_name << "_str, &" << param_name << "_len) == -1) {\n";
@ -4720,11 +4729,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
+ "_str, &" + param_name + "_len";
}
// if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) {
// pexpr_string = "&std::string(" + param_name + "_str, " + param_name +
// "_len)"; } else {
pexpr_string = param_name + "_str, " + param_name + "_len";
// }
//if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) {
// pexpr_string = "&std::string(" + param_name + "_str, " + param_name + "_len)";
//} else {
pexpr_string = param_name + "_str, " + param_name + "_len";
//}
expected_params += "str";
}
// Remember to clear the TypeError that any of the above methods raise.

View File

@ -156,7 +156,11 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
}
}
#if PY_MAJOR_VERSION >= 3
PyObject *result = Py_BuildValue("(O(y#))", func, bam_stream.data(), (Py_ssize_t) bam_stream.size());
#else
PyObject *result = Py_BuildValue("(O(s#))", func, bam_stream.data(), (Py_ssize_t) bam_stream.size());
#endif
Py_DECREF(func);
Py_DECREF(this_class);
return result;

View File

@ -110,7 +110,11 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
}
}
#if PY_MAJOR_VERSION >= 3
PyObject *result = Py_BuildValue("(O(Oy#))", func, this_class, bam_stream.data(), (Py_ssize_t) bam_stream.size());
#else
PyObject *result = Py_BuildValue("(O(Os#))", func, this_class, bam_stream.data(), (Py_ssize_t) bam_stream.size());
#endif
Py_DECREF(func);
Py_DECREF(this_class);
return result;
@ -212,10 +216,18 @@ py_decode_TypedWritable_from_bam_stream_persist(PyObject *pickler, PyObject *thi
PyObject *result;
if (py_reader != NULL){
#if PY_MAJOR_VERSION >= 3
result = PyObject_CallFunction(func, (char *)"(y#O)", data.data(), (Py_ssize_t) data.size(), py_reader);
#else
result = PyObject_CallFunction(func, (char *)"(s#O)", data.data(), (Py_ssize_t) data.size(), py_reader);
#endif
Py_DECREF(py_reader);
} else {
#if PY_MAJOR_VERSION >= 3
result = PyObject_CallFunction(func, (char *)"(y#)", data.data(), (Py_ssize_t) data.size());
#else
result = PyObject_CallFunction(func, (char *)"(s#)", data.data(), (Py_ssize_t) data.size());
#endif
}
if (result == NULL) {