[Python-checkins] r84403 - in python/branches/py3k: Doc/library/array.rst Lib/multiprocessing/managers.py Lib/sre_compile.py Lib/test/test_array.py Lib/test/test_file.py Lib/test/test_io.py Lib/test/test_memoryio.py Lib/test/test_memoryview.py Lib/test/test_struct.py Lib/wave.py Misc/NEWS Modules/arraymodule.c

antoine.pitrou python-checkins at python.org
Wed Sep 1 22:29:34 CEST 2010


Author: antoine.pitrou
Date: Wed Sep  1 22:29:34 2010
New Revision: 84403

Log:
Issue #8990: array.fromstring() and array.tostring() get renamed to
frombytes() and tobytes(), respectively, to avoid confusion.  Furthermore,
array.frombytes(), array.extend() as well as the array.array()
constructor now accept bytearray objects.  Patch by Thomas Jollans.



Modified:
   python/branches/py3k/Doc/library/array.rst
   python/branches/py3k/Lib/multiprocessing/managers.py
   python/branches/py3k/Lib/sre_compile.py
   python/branches/py3k/Lib/test/test_array.py
   python/branches/py3k/Lib/test/test_file.py
   python/branches/py3k/Lib/test/test_io.py
   python/branches/py3k/Lib/test/test_memoryio.py
   python/branches/py3k/Lib/test/test_memoryview.py
   python/branches/py3k/Lib/test/test_struct.py
   python/branches/py3k/Lib/wave.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/arraymodule.c

Modified: python/branches/py3k/Doc/library/array.rst
==============================================================================
--- python/branches/py3k/Doc/library/array.rst	(original)
+++ python/branches/py3k/Doc/library/array.rst	Wed Sep  1 22:29:34 2010
@@ -60,7 +60,7 @@
    appropriate type.
 
    If given a list or string, the initializer is passed to the new array's
-   :meth:`fromlist`, :meth:`fromstring`, or :meth:`fromunicode` method (see below)
+   :meth:`fromlist`, :meth:`frombytes`, or :meth:`fromunicode` method (see below)
    to add initial items to the array.  Otherwise, the iterable initializer is
    passed to the :meth:`extend` method.
 
@@ -136,6 +136,15 @@
    must be the right type to be appended to the array.
 
 
+.. method:: array.frombytes(s)
+
+   Appends items from the string, interpreting the string as an array of machine
+   values (as if it had been read from a file using the :meth:`fromfile` method).
+
+   .. versionadded:: 3.2
+      :meth:`fromstring` is renamed to :meth:`frombytes` for clarity.
+
+
 .. method:: array.fromfile(f, n)
 
    Read *n* items (as machine values) from the file object *f* and append them to
@@ -151,17 +160,16 @@
    a.append(x)`` except that if there is a type error, the array is unchanged.
 
 
-.. method:: array.fromstring(s)
+.. method:: array.fromstring()
 
-   Appends items from the string, interpreting the string as an array of machine
-   values (as if it had been read from a file using the :meth:`fromfile` method).
+   Deprecated alias for :meth:`frombytes`.
 
 
 .. method:: array.fromunicode(s)
 
    Extends this array with data from the given unicode string.  The array must
    be a type ``'u'`` array; otherwise a :exc:`ValueError` is raised.  Use
-   ``array.fromstring(unicodestring.encode(enc))`` to append Unicode data to an
+   ``array.frombytes(unicodestring.encode(enc))`` to append Unicode data to an
    array of some other type.
 
 
@@ -194,6 +202,16 @@
    Reverse the order of the items in the array.
 
 
+.. method:: array.tobytes()
+
+   Convert the array to an array of machine values and return the bytes
+   representation (the same sequence of bytes that would be written to a file by
+   the :meth:`tofile` method.)
+
+   .. versionadded:: 3.2
+      :meth:`tostring` is renamed to :meth:`tobytes` for clarity.
+
+
 .. method:: array.tofile(f)
 
    Write all items (as machine values) to the file object *f*.
