Author: Richard Plangger <[email protected]>
Branch: py3.5-memoryview
Changeset: r86675:97a4f9949ccd
Date: 2016-08-29 11:02 +0200
http://bitbucket.org/pypy/pypy/changeset/97a4f9949ccd/
Log: progress on implementing descr_cast 1 -> N dimensions, translation
fixes
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
@@ -26,18 +26,43 @@
an interp-level buffer.
"""
- def __init__(self, buf, format=None, 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
self.format = format
self.itemsize = itemsize
+ self.shape = shape
+ self.strides = strides
+ self.suboffsets = suboffsets
+ self.ndim = ndim
self.flags = 0
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):
- # memoryview needs to modify the field 'format', to prevent the
modification
- # of the buffer, we save the new format here!
if self.format is None:
return self.buf.getformat()
return self.format
@@ -94,18 +119,51 @@
def descr_tolist(self, space):
self._check_released(space)
+
+ buf = self.buf
+ dim = buf.getndim()
+ fmt = self.getformat()
+ if dim == 0:
+ raise NotImplementedError
+ elif dim == 1:
+ return self._tolist(space, buf, self.getlength(), fmt)
+ else:
+ return self._tolist_rec(space, buf, 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.interpret(fmt * count)
return space.newlist(fmtiter.result_w)
+ def _tolist_rec(self, space, buf, start, dim, fmt):
+ idim = dim-1
+ strides = self.getstrides()
+ stride = strides[idim]
+ itemsize = self.getitemsize()
+ if dim >= buf.getndim():
+ return self._tolist(space, SubBuffer(buf, start, itemsize), stride
// itemsize, fmt)
+ shape = self.getshape()
+ dimshape = shape[idim]
+ items = [None] * dimshape
+
+ for i in range(dimshape):
+ item = self._tolist_rec(space, SubBuffer(buf, start,
self.itemsize), dim+1, fmt)
+ items[i] = item
+ start += stride
+
+ return space.newlist(items,len(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)
@@ -166,7 +224,7 @@
# XXX why? returns a memory view on int index if step == 0:
# step = 1
- # start & stop are now byte offset, thus use self.bug.getlength()
+ # 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')
if step not in (0, 1):
@@ -208,7 +266,7 @@
# TODO: this probably isn't very fast
fmtiter = PackFormatIterator(space, [w_obj], self.itemsize)
try:
- fmtiter.interpret(self.format)
+ fmtiter.interpret(self.getformat())
except StructError as e:
raise oefmt(space.w_TypeError,
"memoryview: invalid type for format '%s'",
@@ -328,10 +386,10 @@
return size
def _zero_in_shape(self):
- # TODO move to buffer
- view = self.buf
- shape = view.shape
- for i in range(view.ndim):
+ # 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
@@ -359,14 +417,15 @@
itemsize = self.get_native_fmtchar(fmt)
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:
+ 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)
- if ndim != buf.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"))
@@ -374,8 +433,8 @@
origfmt = mv.getformat()
mv._cast_to_1D(space, origfmt, fmt, itemsize)
if w_shape:
- shape = [space.int_w(w_obj) for w_obj in
w_shape.fixedview_unroll()]
- mv._cast_to_ND(space, shape, dim)
+ shape = [space.int_w(w_obj) for w_obj in w_shape.getitems_unroll()]
+ mv._cast_to_ND(space, shape, ndim)
return mv
def _init_flags(self):
@@ -426,7 +485,7 @@
self.itemsize = itemsize
self.ndim = 1
self.shape = [buf.getlength() // buf.getitemsize()]
- self.srides = [buf.getitemsize()]
+ self.strides = [buf.getitemsize()]
# XX suboffsets
self._init_flags()
@@ -457,7 +516,32 @@
return None
def _cast_to_ND(self, space, shape, ndim):
- pass
+ 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):
+ s = [0] * len(self.shape)
+ self.strides = s
+ dim = self.getndim()
+ s[dim-1] = self.itemsize
+ for i in range(0,ndim-2,-1):
+ s[i] = s[i+1] * shape[i+1]
def descr_hex(self, space):
from pypy.objspace.std.bytearrayobject import _array_to_hexstring
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
@@ -199,7 +199,10 @@
for j, w_obj in enumerate(w_work.getitems_unroll()):
worklist.insert(0, (dim+1, w_obj))
continue
- self.data.append(space.int_w(w_work))
+ byte = struct.pack(self.format, space.int_w(w_work))
+ for c in byte:
+ self.data.append(c)
+ self.data = ''.join(self.data)
def getslice(self, start, stop, step, size):
items = []
@@ -218,10 +221,10 @@
return self.format
def getitem(self, index):
- return struct.pack(self.format, self.data[index])
+ return self.data[index:index+1]
def getlength(self):
- return len(self.data) * self.itemsize
+ return len(self.data)
def getitemsize(self):
return self.itemsize
@@ -329,3 +332,14 @@
except TypeError:
pass
+ 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]]
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit