[pypy-svn] r52333 - in pypy/branch/buffer/pypy/module/_rawffi: . test

arigo at codespeak.net arigo at codespeak.net
Sun Mar 9 15:09:01 CET 2008


Author: arigo
Date: Sun Mar  9 15:08:59 2008
New Revision: 52333

Modified:
   pypy/branch/buffer/pypy/module/_rawffi/array.py
   pypy/branch/buffer/pypy/module/_rawffi/test/test__rawffi.py
Log:
A useful extension to arrays of shape 'c': buffer-like slicing,
because this can be implemented kind-of-efficiently.


Modified: pypy/branch/buffer/pypy/module/_rawffi/array.py
==============================================================================
--- pypy/branch/buffer/pypy/module/_rawffi/array.py	(original)
+++ pypy/branch/buffer/pypy/module/_rawffi/array.py	Sun Mar  9 15:08:59 2008
@@ -113,7 +113,8 @@
                                                                self.length))
     descr_repr.unwrap_spec = ['self', ObjSpace]
 
-    # XXX don't allow negative indexes, nor slices
+    # This only allows non-negative indexes.  Arrays of shape 'c' also
+    # support simple slices.
 
     def setitem(self, space, num, w_value):
         if not self.ll_buffer:
@@ -122,7 +123,17 @@
             raise OperationError(space.w_IndexError, space.w_None)
         unwrap_value(space, push_elem, self.ll_buffer, num, self.shape.itemtp,
                      w_value)
-    setitem.unwrap_spec = ['self', ObjSpace, int, W_Root]
+
+    def descr_setitem(self, space, w_index, w_value):
+        try:
+            num = space.int_w(w_index)
+        except OperationError, e:
+            if not e.match(space, space.w_TypeError):
+                raise
+            self.setslice(space, w_index, w_value)
+        else:
+            self.setitem(space, num, w_value)
+    descr_setitem.unwrap_spec = ['self', ObjSpace, W_Root, W_Root]
 
     def getitem(self, space, num):
         if not self.ll_buffer:
@@ -131,7 +142,17 @@
             raise OperationError(space.w_IndexError, space.w_None)
         return wrap_value(space, get_elem, self.ll_buffer, num,
                           self.shape.itemtp)
-    getitem.unwrap_spec = ['self', ObjSpace, int]
+
+    def descr_getitem(self, space, w_index):
+        try:
+            num = space.int_w(w_index)
+        except OperationError, e:
+            if not e.match(space, space.w_TypeError):
+                raise
+            return self.getslice(space, w_index)
+        else:
+            return self.getitem(space, num)
+    descr_getitem.unwrap_spec = ['self', ObjSpace, W_Root]
 
     def getlength(self, space):
         return space.wrap(self.length)
@@ -147,11 +168,59 @@
         _, itemsize, _ = self.shape.itemtp
         return itemsize * self.length
 
+    def decodeslice(self, space, w_slice):
+        if not space.is_true(space.isinstance(w_slice, space.w_slice)):
+            return OperationError(space.w_TypeError,
+                                  space.wrap('index must be int or slice'))
+        letter, _, _ = self.shape.itemtp
+        if letter != 'c':
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("only 'c' arrays support slicing"))
+        w_start = space.getattr(w_slice, space.wrap('start'))
+        w_stop = space.getattr(w_slice, space.wrap('stop'))
+        w_step = space.getattr(w_slice, space.wrap('step'))
+
+        if space.is_w(w_start, space.w_None):
+            start = 0
+        else:
+            start = space.int_w(w_start)
+        if space.is_w(w_stop, space.w_None):
+            stop = self.length
+        else:
+            stop = space.int_w(w_stop)
+        if not space.is_w(w_step, space.w_None):
+            step = space.int_w(w_step)
+            if step != 1:
+                raise OperationError(space.w_ValueError,
+                                     space.wrap("no step support"))
+        if not (0 <= start <= stop <= self.length):
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("slice out of bounds"))
+        if not self.ll_buffer:
+            raise segfault_exception(space, "accessing a freed array")
+        return start, stop
+
+    def getslice(self, space, w_slice):
+        start, stop = self.decodeslice(space, w_slice)
+        ll_buffer = self.ll_buffer
+        result = [ll_buffer[i] for i in range(start, stop)]
+        return space.wrap(''.join(result))
+
+    def setslice(self, space, w_slice, w_value):
+        start, stop = self.decodeslice(space, w_slice)
+        value = space.bufferstr_w(w_value)
+        if start + len(value) != stop:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("cannot resize array"))
+        ll_buffer = self.ll_buffer
+        for i in range(len(value)):
+            ll_buffer[start + i] = value[i]
+
 W_ArrayInstance.typedef = TypeDef(
     'ArrayInstance',
     __repr__    = interp2app(W_ArrayInstance.descr_repr),
-    __setitem__ = interp2app(W_ArrayInstance.setitem),
-    __getitem__ = interp2app(W_ArrayInstance.getitem),
+    __setitem__ = interp2app(W_ArrayInstance.descr_setitem),
+    __getitem__ = interp2app(W_ArrayInstance.descr_getitem),
     __len__     = interp2app(W_ArrayInstance.getlength),
     __buffer__  = interp2app(W_ArrayInstance.descr_buffer),
     buffer      = GetSetProperty(W_ArrayInstance.getbuffer),
@@ -174,8 +243,8 @@
 W_ArrayInstanceAutoFree.typedef = TypeDef(
     'ArrayInstanceWithFree',
     __repr__    = interp2app(W_ArrayInstance.descr_repr),
-    __setitem__ = interp2app(W_ArrayInstance.setitem),
-    __getitem__ = interp2app(W_ArrayInstance.getitem),
+    __setitem__ = interp2app(W_ArrayInstance.descr_setitem),
+    __getitem__ = interp2app(W_ArrayInstance.descr_getitem),
     __len__     = interp2app(W_ArrayInstance.getlength),
     __buffer__  = interp2app(W_ArrayInstance.descr_buffer),
     buffer      = GetSetProperty(W_ArrayInstance.getbuffer),

Modified: pypy/branch/buffer/pypy/module/_rawffi/test/test__rawffi.py
==============================================================================
--- pypy/branch/buffer/pypy/module/_rawffi/test/test__rawffi.py	(original)
+++ pypy/branch/buffer/pypy/module/_rawffi/test/test__rawffi.py	Sun Mar  9 15:08:59 2008
@@ -180,6 +180,17 @@
         dupaptr.free()
         dupa.free()
 
+    def test_chararray_as_bytebuffer(self):
+        # a useful extension to arrays of shape 'c': buffer-like slicing
+        import _rawffi
+        A = _rawffi.Array('c')
+        buf = A(10, autofree=True)
+        buf[0] = '*'
+        assert buf[1:5] == '\x00' * 4
+        buf[7:] = 'abc'
+        assert buf[9] == 'c'
+        assert buf[:8] == '*' + '\x00'*6 + 'a'
+
     def test_returning_str(self):
         import _rawffi
         lib = _rawffi.CDLL(self.lib_name)



More information about the Pypy-commit mailing list