[pypy-commit] pypy default: merge array_interface which implements common usages of __array_interface__
mattip
noreply at buildbot.pypy.org
Sun Nov 8 14:50:59 EST 2015
Author: mattip <matti.picus at gmail.com>
Branch:
Changeset: r80599:8633f40661db
Date: 2015-11-08 21:40 +0200
http://bitbucket.org/pypy/pypy/changeset/8633f40661db/
Log: merge array_interface which implements common usages of
__array_interface__
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -25,3 +25,7 @@
preserves all int16 values, even across nan conversions. Also fix argmax, argmin
for nan comparisons
+.. branch: array_interface
+
+Support common use-cases for __array_interface__, passes upstream tests
+
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -371,6 +371,8 @@
@specialize.arg(2)
def call_method(self, w_obj, s, *args):
# XXX even the hacks have hacks
+ if s == 'size': # used in _array() but never called by tests
+ return IntObject(0)
return getattr(w_obj, 'descr_' + s)(self, *args)
@specialize.arg(1)
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
@@ -2,6 +2,7 @@
from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
from rpython.rlib.buffer import SubBuffer
from rpython.rlib.rstring import strip_spaces
+from rpython.rlib.rawstorage import RAW_STORAGE_PTR
from rpython.rtyper.lltypesystem import lltype, rffi
from pypy.module.micronumpy import descriptor, loop, support
@@ -45,7 +46,7 @@
try:
w_interface = space.getattr(w_object, space.wrap("__array_interface__"))
if w_interface is None:
- return None
+ return None, False
version_w = space.finditem(w_interface, space.wrap("version"))
if version_w is None:
raise oefmt(space.w_ValueError, "__array_interface__ found without"
@@ -67,19 +68,46 @@
raise oefmt(space.w_ValueError,
"__array_interface__ missing one or more required keys: shape, typestr"
)
- raise oefmt(space.w_NotImplementedError,
- "creating array from __array_interface__ not supported yet")
- '''
- data_w = space.listview()
+ if w_descr is not None:
+ raise oefmt(space.w_NotImplementedError,
+ "__array_interface__ descr not supported yet")
+ if w_strides is None or space.is_w(w_strides, space.w_None):
+ strides = None
+ else:
+ strides = [space.int_w(i) for i in space.listview(w_strides)]
shape = [space.int_w(i) for i in space.listview(w_shape)]
dtype = descriptor.decode_w_dtype(space, w_dtype)
- rw = space.is_true(data_w[1])
- '''
- #print 'create view from shape',shape,'dtype',dtype,'descr',w_descr,'data',data_w[0],'rw',rw
- return None
+ if dtype is None:
+ raise oefmt(space.w_ValueError,
+ "__array_interface__ could not decode dtype %R", w_dtype
+ )
+ 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]))
+ read_only = True # XXX why not space.is_true(data_w[1])
+ offset = 0
+ return W_NDimArray.from_shape_and_storage(space, shape, data,
+ dtype, strides=strides, start=offset), read_only
+ if w_data is None:
+ data = w_object
+ else:
+ data = w_data
+ w_offset = space.finditem(w_interface, space.wrap('offset'))
+ if w_offset is None:
+ offset = 0
+ else:
+ offset = space.int_w(w_offset)
+ #print 'create view from shape',shape,'dtype',dtype,'data',data
+ 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)
+ new_impl = arr.implementation.reshape(arr, shape)
+ return W_NDimArray(new_impl), False
+
except OperationError as e:
if e.match(space, space.w_AttributeError):
- return None
+ return None, False
raise
@@ -103,19 +131,20 @@
if space.isinstance_w(w_object, space.w_type):
raise oefmt(space.w_ValueError, "cannot create ndarray from type instance")
# for anything that isn't already an array, try __array__ method first
+ dtype = descriptor.decode_w_dtype(space, w_dtype)
if not isinstance(w_object, W_NDimArray):
w_array = try_array_method(space, w_object, w_dtype)
if w_array is not None:
# continue with w_array, but do further operations in place
w_object = w_array
copy = False
+ dtype = w_object.get_dtype()
if not isinstance(w_object, W_NDimArray):
- w_array = try_interface_method(space, w_object)
+ w_array, _copy = try_interface_method(space, w_object)
if w_array is not None:
w_object = w_array
- copy = False
- dtype = descriptor.decode_w_dtype(space, w_dtype)
-
+ copy = _copy
+ dtype = w_object.get_dtype()
if isinstance(w_object, W_NDimArray):
npy_order = order_converter(space, w_order, NPY.ANYORDER)
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
@@ -3070,7 +3070,7 @@
assert (b == zeros(10)).all()
def test_array_interface(self):
- from numpy import array
+ from numpy import array, ones
a = array(2.5)
i = a.__array_interface__
assert isinstance(i['data'][0], int)
@@ -3093,7 +3093,7 @@
class Dummy(object):
def __init__(self, aif=None):
- if aif:
+ if aif is not None:
self.__array_interface__ = aif
a = array(Dummy())
@@ -3102,6 +3102,31 @@
raises(ValueError, array, Dummy({'version': 0}))
raises(ValueError, array, Dummy({'version': 'abc'}))
raises(ValueError, array, Dummy({'version': 3}))
+ raises(TypeError, array, Dummy({'version': 3, 'typestr': 'f8', 'shape': ('a', 3)}))
+
+ a = array([1, 2, 3])
+ b = array(Dummy(a.__array_interface__))
+ b[1] = 200
+ assert a[1] == 2 # upstream compatibility, is this a bug?
+ interface_a = a.__array_interface__
+ interface_b = b.__array_interface__
+ # only the data[0] value should differ
+ assert interface_a['data'][0] != interface_b['data'][0]
+ assert interface_b['data'][1] == interface_a['data'][1]
+ interface_b.pop('data')
+ interface_a.pop('data')
+ assert interface_a == interface_b
+
+ b = array(Dummy({'version':3, 'shape': (50,), 'typestr': 'u1',
+ 'data': 'a'*100}))
+ assert b.dtype == 'uint8'
+ assert b.shape == (50,)
+
+ a = ones((1,), dtype='float16')
+ b = Dummy(a.__array_interface__)
+ c = array(b)
+ assert c.dtype == 'float16'
+ assert (a == c).all()
def test_array_indexing_one_elem(self):
from numpy import array, arange
More information about the pypy-commit
mailing list