[pypy-commit] pypy refactor-buffer-api: clean up buffer/memoryview setitem

bdkearns noreply at buildbot.pypy.org
Thu Apr 24 09:40:33 CEST 2014


Author: Brian Kearns <bdkearns at gmail.com>
Branch: refactor-buffer-api
Changeset: r70920:fc458f88faff
Date: 2014-04-24 01:44 -0400
http://bitbucket.org/pypy/pypy/changeset/fc458f88faff/

Log:	clean up buffer/memoryview setitem

diff --git a/pypy/module/__pypy__/test/test_bytebuffer.py b/pypy/module/__pypy__/test/test_bytebuffer.py
--- a/pypy/module/__pypy__/test/test_bytebuffer.py
+++ b/pypy/module/__pypy__/test/test_bytebuffer.py
@@ -13,3 +13,15 @@
         assert b[-1] == '*'
         assert b[-2] == '-'
         assert b[-3] == '+'
+        exc = raises(TypeError, "b[3] = 'abc'")
+        assert str(exc.value) == "right operand must be a single byte"
+        exc = raises(TypeError, "b[3:5] = 'abc'")
+        assert str(exc.value) == "right operand length must match slice length"
+        exc = raises(TypeError, "b[3:7:2] = 'abc'")
+        assert str(exc.value) == "right operand length must match slice length"
+
+        b = bytebuffer(10)
+        b[1:3] = 'xy'
+        assert str(b) == "\x00xy" + "\x00" * 7
+        b[4:8:2] = 'zw'
+        assert str(b) == "\x00xy\x00z\x00w" + "\x00" * 3
diff --git a/pypy/objspace/std/bufferobject.py b/pypy/objspace/std/bufferobject.py
--- a/pypy/objspace/std/bufferobject.py
+++ b/pypy/objspace/std/bufferobject.py
@@ -10,7 +10,6 @@
 from pypy.interpreter.typedef import TypeDef
 from rpython.rlib.objectmodel import compute_hash
 from rpython.rlib.rstring import StringBuilder
-from pypy.objspace.std.memoryobject import _buffer_setitem
 
 
 class W_Buffer(W_Root):
@@ -71,12 +70,26 @@
         res = self.buf.getslice(start, stop, step, size)
         return space.wrap(res)
 
-    @unwrap_spec(newstring='bufferstr')
-    def descr_setitem(self, space, w_index, newstring):
+    def descr_setitem(self, space, w_index, w_obj):
         if not self.buf.is_writable():
             raise OperationError(space.w_TypeError,
                                  space.wrap("buffer is read-only"))
-        _buffer_setitem(space, self.buf, w_index, newstring)
+        start, stop, step, size = space.decode_index4(w_index, self.buf.getlength())
+        value = space.readbuf_w(w_obj)
+        if step == 0:  # index only
+            if value.getlength() != 1:
+                msg = "right operand must be a single byte"
+                raise OperationError(space.w_TypeError, space.wrap(msg))
+            self.buf.setitem(start, value.getitem(0))
+        else:
+            if value.getlength() != size:
+                msg = "right operand length must match slice length"
+                raise OperationError(space.w_TypeError, space.wrap(msg))
+            if step == 1:
+                self.buf.setslice(start, value.as_str())
+            else:
+                for i in range(size):
+                    self.buf.setitem(start + i * step, value.getitem(i))
 
     def descr_str(self, space):
         return space.wrap(self.buf.as_str())
diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -10,25 +10,6 @@
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 
 
