[pypy-svn] pypy fast-forward: Implemented extended slicing for buffers.

alex_gaynor commits-noreply at bitbucket.org
Sat Jan 8 09:34:45 CET 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: fast-forward
Changeset: r40479:e8e6655da29d
Date: 2011-01-08 02:34 -0600
http://bitbucket.org/pypy/pypy/changeset/e8e6655da29d/

Log:	Implemented extended slicing for buffers.

diff --git a/pypy/module/__builtin__/test/test_buffer.py b/pypy/module/__builtin__/test/test_buffer.py
--- a/pypy/module/__builtin__/test/test_buffer.py
+++ b/pypy/module/__builtin__/test/test_buffer.py
@@ -160,6 +160,17 @@
         raises(ValueError, buffer, a, -1)
         raises(ValueError, buffer, a, 0, -2)
 
+    def test_slice(self):
+        # Test extended slicing by comparing with list slicing.
+        s = "".join(chr(c) for c in list(range(255, -1, -1)))
+        b = buffer(s)
+        indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
+        for start in indices:
+            for stop in indices:
+                # Skip step 0 (invalid)
+                for step in indices[1:]:
+                    assert b[start:stop:step] == s[start:stop:step]
+
 class AppTestMemoryView:
     def test_basic(self):
         v = memoryview("abc")

diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py
--- a/pypy/interpreter/buffer.py
+++ b/pypy/interpreter/buffer.py
@@ -33,15 +33,15 @@
     def as_str(self):
         "Returns an interp-level string with the whole content of the buffer."
         # May be overridden.
-        return self.getslice(0, self.getlength())
+        return self.getslice(0, self.getlength(), 1, self.getlength())
 
     def getitem(self, index):
         "Returns the index'th character in the buffer."
         raise NotImplementedError   # Must be overriden.  No bounds checks.
 
-    def getslice(self, start, stop):
+    def getslice(self, start, stop, step, size):
         # May be overridden.  No bounds checks.
-        return ''.join([self.getitem(i) for i in range(start, stop)])
+        return ''.join([self.getitem(i) for i in range(start, stop, step)])
 
     # __________ app-level support __________
 
@@ -50,16 +50,11 @@
     descr_len.unwrap_spec = ['self', ObjSpace]
 
     def descr_getitem(self, space, w_index):
-        start, stop, step = space.decode_index(w_index, self.getlength())
+        start, stop, step, size = space.decode_index4(w_index, self.getlength())
         if step == 0:  # index only
             return space.wrap(self.getitem(start))
-        elif step == 1:
-            res = self.getslice(start, stop)
-            return space.wrap(res)
-        else:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("buffer object does not support"
-                                            " slicing with a step"))
+        res = self.getslice(start, stop, step, size)
+        return space.wrap(res)
     descr_getitem.unwrap_spec = ['self', ObjSpace, W_Root]
 
     def descr_setitem(self, space, w_index, newstring):
@@ -135,7 +130,7 @@
         else:
             info = 'read-only buffer'
         addrstring = self.getaddrstring(space)
-        
+
         return space.wrap("<%s for 0x%s, size %d>" %
                           (info, addrstring, self.getlength()))
     descr_repr.unwrap_spec = ['self', ObjSpace]
@@ -226,9 +221,10 @@
     def getitem(self, index):
         return self.value[index]
 
-    def getslice(self, start, stop):
-        assert 0 <= start <= stop <= len(self.value)
-        return self.value[start:stop]
+    def getslice(self, start, stop, step, size):
+        if step == 1:
+            return self.value[start:stop]
+        return "".join([self.value[start + i*step] for i in xrange(size)])
 
 
 class StringLikeBuffer(Buffer):
@@ -282,11 +278,11 @@
     def getitem(self, index):
         return self.buffer.getitem(self.offset + index)
 
-    def getslice(self, start, stop):
+    def getslice(self, start, stop, step, size):
         if start == stop:
             return ''     # otherwise, adding self.offset might make them
                           # out of bounds
-        return self.buffer.getslice(self.offset + start, self.offset + stop)
+        return self.buffer.getslice(self.offset + start, self.offset + stop, step, size)
 
 class SubBuffer(SubBufferMixin, Buffer):
     pass


More information about the Pypy-commit mailing list