@@ -206,15 +224,13 @@
 
 .. method:: array.tostring()
 
-   Convert the array to an array of machine values and return the string
-   representation (the same sequence of bytes that would be written to a file by
-   the :meth:`tofile` method.)
+   Deprecated alias for :meth:`tobytes`.
 
 
 .. method:: array.tounicode()
 
    Convert the array to a unicode string.  The array must be a type ``'u'`` array;
-   otherwise a :exc:`ValueError` is raised. Use ``array.tostring().decode(enc)`` to
+   otherwise a :exc:`ValueError` is raised. Use ``array.tobytes().decode(enc)`` to
    obtain a unicode string from an array of some other type.
 
 

Modified: python/branches/py3k/Lib/multiprocessing/managers.py
==============================================================================
--- python/branches/py3k/Lib/multiprocessing/managers.py	(original)
+++ python/branches/py3k/Lib/multiprocessing/managers.py	Wed Sep  1 22:29:34 2010
@@ -32,7 +32,7 @@
 #
 
 def reduce_array(a):
-    return array.array, (a.typecode, a.tostring())
+    return array.array, (a.typecode, a.tobytes())
 ForkingPickler.register(array.array, reduce_array)
 
 view_types = [type(getattr({}, name)()) for name in ('items','keys','values')]

Modified: python/branches/py3k/Lib/sre_compile.py
==============================================================================
--- python/branches/py3k/Lib/sre_compile.py	(original)
+++ python/branches/py3k/Lib/sre_compile.py	Wed Sep  1 22:29:34 2010
@@ -343,7 +343,7 @@
     else:
         code = 'I'
     # Convert block indices to byte array of 256 bytes
-    mapping = array.array('b', mapping).tostring()
+    mapping = array.array('b', mapping).tobytes()
     # Convert byte array to word array
     mapping = array.array(code, mapping)
     assert mapping.itemsize == _sre.CODESIZE

Modified: python/branches/py3k/Lib/test/test_array.py
==============================================================================
--- python/branches/py3k/Lib/test/test_array.py	(original)
+++ python/branches/py3k/Lib/test/test_array.py	Wed Sep  1 22:29:34 2010
@@ -11,6 +11,7 @@
 import io
 import math
 import struct
+import warnings
 
 import array
 from array import _array_reconstructor as array_reconstructor
@@ -367,15 +368,35 @@
         self.assertEqual(a, b)
 
     def test_tofromstring(self):
+        nb_warnings = 4
+        with warnings.catch_warnings(record=True) as r:
+            warnings.filterwarnings("always",
+                                    message=r"(to|from)string\(\) is deprecated",
+                                    category=DeprecationWarning)
+            a = array.array(self.typecode, 2*self.example)
+            b = array.array(self.typecode)
+            self.assertRaises(TypeError, a.tostring, 42)
+            self.assertRaises(TypeError, b.fromstring)
+            self.assertRaises(TypeError, b.fromstring, 42)
+            b.fromstring(a.tostring())
+            self.assertEqual(a, b)
+            if a.itemsize>1:
+                self.assertRaises(ValueError, b.fromstring, "x")
+                nb_warnings += 1
+        self.assertEqual(len(r), nb_warnings)
+
+    def test_tofrombytes(self):
         a = array.array(self.typecode, 2*self.example)
         b = array.array(self.typecode)
-        self.assertRaises(TypeError, a.tostring, 42)
-        self.assertRaises(TypeError, b.fromstring)
-        self.assertRaises(TypeError, b.fromstring, 42)
-        b.fromstring(a.tostring())
+        self.assertRaises(TypeError, a.tobytes, 42)
+        self.assertRaises(TypeError, b.frombytes)
+        self.assertRaises(TypeError, b.frombytes, 42)
+        b.frombytes(a.tobytes())
+        c = array.array(self.typecode, bytearray(a.tobytes()))
         self.assertEqual(a, b)
