Author: Richard Plangger <planri...@gmail.com>
Branch: py3.5
Changeset: r89540:4cada5dbc4cd
Date: 2017-01-13 13:10 +0100
http://bitbucket.org/pypy/pypy/changeset/4cada5dbc4cd/

Log:    new test case (reverse buffer type i), copy over flag checking from
        cpyext and adapt the code there. changes needed to properly setup
        the memoryview flags

diff --git a/pypy/module/cpyext/memoryobject.py 
b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -8,7 +8,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rlib.rarithmetic import widen
 from pypy.interpreter.error import oefmt
-from pypy.objspace.std.memoryobject import W_MemoryView
+from pypy.objspace.std.memoryobject import W_MemoryView, _pybuffer_iscontiguous
 from pypy.module.cpyext.object import _dealloc
 from pypy.module.cpyext.import_ import PyImport_Import
 
@@ -164,41 +164,8 @@
     view.c_internal = lltype.nullptr(rffi.VOIDP.TO)
     return 0
 
-def _IsFortranContiguous(view):
-    ndim = widen(view.c_ndim)
-    if ndim == 0:
-        return 1
-    if not view.c_strides:
-        return ndim == 1
-    sd = view.c_itemsize
-    if ndim == 1:
-        return view.c_shape[0] == 1 or sd == view.c_strides[0]
-    for i in range(view.c_ndim):
-        dim = view.c_shape[i]
-        if dim == 0:
-            return 1
-        if view.c_strides[i] != sd:
-            return 0
-        sd *= dim
-    return 1
-
-def _IsCContiguous(view):
-    ndim = widen(view.c_ndim)
-    if ndim == 0:
-        return 1
-    if not view.c_strides:
-        return ndim == 1
-    sd = view.c_itemsize
-    if ndim == 1:
-        return view.c_shape[0] == 1 or sd == view.c_strides[0]
-    for i in range(ndim - 1, -1, -1):
-        dim = view.c_shape[i]
-        if dim == 0:
-            return 1
-        if view.c_strides[i] != sd:
-            return 0
-        sd *= dim
-    return 1
+# If you are looking for _IsFortran/CContiguous look in 
+# pypy/module/cpyext/memoryobject.py
 
 @cpython_api([Py_bufferP, lltype.Char], rffi.INT_real, error=CANNOT_FAIL)
 def PyBuffer_IsContiguous(space, view, fort):
