[pypy-commit] pypy py3.5-memoryview: lots of logic for memoryview (work in progress)

plan_rich pypy.commits at gmail.com
Mon Aug 22 07:18:48 EDT 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5-memoryview
Changeset: r86415:970730c55763
Date: 2016-08-22 13:18 +0200
http://bitbucket.org/pypy/pypy/changeset/970730c55763/

Log:	lots of logic for memoryview (work in progress)

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1428,7 +1428,6 @@
 
     BUF_SIMPLE   = 0x0000
     BUF_WRITABLE = 0x0001
-    BUF_C        = 0x0002
     BUF_FORMAT   = 0x0004
     BUF_ND       = 0x0008
     BUF_STRIDES  = 0x0010 | BUF_ND
@@ -1440,6 +1439,12 @@
     BUF_FULL_RO = BUF_INDIRECT | BUF_FORMAT
     BUF_FULL    = BUF_INDIRECT | BUF_FORMAT | BUF_WRITABLE
 
+    MEMORYVIEW_MAX_DIM = 64
+    MEMORYVIEW_C        = 0x0002
+    MEMORYVIEW_FORTRAN  = 0x0004
+    MEMORYVIEW_SCLAR    = 0x0008
+    MEMORYVIEW_PIL      = 0x0010
+
     def check_buf_flags(self, flags, readonly):
         if readonly and flags & self.BUF_WRITABLE == self.BUF_WRITABLE:
             raise oefmt(self.w_BufferError, "Object is not writable.")
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
@@ -225,6 +225,14 @@
             size = rffi.sizeof(rffi.VOIDP)
         return size
 
+    def _zero_in_shape(self):
+        view = self.buf
+        shape = view.shape
+        for i in range(view.ndim):
+            if shape[i] == 0:
+                return True
+        return False
+
     def descr_cast(self, space, w_format, w_shape=None):
         self._check_released(space)
 
@@ -232,21 +240,111 @@
             raise OperationError(space.w_TypeError, \
                     space.wrap("memoryview: format argument must be a string"))
 
-        # XXX fixme. does not do anything near cpython (see memoryobjet.c memory_cast)
-        #if self.flags & (space.BUF_CONTIG_RO|space.BUF_C) == 0:
-        #    raise OperationError(space.w_TypeError, \
-        #            space.wrap("memoryview: casts are restricted" \
-        #                       " to C-contiguous views"))
+        buf = self.buf
+        ndim = 1
 
-        fmt = space.str_w(w_format)
-        newitemsize = self.get_native_fmtchar(fmt)
-        return W_MemoryView(self.buf, fmt, newitemsize)
+        if not memory_view_c_contiguous(buf.flags):
+            raise OperationError(space.w_TypeError, \
+                    space.wrap("memoryview: casts are restricted" \
+                               " to C-contiguous views"))
+
+        if (w_shape or buf.ndim != 1) and self._zero_in_shape():
+            raise OperationError(space.w_TypeError, \
+                    space.wrap("memoryview: cannot casts view with" \
+                               " zeros in shape or strides"))
+
+        if w_shape:
+            if not (space.is_w(w_obj, space.w_list) or space.is_w(w_obj, space.w_tuple)):
+                raise oefmt(space.w_TypeError, "expected list or tuple got %T", w_obj)
+            ndim = space.len_w(w_obj)
+            if ndim > space.BUF_MAX_DIM:
+                raise oefmt(space.w_ValueError, \
+                        "memoryview: number of dimensions must not exceed %d",
+                        ndim)
+            if ndim != buf.ndim:
+                raise OperationError(space.w_TypeError, \
+                    space.wrap("memoryview: cast must be 1D -> ND or ND -> 1D"))
+
+        mv = W_MemoryView(self.buf)
+        mv._init_shared_values(space, self)
+        mv.itemsize = self.get_native_fmtchar(fmt)
+
+        if not mv._cast_to_1D(space, fmt):
+            return space.w_None
+        if w_shape is not space.w_None:
+            shape = space.fixedview(w_shape)
+            if not mv._cast_to_ND(space, shape, ndim):
+                return space.w_None
+        return mv
+
+    def _init_flags(self):
+        view = self.buf
+        ndim = view.ndim
+        flags = 0
+        if ndim == 0:
+            flags |= space.MEMORYVIEW_SCALAR | space.MEMORYVIEW_C | space.MEMORYVIEW_FORTRAN
+        if ndim == 1:
+            if view.shape[0] == 1 and view.strides[0] == view.itemsize:
+                flags |= space.MEMORYVIEW_C | space.MEMORYVIEW_SCALAR
+        if view.is_contiguous('C'):
+            flags |= space.MEMORYVIEW_C
+        elif view.is_contiguous('F'):
+            flags |= space.MEMORYVIEW_SCALAR
+
+        # XXX missing suboffsets
+
+        view.flags = flags
+
+    def _cast_to_1D(self, space, fmt):
+        itemsize = self.get_native_fmtchar(fmt)
+        view = self.buf
+        if itemsize < 0:
+            raise OperationError(space.w_ValueError, "memoryview: destination" \
+                    " format must be a native single character format prefixed" \
+                    " with an optional '@'")
+
+        if self.get_native_fmtchar(view.format) < 0 or \
+           (not is_byte_format(fmt) and not is_byte_format(view.format)):
+            raise OperationError(space.w_TypeError,
+                    "memoryview: cannot cast between" \
+                    " two non-byte formats")
+
+        if view.length % itemsize != 0:
+            raise OperationError(space.w_TypeError,
+                    "memoryview: length is not a multiple of itemsize")
+
+        view.format = get_native_fmtstr(fmt)
+        if not view.format:
+            raise OperationError(space.w_RuntimeError,
+                    "memoryview: internal error")
+        view.itemsize = itemsize
+        view.ndim = 1
+        view.shape[0] = view.length / view.itemsize
+        view.srides[0] = view.itemsize
+        # XX suboffsets
+
+        mv._init_flags()
+
+    def _cast_to_ND(self, space, shape, ndim):
+        pass
+
+    def _init_shared_values(self, space, of):
+        mv.buf = buf # XXX not quite right
+        mv.format = of.format
+        mv.readonly = of.readonly
+        mv.itemsize = of.itemsize
+        return mv
 
     def descr_hex(self, space):
         from pypy.objspace.std.bytearrayobject import _array_to_hexstring
         self._check_released(space)
         return _array_to_hexstring(space, self.buf)
 
+def is_byte_format(char):
+    return char == 'b' or char == 'B' or char == 'c'
+
+def memory_view_c_contiguous(flags):
+    return flags & (space.BUF_CONTIG_RO|space.BUF_C) != 0
 
 W_MemoryView.typedef = TypeDef(
     "memoryview",


More information about the pypy-commit mailing list