+        self.assertEqual(a, c)
         if a.itemsize>1:
-            self.assertRaises(ValueError, b.fromstring, "x")
+            self.assertRaises(ValueError, b.frombytes, b"x")
 
     def test_repr(self):
         a = array.array(self.typecode, 2*self.example)
@@ -898,8 +919,8 @@
         a = array.array(self.typecode, self.example)
         m = memoryview(a)
         expected = m.tobytes()
-        self.assertEqual(a.tostring(), expected)
-        self.assertEqual(a.tostring()[0], expected[0])
+        self.assertEqual(a.tobytes(), expected)
+        self.assertEqual(a.tobytes()[0], expected[0])
         # Resizing is forbidden when there are buffer exports.
         # For issue 4509, we also check after each error that
         # the array was not modified.
@@ -913,7 +934,7 @@
         self.assertEqual(m.tobytes(), expected)
         self.assertRaises(BufferError, a.fromlist, a.tolist())
         self.assertEqual(m.tobytes(), expected)
-        self.assertRaises(BufferError, a.fromstring, a.tostring())
+        self.assertRaises(BufferError, a.frombytes, a.tobytes())
         self.assertEqual(m.tobytes(), expected)
         if self.typecode == 'u':
             self.assertRaises(BufferError, a.fromunicode, a.tounicode())
@@ -932,7 +953,7 @@
     def test_weakref(self):
         s = array.array(self.typecode, self.example)
         p = weakref.proxy(s)
-        self.assertEqual(p.tostring(), s.tostring())
+        self.assertEqual(p.tobytes(), s.tobytes())
         s = None
         self.assertRaises(ReferenceError, len, p)
 
@@ -1110,6 +1131,23 @@
         upper = int(pow(2, a.itemsize * 8)) - 1
         self.check_overflow(lower, upper)
 
+    def test_bytes_extend(self):
+        s = bytes(self.example)
+
+        a = array.array(self.typecode, self.example)
+        a.extend(s)
+        self.assertEqual(
+            a,
+            array.array(self.typecode, self.example+self.example)
+        )
+
+        a = array.array(self.typecode, self.example)
+        a.extend(bytearray(reversed(s)))
+        self.assertEqual(
+            a,
+            array.array(self.typecode, self.example+self.example[::-1])
+        )
+
 
 class ByteTest(SignedNumberTest):
     typecode = 'b'
@@ -1172,7 +1210,7 @@
                 # On alphas treating the byte swapped bit patters as
                 # floats/doubles results in floating point exceptions
                 # => compare the 8bit string values instead
-                self.assertNotEqual(a.tostring(), b.tostring())
+                self.assertNotEqual(a.tobytes(), b.tobytes())
             b.byteswap()
             self.assertEqual(a, b)
 

Modified: python/branches/py3k/Lib/test/test_file.py
==============================================================================
--- python/branches/py3k/Lib/test/test_file.py	(original)
+++ python/branches/py3k/Lib/test/test_file.py	Wed Sep  1 22:29:34 2010
@@ -44,7 +44,7 @@
         a = array('b', b'x'*10)
         self.f = self.open(TESTFN, 'rb')
         n = self.f.readinto(a)
-        self.assertEquals(b'12', a.tostring()[:n])
+        self.assertEquals(b'12', a.tobytes()[:n])
 
     def testReadinto_text(self):
         # verify readinto refuses text files
@@ -281,7 +281,7 @@
             except ValueError:
                 self.fail("readinto() after next() with supposedly empty "
                           "iteration-buffer failed anyway")
-            line = buf.tostring()
+            line = buf.tobytes()
             if line != testline:
                 self.fail("readinto() after next() with empty buffer "
                           "failed. Got %r, expected %r" % (line, testline))

