[pypy-commit] pypy py3.5-ssl: several changes to the memoryview object to pass the tests, most of the problems were related to wrong index calculations

plan_rich pypy.commits at gmail.com
Wed Dec 7 05:48:19 EST 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5-ssl
Changeset: r88930:c9097583272c
Date: 2016-12-07 11:47 +0100
http://bitbucket.org/pypy/pypy/changeset/c9097583272c/

Log:	several changes to the memoryview object to pass the tests, most of
	the problems were related to wrong index calculations

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
@@ -115,8 +115,6 @@
         return ''.join(self.copy_buffer())
 
     def copy_buffer(self):
-        buf = self.buf
-        n_bytes = buf.getlength()
         data = []
         self._copy_rec(0, data, 0)
         return data
@@ -130,7 +128,6 @@
             self._copy_base(data,off)
             return
 
-        # TODO add a test that has at least 2 dims
         for i in range(shape):
             self._copy_rec(idim+1,data,off)
             off += strides[idim]
@@ -140,18 +137,21 @@
         step = shapes[0]
         strides = self.getstrides()
         itemsize = self.getitemsize()
+        bytesize = self.getlength()
+        copiedbytes = 0
         for i in range(step):
             bytes = self.buf.getslice(off, off+itemsize, 1, itemsize)
             data.append(bytes)
+            copiedbytes += len(bytes)
             off += strides[0]
             # do notcopy data if the sub buffer is out of bounds
-            if off >= self.buf.getlength():
+            if copiedbytes >= bytesize:
                 break
 
     def getlength(self):
         if self.length != -1:
-            return self.length // self.itemsize
-        return self.buf.getlength() // self.itemsize
+            return self.length
+        return self.buf.getlength()
 
     def descr_tobytes(self, space):
         self._check_released(space)
@@ -198,8 +198,9 @@
             return self._tolist(space, buf, bytecount, itemsize, fmt, [stride])
         items = [None] * dimshape
 
+        orig_buf = buf
         for i in range(dimshape):
-            buf = SubBuffer(buf, start, stride)
+            buf = SubBuffer(orig_buf, start, stride)
             item = self._tolist_rec(space, buf, start, idim+1, fmt)
             items[i] = item
             start += stride
@@ -232,9 +233,8 @@
         if index < 0 or index >= nitems:
             raise oefmt(space.w_IndexError,
                 "index out of bounds on dimension %d", dim+1)
-        start += strides[dim] * index
         # TODO suboffsets?
-        return start
+        return start + strides[dim] * index
 
     def _getitem_tuple_indexed(self, space, w_index):
         view = self.buf
@@ -259,54 +259,60 @@
         fmtiter.interpret(fmt)
         return fmtiter.result_w[0]
 
+    def _decode_index(self, space, w_index, is_slice):
+        shape = self.getshape()
+        if len(shape) == 0:
+            count = 1
+        else:
+            count = shape[0]
+        return space.decode_index4(w_index, count)
 
     def descr_getitem(self, space, w_index):
         self._check_released(space)
 
         if space.isinstance_w(w_index, space.w_tuple):
             return self._getitem_tuple_indexed(space, w_index)
-
-        shape = self.getshape()
-        start, stop, step, slicelength = space.decode_index4(w_index, shape[0])
+        is_slice = space.isinstance_w(w_index, space.w_slice)
+        start, stop, step, slicelength = self._decode_index(space, w_index, is_slice)
         # ^^^ for a non-slice index, this returns (index, 0, 0, 1)
         if step == 0:  # index only
             itemsize = self.getitemsize()
             dim = self.getndim()
-            if itemsize == 1:
-                if dim == 0:
-                    raise oefmt(space.w_TypeError, "invalid indexing of 0-dim memory")
-                elif dim == 1:
-                    idx = self.lookup_dimension(space, self, 0, 0, start)
+            if dim == 0:
+                raise oefmt(space.w_TypeError, "invalid indexing of 0-dim memory")
+            elif dim == 1:
+                idx = self.lookup_dimension(space, self, 0, 0, start)
+                if itemsize == 1:
                     ch = self.buf.getitem(idx)
                     return space.newint(ord(ch))
                 else:
-                    raise oefmt(space.w_NotImplementedError, "multi-dimensional sub-views are not implemented")
+                    # TODO: this probably isn't very fast
+                    buf = SubBuffer(self.buf, idx, itemsize)
+                    fmtiter = UnpackFormatIterator(space, buf)
+                    fmtiter.length = buf.getlength()
+                    fmtiter.interpret(self.format)
+                    return fmtiter.result_w[0]
             else:
-                # TODO: this probably isn't very fast
-                buf = SubBuffer(self.buf, start*itemsize, itemsize)
-                fmtiter = UnpackFormatIterator(space, buf)
-                fmtiter.interpret(self.format)
-                return fmtiter.result_w[0]
-        elif step == 1:
-            mv = W_MemoryView.copy(self)
-            mv.init_slice(start, stop, step, slicelength, 0)
-            mv._init_flags()
-            return mv
-        else:
+                raise oefmt(space.w_NotImplementedError, "multi-dimensional sub-views are not implemented")
+        elif is_slice:
             mv = W_MemoryView.copy(self)
             mv.init_slice(start, stop, step, slicelength, 0)
             mv.init_len()
             mv._init_flags()
             return mv
+        # multi index is handled at the top of this function
+        else:
+            raise TypeError("memoryview: invalid slice key")
 
     def init_slice(self, start, stop, step, slicelength, dim):
         # modifies the buffer, shape and stride to allow step to be > 1
-        # TODO subbuffer
         self.strides = strides = self.getstrides()[:]
         self.shape = shape = self.getshape()[:]
-        self.buf = SubBuffer(self.buf, strides[dim] * start, slicelength)
+        bytesize = self.getitemsize() * slicelength
+        self.buf = SubBuffer(self.buf, strides[dim] * start, bytesize)
         shape[dim] = slicelength
         strides[dim] = strides[dim] * step
+        # TODO subbuffer
 
     def init_len(self):
         self.length = self.bytecount_from_shape()
@@ -334,6 +340,8 @@
         if space.isinstance_w(w_index, space.w_tuple):
             raise oefmt(space.w_NotImplementedError, "")
         start, stop, step, size = space.decode_index4(w_index, self.getlength())
+        is_slice = space.isinstance_w(w_index, space.w_slice)
+        start, stop, step, slicelength = self._decode_index(space, w_index, is_slice)
         itemsize = self.getitemsize()
         if step == 0:  # index only
             if itemsize == 1:
@@ -351,7 +359,7 @@
                 self.buf.setslice(start * itemsize, fmtiter.result.build())
         elif step == 1:
             value = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
-            if value.getlength() != size * itemsize:
+            if value.getlength() != slicelength * itemsize:
                 raise oefmt(space.w_ValueError,
                             "cannot modify size of memoryview object")
             self.buf.setslice(start * itemsize, value.as_str())
@@ -367,11 +375,11 @@
             src = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
             dst_strides = self.getstrides()
             dim = 0
-            dst = SubBuffer(self.buf, start * itemsize, size * itemsize)
+            dst = SubBuffer(self.buf, start * itemsize, slicelength * itemsize)
             src_stride0 = dst_strides[dim]
 
             off = 0
-            src_shape0 = size
+            src_shape0 = slicelength
             src_stride0 = src.getstrides()[0]
             if isinstance(w_obj, W_MemoryView):
                 src_stride0 = w_obj.getstrides()[0]
@@ -386,11 +394,15 @@
 
     def descr_len(self, space):
         self._check_released(space)
-        return space.wrap(self.getlength())
+        dim = self.getndim()
+        if dim == 0:
+            return 1
+        shape = self.getshape()
+        return space.wrap(shape[0])
 
     def w_get_nbytes(self, space):
         self._check_released(space)
-        return space.wrap(self.buf.getlength())
+        return space.wrap(self.getlength())
 
     def w_get_format(self, space):
         self._check_released(space)
@@ -398,11 +410,11 @@
 
     def w_get_itemsize(self, space):
         self._check_released(space)
-        return space.wrap(self.itemsize)
+        return space.wrap(self.getitemsize())
 
     def w_get_ndim(self, space):
         self._check_released(space)
-        return space.wrap(self.buf.getndim())
+        return space.wrap(self.getndim())
 
     def w_is_readonly(self, space):
         self._check_released(space)
@@ -410,13 +422,13 @@
 
     def w_get_shape(self, space):
         self._check_released(space)
-        if self.buf.getndim() == 0:
+        if self.getndim() == 0:
             return space.w_None
         return space.newtuple([space.wrap(x) for x in self.getshape()])
 
     def w_get_strides(self, space):
         self._check_released(space)
-        if self.buf.getndim() == 0:
+        if self.getndim() == 0:
             return space.w_None
         return space.newtuple([space.wrap(x) for x in self.getstrides()])
 
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
@@ -43,13 +43,13 @@
     def test_extended_slice(self):
         data = bytearray(b'abcefg')
         v = memoryview(data)
-        w = v[0:2:2]      # failing for now: NotImplementedError
+        w = v[0:2:2]
         assert len(w) == 1
         assert list(w) == [97]
         v[::2] = b'ABC'
         assert data == bytearray(eval("b'AbBeCg'"))
-        assert v[::2] == b'ABC'
-        assert v[::-2] == b'geb'
+        assert v[::2].tobytes() == b'ABC'
+        assert v[::-2].tobytes() == b'geb'
 
     def test_memoryview_attrs(self):
         v = memoryview(b"a"*100)


More information about the pypy-commit mailing list