[pypy-svn] r15604 - in pypy/dist: lib-python lib-python/modified-2.4.1/test pypy/interpreter pypy/module/__builtin__ pypy/module/__builtin__/test pypy/module/array

nik at codespeak.net nik at codespeak.net
Thu Aug 4 12:06:16 CEST 2005


Author: nik
Date: Thu Aug  4 12:06:12 2005
New Revision: 15604

Added:
   pypy/dist/lib-python/modified-2.4.1/test/test_array.py
      - copied, changed from r15538, pypy/dist/lib-python/2.4.1/test/test_array.py
   pypy/dist/pypy/module/array/
   pypy/dist/pypy/module/array/__init__.py   (contents, props changed)
   pypy/dist/pypy/module/array/app_array.py   (contents, props changed)
Modified:
   pypy/dist/lib-python/conftest.py
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/module/__builtin__/app_buffer.py
   pypy/dist/pypy/module/__builtin__/test/test_buffer.py
Log:
integrated the array module. this one doesn't break the translation. ;)
in fact i have also been able to translate successfully with _sre enabled -
the problem was the faked array module.


Modified: pypy/dist/lib-python/conftest.py
==============================================================================
--- pypy/dist/lib-python/conftest.py	(original)
+++ pypy/dist/lib-python/conftest.py	Thu Aug  4 12:06:12 2005
@@ -355,7 +355,7 @@
     RegrTest('test_al.py', enabled=False, dumbtest=1),
     RegrTest('test_anydbm.py', enabled=True, core=True),
     RegrTest('test_applesingle.py', enabled=False),
-    RegrTest('test_array.py', enabled=False),
+    RegrTest('test_array.py', enabled=True),
     RegrTest('test_asynchat.py', enabled=False),
     RegrTest('test_atexit.py', enabled=False, dumbtest=1, core=True),
     RegrTest('test_audioop.py', enabled=False, dumbtest=1),

Copied: pypy/dist/lib-python/modified-2.4.1/test/test_array.py (from r15538, pypy/dist/lib-python/2.4.1/test/test_array.py)
==============================================================================
--- pypy/dist/lib-python/2.4.1/test/test_array.py	(original)
+++ pypy/dist/lib-python/modified-2.4.1/test/test_array.py	Thu Aug  4 12:06:12 2005
@@ -5,7 +5,7 @@
 
 import unittest
 from test import test_support
-from weakref import proxy
+#from weakref import proxy
 import array, cStringIO, math
 
 tests = [] # list to accumulate all tests
@@ -635,7 +635,8 @@
         b = buffer(a)
         self.assertEqual(b[0], a.tostring()[0])
 
-    def test_weakref(self):
+    def DONOTtest_weakref(self):
+        # XXX disabled until PyPy grows weakref support
         s = array.array(self.typecode, self.example)
         p = proxy(s)
         self.assertEqual(p.tostring(), s.tostring())

Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Thu Aug  4 12:06:12 2005
@@ -163,7 +163,8 @@
         except AttributeError:
             pass
 
-        modules = ['sys', '__builtin__', 'exceptions', 'unicodedata', '_codecs']
+        modules = ['sys', '__builtin__', 'exceptions', 'unicodedata', '_codecs',
+            'array']
 
         if self.options.nofaking:
             modules.append('posix')

Modified: pypy/dist/pypy/module/__builtin__/app_buffer.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/app_buffer.py	(original)
+++ pypy/dist/pypy/module/__builtin__/app_buffer.py	Thu Aug  4 12:06:12 2005
@@ -1,5 +1,7 @@
+# NOT_RPYTHON (because of array import)
 # Might probably be deprecated in Python at some point.
 import sys
+from array import array
 from struct import pack, unpack
 
 class buffer(object):
@@ -25,8 +27,9 @@
             object = str_object
         elif isinstance(object, buffer):
             object = object.buf
+        elif isinstance(object, array):
+            object = object.tostring()
         else:
-            # XXX check for more types
             raise TypeError, "buffer object expected"
         if offset < 0:
             raise ValueError, "offset must be zero or positive"

Modified: pypy/dist/pypy/module/__builtin__/test/test_buffer.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/test/test_buffer.py	(original)
+++ pypy/dist/pypy/module/__builtin__/test/test_buffer.py	Thu Aug  4 12:06:12 2005
@@ -19,3 +19,9 @@
                 assert b[0:8] == "\x00\x00\x00a\x00\x00\x00b"
             else:
                 assert b[0:8] == "a\x00\x00\x00b\x00\x00\x00"