-def _buffer_setitem(space, buf, w_index, newstring):
-    start, stop, step, size = space.decode_index4(w_index, buf.getlength())
-    if step == 0:  # index only
-        if len(newstring) != 1:
-            msg = 'buffer[index]=x: x must be a single character'
-            raise OperationError(space.w_TypeError, space.wrap(msg))
-        char = newstring[0]   # annotator hint
-        buf.setitem(start, char)
-    elif step == 1:
-        if len(newstring) != size:
-            msg = "right operand length must match slice length"
-            raise OperationError(space.w_ValueError, space.wrap(msg))
-        buf.setslice(start, newstring)
-    else:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("buffer object does not support"
-                                        " slicing with a step"))
-
-
 class W_MemoryView(W_Root):
     """Implement the built-in 'memoryview' type as a wrapper around
     an interp-level buffer.
@@ -40,7 +21,8 @@
         self.buf = buf
 
     def buffer_w(self, space, flags):
-        return space.buffer_w(self.obj, flags)
+        space.check_buf_flags(flags, self.buf.readonly)
+        return self.buf
 
     @staticmethod
     def descr_new_memoryview(space, w_subtype, w_object):
@@ -101,22 +83,28 @@
 
     def descr_getitem(self, space, w_index):
         start, stop, step = space.decode_index(w_index, self.getlength())
+        if step not in (0, 1):
+            raise OperationError(space.w_NotImplementedError, space.wrap(""))
         if step == 0:  # index only
             return space.wrap(self.buf.getitem(start))
+        res = self.getslice(start, stop)
+        return space.wrap(res)
+
+    def descr_setitem(self, space, w_index, w_obj):
+        if not self.buf.is_writable():
+            raise OperationError(space.w_TypeError, space.wrap(
+                "cannot modify read-only memory"))
+        start, stop, step, size = space.decode_index4(w_index, self.buf.getlength())
+        if step not in (0, 1):
+            raise OperationError(space.w_NotImplementedError, space.wrap(""))
+        value = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
+        if value.getlength() != size:
+            raise OperationError(space.w_ValueError, space.wrap(
+                "cannot modify size of memoryview object"))
+        if step == 0:  # index only
+            self.buf.setitem(start, value.getitem(0))
         elif step == 1:
-            res = self.getslice(start, stop)
-            return space.wrap(res)
-        else:
-            raise OperationError(space.w_ValueError,
-                space.wrap("memoryview object does not support"
-                           " slicing with a step"))
-
-    @unwrap_spec(newstring='bufferstr')
-    def descr_setitem(self, space, w_index, newstring):
-        if not self.buf.is_writable():
-            raise OperationError(space.w_TypeError,
-                                 space.wrap("cannot modify read-only memory"))
-        _buffer_setitem(space, self.buf, w_index, newstring)
+            self.buf.setslice(start, value.as_str())
 
     def descr_len(self, space):
         return space.wrap(self.buf.getlength())
diff --git a/pypy/objspace/std/test/test_memoryobject.py b/pypy/objspace/std/test/test_memoryobject.py
--- a/pypy/objspace/std/test/test_memoryobject.py
+++ b/pypy/objspace/std/test/test_memoryobject.py
@@ -7,11 +7,14 @@
         assert v.tolist() == [97, 98, 99]
         assert v[1] == "b"
         assert v[-1] == "c"
-        raises(TypeError, "v[1] = 'x'")
+        exc = raises(TypeError, "v[1] = 'x'")
+        assert str(exc.value) == "cannot modify read-only memory"
         assert v.readonly is True
         w = v[1:234]
         assert isinstance(w, memoryview)
         assert len(w) == 2
+        exc = raises(NotImplementedError, "v[0:2:2]")
+        assert str(exc.value) == ""
 
     def test_rw(self):
         data = bytearray('abcefg')
@@ -21,7 +24,12 @@
         assert data == bytearray(eval("b'zbcefg'"))
         v[1:4] = '123'
         assert data == bytearray(eval("b'z123fg'"))
-        raises((ValueError, TypeError), "v[2] = 'spam'")
+        v[0:3] = v[2:5]
+        assert data == bytearray(eval("b'23f3fg'"))
+        exc = raises(ValueError, "v[2] = 'spam'")
+        assert str(exc.value) == "cannot modify size of memoryview object"
+        exc = raises(NotImplementedError, "v[0:2:2] = 'spam'")
+        assert str(exc.value) == ""
 
     def test_memoryview_attrs(self):
         v = memoryview("a"*100)


More information about the pypy-commit mailing list