]> granicus.if.org Git - python/commitdiff
Issue #2389: Pickle array objects using a list representation for portability
authorAlexandre Vassalotti <alexandre@peadrop.com>
Wed, 15 Jul 2009 18:19:47 +0000 (18:19 +0000)
committerAlexandre Vassalotti <alexandre@peadrop.com>
Wed, 15 Jul 2009 18:19:47 +0000 (18:19 +0000)
across different machine architectures and compatibility with Python 3.x.

Misc/NEWS
Modules/arraymodule.c

index 63115f41fd6d3fbb7456ad282979475459bae7e7..51930409e357a7d28c98035b7289f36010f8050b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1262,6 +1262,8 @@ Tests
   support.EnvironmentVarGuard objects restored the environment variables
   incorrectly on __exit__.
 
+- Issue #2389: Array objects are now pickled in a portable manner.
+
 
 What's New in Python 2.6 final
 ==============================
index 6fad71c8a6a31a473a572d312b12f648bcdb3e7e..018ab873d42457aa10fda8b0f5375b4afcd375d5 100644 (file)
@@ -1156,40 +1156,6 @@ PyDoc_STRVAR(byteswap_doc,
 Byteswap all items of the array.  If the items in the array are not 1, 2,\n\
 4, or 8 bytes in size, RuntimeError is raised.");
 
-static PyObject *
-array_reduce(arrayobject *array)
-{
-       PyObject *dict, *result;
-
-       dict = PyObject_GetAttrString((PyObject *)array, "__dict__");
-       if (dict == NULL) {
-               PyErr_Clear();
-               dict = Py_None;
-               Py_INCREF(dict);
-       }
-       if (Py_SIZE(array) > 0) {
-               if (array->ob_descr->itemsize 
-                               > PY_SSIZE_T_MAX / array->ob_size) {
-                       return PyErr_NoMemory();
-               }
-               result = Py_BuildValue("O(cs#)O", 
-                       Py_TYPE(array), 
-                       array->ob_descr->typecode,
-                       array->ob_item,
-                       Py_SIZE(array) * array->ob_descr->itemsize,
-                       dict);
-       } else {
-               result = Py_BuildValue("O(c)O", 
-                       Py_TYPE(array), 
-                       array->ob_descr->typecode,
-                       dict);
-       }
-       Py_DECREF(dict);
-       return result;
-}
-
-PyDoc_STRVAR(array_doc, "Return state information for pickling.");
-
 static PyObject *
 array_reverse(arrayobject *self, PyObject *unused)
 {
@@ -1527,6 +1493,38 @@ an array of some other type.");
 
 #endif /* Py_USING_UNICODE */
 
+static PyObject *
+array_reduce(arrayobject *array)
+{
+       PyObject *dict, *result, *list;
+
+       dict = PyObject_GetAttrString((PyObject *)array, "__dict__");
+       if (dict == NULL) {
+               if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+                       return NULL;
+               PyErr_Clear();
+               dict = Py_None;
+               Py_INCREF(dict);
+       }
+       /* Unlike in Python 3.x, we never use the more efficient memory
+        * representation of an array for pickling.  This is unfortunately
+        * necessary to allow array objects to be unpickled by Python 3.x,
+        * since str objects from 2.x are always decoded to unicode in
+        * Python 3.x.
+        */
+       list = array_tolist(array, NULL);
+       if (list == NULL) {
+               Py_DECREF(dict);
+               return NULL;
+       }
+       result = Py_BuildValue(
+               "O(cO)O", Py_TYPE(array), array->ob_descr->typecode, list, dict);
+       Py_DECREF(list);
+       Py_DECREF(dict);
+       return result;
+}
+
+PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
 
 static PyObject *
 array_get_typecode(arrayobject *a, void *closure)
@@ -1583,7 +1581,7 @@ static PyMethodDef array_methods[] = {
        {"read",        (PyCFunction)array_fromfile_as_read,    METH_VARARGS,
         fromfile_doc},
        {"__reduce__",  (PyCFunction)array_reduce,      METH_NOARGS,
-        array_doc},
+        reduce_doc},
        {"remove",      (PyCFunction)array_remove,      METH_O,
         remove_doc},
        {"reverse",     (PyCFunction)array_reverse,     METH_NOARGS,