Author: mattip <matti.pi...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit