Commit 99866336 authored by Martin v. Löwis's avatar Martin v. Löwis

Patch 520694: arraymodule.c improvements:

- make array.array a type
- add Py_UNICODE arrays
- support +=, *=
parent 272cb40e
......@@ -5,7 +5,7 @@
\modulesynopsis{Efficient arrays of uniformly typed numeric values.}
This module defines a new object type which can efficiently represent
This module defines an object type which can efficiently represent
an array of basic values: characters, integers, floating point
numbers. Arrays\index{arrays} are sequence types and behave very much
like lists, except that the type of objects stored in them is
......@@ -17,6 +17,7 @@ codes are defined:
\lineiii{'c'}{character}{1}
\lineiii{'b'}{signed int}{1}
\lineiii{'B'}{unsigned int}{1}
\lineiii{'u'}{Unicode character}{2}
\lineiii{'h'}{signed int}{2}
\lineiii{'H'}{unsigned int}{2}
\lineiii{'i'}{signed int}{2}
......@@ -35,23 +36,25 @@ Python long integers when retrieved, because Python's plain integer
type cannot represent the full range of C's unsigned (long) integers.
The module defines the following function and type object:
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 new array's
\method{fromlist()} or \method{fromstring()} method (see below) to add
initial items to the array.
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
new array's \method{fromlist()}, \method{fromstring()}, or
\method{fromunicode()} method (see below) to add initial items to
the array.
\end{funcdesc}
\begin{datadesc}{ArrayType}
Type object corresponding to the objects returned by
\function{array()}.
Obsolete alias for \function{array}.
\end{datadesc}
Array objects support the following data items and methods:
Array objects support the ordinary sequence operations of
indexing, slicing, concatenation, and multiplication. The
following data items and methods are also supported:
\begin{memberdesc}[array]{typecode}
The typecode character used to create the array.
......@@ -121,6 +124,13 @@ array of machine values (as if it had been read from a
file using the \method{fromfile()} method).
\end{methoddesc}
\begin{methoddesc}[array]{fromunicode}{s}
Extends this array with data from the given unicode string.
The array must be a type 'u' array; otherwise a ValueError
is raised. Use \samp{array.fromstring(ustr.decode(enc))} to
append Unicode data to an array of some other type.
\end{methoddesc}
\begin{methoddesc}[array]{index}{x}
Return the smallest \var{i} such that \var{i} is the index of
the first occurence of \var{x} in the array.
......@@ -134,7 +144,7 @@ Insert a new item with value \var{x} in the array before position
\begin{methoddesc}[array]{pop}{\optional{i}}
Removes the item with the index \var{i} from the array and returns
it. The optional argument defaults to \code{-1}, so that by default
the last item is removed and returned.
the last item is removed and returned.
\end{methoddesc}
\begin{methoddesc}[array]{read}{f, n}
......@@ -170,6 +180,13 @@ string representation (the same sequence of bytes that would
be written to a file by the \method{tofile()} method.)
\end{methoddesc}
\begin{methoddesc}[array]{tounicode}{}
Convert the array to a unicode string. The array must be
a type 'u' array; otherwise a ValueError is raised. Use
array.tostring().decode(enc) to obtain a unicode string
from an array of some other type.
\end{methoddesc}
\begin{methoddesc}[array]{write}{f}
\deprecated {1.5.1}
{Use the \method{tofile()} method.}
......@@ -188,6 +205,7 @@ imported using \code{from array import array}. Examples:
\begin{verbatim}
array('l')
array('c', 'hello world')
array('u', u'hello \textbackslash u2641')
array('l', [1, 2, 3, 4, 5])
array('d', [1.0, 2.0, 3.14])
\end{verbatim}
......
......@@ -6,14 +6,87 @@ import array
from test_support import verbose, TESTFN, unlink, TestFailed
def main():
testtype('c', 'c')
testtype('u', u'\u263a')
for type in (['b', 'h', 'i', 'l', 'f', 'd']):
testtype(type, 1)
testunicode()
testsubclassing()
unlink(TESTFN)
def testunicode():
try:
array.array('b', u'foo')
except TypeError:
pass
else:
raise TestFailed("creating a non-unicode array from "
"a Unicode string should fail")
x = array.array('u', u'\xa0\xc2\u1234')
x.fromunicode(u' ')
x.fromunicode(u'')
x.fromunicode(u'')
x.fromunicode(u'\x11abc\xff\u1234')
s = x.tounicode()
if s != u'\xa0\xc2\u1234 \x11abc\xff\u1234':
raise TestFailed("fromunicode()/tounicode()")
s = u'\x00="\'a\\b\x80\xff\u0000\u0001\u1234'
a = array.array('u', s)
if verbose:
print "repr of type 'u' array:", repr(a)
print " expected: array('u', %r)" % s
def testsubclassing():
class EditableString(array.array):
def __new__(cls, s, *args, **kwargs):
return array.array.__new__(cls, 'c', s)
def __init__(self, s, color='blue'):
array.array.__init__(self, 'c', s)
self.color = color
def strip(self):
self[:] = array.array('c', self.tostring().strip())
def __repr__(self):
return 'EditableString(%r)' % self.tostring()
s = EditableString("\ttest\r\n")
s.strip()
if s.tostring() != 'test':
raise TestFailed, "subclassing array.array failed somewhere"
if s.color != 'blue':
raise TestFailed, "assigning attributes to instance of array subclass"
s.color = 'red'
if s.color != 'red':
raise TestFailed, "assigning attributes to instance of array subclass"
if s.__dict__.keys() != ['color']:
raise TestFailed, "array subclass __dict__"
class ExaggeratingArray(array.array):
__slots__ = ['offset']
def __new__(cls, typecode, data, offset):
return array.array.__new__(cls, typecode, data)
def __init__(self, typecode, data, offset):
self.offset = offset
def __getitem__(self, i):
return array.array.__getitem__(self, i) + self.offset
a = ExaggeratingArray('i', [3, 6, 7, 11], 4)
if a[0] != 7:
raise TestFailed, "array subclass overriding __getitem__"
try:
a.color = 'blue'
except AttributeError:
pass
else:
raise TestFailed, "array subclass __slots__ was ignored"
def testoverflow(type, lowerLimit, upperLimit):
# should not overflow assigning lower limit
......@@ -54,7 +127,6 @@ def testoverflow(type, lowerLimit, upperLimit):
def testtype(type, example):
a = array.array(type)
a.append(example)
if verbose:
......@@ -97,6 +169,33 @@ def testtype(type, example):
print 'array of %s converted to a string: ' \
% a.typecode, `a.tostring()`
# Try out inplace addition and multiplication
a = array.array(type, [example])
b = a
a += array.array(type, [example]*2)
if a is not b:
raise TestFailed, "array(%s) inplace addition" % `type`
if a != array.array(type, [example] * 3):
raise TestFailed, "array(%s) inplace addition" % `type`
a *= 5
if a is not b:
raise TestFailed, "array(%s) inplace multiplication" % `type`
if a != array.array(type, [example] * 15):
raise TestFailed, "array(%s) inplace multiplication" % `type`
a *= 0
if a is not b:
raise TestFailed, "array(%s) inplace multiplication by 0" % `type`
if a != array.array(type, []):
raise TestFailed, "array(%s) inplace multiplication by 0" % `type`
a *= 1000
if a is not b:
raise TestFailed, "empty array(%s) inplace multiplication" % `type`
if a != array.array(type, []):
raise TestFailed, "empty array(%s) inplace multiplication" % `type`
if type == 'c':
a = array.array(type, "abcde")
a[:-1] = a
......@@ -135,6 +234,44 @@ def testtype(type, example):
a.reverse()
if a != array.array(type, "dca"):
raise TestFailed, "array(%s) reverse-test" % `type`
elif type == 'u':
a = array.array(type, u"abcde")
a[:-1] = a
if a != array.array(type, u"abcdee"):
raise TestFailed, "array(%s) self-slice-assign (head)" % `type`
a = array.array(type, u"abcde")
a[1:] = a
if a != array.array(type, u"aabcde"):
raise TestFailed, "array(%s) self-slice-assign (tail)" % `type`
a = array.array(type, u"abcde")
a[1:-1] = a
if a != array.array(type, u"aabcdee"):
raise TestFailed, "array(%s) self-slice-assign (cntr)" % `type`
if a.index(u"e") != 5:
raise TestFailed, "array(%s) index-test" % `type`
if a.count(u"a") != 2:
raise TestFailed, "array(%s) count-test" % `type`
a.remove(u"e")
if a != array.array(type, u"aabcde"):
raise TestFailed, "array(%s) remove-test" % `type`
if a.pop(0) != u"a":
raise TestFailed, "array(%s) pop-test" % `type`
if a.pop(1) != u"b":
raise TestFailed, "array(%s) pop-test" % `type`
a.extend(array.array(type, u"xyz"))
if a != array.array(type, u"acdexyz"):
raise TestFailed, "array(%s) extend-test" % `type`
a.pop()
a.pop()
a.pop()
x = a.pop()
if x != u'e':
raise TestFailed, "array(%s) pop-test" % `type`
if a != array.array(type, u"acd"):
raise TestFailed, "array(%s) pop-test" % `type`
a.reverse()
if a != array.array(type, u"dca"):
raise TestFailed, "array(%s) reverse-test" % `type`
else:
a = array.array(type, [1, 2, 3, 4, 5])
a[:-1] = a
......
......@@ -17,6 +17,11 @@ Core and builtins
Extension modules
- array.array is now a type object. A new format character
'u' indicates Py_UNICODE arrays. For those, .tounicode and
.fromunicode methods are available. Arrays now support __iadd__
and __imul__.
- dl now builds on every system that has dlfcn.h. Failure in case
of sizeof(int)!=sizeof(long)!=sizeof(void*) is delayed until dl.open
is called.
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment