]> granicus.if.org Git - python/commitdiff
SF feature request #992967: array.array objects should support sequences.
authorRaymond Hettinger <python@rcn.com>
Sun, 29 Aug 2004 07:50:43 +0000 (07:50 +0000)
committerRaymond Hettinger <python@rcn.com>
Sun, 29 Aug 2004 07:50:43 +0000 (07:50 +0000)
Made the constructor accept general iterables.

Doc/lib/libarray.tex
Lib/test/test_array.py
Misc/NEWS
Modules/arraymodule.c

index 6fd8b0c9c65a2ffe5e397281738f35a6a9818937..e168e54256ca027b6a01ca04056f71e11be1b4c7 100644 (file)
@@ -41,10 +41,14 @@ The module defines the following type:
 \begin{funcdesc}{array}{typecode\optional{, initializer}}
 Return a new array whose items are restricted by \var{typecode},
 and initialized from the optional \var{initializer} value, which
-must be a list or a string.  The list or string is passed to the
+must be a list, string, or iterable over elements of the
+appropriate type.
+\versionchanged[Formerly, only lists or strings were accepted]{2.4}
+If given a list or string, the initializer is passed to the
 new array's \method{fromlist()}, \method{fromstring()}, or
 \method{fromunicode()} method (see below) to add initial items to
-the array.
+the array.  Otherwise, the iterable initializer is passed to the
+\method{extend()} method.
 \end{funcdesc}
 
 \begin{datadesc}{ArrayType}
index d03618d04fa79c86385b9784870ade215a6e94f4..b15298fbfedc07b17540b53787d5e7ca70100185 100755 (executable)
@@ -600,6 +600,26 @@ class BaseTest(unittest.TestCase):
             array.array(self.typecode, self.example+self.example[::-1])
         )
 
+    def test_constructor_with_iterable_argument(self):
+        a = array.array(self.typecode, iter(self.example))
+        b = array.array(self.typecode, self.example)
+        self.assertEqual(a, b)
+
+        # non-iterable argument
+        self.assertRaises(TypeError, array.array, self.typecode, 10)
+
+        # pass through errors raised in __iter__
+        class A:
+            def __iter__(self):
+                raise UnicodeError
+        self.assertRaises(UnicodeError, array.array, self.typecode, A())
+
+        # pass through errors raised in next()
+        def B():
+            raise UnicodeError
+            yield None
+        self.assertRaises(UnicodeError, array.array, self.typecode, B())
+
     def test_coveritertraverse(self):
         try:
             import gc
@@ -904,8 +924,20 @@ class DoubleTest(FPTest):
     minitemsize = 8
 tests.append(DoubleTest)
 
-def test_main():
+def test_main(verbose=None):
+    import sys
+
     test_support.run_unittest(*tests)
 
-if __name__=="__main__":
-    test_main()
+    # verify reference counting
+    if verbose and hasattr(sys, "gettotalrefcount"):
+        import gc
+        counts = [None] * 5
+        for i in xrange(len(counts)):
+            test_support.run_unittest(*tests)
+            gc.collect()
+            counts[i] = sys.gettotalrefcount()
+        print counts
+
+if __name__ == "__main__":
+    test_main(verbose=True)
index c7478d49cacc5983f52178aff880518902b1675c..d294440db5285c76007ba841d3d964f2bbd234d8 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -732,8 +732,8 @@ Extension modules
 - array objects now support the copy module.  Also, their resizing
   scheme has been updated to match that used for list objects.  This improves
   the performance (speed and memory usage) of append() operations.
-  Also, array.extend() now accepts any iterable argument for repeated
-  appends without needing to create another temporary array.
+  Also, array.array() and array.extend() now accept any iterable argument
+  for repeated appends without needing to create another temporary array.
 
 - cStringIO.writelines() now accepts any iterable argument and writes
   the lines one at a time rather than joining them and writing once.
index ab904bdce5ac9e837155526404f932d6444d8de9..7ed3b73d536ba41df6ad98be215f9cf9b943016d 100644 (file)
@@ -1772,7 +1772,7 @@ static PyObject *
 array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
        char c;
-       PyObject *initial = NULL;
+       PyObject *initial = NULL, *it = NULL;
        struct arraydescr *descr;
 
        if (kwds != NULL) {
@@ -1793,9 +1793,15 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
        if (!(initial == NULL || PyList_Check(initial)
              || PyString_Check(initial) || PyTuple_Check(initial)
              || (c == 'u' && PyUnicode_Check(initial)))) {
-               PyErr_SetString(PyExc_TypeError,
-                   "array initializer must be list or string");
-               return NULL;
+               it = PyObject_GetIter(initial);
+               if (it == NULL)
+                       return NULL;
+               /* We set initial to NULL so that the subsequent code
+                  will create an empty array of the appropriate type
+                  and afterwards we can use array_iter_extend to populate
+                  the array.
+               */
+               initial = NULL;
        }
        for (descr = descriptors; descr->typecode != '\0'; descr++) {
                if (descr->typecode == c) {
@@ -1859,6 +1865,14 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
                                }
 #endif
                        }
+                       if (it != NULL) {
+                               if (array_iter_extend((arrayobject *)a, it) == -1) {
+                                       Py_DECREF(it);
+                                       Py_DECREF(a);
+                                       return NULL;
+                               }
+                               Py_DECREF(it);
+                       }
                        return a;
                }
        }
@@ -1899,8 +1913,8 @@ PyDoc_STRVAR(arraytype_doc,
 "array(typecode [, initializer]) -> array\n\
 \n\
 Return a new array whose items are restricted by typecode, and\n\
-initialized from the optional initializer value, which must be a list\n\
-or a string.\n\
+initialized from the optional initializer value, which must be a list,\n\
+string. or iterable over elements of the appropriate type.\n\
 \n\
 Arrays represent basic values and behave very much like lists, except\n\
 the type of objects stored in them is constrained.\n\