+
+    def test_array_buffer(self):
+        import array
+        b = buffer(array.array("B", [1, 2, 3]))
+        assert len(b) == 3
+        assert b[0:3] == "\x01\x02\x03"

Added: pypy/dist/pypy/module/array/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/array/__init__.py	Thu Aug  4 12:06:12 2005
@@ -0,0 +1,11 @@
+from pypy.interpreter.mixedmodule import MixedModule
+    
+class Module(MixedModule):
+    appleveldefs = {
+         '__doc__' :  'app_array.__doc__',
+         '__name__' :  'app_array.__name__',
+         'array' :  'app_array.array',
+         'ArrayType' :  'app_array.ArrayType',
+    }
+    interpleveldefs = {
+    }

Added: pypy/dist/pypy/module/array/app_array.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/array/app_array.py	Thu Aug  4 12:06:12 2005
@@ -0,0 +1,480 @@
+# NOT_RPYTHON
+"""This module defines an object type which can efficiently represent
+an array of basic values: characters, integers, floating point
+numbers.  Arrays are sequence types and behave very much like lists,
+except that the type of objects stored in them is constrained.  The
+type is specified at object creation time by using a type code, which
+is a single character.  The following type codes are defined:
+
+    Type code   C Type             Minimum size in bytes 
+    'c'         character          1 
+    'b'         signed integer     1 
+    'B'         unsigned integer   1 
+    'u'         Unicode character  2 
+    'h'         signed integer     2 
+    'H'         unsigned integer   2 
+    'i'         signed integer     2 
+    'I'         unsigned integer   2 
+    'l'         signed integer     4 
+    'L'         unsigned integer   4 
+    'f'         floating point     4 
+    'd'         floating point     8 
+
+The constructor is:
+
+array(typecode [, initializer]) -- create a new array
+"""
+import sys
+from struct import pack, unpack
+
+if sys.maxunicode == 65535:
+    UNICODE_SIZE = 2
+    UNICODE_FORMAT = "H"
+else:
+    UNICODE_SIZE = 4
+    UNICODE_FORMAT = "I"
+
+def c_type_check(x):
+    if not isinstance(x, str) or len(x) != 1:
+        raise TypeError("array item must be char")
+    return x
+
+def general_int_type_check(x, lower_bound, upper_bound):
+    if not (isinstance(x, int) or isinstance(x, long) or isinstance(x, float)):
+        raise TypeError("an integer is required")
+    x_int = int(x)
+    if not (x_int >= lower_bound and x_int <= upper_bound):
+        raise OverflowError("integer is not in the allowed range")
+    return x_int    
+
+def b_type_check(x):
+    return general_int_type_check(x, -128, 127)
+
+def BB_type_check(x):
+    return general_int_type_check(x, 0, 255)
+
+def u_type_check(x):
+    if isinstance(x, str):
+        if len(x) / UNICODE_SIZE == 1:
+            # XXX Problem: CPython will gladly accept any unicode codepoint
+            # up to 0xFFFFFFFF in UCS-4 builds here, but unichr which is used
+            # to implement decode for unicode_internal in PyPy will
+            # reject anything above 0x00110000. I don't think there is a
+            # way to replicate CPython behaviour without resorting to C.
+            x_uni = x[:UNICODE_SIZE].decode("unicode_internal")
+        else:
+            raise TypeError("array item must be unicode character")
+    elif isinstance(x, unicode):
+        x_uni = x
+    else:
+        raise TypeError("array item must be unicode character")
+    if len(x_uni) != 1:
+        raise TypeError("array item must be unicode character")
+    return x_uni
+
+def h_type_check(x):
+    return general_int_type_check(x, -32768, 32767)
+
+def HH_type_check(x):
+    return general_int_type_check(x, 0, 65535)
+
+def i_type_check(x):
+    return general_int_type_check(x, -2147483648, 2147483647)
+
+def general_long_type_check(x, lower_bound, upper_bound):
+    if not (isinstance(x, int) or isinstance(x, long) or isinstance(x, float)):
+        raise TypeError("an integer is required")
+    x_long = long(x)
+    if not (x_long >= lower_bound and x_long <= upper_bound):
+        raise OverflowError("integer/long is not in the allowed range")
+    return x_long
+
+def II_type_check(x):
+    return general_long_type_check(x, 0, 4294967295L)
+
+l_type_check = i_type_check
+
+LL_type_check = II_type_check
+
+def f_type_check(x):
+    if not (isinstance(x, int) or isinstance(x, long) or isinstance(x, float)):
+        raise TypeError("a float is required")
+    x_float = float(x)
+    # XXX This is not exactly a nice way of checking bounds. Formerly, I tried
+    # this: return unpack("f", pack("f", x_float))[0]
+    # Which works in CPython, but PyPy struct is not currently intelligent
+    # enough to handle this.
+    if x_float > 3.4028e38:
+        x_float = 3.4028e38
+    elif x_float < -3.4028e38:
+        x_float = -3.4028e38
+    return x_float
+
+def d_type_check(x):
+    if not (isinstance(x, int) or isinstance(x, long) or isinstance(x, float)):
+        raise TypeError("a float is required")
+    return float(x)
+
+def dummy_type_check(x):
+    return x
+
+# XXX Assuming fixed sizes of the different types, independent of platform.
+# These are the same assumptions that struct makes at the moment.
+descriptors = {
+    'c' : ('char', 1, c_type_check),
+    'b' : ('signed char', 1, b_type_check),
+    'B' : ('unsigned char', 1, BB_type_check),
+    'u' : ('Py_UNICODE', UNICODE_SIZE, u_type_check),
+    'h' : ('signed short', 2, h_type_check),
+    'H' : ('unsigned short', 2, HH_type_check),
+    'i' : ('signed int', 4, i_type_check),
+    'I' : ('unsigned int', 4, II_type_check),
+    'l' : ('signed long', 4, l_type_check),
+    'L' : ('unsigned long', 4, LL_type_check),
+    'f' : ('float', 4, f_type_check),
+    'd' : ('double', 8, d_type_check),
+}
+
+class array(object):
+    """array(typecode [, initializer]) -> array
+    
+    Return a new array whose items are restricted by typecode, and
+    initialized from the optional initializer value, which must be a list,
+    string. or iterable over elements of the appropriate type.
+    
+    Arrays represent basic values and behave very much like lists, except
+    the type of objects stored in them is constrained.
+    
+    Methods:
+    
+    append() -- append a new item to the end of the array
+    buffer_info() -- return information giving the current memory info
+    byteswap() -- byteswap all the items of the array
+    count() -- return number of occurences of an object
+    extend() -- extend array by appending multiple elements from an iterable
+    fromfile() -- read items from a file object
+    fromlist() -- append items from the list
+    fromstring() -- append items from the string
+    index() -- return index of first occurence of an object
+    insert() -- insert a new item into the array at a provided position
+    pop() -- remove and return item (default last)
+    read() -- DEPRECATED, use fromfile()
+    remove() -- remove first occurence of an object
+    reverse() -- reverse the order of the items in the array
+    tofile() -- write all items to a file object
+    tolist() -- return the array converted to an ordinary list
+    tostring() -- return the array converted to a string
+    write() -- DEPRECATED, use tofile()
+    
+    Attributes:
+    
+    typecode -- the typecode character used to create the array
+    itemsize -- the length in bytes of one array item
+    """
+    __slots__ = ["typecode", "itemsize", "_data", "_descriptor", "__weakref__"]
+
+    def __new__(cls, typecode, initializer=[]):
+        self = object.__new__(cls)
+        if not isinstance(typecode, str) or len(typecode) != 1:
+            raise TypeError(
+                     "array() argument 1 must be char, not %s" % type(typecode))
+        if not descriptors.has_key(typecode):
+            raise ValueError(
+                  "bad typecode (must be c, b, B, u, h, H, i, I, l, L, f or d)")
+        self._descriptor = descriptors[typecode]
+        self._data = []
+        self.typecode = typecode
+        self.itemsize = self._descriptor[1]
+        if isinstance(initializer, list):
+            self.fromlist(initializer)
+        elif isinstance(initializer, str):
+            self.fromstring(initializer)
+        elif isinstance(initializer, unicode) and self.typecode == "u":
+            self.fromunicode(initializer)
+        else:
+            self.extend(initializer)
+        return self
+
+    ##### array-specific operations
+
+    def fromfile(self, f, n):
+        """Read n objects from the file object f and append them to the end of
+        the array. Also called as read."""
+        if not isinstance(f, file):
+            raise TypeError("arg1 must be open file")
+        for i in range(n):
+            item = f.read(self.itemsize)
+            if len(item) < self.itemsize:
+                raise EOFError("not enough items in file")
+            self.fromstring(item)
+
+    def fromlist(self, l):
+        """Append items to array from list."""
+        if not isinstance(l, list):
+            raise TypeError("arg must be list")
+        self._fromiterable(l)
+        
+    def fromstring(self, s):
+        """Appends items from the string, interpreting it as an array of machine
+        values, as if it had been read from a file using the fromfile()
+        method)."""
+        if isinstance(s, unicode):
+            s = str(s)
+        if not (isinstance(s, str) or isinstance(s, buffer)):
+            raise TypeError(
+                   "fromstring() argument 1 must be string or read-only buffer")
+        if len(s) % self.itemsize != 0:
+            raise ValueError("string length not a multiple of item size")
+        items = []
+        if self.typecode == "u":
+            for i in range(0, len(s), self.itemsize):
+                items.append(u_type_check(s[i:i + self.itemsize]))
+        else:
+            for i in range(0, len(s), self.itemsize):
+                item = unpack(self.typecode, s[i:i + self.itemsize])[0]
+                # the item needn't be type checked if unpack succeeded
+                items.append(item)
+        self._data.extend(items)
+
+    def fromunicode(self, ustr):
+        """Extends this array with data from the unicode string ustr. The array
+        must be a type 'u' array; otherwise a ValueError is raised. Use
+        array.fromstring(ustr.encode(...)) to append Unicode data to an array of
+        some other type."""
+        if not self.typecode == "u":
+            raise ValueError(
+                          "fromunicode() may only be called on type 'u' arrays")
+        if isinstance(ustr, unicode):
+            self._fromiterable(ustr)
+        elif isinstance(ustr, str) or isinstance(ustr, buffer):
+            # CPython strangely truncates string arguments at multiples of the
+            # unicode byte size ...
+            trunc_s = ustr[:len(ustr) - (len(ustr) % self.itemsize)]
+            self.fromstring(trunc_s)
+        else:
+            raise TypeError(
+                  "fromunicode() argument 1 must be string or read-only buffer")
+
+    def tofile(self, f):
+        """Write all items (as machine values) to the file object f.  Also
+        called as write."""
+        if not isinstance(f, file):
+            raise TypeError("arg must be open file")
+        f.write(self.tostring())
+        
+    def tolist(self):
+        """Convert array to an ordinary list with the same items."""
+        return self._data[:]
+
+    def tostring(self):
+        """Convert the array to an array of machine values and return the string
+        representation."""
+        if self.typecode == "u":
+            return u"".join(self._data).encode("unicode_internal")
+        else:
+            strings = []
+            for item in self._data:
+                strings.append(pack(self.typecode, item))
+            return "".join(strings)
+
+    def tounicode(self):
+        """Convert the array to a unicode string. The array must be a type 'u'
+        array; otherwise a ValueError is raised. Use array.tostring().decode()
+        to obtain a unicode string from an array of some other type."""
+        if self.typecode != "u":
+            raise ValueError("tounicode() may only be called on type 'u' arrays")
+        return u"".join(self._data)
+
+    def byteswap(self):
+        """Byteswap all items of the array.  If the items in the array are not
+        1, 2, 4, or 8 bytes in size, RuntimeError is raised."""
+        if self.itemsize not in [1, 2, 4, 8]:
+            raise RuntimeError("byteswap not supported for this array")
+        bytes = self.tostring()
+        swapped = []
+        for offset in range(0, len(self._data) * self.itemsize, self.itemsize):
+            l = list(bytes[offset:offset + self.itemsize])
+            l.reverse()
+            swapped += l
+        self._data = []
+        self.fromstring("".join(swapped))
+
+    def buffer_info(self):
+        """Return a tuple (address, length) giving the current memory address
+        and the length in items of the buffer used to hold array's contents. The
+        length should be multiplied by the itemsize attribute to calculate the
+        buffer length in bytes. In PyPy the return values are not really
+        meaningful."""
+        return (0, len(self._data))
+    
+    read = fromfile
+
+    write = tofile
+
+    ##### general object protocol
+    
+    def __repr__(self):
+        if len(self._data) == 0:
+            return "array('%s')" % self.typecode
+        elif self.typecode == "c":
+            return "array('%s', %s)" % (self.typecode, repr(self.tostring()))
+        elif self.typecode == "u":
+            return "array('%s', %s)" % (self.typecode, repr(self.tounicode()))
+        else:
+            return "array('%s', %s)" % (self.typecode, repr(self.tolist()))
+
+    def __copy__(self):
+        a = array(self.typecode)
+        a._data = self._data[:]
+        return a
+
+    def __eq__(self, other):
+        if not isinstance(other, array):
+            return NotImplemented
+        return self._data == other._data
+
+    def __ne__(self, other):
+        if not isinstance(other, array):
+            return NotImplemented
+        return self._data != other._data
+
+    def __lt__(self, other):
+        if not isinstance(other, array):
+            return NotImplemented
+        return self._data < other._data
+
+    def __gt__(self, other):
+        if not isinstance(other, array):
+            return NotImplemented
+        return self._data > other._data
+
+    def __le__(self, other):
+        if not isinstance(other, array):
+            return NotImplemented
+        return self._data <= other._data
+
+    def __ge__(self, other):
+        if not isinstance(other, array):
+            return NotImplemented
+        return self._data >= other._data
+
+    ##### list methods
+    
+    def append(self, x):
+        """Append new value x to the end of the array."""
+        x_checked = self._type_check(x)
+        self._data.append(x_checked)
+
+    def count(self, x):
+        """Return number of occurences of x in the array."""
+        return self._data.count(x)
+
+    def extend(self, iterable):
+        """Append items to the end of the array."""
+        if isinstance(iterable, array) \
+                                    and not self.typecode == iterable.typecode:
+            raise TypeError("can only extend with array of same kind")
+        self._fromiterable(iterable)
+
+    def index(self, x):
+        """Return index of first occurence of x in the array."""
+        return self._data.index(x)
+    
+    def insert(self, i, x):
+        """Insert a new item x into the array before position i."""
+        x_checked = self._type_check(x)
+        self._data.insert(i, x_checked)
+        
+    def pop(self, i=-1):
+        """Return the i-th element and delete it from the array. i defaults to
+        -1."""
+        return self._data.pop(i)
+        
+    def remove(self, x):
+        """Remove the first occurence of x in the array."""
+        self._data.remove(x)
+        
+    def reverse(self):
+        """Reverse the order of the items in the array."""
+        self._data.reverse()
+
+    ##### list protocol
+    
+    def __len__(self):
+        return len(self._data)
+    
+    def __add__(self, other):
+        if not isinstance(other, array):
+            raise TypeError("can only append array to array")
+        if self.typecode != other.typecode:
+            raise TypeError("bad argument type for built-in operation")
+        return array(self.typecode, self._data + other._data)
+
+    def __mul__(self, repeat):
+        return array(self.typecode, self._data * repeat)
+
+    __rmul__ = __mul__
+
+    def __getitem__(self, i):
+        if isinstance(i, slice):
+            sliced = array(self.typecode)
+            sliced._data = self._data[i]
+            return sliced
+        return self._data[i]
+
+    def __getslice__(self, i, j):
+        return self.__getitem__(slice(i, j))
+
+    def __setitem__(self, i, x):
+        if isinstance(i, slice):
+            if not isinstance(x, array):
+                raise TypeError("can only assign array to array slice")
+            if x.typecode != self.typecode:
+                raise TypeError("bad argument type for built-in operation")
+            self._data[i] = x._data
+            return
+        if not (isinstance(i, int) or isinstance(i, long)):
+            raise TypeError("list indices must be integers")
+        if i >= len(self._data) or i < -len(self._data):
+            raise IndexError("array assignment index out of range")
+        x_checked = self._type_check(x)
+        self._data[i] = x_checked
+
+    def __setslice__(self, i, j, x):
+        self.__setitem__(slice(i, j), x)
+
+    def __delitem__(self, i):
+        del self._data[i]
+
+    def __delslice__(self, i, j):
+        self.__delitem__(slice(i, j))
+
+    def __contains__(self, item):
+        return item in self._data
+
+    def __iadd__(self, other):
+        if not isinstance(other, array):
+            raise TypeError("can only extend array with array")
+        self.extend(other)
+        return self
+
+    def __imul__(self, repeat):
+        self._data *= repeat
+        return self
+
+    def __iter__(self):
+        return iter(self._data)
+
+    ##### internal methods
+    
+    def _type_check(self, x):
+        return self._descriptor[2](x)
+
+    def _fromiterable(self, iterable):
+        items = []
+        for item in iterable:
+            item_checked = self._type_check(item)
+            items.append(item_checked)
+        self._data.extend(items)
+
+ArrayType = array



More information about the Pypy-commit mailing list