Modified: python/branches/py3k/Lib/test/test_io.py
==============================================================================
--- python/branches/py3k/Lib/test/test_io.py	(original)
+++ python/branches/py3k/Lib/test/test_io.py	Wed Sep  1 22:29:34 2010
@@ -480,7 +480,7 @@
 
     def test_array_writes(self):
         a = array.array('i', range(10))
-        n = len(a.tostring())
+        n = len(a.tobytes())
         with self.open(support.TESTFN, "wb", 0) as f:
             self.assertEqual(f.write(a), n)
         with self.open(support.TESTFN, "wb") as f:

Modified: python/branches/py3k/Lib/test/test_memoryio.py
==============================================================================
--- python/branches/py3k/Lib/test/test_memoryio.py	(original)
+++ python/branches/py3k/Lib/test/test_memoryio.py	Wed Sep  1 22:29:34 2010
@@ -425,7 +425,7 @@
         a = array.array('b', b"hello world")
         memio = self.ioclass(buf)
         memio.readinto(a)
-        self.assertEqual(a.tostring(), b"1234567890d")
+        self.assertEqual(a.tobytes(), b"1234567890d")
         memio.close()
         self.assertRaises(ValueError, memio.readinto, b)
 

Modified: python/branches/py3k/Lib/test/test_memoryview.py
==============================================================================
--- python/branches/py3k/Lib/test/test_memoryview.py	(original)
+++ python/branches/py3k/Lib/test/test_memoryview.py	Wed Sep  1 22:29:34 2010
@@ -231,7 +231,7 @@
 class BaseArrayMemoryTests(AbstractMemoryTests):
     ro_type = None
     rw_type = lambda self, b: array.array('i', list(b))
-    getitem_type = lambda self, b: array.array('i', list(b)).tostring()
+    getitem_type = lambda self, b: array.array('i', list(b)).tobytes()
     itemsize = array.array('i').itemsize
     format = 'i'
 

Modified: python/branches/py3k/Lib/test/test_struct.py
==============================================================================
--- python/branches/py3k/Lib/test/test_struct.py	(original)
+++ python/branches/py3k/Lib/test/test_struct.py	Wed Sep  1 22:29:34 2010
@@ -430,12 +430,12 @@
 
         # Test without offset
         s.pack_into(writable_buf, 0, test_string)
-        from_buf = writable_buf.tostring()[:len(test_string)]
+        from_buf = writable_buf.tobytes()[:len(test_string)]
         self.assertEqual(from_buf, test_string)
 
         # Test with offset.
         s.pack_into(writable_buf, 10, test_string)
-        from_buf = writable_buf.tostring()[:len(test_string)+10]
+        from_buf = writable_buf.tobytes()[:len(test_string)+10]
         self.assertEqual(from_buf, test_string[:10] + test_string)
 
         # Go beyond boundaries.
@@ -458,12 +458,12 @@
 
         # Test without offset.
         pack_into(writable_buf, 0, test_string)
-        from_buf = writable_buf.tostring()[:len(test_string)]
+        from_buf = writable_buf.tobytes()[:len(test_string)]
         self.assertEqual(from_buf, test_string)
 
         # Test with offset.
         pack_into(writable_buf, 10, test_string)
-        from_buf = writable_buf.tostring()[:len(test_string)+10]
+        from_buf = writable_buf.tobytes()[:len(test_string)+10]
         self.assertEqual(from_buf, test_string[:10] + test_string)
 
         # Go beyond boundaries.

Modified: python/branches/py3k/Lib/wave.py
==============================================================================
--- python/branches/py3k/Lib/wave.py	(original)
+++ python/branches/py3k/Lib/wave.py	Wed Sep  1 22:29:34 2010
@@ -248,7 +248,7 @@
             chunk = chunk.file
             chunk.size_read = chunk.size_read + nitems * self._sampwidth
             data.byteswap()
