[pypy-commit] pypy buffer-interface: test, implement creation of numpypy array from memoryview
mattip
pypy.commits at gmail.com
Tue Aug 30 22:08:08 EDT 2016
Author: Matti Picus <matti.picus at gmail.com>
Branch: buffer-interface
Changeset: r86759:844b80dca877
Date: 2016-08-31 05:07 +0300
http://bitbucket.org/pypy/pypy/changeset/844b80dca877/
Log: test, implement creation of numpypy array from memoryview
diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -465,6 +465,13 @@
self.storage = storage
self.start = start
self.gcstruct = V_OBJECTSTORE
+ if dtype.num == NPY.OBJECT:
+ self.gcstruct = _create_objectstore(storage, self.size,
+ dtype.elsize)
+
+ def __del__(self):
+ if self.gcstruct:
+ self.gcstruct.length = 0
def fill(self, space, box):
self.dtype.itemtype.fill(
diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py
--- a/pypy/module/micronumpy/ctors.py
+++ b/pypy/module/micronumpy/ctors.py
@@ -11,6 +11,7 @@
from pypy.module.micronumpy.converters import shape_converter, order_converter
import pypy.module.micronumpy.constants as NPY
from .casting import scalar2dtype
+from pypy.objspace.std.memoryobject import W_MemoryView
def build_scalar(space, w_dtype, w_state):
@@ -83,15 +84,13 @@
)
if w_data is not None and (space.isinstance_w(w_data, space.w_tuple) or space.isinstance_w(w_data, space.w_list)):
data_w = space.listview(w_data)
- data = rffi.cast(RAW_STORAGE_PTR, space.int_w(data_w[0]))
+ w_data = rffi.cast(RAW_STORAGE_PTR, space.int_w(data_w[0]))
read_only = True # XXX why not space.is_true(data_w[1])
offset = 0
- return W_NDimArray.from_shape_and_storage(space, shape, data,
+ return W_NDimArray.from_shape_and_storage(space, shape, w_data,
dtype, strides=strides, start=offset), read_only
if w_data is None:
- data = w_object
- else:
- data = w_data
+ w_data = w_object
w_offset = space.finditem(w_interface, space.wrap('offset'))
if w_offset is None:
offset = 0
@@ -101,7 +100,7 @@
if strides is not None:
raise oefmt(space.w_NotImplementedError,
"__array_interface__ strides not fully supported yet")
- arr = frombuffer(space, data, dtype, support.product(shape), offset)
+ arr = frombuffer(space, w_data, dtype, support.product(shape), offset)
new_impl = arr.implementation.reshape(arr, shape)
return W_NDimArray(new_impl), False
@@ -110,6 +109,62 @@
return None, False
raise
+def _descriptor_from_pep3118_format(space, c_format):
+ descr = descriptor.decode_w_dtype(space, space.wrap(c_format))
+ if descr:
+ return descr
+ msg = "invalid PEP 3118 format string: '%s'" % c_format
+ space.warn(space.wrap(msg), space.w_RuntimeWarning)
+ return None
+
+def _array_from_buffer_3118(space, w_object, dtype):
+ buf = w_object.buf
+ if buf.getformat():
+ descr = _descriptor_from_pep3118_format(space, buf.getformat())
+ if not descr:
+ return w_object
+ if dtype and descr:
+ raise oefmt(space.w_NotImplementedError,
+ "creating an array from a memoryview while specifying dtype "
+ "not supported")
+ if descr.elsize != buf.getitemsize():
+ msg = ("Item size computed from the PEP 3118 buffer format "
+ "string does not match the actual item size.")
+ space.warn(space.wrap(msg), space.w_RuntimeWarning)
+ return w_object
+ dtype = descr
+ elif not dtype:
+ dtype = descriptor.get_dtype_cache(space).w_stringdtype
+ dtype.elsize = buf.getitemsize()
+ nd = buf.getndim()
+ shape = buf.getshape()
+ strides = []
+ if shape:
+ strides = buf.getstrides()
+ if not strides:
+ d = len(buf)
+ strides = [0] * nd
+ for k in range(nd):
+ if shape[k] > 0:
+ d /= shape[k]
+ strides[k] = d
+ else:
+ if nd == 1:
+ shape = [len(buf) / dtype.elsize, ]
+ strides = [dtype.elsize, ]
+ elif nd > 1:
+ msg = ("ndim computed from the PEP 3118 buffer format "
+ "is greater than 1, but shape is NULL.")
+ space.warn(space.wrap(msg), space.w_RuntimeWarning)
+ return w_object
+ storage = buf.get_raw_address()
+ writable = not buf.readonly
+ w_ret = W_NDimArray.from_shape_and_storage(space, shape, storage,
+ storage_bytes=len(buf), dtype=dtype, w_base=w_object,
+ writable=writable, strides=strides)
+ if w_ret:
+ return w_ret
+ return w_object
@unwrap_spec(ndmin=int, copy=bool, subok=bool)
def array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False,
@@ -139,6 +194,9 @@
w_object = w_array
copy = False
dtype = w_object.get_dtype()
+ elif isinstance(w_object, W_MemoryView):
+ # use buffer interface
+ w_object = _array_from_buffer_3118(space, w_object, dtype)
if not isinstance(w_object, W_NDimArray):
w_array, _copy = try_interface_method(space, w_object)
if w_array is not None:
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -3594,6 +3594,7 @@
cls.w_float32val = cls.space.wrap(struct.pack('f', 5.2))
cls.w_float64val = cls.space.wrap(struct.pack('d', 300.4))
cls.w_ulongval = cls.space.wrap(struct.pack('L', 12))
+ cls.w_one = cls.space.wrap(struct.pack('i', 1))
def test_frombuffer(self):
import numpy as np
@@ -3645,8 +3646,6 @@
else:
EMPTY = None
x = np.array([1, 2, 3, 4, 5], dtype='i')
- y = memoryview('abc')
- assert y.format == 'B'
y = memoryview(x)
assert y.format == 'i'
assert y.shape == (5,)
@@ -3654,6 +3653,16 @@
assert y.strides == (4,)
assert y.suboffsets == EMPTY
assert y.itemsize == 4
+ assert isinstance(y, memoryview)
+ assert y[0] == self.one
+ assert (np.array(y) == x).all()
+
+ x = np.array([0, 0, 0, 0], dtype='O')
+ y = memoryview(x)
+ # handles conversion of address to pinned object?
+ z = np.array(y)
+ assert z.dtype == 'O'
+ assert (z == x).all()
def test_fromstring(self):
import sys
More information about the pypy-commit
mailing list