From b0900e6a217480def244b0b55d718ce705e8e73a Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Thu, 16 Dec 2004 16:23:40 +0000 Subject: [PATCH] SF #1085304: Make array.array pickle-able --- Lib/test/test_array.py | 19 +++++++++++++++++++ Misc/NEWS | 2 ++ Modules/arraymodule.c | 25 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index b15298fbfed..c24b41b931a 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -7,6 +7,10 @@ import unittest from test import test_support from weakref import proxy import array, cStringIO, math +from cPickle import loads, dumps + +class ArraySubclass(array.array): + pass tests = [] # list to accumulate all tests typecodes = "cubBhHiIlLfd" @@ -81,6 +85,21 @@ class BaseTest(unittest.TestCase): self.assertNotEqual(id(a), id(b)) self.assertEqual(a, b) + def test_pickle(self): + for protocol in (0, 1, 2): + a = array.array(self.typecode, self.example) + b = loads(dumps(a, protocol)) + self.assertNotEqual(id(a), id(b)) + self.assertEqual(a, b) + + a = ArraySubclass(self.typecode, self.example) + a.x = 10 + b = loads(dumps(a, protocol)) + self.assertNotEqual(id(a), id(b)) + self.assertEqual(a, b) + self.assertEqual(a.x, b.x) + self.assertEqual(type(a), type(b)) + def test_insert(self): a = array.array(self.typecode, self.example) a.insert(0, self.example[0]) diff --git a/Misc/NEWS b/Misc/NEWS index 6bf7ab4dbcd..570addacffd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,8 @@ Core and builtins Extension Modules ----------------- +- array.array objects are now picklable. + - the cPickle module no longer accepts the deprecated None option in the args tuple returned by __reduce__(). diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 7ed3b73d536..64303330012 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1132,6 +1132,29 @@ 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); + } + result = Py_BuildValue("O(cs#)O", + array->ob_type, + array->ob_descr->typecode, + array->ob_item, + array->ob_size * array->ob_descr->itemsize, + dict); + Py_DECREF(dict); + return result; +} + +PyDoc_STRVAR(array_doc, "Return state information for pickling."); + static PyObject * array_reverse(arrayobject *self, PyObject *unused) { @@ -1490,6 +1513,8 @@ PyMethodDef array_methods[] = { pop_doc}, {"read", (PyCFunction)array_fromfile, METH_VARARGS, fromfile_doc}, + {"__reduce__", (PyCFunction)array_reduce, METH_NOARGS, + array_doc}, {"remove", (PyCFunction)array_remove, METH_O, remove_doc}, {"reverse", (PyCFunction)array_reverse, METH_NOARGS,