[pypy-commit] pypy py3.5: merge translation fix
plan_rich
pypy.commits at gmail.com
Tue Aug 30 14:49:02 EDT 2016
Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5
Changeset: r86754:21d53f6805c2
Date: 2016-08-30 20:46 +0200
http://bitbucket.org/pypy/pypy/changeset/21d53f6805c2/
Log: merge translation fix
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -636,6 +636,18 @@
def getlength(self):
return self.array.len * self.array.itemsize
+ def getformat(self):
+ return self.array.typecode
+
+ def getitemsize(self):
+ return self.array.itemsize
+
+ def getndim(self):
+ return 1
+
+ def getstrides(self):
+ return [self.getitemsize()]
+
def getitem(self, index):
array = self.array
data = array._charbuf_start()
diff --git a/pypy/module/micronumpy/test/__init__.py b/pypy/module/micronumpy/test/__init__.py
--- a/pypy/module/micronumpy/test/__init__.py
+++ b/pypy/module/micronumpy/test/__init__.py
@@ -1,2 +1,2 @@
import py
-py.test.py3k_skip('not yet supported')
+# XXX py.test.py3k_skip('not yet supported')
diff --git a/pypy/module/micronumpy/test/dummy_module.py b/pypy/module/micronumpy/test/dummy_module.py
--- a/pypy/module/micronumpy/test/dummy_module.py
+++ b/pypy/module/micronumpy/test/dummy_module.py
@@ -20,7 +20,9 @@
for t in types:
globals()[t] = dtype(t).type
-types = ['bool', 'int', 'float', 'complex', 'str', 'string', 'unicode', 'object']
+# removed 'string' and 'unicode' from that list to handle an error in
+# make_new_dtype (micronumpy/descriptor.py)
+types = ['bool', 'int', 'float', 'complex', 'str', 'object']
for t in types:
globals()[t + '_'] = dtype(t).type
del types
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -9,7 +9,7 @@
@classmethod
def setup_class(cls):
- py.test.py3k_skip("micronumpy not supported on py3k")
+ # XXX py.test.py3k_skip("micronumpy not supported on py3k")
if option.runappdirect:
import sys
if '__pypy__' not in sys.builtin_module_names:
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -502,6 +502,7 @@
return data
HEXDIGITS = "0123456789abcdef"
+PY_SIZE_T_MAX = intmask(2**(rffi.sizeof(rffi.SIZE_T)*8-1)-1)
@specialize.arg(3) # raw access
def _array_to_hexstring(space, buf, len=0, rawaccess=False):
@@ -509,11 +510,11 @@
length = len
else:
length = buf.getlength()
+ hexstring = StringBuilder(length*2)
- if length > sys.maxint / 2:
+ if length > PY_SIZE_T_MAX/2:
raise OperationError(space.w_MemoryError, space.w_None)
- hexstring = StringBuilder(length*2)
for i in range(length):
if rawaccess:
byte = ord(buf[i])
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -659,6 +659,10 @@
def descr_upper(self, space):
return W_BytesObject(self._value.upper())
+ def descr_hex(self, space):
+ from pypy.objspace.std.bytearrayobject import _array_to_hexstring
+ return _array_to_hexstring(space, StringBuffer(self._value))
+
@staticmethod
def _iter_getitem_result(self, space, index):
assert isinstance(self, W_BytesObject)
@@ -843,6 +847,7 @@
fromhex = interp2app(W_BytesObject.descr_fromhex, as_classmethod=True),
maketrans = interp2app(W_BytesObject.descr_maketrans, as_classmethod=True),
+ hex = interp2app(W_BytesObject.descr_hex),
)
W_BytesObject.typedef.flag_sequence_bug_compat = True
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,27 +10,73 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef, GetSetProperty, make_weakref_descr
+from pypy.module.struct.formatiterator import UnpackFormatIterator, PackFormatIterator
from pypy.objspace.std.bytesobject import getbytevalue
-from pypy.module.struct.formatiterator import UnpackFormatIterator, PackFormatIterator
+from rpython.rlib.unroll import unrolling_iterable
+
+MEMORYVIEW_MAX_DIM = 64
+MEMORYVIEW_SCALAR = 0x0001
+MEMORYVIEW_C = 0x0002
+MEMORYVIEW_FORTRAN = 0x0004
+MEMORYVIEW_SCALAR = 0x0008
+MEMORYVIEW_PIL = 0x0010
class W_MemoryView(W_Root):
"""Implement the built-in 'memoryview' type as a wrapper around
an interp-level buffer.
"""
- _immutable_fields_ = ['format', 'itemsize']
- def __init__(self, buf, format='B', itemsize=1):
+ def __init__(self, buf, format=None, itemsize=1, ndim=-1,
+ shape=None, strides=None, suboffsets=None):
assert isinstance(buf, Buffer)
self.buf = buf
self._hash = -1
+ # private copies of format, shape, itemsize, ... on this class
self.format = format
self.itemsize = itemsize
+ self.shape = shape
+ self.strides = strides
+ self.suboffsets = suboffsets
+ self.ndim = ndim
+ self.flags = 0
+ self.length = -1
+ self._init_flags()
+
+ # several fields are "overwritten" by the memory view (shape, strides, ...)
+ # thus use only those getter fields instead of directly accessing the fields
+ def getndim(self):
+ if self.ndim == -1:
+ return self.buf.getndim()
+ return self.ndim
+
+ def getshape(self):
+ if self.shape is None:
+ return self.buf.getshape()
+ return self.shape
+
+ def getstrides(self):
+ if self.strides is None:
+ return self.buf.getstrides()
+ return self.strides
+
+ def getitemsize(self):
+ return self.itemsize
+
+ # memoryview needs to modify the field 'format', to prevent the modification
+ # of the buffer, we save the new format here!
+ def getformat(self):
+ if self.format is None:
+ return self.buf.getformat()
+ return self.format
+
+ def setformat(self, value):
+ self.format = value
def buffer_w_ex(self, space, flags):
self._check_released(space)
space.check_buf_flags(flags, self.buf.readonly)
- return self.buf, self.format, self.itemsize
+ return self.buf, self.getformat(), self.itemsize
@staticmethod
def descr_new_memoryview(space, w_subtype, w_object):
@@ -63,10 +109,45 @@
descr_ne = _make_descr__cmp('ne')
def as_str(self):
+ return ''.join(self.copy_buffer())
+
+ def copy_buffer(self):
buf = self.buf
- return buf.as_str()
+ n_bytes = buf.getlength()
+ data = []
+ self._copy_rec(0, data, 0)
+ return data
+
+ def _copy_rec(self, idim, data, off):
+ shapes = self.getshape()
+ shape = shapes[idim]
+ strides = self.getstrides()
+
+ if self.getndim()-1 == idim:
+ 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]
+
+ def _copy_base(self, data, off):
+ shapes = self.getshape()
+ step = shapes[0]
+ strides = self.getstrides()
+ itemsize = self.getitemsize()
+ for i in range(step):
+ bytes = self.buf.getslice(off, off+itemsize, 1, itemsize)
+ data.append(bytes)
+ off += strides[0]
+ # do notcopy data if the sub buffer is out of bounds
+ if off >= self.buf.getlength():
+ break
def getlength(self):
+ if self.length != -1:
+ return self.length // self.itemsize
return self.buf.getlength() // self.itemsize
def descr_tobytes(self, space):
@@ -75,43 +156,184 @@
def descr_tolist(self, space):
self._check_released(space)
+
+ buf = self.buf
+ dim = self.getndim()
+ fmt = self.getformat()
+ if dim == 0:
+ raise NotImplementedError
+ elif dim == 1:
+ itemsize = self.getitemsize()
+ return self._tolist(space, buf, buf.getlength() // itemsize, fmt)
+ else:
+ return self._tolist_rec(space, buf, 0, 0, fmt)
+
+ def _tolist(self, space, buf, count, fmt):
# TODO: this probably isn't very fast
- fmtiter = UnpackFormatIterator(space, self.buf)
- fmtiter.interpret(self.format * self.getlength())
+ fmtiter = UnpackFormatIterator(space, buf)
+ fmtiter.interpret(fmt * count)
return space.newlist(fmtiter.result_w)
+ def _tolist_rec(self, space, buf, start, idim, fmt):
+ strides = self.getstrides()
+ shape = self.getshape()
+ #
+ dim = idim+1
+ stride = strides[idim]
+ itemsize = self.getitemsize()
+ dimshape = shape[idim]
+ #
+ if dim >= self.getndim():
+ bytecount = (stride * dimshape)
+ count = bytecount // itemsize
+ return self._tolist(space, buf, count, fmt)
+ items = [None] * dimshape
+
+ for i in range(dimshape):
+ item = self._tolist_rec(space, SubBuffer(buf, start, stride), start, idim+1, fmt)
+ items[i] = item
+ start += stride
+
+ return space.newlist(items)
+
+
+ def _start_from_tuple(self, space, w_tuple):
+ from pypy.objspace.std.tupleobject import W_TupleObject
+ start = 0
+
+ view = self.buf
+ length = space.len_w(w_tuple)
+ dim = view.getndim()
+ dim = 0
+ assert isinstance(w_tuple, W_TupleObject)
+ while dim < length:
+ w_obj = w_tuple.getitem(space, dim)
+ index = w_obj.int_w(space)
+ start = self.lookup_dimension(space, start, dim, index)
+ dim += 1
+ return start
+
+ def lookup_dimension(self, space, start, dim, index):
+ view = self.buf
+ shape = view.getshape()
+ strides = view.getstrides()
+ nitems = shape[dim]
+ if index < 0:
+ index += nitems
+ 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
+
+ def _getitem_tuple_indexed(self, space, w_index):
+ view = self.buf
+
+ fmt = view.getformat() # TODO adjust format?
+
+ length = space.len_w(w_index)
+ ndim = view.getndim()
+ if length < ndim:
+ raise OperationError(space.w_NotImplementedError, \
+ space.wrap("sub-views are not implemented"))
+
+ if length > ndim:
+ raise oefmt(space.w_TypeError, \
+ "cannot index %d-dimension view with %d-element tuple",
+ length, ndim)
+
+ start = self._start_from_tuple(space, w_index)
+
+ buf = SubBuffer(self.buf, start, view.getitemsize())
+ fmtiter = UnpackFormatIterator(space, buf)
+ fmtiter.interpret(fmt)
+ return fmtiter.result_w[0]
+
+
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)
+
start, stop, step, size = space.decode_index4(w_index, self.getlength())
# ^^^ for a non-slice index, this returns (index, 0, 0, 1)
- itemsize = self.itemsize
+ itemsize = self.getitemsize()
+ start, stop, size = self._apply_itemsize(space, start, size, itemsize)
if step == 0: # index only
if itemsize == 1:
ch = self.buf.getitem(start)
return space.newint(ord(ch))
else:
# TODO: this probably isn't very fast
- buf = SubBuffer(self.buf, start * itemsize, itemsize)
+ buf = SubBuffer(self.buf, start, itemsize)
fmtiter = UnpackFormatIterator(space, buf)
fmtiter.interpret(self.format)
return fmtiter.result_w[0]
elif step == 1:
- buf = SubBuffer(self.buf, start * itemsize, size * itemsize)
- return W_MemoryView(buf, self.format, itemsize)
+ mv = W_MemoryView.copy(self)
+ mv.slice(start, stop, step, size)
+ mv._init_flags()
+ return mv
else:
- # XXX needs to return a W_MemoryView with a NonContiguousSubBuffer
- # maybe? Need to check the cpyext requirements for that
- raise oefmt(space.w_NotImplementedError,
- "XXX extended slicing")
+ mv = W_MemoryView.copy(self)
+ mv.slice(start, stop, step, size)
+ mv.length = mv.bytecount_from_shape()
+ mv._init_flags()
+ return mv
+
+ def slice(self, start, stop, step, size):
+ # modifies the buffer, shape and stride to allow step to be > 1
+ # NOTE that start, stop & size are already byte offsets/count
+ # TODO subbuffer
+ strides = self.getstrides()[:]
+ shape = self.getshape()[:]
+ itemsize = self.getitemsize()
+ dim = 0
+ self.buf = SubBuffer(self.buf, strides[dim] * (start//itemsize), size*step)
+ shape[dim] = size
+ strides[dim] = strides[dim] * step
+ self.strides = strides
+ self.shape = shape
+
+ def bytecount_from_shape(self):
+ dim = self.getndim()
+ shape = self.getshape()
+ length = 1
+ for i in range(dim):
+ length *= shape[i]
+ return length * self.getitemsize()
+
+ @staticmethod
+ def copy(view, buf=None):
+ # TODO suboffsets
+ if buf == None:
+ buf = view.buf
+ return W_MemoryView(buf, view.getformat(), view.getitemsize(),
+ view.getndim(), view.getshape()[:], view.getstrides()[:])
+
+ def _apply_itemsize(self, space, start, size, itemsize):
+ if itemsize > 1:
+ start *= itemsize
+ size *= itemsize
+
+ stop = start + size
+ # start & stop are now byte offset, thus use self.buf.getlength()
+ if stop > self.buf.getlength():
+ raise oefmt(space.w_IndexError, 'index out of range')
+
+ return start, stop, size
def descr_setitem(self, space, w_index, w_obj):
self._check_released(space)
if self.buf.readonly:
raise oefmt(space.w_TypeError, "cannot modify read-only memory")
if space.isinstance_w(w_index, space.w_tuple):
- raise oefmt(space.w_NotImplementedError, "XXX tuple setitem")
+ raise oefmt(space.w_NotImplementedError, "")
start, stop, step, size = space.decode_index4(w_index, self.getlength())
- itemsize = self.itemsize
+ itemsize = self.getitemsize()
+ start, stop, size = self._apply_itemsize(space, start, size, itemsize)
if step == 0: # index only
if itemsize == 1:
ch = getbytevalue(space, w_obj)
@@ -125,16 +347,41 @@
raise oefmt(space.w_TypeError,
"memoryview: invalid type for format '%s'",
self.format)
- self.buf.setslice(start * itemsize, fmtiter.result.build())
+ self.buf.setslice(start, fmtiter.result.build())
elif step == 1:
value = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
- if value.getlength() != size * self.itemsize:
+ if value.getlength() != size:
raise oefmt(space.w_ValueError,
"cannot modify size of memoryview object")
- self.buf.setslice(start * itemsize, value.as_str())
+ self.buf.setslice(start, value.as_str())
else:
- raise oefmt(space.w_NotImplementedError,
- "XXX extended slicing")
+ if self.getndim() != 1:
+ raise oefmt(space.w_NotImplementedError,
+ "memoryview slice assignments are currently "
+ "restricted to ndim = 1")
+ # this is the case of a one dimensional copy!
+ # NOTE we could maybe make use of copy_base, but currently we do not
+ itemsize = self.getitemsize()
+ data = []
+ src = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
+ dst_strides = self.getstrides()
+ dim = 0
+ dst = SubBuffer(self.buf, start, size)
+ src_stride0 = dst_strides[dim]
+
+ off = 0
+ src_shape0 = size // itemsize
+ src_stride0 = src.getstrides()[0]
+ if isinstance(w_obj, W_MemoryView):
+ src_stride0 = w_obj.getstrides()[0]
+ for i in range(src_shape0):
+ data.append(src.getslice(off,off+itemsize,1,itemsize))
+ off += src_stride0
+ off = 0
+ dst_stride0 = self.getstrides()[0] * step
+ for dataslice in data:
+ dst.setslice(off, dataslice)
+ off += dst_stride0
def descr_len(self, space):
self._check_released(space)
@@ -142,11 +389,11 @@
def w_get_format(self, space):
self._check_released(space)
- return space.wrap(self.format)
+ return space.wrap(self.getformat())
def w_get_itemsize(self, space):
self._check_released(space)
- return space.newint(self.itemsize)
+ return space.wrap(self.itemsize)
def w_get_ndim(self, space):
self._check_released(space)
@@ -158,11 +405,11 @@
def w_get_shape(self, space):
self._check_released(space)
- return space.newtuple([space.newint(self.getlength())])
+ return space.newtuple([space.wrap(x) for x in self.getshape()])
def w_get_strides(self, space):
self._check_released(space)
- return space.newtuple([space.newint(self.itemsize)])
+ return space.newtuple([space.wrap(x) for x in self.getstrides()])
def w_get_suboffsets(self, space):
self._check_released(space)
@@ -240,20 +487,179 @@
size = rffi.sizeof(rffi.VOIDP)
return size
+ def _zero_in_shape(self):
+ # this method could be moved to the class Buffer
+ buf = self.buf
+ shape = buf.getshape()
+ for i in range(buf.getndim()):
+ if shape[i] == 0:
+ return True
+ return False
+
def descr_cast(self, space, w_format, w_shape=None):
self._check_released(space)
- if not space.is_none(w_shape):
- raise oefmt(space.w_NotImplementedError,
- "XXX cast() with a shape")
+
+ if not space.isinstance_w(w_format, space.w_unicode):
+ raise OperationError(space.w_TypeError, \
+ space.wrap("memoryview: format argument must be a string"))
+
fmt = space.str_w(w_format)
- newitemsize = self.get_native_fmtchar(fmt)
- return W_MemoryView(self.buf, fmt, newitemsize)
+ buf = self.buf
+ ndim = 1
+
+ if not memory_view_c_contiguous(space, self.flags):
+ raise OperationError(space.w_TypeError, \
+ space.wrap("memoryview: casts are restricted" \
+ " to C-contiguous views"))
+
+ if (w_shape or buf.getndim() != 1) and self._zero_in_shape():
+ raise OperationError(space.w_TypeError, \
+ space.wrap("memoryview: cannot casts view with" \
+ " zeros in shape or strides"))
+
+ itemsize = self.get_native_fmtchar(fmt)
+ if w_shape:
+ if not (space.isinstance_w(w_shape, space.w_list) or space.isinstance_w(w_shape, space.w_tuple)):
+ raise oefmt(space.w_TypeError, "expected list or tuple got %T", w_shape)
+ ndim = space.len_w(w_shape)
+ if ndim > MEMORYVIEW_MAX_DIM:
+ raise oefmt(space.w_ValueError, \
+ "memoryview: number of dimensions must not exceed %d",
+ ndim)
+ # yes access ndim as field
+ if self.ndim > 1 and buf.getndim() != 1:
+ raise OperationError(space.w_TypeError, \
+ space.wrap("memoryview: cast must be 1D -> ND or ND -> 1D"))
+
+ mv = W_MemoryView(buf, self.format, self.itemsize)
+ origfmt = mv.getformat()
+ mv._cast_to_1D(space, origfmt, fmt, itemsize)
+ if w_shape:
+ fview = space.fixedview(w_shape)
+ shape = [space.int_w(w_obj) for w_obj in fview]
+ mv._cast_to_ND(space, shape, ndim)
+ return mv
+
+ def _init_flags(self):
+ buf = self.buf
+ ndim = buf.getndim()
+ 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():
+ 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
+
+ # TODO missing suboffsets
+
+ self.flags = flags
+
+ def _cast_to_1D(self, space, origfmt, fmt, itemsize):
+ buf = self.buf
+ if itemsize < 0:
+ raise oefmt(space.w_ValueError, "memoryview: destination" \
+ " format must be a native single character format prefixed" \
+ " with an optional '@'")
+
+ if self.get_native_fmtchar(origfmt) < 0 or \
+ (not is_byte_format(fmt) and not is_byte_format(origfmt)):
+ raise oefmt(space.w_TypeError,
+ "memoryview: cannot cast between" \
+ " two non-byte formats")
+
+ if buf.getlength() % itemsize != 0:
+ raise oefmt(space.w_TypeError,
+ "memoryview: length is not a multiple of itemsize")
+
+ newfmt = self.get_native_fmtstr(fmt)
+ if not newfmt:
+ raise oefmt(space.w_RuntimeError,
+ "memoryview: internal error")
+ self.format = newfmt
+ self.itemsize = itemsize
+ self.ndim = 1
+ self.shape = [buf.getlength() // itemsize]
+ self.strides = [itemsize]
+ # XX suboffsets
+
+ self._init_flags()
+
+ def get_native_fmtstr(self, fmt):
+ lenfmt = len(fmt)
+ nat = False
+ if lenfmt == 0:
+ return None
+ elif lenfmt == 1:
+ format = fmt[0] # fine!
+ elif lenfmt == 2:
+ if fmt[0] == '@':
+ nat = True
+ format = fmt[1]
+ else:
+ return None
+ else:
+ return None
+
+ chars = ['c','b','B','h','H','i','I','l','L','q',
+ 'Q','n','N','f','d','?','P']
+ for c in unrolling_iterable(chars):
+ if c == format:
+ if nat: return '@'+c
+ else: return c
+
+ return None
+
+ def _cast_to_ND(self, space, shape, ndim):
+ buf = self.buf
+
+ self.ndim = ndim
+ length = self.itemsize
+ if ndim == 0:
+ self.shape = []
+ self.strides = []
+ else:
+ self.shape = shape
+ for i in range(ndim):
+ length *= shape[i]
+ self._init_strides_from_shape()
+
+ if length != self.buf.getlength():
+ raise OperationError(space.w_TypeError,
+ space.wrap("memoryview: product(shape) * itemsize != buffer size"))
+
+ self._init_flags()
+
+ def _init_strides_from_shape(self):
+ shape = self.getshape()
+ s = [0] * len(shape)
+ self.strides = s
+ ndim = self.getndim()
+ s[ndim-1] = self.itemsize
+ i = ndim-2
+ while i >= 0:
+ s[i] = s[i+1] * shape[i+1]
+ i -= 1
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(space, flags):
+ return flags & (space.BUF_CONTIG_RO|MEMORYVIEW_C) != 0
+
W_MemoryView.typedef = TypeDef(
"memoryview",
__doc__ = """\
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
@@ -1,3 +1,11 @@
+import py
+import struct
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
+from rpython.rlib.buffer import Buffer
+from pypy.conftest import option
+
class AppTestMemoryView:
spaceconfig = dict(usemodules=['array'])
@@ -38,7 +46,7 @@
assert len(w) == 1
assert list(w) == [97]
v[::2] = b'ABC'
- assert data == bytearray(b'AbBeCg')
+ assert data == bytearray(eval("b'AbBeCg'"))
def test_memoryview_attrs(self):
v = memoryview(b"a"*100)
@@ -217,4 +225,159 @@
data = bytearray(b'abcdefghij')
m3 = memoryview(data).cast('h')
m3[1:5:2] = memoryview(b"xyXY").cast('h')
- assert data == bytearray(b'abxyefXYij')
+ assert data == bytearray(eval("b'abxyefXYij'"))
+
+class MockBuffer(Buffer):
+ def __init__(self, space, w_arr, w_dim, w_fmt, \
+ w_itemsize, w_strides, w_shape):
+ self.space = space
+ self.w_arr = w_arr
+ self.arr = []
+ self.ndim = space.int_w(w_dim)
+ self.format = space.str_w(w_fmt)
+ self.itemsize = space.int_w(w_itemsize)
+ self.strides = []
+ for w_i in w_strides.getitems_unroll():
+ self.strides.append(space.int_w(w_i))
+ self.shape = []
+ for w_i in w_shape.getitems_unroll():
+ self.shape.append(space.int_w(w_i))
+ self.readonly = True
+ self.shape.append(space.len_w(w_arr))
+ self.data = []
+ itemsize = 1
+ worklist = [(1,w_arr)]
+ while worklist:
+ dim, w_work = worklist.pop()
+ if space.isinstance_w(w_work, space.w_list):
+ for j, w_obj in enumerate(w_work.getitems_unroll()):
+ worklist.insert(0, (dim+1, w_obj))
+ continue
+ byte = struct.pack(self.format, space.int_w(w_work))
+ for c in byte:
+ self.data.append(c)
+ self.data = ''.join(self.data)
+
+ def getformat(self):
+ return self.format
+
+ def getitem(self, index):
+ return self.data[index:index+1]
+
+ def getlength(self):
+ return len(self.data)
+
+ def getitemsize(self):
+ return self.itemsize
+
+ def getndim(self):
+ return self.ndim
+
+ def getstrides(self):
+ return self.strides
+
+ def getshape(self):
+ return self.shape
+
+ def is_contiguous(self, format):
+ return format == 'C'
+
+class W_MockArray(W_Root):
+ def __init__(self, w_list, w_dim, w_fmt, w_size, w_strides, w_shape):
+ self.w_list = w_list
+ self.w_dim = w_dim
+ self.w_fmt = w_fmt
+ self.w_size = w_size
+ self.w_strides = w_strides
+ self.w_shape = w_shape
+
+ @staticmethod
+ def descr_new(space, w_type, w_list, w_dim, w_fmt, \
+ w_size, w_strides, w_shape):
+ return W_MockArray(w_list, w_dim, w_fmt, w_size, w_strides, w_shape)
+
+ def buffer_w(self, space, flags):
+ return MockBuffer(space, self.w_list, self.w_dim, self.w_fmt, \
+ self.w_size, self.w_strides, self.w_shape)
+
+ def buffer_w_ex(self, space, flags):
+ return self.buffer_w(space, flags), space.str_w(self.w_fmt), space.int_w(self.w_size)
+
+W_MockArray.typedef = TypeDef("MockArray",
+ __new__ = interp2app(W_MockArray.descr_new),
+)
+
+class AppTestMemoryViewMockBuffer(object):
+ spaceconfig = dict(usemodules=[])
+ def setup_class(cls):
+ if option.runappdirect:
+ py.test.skip("Impossible to run on appdirect")
+ cls.w_MockArray = cls.space.gettypefor(W_MockArray)
+
+ def test_tuple_indexing(self):
+ content = self.MockArray([[0,1,2,3], [4,5,6,7], [8,9,10,11]],
+ dim=2, fmt='B', size=1,
+ strides=[4,1], shape=[3,4])
+ view = memoryview(content)
+ assert view[0,0] == 0
+ assert view[2,0] == 8
+ assert view[2,3] == 11
+ assert view[-1,-1] == 11
+ assert view[-3,-4] == 0
+
+ raises(IndexError, "view.__getitem__((2**63-1,0))")
+ raises(TypeError, "view.__getitem__((0, 0, 0))")
+
+ def test_tuple_indexing_int(self):
+ content = self.MockArray([ [[1],[2],[3]], [[4],[5],[6]] ],
+ dim=3, fmt='i', size=4,
+ strides=[12,4,4], shape=[2,3,1])
+ view = memoryview(content)
+ assert view[0,0,0] == 1
+ assert view[-1,2,0] == 6
+
+ def test_cast_non_byte(self):
+ empty = self.MockArray([], dim=1, fmt='i', size=4, strides=[1], shape=[1])
+ view = memoryview(empty)
+ raises(TypeError, "view.cast('l')")
+ try:
+ view.cast('l')
+ assert False, "i -> l not possible. buffer must be byte format"
+ except TypeError:
+ pass
+
+ def test_cast_empty(self):
+ empty = self.MockArray([], dim=1, fmt='b', size=1, strides=[1], shape=[1])
+ view = memoryview(empty)
+ cview = view.cast('i')
+ assert cview.tobytes() == b''
+ assert cview.tolist() == []
+ assert view.format == 'b'
+ assert cview.format == 'i'
+ #
+ assert cview.cast('b').cast('q').cast('b').tolist() == []
+ #
+ assert cview.format == 'i'
+ raises(TypeError, "cview.cast('i')")
+
+ 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])
+ view = memoryview(empty)
+ byteview = view.cast('b')
+ assert byteview.tolist() == [1,0,0,0,2,0,0,0,3,0,0,0]
+ i32view = byteview.cast('i', shape=[1,3])
+ assert i32view.format == 'i'
+ assert i32view.itemsize == 4
+ assert i32view.tolist() == [[1,2,3]]
+ i32view = byteview.cast('i', shape=(1,3))
+ assert i32view.tolist() == [[1,2,3]]
+
+ def test_cast_bytes(self):
+ bytes = b"\x02\x00\x03\x00\x04\x00" \
+ b"\x05\x00\x06\x00\x07\x00"
+ view = memoryview(bytes)
+ v = view.cast('h', shape=(3,2))
+ assert v.tolist() == [[2,3],[4,5],[6,7]]
+ raises(TypeError, "view.cast('h', shape=(3,3))")
More information about the pypy-commit
mailing list