mirror of https://github.com/python/cpython
SF feature request #992967: array.array objects should support sequences.
Made the constructor accept general iterables.
This commit is contained in:
parent
df7a208ff7
commit
6ab78cd0c0
|
@ -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}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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\
|
||||
|
|
Loading…
Reference in New Issue