[pypy-commit] pypy py3.5: new test case (reverse buffer type i),
plan_rich
pypy.commits at gmail.com
Fri Jan 13 07:12:26 EST 2017
Author: Richard Plangger <planrichi at 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
+
+ at 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]
More information about the pypy-commit
mailing list