-            data = data.tostring()
+            data = data.tobytes()
         else:
             data = self._data_chunk.read(nframes * self._framesize)
         if self._convert and data:

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Wed Sep  1 22:29:34 2010
@@ -149,6 +149,11 @@
 Library
 -------
 
+- Issue #8990: array.fromstring() and array.tostring() get renamed to
+  frombytes() and tobytes(), respectively, to avoid confusion.  Furthermore,
+  array.frombytes(), array.extend() as well as the array.array()
+  constructor now accept bytearray objects.  Patch by Thomas Jollans.
+
 - Issue #808164: Fixed socket.close to avoid references to globals, to
   avoid issues when socket.close is called from a __del__ method.
 

Modified: python/branches/py3k/Modules/arraymodule.c
==============================================================================
--- python/branches/py3k/Modules/arraymodule.c	(original)
+++ python/branches/py3k/Modules/arraymodule.c	Wed Sep  1 22:29:34 2010
@@ -1175,7 +1175,7 @@
 
 
 /* Forward */
-static PyObject *array_fromstring(arrayobject *self, PyObject *args);
+static PyObject *array_frombytes(arrayobject *self, PyObject *args);
 
 static PyObject *
 array_fromfile(arrayobject *self, PyObject *args)
@@ -1212,7 +1212,7 @@
     if (args == NULL)
         return NULL;
 
-    res = array_fromstring(self, args);
+    res = array_frombytes(self, args);
     Py_DECREF(args);
     if (res == NULL)
         return NULL;
@@ -1331,45 +1331,84 @@
 \n\
 Convert array to an ordinary list with the same items.");
 
-
 static PyObject *
-array_fromstring(arrayobject *self, PyObject *args)
+frombytes(arrayobject *self, Py_buffer *buffer)
 {
-    char *str;
-    Py_ssize_t n;
     int itemsize = self->ob_descr->itemsize;
-    if (!PyArg_ParseTuple(args, "s#:fromstring", &str, &n))
+    Py_ssize_t n;
+    if (buffer->itemsize != 1) {
+        PyBuffer_Release(buffer);
+        PyErr_SetString(PyExc_TypeError, "string/buffer of bytes required.");
         return NULL;
+    }
+    n = buffer->len;
     if (n % itemsize != 0) {
+        PyBuffer_Release(buffer);
         PyErr_SetString(PyExc_ValueError,
                    "string length not a multiple of item size");
         return NULL;
     }
     n = n / itemsize;
     if (n > 0) {
-    Py_ssize_t old_size = Py_SIZE(self);
+        Py_ssize_t old_size = Py_SIZE(self);
         if ((n > PY_SSIZE_T_MAX - old_size) ||
             ((old_size + n) > PY_SSIZE_T_MAX / itemsize)) {
+                PyBuffer_Release(buffer);
                 return PyErr_NoMemory();
         }
-        if (array_resize(self, old_size + n) == -1)
+        if (array_resize(self, old_size + n) == -1) {
+            PyBuffer_Release(buffer);
             return NULL;
+        }
         memcpy(self->ob_item + old_size * itemsize,
-            str, n * itemsize);
+            buffer->buf, n * itemsize);
     }
+    PyBuffer_Release(buffer);
     Py_INCREF(Py_None);
     return Py_None;
 }
 
+static PyObject *
+array_fromstring(arrayobject *self, PyObject *args)
+{
+    Py_buffer buffer;
+    if (PyErr_WarnEx(PyExc_DeprecationWarning,
+            "fromstring() is deprecated. Use frombytes() instead.", 2) != 0)
+        return NULL;
+    if (!PyArg_ParseTuple(args, "s*:fromstring", &buffer))
+        return NULL;
+    else
+        return frombytes(self, &buffer);
+}
+
 PyDoc_STRVAR(fromstring_doc,
 "fromstring(string)\n\
 \n\
 Appends items from the string, interpreting it as an array of machine\n\
+values, as if it had been read from a file using the fromfile() method).\n\
+\n\
+This method is deprecated. Use frombytes instead.");
+
+
+static PyObject *
+array_frombytes(arrayobject *self, PyObject *args)
+{
+    Py_buffer buffer;
+    if (!PyArg_ParseTuple(args, "y*:frombytes", &buffer))
+        return NULL;
+    else
+        return frombytes(self, &buffer);
+}
+
+PyDoc_STRVAR(frombytes_doc,
+"frombytes(bytestring)\n\
+\n\
+Appends items from the string, interpreting it as an array of machine\n\
 values, as if it had been read from a file using the fromfile() method).");
 
 
 static PyObject *
