Index: Modules/arraymodule.c =================================================================== --- Modules/arraymodule.c (revision 73401) +++ Modules/arraymodule.c (working copy) @@ -389,7 +389,10 @@ return 0; } -/* Description of types */ +/* Description of types. + Don't forget to update allowed_typecode in array_reduce() and + typecode_to_mformat_code() if you add a new typecode. +*/ static struct arraydescr descriptors[] = { {'c', sizeof(char), c_getitem, c_setitem}, {'b', sizeof(char), b_getitem, b_setitem}, @@ -626,7 +629,7 @@ } static PyObject * -array_copy(arrayobject *a, PyObject *unused) +array_copy(arrayobject *a) { return array_slice(a, 0, Py_SIZE(a)); } @@ -1053,6 +1056,7 @@ { Py_ssize_t i; PyObject *v; + if (!PyArg_ParseTuple(args, "nO:insert", &i, &v)) return NULL; return ins(self, i, v); @@ -1065,7 +1069,7 @@ static PyObject * -array_buffer_info(arrayobject *self, PyObject *unused) +array_buffer_info(arrayobject *self) { PyObject* retval = NULL; retval = PyTuple_New(2); @@ -1100,7 +1104,7 @@ static PyObject * -array_byteswap(arrayobject *self, PyObject *unused) +array_byteswap(arrayobject *self) { char *p; Py_ssize_t i; @@ -1157,42 +1161,8 @@ 4, or 8 bytes in size, RuntimeError is raised."); static PyObject * -array_reduce(arrayobject *array) +array_reverse(arrayobject *self) { - 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) -{ register Py_ssize_t itemsize = self->ob_descr->itemsize; register char *p, *q; /* little buffer to hold items while swapping */ @@ -1376,7 +1346,7 @@ static PyObject * -array_tolist(arrayobject *self, PyObject *unused) +array_tolist(arrayobject *self) { PyObject *list = PyList_New(Py_SIZE(self)); Py_ssize_t i; @@ -1443,7 +1413,7 @@ static PyObject * -array_tostring(arrayobject *self, PyObject *unused) +array_tostring(arrayobject *self) { if (self->ob_size <= PY_SSIZE_T_MAX / self->ob_descr->itemsize) { return PyString_FromStringAndSize(self->ob_item, @@ -1507,7 +1477,7 @@ static PyObject * -array_tounicode(arrayobject *self, PyObject *unused) +array_tounicode(arrayobject *self) { if (self->ob_descr->typecode != 'u') { PyErr_SetString(PyExc_ValueError, @@ -1528,7 +1498,421 @@ #endif /* Py_USING_UNICODE */ +/*********************** Pickling support ************************/ + +enum machine_format_code { + UNKNOWN_FORMAT = -1, + CHARACTER = 0, + UNSIGNED_INT8 = 1, + SIGNED_INT8 = 2, + UNSIGNED_INT16_LE = 3, + UNSIGNED_INT16_BE = 4, + SIGNED_INT16_LE = 5, + SIGNED_INT16_BE = 6, + UNSIGNED_INT32_LE = 7, + UNSIGNED_INT32_BE = 8, + SIGNED_INT32_LE = 9, + SIGNED_INT32_BE = 10, + UNSIGNED_INT64_LE = 11, + UNSIGNED_INT64_BE = 12, + SIGNED_INT64_LE = 13, + SIGNED_INT64_BE = 14, + IEEE_754_FLOAT_LE = 15, + IEEE_754_FLOAT_BE = 16, + IEEE_754_DOUBLE_LE = 17, + IEEE_754_DOUBLE_BE = 18, + UTF16_LE = 19, + UTF16_BE = 20, + UTF32_LE = 21, + UTF32_BE = 22 +}; +#define MACHINE_FORMAT_CODE_MIN -1 +#define MACHINE_FORMAT_CODE_MAX 22 + +static const struct { + size_t size; + int is_signed; + int is_big_endian; +} mformat_descriptors[] = { + {1, 1, 0}, /* 0: CHARACTER */ + {1, 0, 0}, /* 1: UNSIGNED_INT8 */ + {1, 1, 0}, /* 2: SIGNED_INT8 */ + {2, 0, 0}, /* 3: UNSIGNED_INT16_LE */ + {2, 0, 1}, /* 4: UNSIGNED_INT16_BE */ + {2, 1, 0}, /* 5: SIGNED_INT16_LE */ + {2, 1, 1}, /* 6: SIGNED_INT16_BE */ + {4, 0, 0}, /* 7: UNSIGNED_INT32_LE */ + {4, 0, 1}, /* 8: UNSIGNED_INT32_BE */ + {4, 1, 0}, /* 9: SIGNED_INT32_LE */ + {4, 1, 1}, /* 10: SIGNED_INT32_BE */ + {8, 0, 0}, /* 11: UNSIGNED_INT64_LE */ + {8, 0, 1}, /* 12: UNSIGNED_INT64_BE */ + {8, 1, 0}, /* 13: SIGNED_INT64_LE */ + {8, 1, 1}, /* 14: SIGNED_INT64_BE */ + {4, 0, 0}, /* 15: IEEE_754_FLOAT_LE */ + {4, 0, 1}, /* 16: IEEE_754_FLOAT_BE */ + {8, 0, 0}, /* 17: IEEE_754_DOUBLE_LE */ + {8, 0, 1}, /* 18: IEEE_754_DOUBLE_BE */ + {4, 0, 0}, /* 19: UTF16_LE */ + {4, 0, 1}, /* 20: UTF16_BE */ + {8, 0, 0}, /* 21: UTF32_LE */ + {8, 0, 1} /* 22: UTF32_BE */ +}; + +static enum machine_format_code +typecode_to_mformat_code(int typecode) +{ +#ifdef BYTEORDER_IS_BIG_ENDIAN + const int is_big_endian = 1; +#else + const int is_big_endian = 0; +#endif + size_t intsize; + int is_signed; + + switch (typecode) { + case 'c': + return CHARACTER; + case 'b': + return SIGNED_INT8; + case 'B': + return UNSIGNED_INT8; + +#ifdef Py_USING_UNICODE + case 'u': + if (sizeof(Py_UNICODE) == 2) { + return UTF16_LE + is_big_endian; + } + if (sizeof(Py_UNICODE) == 4) { + return UTF32_LE + is_big_endian; + } + return UNKNOWN_FORMAT; +#endif + case 'f': + if (sizeof(float) == 4) { + const float y = 16711938.0; + if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0) + return IEEE_754_FLOAT_BE; + if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0) + return IEEE_754_FLOAT_LE; + } + return UNKNOWN_FORMAT; + + case 'd': + if (sizeof(double) == 8) { + const double x = 9006104071832581.0; + if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0) + return IEEE_754_DOUBLE_BE; + if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0) + return IEEE_754_DOUBLE_LE; + } + return UNKNOWN_FORMAT; + + /* Integers */ + case 'h': + intsize = sizeof(short); + is_signed = 1; + break; + case 'H': + intsize = sizeof(short); + is_signed = 0; + break; + case 'i': + intsize = sizeof(int); + is_signed = 1; + break; + case 'I': + intsize = sizeof(int); + is_signed = 0; + break; + case 'l': + intsize = sizeof(long); + is_signed = 1; + break; + case 'L': + intsize = sizeof(long); + is_signed = 0; + break; + default: + return UNKNOWN_FORMAT; + } + switch (intsize) { + case 2: + return UNSIGNED_INT16_LE + is_big_endian + (2 * is_signed); + case 4: + return UNSIGNED_INT32_LE + is_big_endian + (2 * is_signed); + case 8: + return UNSIGNED_INT64_LE + is_big_endian + (2 * is_signed); + default: + return UNKNOWN_FORMAT; + } +} + +/* Forward declaration. */ +static PyObject *array_new(PyTypeObject *type, PyObject *args, PyObject *kwds); + static PyObject * +make_array(PyTypeObject *arraytype, int typecode, PyObject *items) +{ + PyObject *new_args; + PyObject *array_obj; + PyObject *typecode_obj; + + assert(arraytype != NULL); + assert(items != NULL); + + typecode_obj = PyString_FromStringAndSize((char *)&typecode, 1); + if (typecode_obj == NULL) + return NULL; + + new_args = PyTuple_New(2); + if (new_args == NULL) + return NULL; + Py_INCREF(items); + PyTuple_SET_ITEM(new_args, 0, typecode_obj); + PyTuple_SET_ITEM(new_args, 1, items); + + array_obj = array_new(arraytype, new_args, NULL); + Py_DECREF(new_args); + if (array_obj == NULL) + return NULL; + + return array_obj; +} + +static PyObject * +array_reconstructor(PyObject *self, PyObject *args) +{ + PyTypeObject *arraytype; + PyObject *items; + PyObject *converted_items; + PyObject *result; + int typecode; + enum machine_format_code mformat_code; + const char allowed_typecode[] = "cbBuhHiIlLfd"; + + if (!PyArg_ParseTuple(args, "OciO:array._array_reconstructor", + &arraytype, &typecode, &mformat_code, &items)) + return NULL; + + if (!PyType_Check(arraytype)) { + PyErr_Format(PyExc_TypeError, + "first argument must a type object, not %.200s", + Py_TYPE(arraytype)->tp_name); + return NULL; + } + if (!PyType_IsSubtype(arraytype, &Arraytype)) { + PyErr_Format(PyExc_TypeError, + "%.200s is not a subtype of %.200s", + arraytype->tp_name, Arraytype.tp_name); + return NULL; + } + if (strchr(allowed_typecode, typecode) == NULL) { + PyErr_SetString(PyExc_ValueError, + "second argument must be a valid typecode"); + return NULL; + } + if (mformat_code < MACHINE_FORMAT_CODE_MIN || + mformat_code > MACHINE_FORMAT_CODE_MAX) { + PyErr_SetString(PyExc_ValueError, + "third argument must be a valid machine format code."); + return NULL; + } + if (mformat_code != UNKNOWN_FORMAT && !PyString_Check(items)) { + PyErr_Format(PyExc_TypeError, + "fourth argument should be bytes, not %.200s", + Py_TYPE(items)->tp_name); + return NULL; + } + + /* Fast path: No decoding has to be done or items is a list */ + if (mformat_code == typecode_to_mformat_code(typecode) || + mformat_code == UNKNOWN_FORMAT || mformat_code == CHARACTER) { + return make_array(arraytype, typecode, items); + } + + /* Slow path: Decode the byte string according to the given machine + format code. This occurs when the computer unpickling the array + object is architecturally different from the one that pickled the + array. */ + + if (Py_SIZE(items) % mformat_descriptors[mformat_code].size != 0) { + PyErr_SetString(PyExc_ValueError, + "string length not a multiple of item size"); + return NULL; + } + switch (mformat_code) { + case IEEE_754_FLOAT_LE: + case IEEE_754_FLOAT_BE: { + int i; + int le = (mformat_code == IEEE_754_FLOAT_LE) ? 1 : 0; + Py_ssize_t itemcount = Py_SIZE(items) / 4; + const unsigned char *memstr = \ + (unsigned char *)PyString_AS_STRING(items); + + converted_items = PyList_New(itemcount); + if (converted_items == NULL) + return NULL; + for (i = 0; i < itemcount; i++) { + PyObject *pyfloat = PyFloat_FromDouble( + _PyFloat_Unpack4(&memstr[i * 4], le)); + if (pyfloat == NULL) + return NULL; + PyList_SET_ITEM(converted_items, i, pyfloat); + } + break; + } + case IEEE_754_DOUBLE_LE: + case IEEE_754_DOUBLE_BE: { + int i; + int le = (mformat_code == IEEE_754_DOUBLE_LE) ? 1 : 0; + Py_ssize_t itemcount = Py_SIZE(items) / 8; + const unsigned char *memstr = \ + (unsigned char *)PyString_AS_STRING(items); + + converted_items = PyList_New(itemcount); + if (converted_items == NULL) + return NULL; + for (i = 0; i < itemcount; i++) { + PyObject *pyfloat = PyFloat_FromDouble( + _PyFloat_Unpack8(&memstr[i * 8], le)); + if (pyfloat == NULL) + return NULL; + PyList_SET_ITEM(converted_items, i, pyfloat); + } + break; + } + case UTF16_LE: + case UTF16_BE: { + int byteorder = (mformat_code == UTF16_LE) ? -1 : 1; + converted_items = PyUnicode_DecodeUTF16( + PyString_AS_STRING(items), Py_SIZE(items), + "strict", &byteorder); + if (converted_items == NULL) + return NULL; + break; + } + case UTF32_LE: + case UTF32_BE: { + int byteorder = (mformat_code == UTF32_LE) ? -1 : 1; + converted_items = PyUnicode_DecodeUTF32( + PyString_AS_STRING(items), Py_SIZE(items), + "strict", &byteorder); + if (converted_items == NULL) + return NULL; + break; + } + + case UNSIGNED_INT8: + case SIGNED_INT8: + case UNSIGNED_INT16_LE: + case UNSIGNED_INT16_BE: + case SIGNED_INT16_LE: + case SIGNED_INT16_BE: + case UNSIGNED_INT32_LE: + case UNSIGNED_INT32_BE: + case SIGNED_INT32_LE: + case SIGNED_INT32_BE: + case UNSIGNED_INT64_LE: + case UNSIGNED_INT64_BE: + case SIGNED_INT64_LE: + case SIGNED_INT64_BE: { + int i; + const int width = mformat_descriptors[mformat_code].size; + Py_ssize_t itemcount = Py_SIZE(items) / width; + const unsigned char *memstr = \ + (unsigned char *)PyString_AS_STRING(items); + + converted_items = PyList_New(itemcount); + if (converted_items == NULL) + return NULL; + for (i = 0; i < itemcount; i++) { + PyObject *pylong; + + pylong = _PyLong_FromByteArray( + &memstr[i * width], + width, + !mformat_descriptors[mformat_code].is_big_endian, + mformat_descriptors[mformat_code].is_signed); + if (pylong == NULL) + return NULL; + PyList_SET_ITEM(converted_items, i, pylong); + } + break; + } + case CHARACTER: + case UNKNOWN_FORMAT: + /* Impossible, but needed to shut up GCC about the unhandled + enumeration value.*/ + return NULL; + } + + result = make_array(arraytype, typecode, converted_items); + Py_DECREF(converted_items); + return result; +} + +static PyObject * +array_reduce(arrayobject *array) +{ + PyObject *dict; + PyObject *result; + PyObject *array_str; + int typecode = array->ob_descr->typecode; + int mformat_code; + static PyObject *array_reconstructor = NULL; + + if (array_reconstructor == NULL) { + PyObject *array_module = PyImport_ImportModule("array"); + if (array_module == NULL) + return NULL; + array_reconstructor = PyObject_GetAttrString( + array_module, + "_array_reconstructor"); + Py_DECREF(array_module); + if (array_reconstructor == NULL) + return NULL; + } + + dict = PyObject_GetAttrString((PyObject *)array, "__dict__"); + if (dict == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + return NULL; + PyErr_Clear(); + dict = Py_None; + Py_INCREF(dict); + } + + mformat_code = typecode_to_mformat_code(typecode); + if (mformat_code == UNKNOWN_FORMAT) { + /* We got something wierd; so convert the array to a list + to get a platform-independent representation. */ + PyObject *list; + list = array_tolist(array); + if (list == NULL) + return NULL; + result = Py_BuildValue("O(cO)O", + Py_TYPE(array), + typecode, + list, + dict); + Py_DECREF(list); + Py_DECREF(dict); + return result; + } + + array_str = array_tostring(array); + if (array == NULL) + return NULL; + result = Py_BuildValue("O(OciN)O", array_reconstructor, Py_TYPE(array), + typecode, mformat_code, array_str, dict); + Py_DECREF(dict); + return result; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * array_get_typecode(arrayobject *a, void *closure) { char tc = a->ob_descr->typecode; @@ -1583,7 +1967,7 @@ {"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, @@ -1620,13 +2004,13 @@ } if (typecode == 'c') - v = array_tostring(a, NULL); + v = array_tostring(a); #ifdef Py_USING_UNICODE else if (typecode == 'u') - v = array_tounicode(a, NULL); + v = array_tounicode(a); #endif else - v = array_tolist(a, NULL); + v = array_tolist(a); t = PyObject_Repr(v); Py_XDECREF(v); @@ -2214,14 +2598,15 @@ }; + /*********************** Install Module **************************/ -/* No functions in array module. */ static PyMethodDef a_methods[] = { - {NULL, NULL, 0, NULL} /* Sentinel */ + {"_array_reconstructor", array_reconstructor, METH_VARARGS, + PyDoc_STR("Internal. Used for pickling support.")}, + {NULL, NULL, 0, NULL} /* Sentinel */ }; - PyMODINIT_FUNC initarray(void) { Index: Lib/test/test_array.py =================================================================== --- Lib/test/test_array.py (revision 73401) +++ Lib/test/test_array.py (working copy) @@ -5,10 +5,23 @@ import unittest from test import test_support -from weakref import proxy -import array, cStringIO -from cPickle import loads, dumps, HIGHEST_PROTOCOL +import array +from array import _array_reconstructor as array_reconstructor +import weakref +import struct + +try: + import cPickle as pickle +except ImportError: + import pickle + +try: + import cStringIO as StringIO +except ImportError: + import StringIO + + class ArraySubclass(array.array): pass @@ -29,6 +42,138 @@ tests.append(BadConstructorTest) +# Machine format codes. +# +# Search for "enum machine_format_code" in Modules/arraymodule.c to find the +# authoritative values. +UNKNOWN_FORMAT = -1 +CHARACTER = 0 +UNSIGNED_INT8 = 1 +SIGNED_INT8 = 2 +UNSIGNED_INT16_LE = 3 +UNSIGNED_INT16_BE = 4 +SIGNED_INT16_LE = 5 +SIGNED_INT16_BE = 6 +UNSIGNED_INT32_LE = 7 +UNSIGNED_INT32_BE = 8 +SIGNED_INT32_LE = 9 +SIGNED_INT32_BE = 10 +UNSIGNED_INT64_LE = 11 +UNSIGNED_INT64_BE = 12 +SIGNED_INT64_LE = 13 +SIGNED_INT64_BE = 14 +IEEE_754_FLOAT_LE = 15 +IEEE_754_FLOAT_BE = 16 +IEEE_754_DOUBLE_LE = 17 +IEEE_754_DOUBLE_BE = 18 +UTF16_LE = 19 +UTF16_BE = 20 +UTF32_LE = 21 +UTF32_BE = 22 + +class ArrayReconstructorTest(unittest.TestCase): + + def test_error(self): + self.assertRaises(TypeError, array_reconstructor, + "", "c", 0, "") + self.assertRaises(TypeError, array_reconstructor, + str, "c", 0, "") + self.assertRaises(TypeError, array_reconstructor, + array.array, "c", '', "") + self.assertRaises(TypeError, array_reconstructor, + array.array, "c", 0, 0) + self.assertRaises(ValueError, array_reconstructor, + array.array, "?", 0, "") + self.assertRaises(ValueError, array_reconstructor, + array.array, "c", -1000, "") + self.assertRaises(ValueError, array_reconstructor, + array.array, "c", 1000, "") + self.assertRaises(ValueError, array_reconstructor, + array.array, "d", 16, "a") + + def test_string(self): + a = array.array('c', "spam") + b = array_reconstructor(array.array, 'c', CHARACTER, "spam") + self.assertEqual(a, b) + + def test_numbers(self): + testcases = ( + (['B', 'H', 'I', 'L'], UNSIGNED_INT8, '=BBBB', + [0x80, 0x7f, 0, 0xff]), + (['b', 'h', 'i', 'l'], SIGNED_INT8, '=bbb', + [-0x80, 0x7f, 0]), + (['H', 'I', 'L'], UNSIGNED_INT16_LE, 'HHHH', + [0x8000, 0x7fff, 0, 0xffff]), + (['h', 'i', 'l'], SIGNED_INT16_LE, 'hhh', + [-0x8000, 0x7fff, 0]), + (['I', 'L'], UNSIGNED_INT32_LE, 'iiii', + [1<<31, (1<<31)-1, 0, (1<<32)-1]), + (['i', 'l'], SIGNED_INT32_LE, 'iii', + [-1<<31, (1<<31)-1, 0]), + (['L'], UNSIGNED_INT64_LE, 'QQQQ', + [1<<63, (1<<63)-1, 0, (1<<64)-1]), + (['l'], SIGNED_INT64_LE, 'qqq', + [-1<<63, (1<<63)-1, 0]), + (['f'], IEEE_754_FLOAT_LE, 'ffff', + [16711938.0, float('inf'), float('-inf'), -0.0]), + (['d'], IEEE_754_DOUBLE_LE, 'dddd', + [9006104071832581.0, float('inf'), float('-inf'), -0.0]) + ) + for testcase in testcases: + valid_typecodes, mformat_code, struct_fmt, values = testcase + arraystr = struct.pack(struct_fmt, *values) + for typecode in valid_typecodes: + a = array.array(typecode, values) + b = array_reconstructor( + array.array, typecode, mformat_code, arraystr) + self.assertEqual(a, b, + msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase)) + itemlist = a.tolist() + c = array_reconstructor( + array.array, typecode, UNKNOWN_FORMAT, itemlist) + self.assertEqual(a, b) + + def test_unicode(self): + teststr = u"Bonne Journ\xe9e \U0002030a\U00020347" + testcases = ( + (UTF16_LE, "UTF-16-LE"), + (UTF16_BE, "UTF-16-BE"), + (UTF32_LE, "UTF-32-LE"), + (UTF32_BE, "UTF-32-BE") + ) + for testcase in testcases: + mformat_code, encoding = testcase + a = array.array('u', teststr) + b = array_reconstructor( + array.array, 'u', mformat_code, teststr.encode(encoding)) + self.assertEqual(a, b, + msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase)) + + a = array.array('u', teststr) + charlist = a.tolist() + b = array_reconstructor(array.array, 'u', UNKNOWN_FORMAT, charlist) + self.assertEqual(a, b) + + +tests.append(ArrayReconstructorTest) + + class BaseTest(unittest.TestCase): # Required class attributes (provided by subclasses # typecode: the typecode to test @@ -97,30 +242,30 @@ self.assertEqual(a, b) def test_pickle(self): - for protocol in range(HIGHEST_PROTOCOL + 1): + for protocol in range(pickle.HIGHEST_PROTOCOL + 1): a = array.array(self.typecode, self.example) - b = loads(dumps(a, protocol)) + b = pickle.loads(pickle.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)) + b = pickle.loads(pickle.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_pickle_for_empty_array(self): - for protocol in range(HIGHEST_PROTOCOL + 1): + for protocol in range(pickle.HIGHEST_PROTOCOL + 1): a = array.array(self.typecode) - b = loads(dumps(a, protocol)) + b = pickle.loads(pickle.dumps(a, protocol)) self.assertNotEqual(id(a), id(b)) self.assertEqual(a, b) a = ArraySubclass(self.typecode) a.x = 10 - b = loads(dumps(a, protocol)) + b = pickle.loads(pickle.dumps(a, protocol)) self.assertNotEqual(id(a), id(b)) self.assertEqual(a, b) self.assertEqual(a.x, b.x) @@ -162,7 +307,7 @@ def test_tofromfile(self): a = array.array(self.typecode, 2*self.example) self.assertRaises(TypeError, a.tofile) - self.assertRaises(TypeError, a.tofile, cStringIO.StringIO()) + self.assertRaises(TypeError, a.tofile, StringIO.StringIO()) test_support.unlink(test_support.TESTFN) f = open(test_support.TESTFN, 'wb') try: @@ -174,7 +319,7 @@ self.assertRaises( TypeError, b.fromfile, - cStringIO.StringIO(), len(self.example) + StringIO.StringIO(), len(self.example) ) b.fromfile(f, len(self.example)) self.assertEqual(b, array.array(self.typecode, self.example)) @@ -722,7 +867,7 @@ def test_weakref(self): s = array.array(self.typecode, self.example) - p = proxy(s) + p = weakref.proxy(s) self.assertEqual(p.tostring(), s.tostring()) s = None self.assertRaises(ReferenceError, len, p)