@@ -207,15 +174,13 @@
     (fort is 'A').  Return 0 otherwise."""
     # traverse the strides, checking for consistent stride increases from
     # right-to-left (c) or left-to-right (fortran). Copied from cpython
-    if view.c_suboffsets:
-        return 0
-    if (fort == 'C'):
-        return _IsCContiguous(view)
-    elif (fort == 'F'):
-        return _IsFortranContiguous(view)
-    elif (fort == 'A'):
-        return (_IsCContiguous(view) or _IsFortranContiguous(view))
-    return 0
+
+    # plan_rich: I wanted to reuse this check in pypy/objspace/std/...
+    # memoryview.py, thus I have rewritten it, maybe it is time to 
+    # find a way to share this code?
+    return _pybuffer_iscontiguous(view.c_suboffsets,
+              widen(view.c_ndim), view.c_shape, view.c_strides,
+              view.c_itemsize, fort)
 
 @cpython_api([PyObject], PyObject, result_is_ll=True)
 def PyMemoryView_FromObject(space, w_obj):
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
@@ -13,6 +13,7 @@
 from pypy.module.struct.formatiterator import UnpackFormatIterator, 
PackFormatIterator
 from pypy.objspace.std.bytesobject import getbytevalue
 from rpython.rlib.unroll import unrolling_iterable
+from rpython.rlib.objectmodel import always_inline
 
 MEMORYVIEW_MAX_DIM = 64
 MEMORYVIEW_SCALAR   = 0x0001
@@ -571,19 +572,26 @@
         flags = 0
         if ndim == 0:
             flags |= MEMORYVIEW_SCALAR | MEMORYVIEW_C | MEMORYVIEW_FORTRAN
-        if ndim == 1:
-            shape = buf.getshape()
-            strides = buf.getstrides()
-            if len(shape) > 0 and shape[0] == 1 and \
-               len(strides) > 0 and strides[0] == buf.getitemsize():
+        elif ndim == 1:
+            shape = self.getshape()
+            strides = self.getstrides()
+            if shape[0] == 1 or strides[0] == self.getitemsize():
                 flags |= MEMORYVIEW_C | MEMORYVIEW_SCALAR
-        # TODO for now?
-        flags |= MEMORYVIEW_C
-        # TODO if buf.is_contiguous('C'):
-        # TODO     flags |= MEMORYVIEW_C
-        # TODO elif buf.is_contiguous('F'):
-        # TODO     flags |= MEMORYVIEW_FORTRAN
+        else:
+            ndim = self.getndim()
+            shape = self.getshape()
+            strides = self.getstrides()
+            itemsize = self.getitemsize()
+            if _pybuffer_iscontiguous(None, ndim, shape, strides,
+                                      itemsize, 'C'):
+                flags |= MEMORYVIEW_C
+            if _pybuffer_iscontiguous(None, ndim, shape, strides,
+                                      itemsize, 'F'):
+                flags |= MEMORYVIEW_C
 
+        if self.suboffsets:
+            flags |= MEMORYVIEW_PIL
+            flags &= ~(MEMORYVIEW_C|MEMORYVIEW_FORTRAN)
         # TODO missing suboffsets
 
         self.flags = flags
@@ -675,19 +683,17 @@
     def descr_hex(self, space):
         from pypy.objspace.std.bytearrayobject import _array_to_hexstring
         self._check_released(space)
-        if isinstance(self.buf, SubBuffer):
-            step = self.strides[0]
-            return _array_to_hexstring(space, self.buf.buffer,
-                                       self.buf.offset, step,
-                                       self.getlength())
+        if memory_view_c_contiguous(space, self.flags):
+            return _array_to_hexstring(space, self.buf, 0, 1, self.getlength())
         else:
-            return _array_to_hexstring(space, self.buf, 0, 1, self.getlength())
+            bytes = self.as_str()
+            return _array_to_hexstring(space, bytes, 0, 1, len(bytes), True)
 
 def is_byte_format(char):
     return char == 'b' or char == 'B' or char == 'c'
 
 def memory_view_c_contiguous(space, flags):
-    return flags & (space.BUF_CONTIG_RO|MEMORYVIEW_C) != 0
+    return flags & (MEMORYVIEW_SCALAR|MEMORYVIEW_C)
 
 W_MemoryView.typedef = TypeDef(
     "memoryview",
@@ -721,3 +727,51 @@
     _pypy_raw_address = interp2app(W_MemoryView.descr_pypy_raw_address),
     )
 W_MemoryView.typedef.acceptable_as_base_class = False
+
+def _IsFortranContiguous(ndim, shape, strides, itemsize):
+    if ndim == 0:
+        return 1
+    if not strides:
+        return ndim == 1
+    sd = itemsize
+    if ndim == 1:
+        return shape[0] == 1 or sd == strides[0]
+    for i in range(ndim):
+        dim = shape[i]
+        if dim == 0:
+            return 1
+        if strides[i] != sd:
+            return 0
+        sd *= dim
+    return 1
+
+def _IsCContiguous(ndim, shape, strides, itemsize):
+    if ndim == 0:
+        return 1
+    if not strides:
+        return ndim == 1
+    sd = itemsize
+    if ndim == 1:
+        return shape[0] == 1 or sd == strides[0]
+    for i in range(ndim - 1, -1, -1):
+        dim = shape[i]
+        if dim == 0:
+            return 1
+        if strides[i] != sd:
+            return 0
+        sd *= dim
+    return 1
+
+@always_inline
+def _pybuffer_iscontiguous(suboffsets, ndim, shape, strides, itemsize, fort):
+    if suboffsets:
+        return 0
+    if (fort == 'C'):
+        return _IsCContiguous(ndim, shape, strides, itemsize)
+    elif (fort == 'F'):
+        return _IsFortranContiguous(ndim, shape, strides, itemsize)
+    elif (fort == 'A'):
+        return (_IsCContiguous(ndim, shape, strides, itemsize) or \
+                _IsFortranContiguous(ndim, shape, strides, itemsize))
+    return 0
+
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
@@ -8,7 +8,7 @@
 from pypy.conftest import option
 
 class AppTestMemoryView:
-    spaceconfig = dict(usemodules=['array'])
+    spaceconfig = dict(usemodules=['array', 'sys'])
 
     def test_basic(self):
         v = memoryview(b"abc")
@@ -199,6 +199,16 @@
         m2 = m1[::-1]
         assert m2.hex() == '3130' * 100000
 
+    def test_hex_2(self):
+        import array
+        import sys
+        m1 = memoryview(array.array('i', [1,2,3,4]))
+        m2 = m1[::-1]
+        if sys.byteorder == 'little':
+            assert m2.hex() == "04000000030000000200000001000000"
+        else:
+            assert m2.hex() == "00000004000000030000000200000001"
+
     def test_memoryview_cast(self):
         m1 = memoryview(b'abcdefgh')
         m2 = m1.cast('I')
@@ -391,7 +401,10 @@
         assert view.format == 'b'
         assert cview.format == 'i'
         #
-        assert cview.cast('b').cast('q').cast('b').tolist() == []
+        a = cview.cast('b')
+        b = a.cast('q')
+        c = b.cast('b')
+        assert c.tolist() == []
         #
         assert cview.format == 'i'
         raises(TypeError, "cview.cast('i')")
@@ -399,7 +412,7 @@
     def test_cast_with_shape(self):
         empty = self.MockArray([1,0,2,0,3,0],
                     dim=1, fmt='h', size=2,
-                    strides=[8], shape=[6])
+                    strides=[2], shape=[6])
         view = memoryview(empty)
         byteview = view.cast('b')
         assert byteview.tolist() == [1,0,0,0,2,0,0,0,3,0,0,0]
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to