-array_tostring(arrayobject *self, PyObject *unused)
+array_tobytes(arrayobject *self, PyObject *unused)
 {
     if (Py_SIZE(self) <= PY_SSIZE_T_MAX / self->ob_descr->itemsize) {
         return PyBytes_FromStringAndSize(self->ob_item,
@@ -1379,13 +1418,30 @@
     }
 }
 
-PyDoc_STRVAR(tostring_doc,
-"tostring() -> string\n\
+PyDoc_STRVAR(tobytes_doc,
+"tobytes() -> bytes\n\
 \n\
-Convert the array to an array of machine values and return the string\n\
+Convert the array to an array of machine values and return the bytes\n\
 representation.");
 
 
+static PyObject *
+array_tostring(arrayobject *self, PyObject *unused)
+{
+    if (PyErr_WarnEx(PyExc_DeprecationWarning, 
+            "tostring() is deprecated. Use tobytes() instead.", 2) != 0)
+        return NULL;
+    return array_tobytes(self, unused);
+}
+
+PyDoc_STRVAR(tostring_doc,
+"tostring() -> bytes\n\
+\n\
+Convert the array to an array of machine values and return the bytes\n\
+representation.\n\
+\n\
+This method is deprecated. Use tobytes instead.");
+
 
 static PyObject *
 array_fromunicode(arrayobject *self, PyObject *args)
@@ -1420,7 +1476,7 @@
 \n\
 Extends this array with data from the unicode string ustr.\n\
 The array must be a unicode type array; otherwise a ValueError\n\
-is raised.  Use array.fromstring(ustr.decode(...)) to\n\
+is raised.  Use array.frombytes(ustr.decode(...)) to\n\
 append Unicode data to an array of some other type.");
 
 
@@ -1927,7 +1983,7 @@
         return result;
     }
 
-    array_str = array_tostring(array, NULL);
+    array_str = array_tobytes(array, NULL);
     if (array_str == NULL) {
         Py_DECREF(dict);
         return NULL;
@@ -1983,6 +2039,8 @@
      fromlist_doc},
     {"fromstring",      (PyCFunction)array_fromstring,  METH_VARARGS,
      fromstring_doc},
+    {"frombytes",       (PyCFunction)array_frombytes,   METH_VARARGS,
+     frombytes_doc},
     {"fromunicode",     (PyCFunction)array_fromunicode, METH_VARARGS,
      fromunicode_doc},
     {"index",           (PyCFunction)array_index,       METH_O,
@@ -2005,6 +2063,8 @@
      tolist_doc},
     {"tostring",        (PyCFunction)array_tostring,    METH_NOARGS,
      tostring_doc},
+    {"tobytes",         (PyCFunction)array_tobytes,     METH_NOARGS,
+     tobytes_doc},
     {"tounicode",   (PyCFunction)array_tounicode,       METH_NOARGS,
      tounicode_doc},
     {NULL,              NULL}           /* sentinel */
@@ -2386,7 +2446,7 @@
                     Py_DECREF(a);
                     return NULL;
                 }
-                v = array_fromstring((arrayobject *)a,
+                v = array_frombytes((arrayobject *)a,
                                          t_initial);
                 Py_DECREF(t_initial);
                 if (v == NULL) {


More information about the Python-checkins mailing list