Author: mattip <matti.pi...@gmail.com> Branch: numpy-fixes Changeset: r77218:c82e8c164d0b Date: 2015-05-08 17:31 +0300 http://bitbucket.org/pypy/pypy/changeset/c82e8c164d0b/
Log: add failing test, support call2; in ufuncs call __array_wrap__ after __array_finalize__ diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py --- a/pypy/module/micronumpy/base.py +++ b/pypy/module/micronumpy/base.py @@ -3,14 +3,16 @@ from rpython.tool.pairtype import extendabletype from pypy.module.micronumpy import support -def wrap_impl(space, w_cls, w_instance, impl): +def wrap_impl(space, w_cls, w_instance, impl, postpone_finalize=False): if w_cls is None or space.is_w(w_cls, space.gettypefor(W_NDimArray)): w_ret = W_NDimArray(impl) else: w_ret = space.allocate_instance(W_NDimArray, w_cls) W_NDimArray.__init__(w_ret, impl) assert isinstance(w_ret, W_NDimArray) - space.call_method(w_ret, '__array_finalize__', w_instance) + if not postpone_finalize: + # ufuncs need to call finalize after wrap + space.call_method(w_ret, '__array_finalize__', w_instance) return w_ret @@ -33,7 +35,8 @@ self.implementation = implementation @staticmethod - def from_shape(space, shape, dtype, order='C', w_instance=None, zero=True): + def from_shape(space, shape, dtype, order='C', w_instance=None, + zero=True, postpone_finalize=False): from pypy.module.micronumpy import concrete, descriptor, boxes from pypy.module.micronumpy.strides import calc_strides strides, backstrides = calc_strides(shape, dtype.base, order) @@ -42,7 +45,8 @@ if dtype == descriptor.get_dtype_cache(space).w_objectdtype: impl.fill(space, boxes.W_ObjectBox(space.w_None)) if w_instance: - return wrap_impl(space, space.type(w_instance), w_instance, impl) + return wrap_impl(space, space.type(w_instance), w_instance, + impl, postpone_finalize=postpone_finalize) return W_NDimArray(impl) @staticmethod diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py --- a/pypy/module/micronumpy/loop.py +++ b/pypy/module/micronumpy/loop.py @@ -60,9 +60,11 @@ right_iter.track_index = False if out is None: - out = W_NDimArray.from_shape(space, shape, res_dtype, - w_instance=lhs_for_subtype) - out_iter, out_state = out.create_iter(shape) + w_ret = W_NDimArray.from_shape(space, shape, res_dtype, + w_instance=lhs_for_subtype, postpone_finalize=True) + else: + w_ret = out + out_iter, out_state = w_ret.create_iter(shape) shapelen = len(shape) while not out_iter.done(out_state): call2_driver.jit_merge_point(shapelen=shapelen, func=func, @@ -76,7 +78,10 @@ out_iter.setitem(out_state, func(calc_dtype, w_left, w_right).convert_to( space, res_dtype)) out_state = out_iter.next(out_state) - return out + if out is None: + w_ret2 = space.call_method(w_rhs, '__array_wrap__', w_ret) + space.call_method(w_ret2, '__array_finalize__', lhs_for_subtype) + return w_ret2 call1_driver = jit.JitDriver( name='numpy_call1', diff --git a/pypy/module/micronumpy/test/test_subtype.py b/pypy/module/micronumpy/test/test_subtype.py --- a/pypy/module/micronumpy/test/test_subtype.py +++ b/pypy/module/micronumpy/test/test_subtype.py @@ -624,3 +624,48 @@ a = asarray(fp[5:6][:,4]) assert (a == vals).all() + def test__array_wrap__(self): + ''' Straight from the documentation of __array_wrap__ + ''' + import numpy as np + + class MySubClass(np.ndarray): + output = '' + + def __new__(cls, input_array, info=None): + obj = np.array(input_array).view(cls) + obj.info = info + return obj + + def __array_finalize__(self, obj): + self.output += 'In __array_finalize__:' + self.output += ' self is %s' % repr(self) + self.output += ' obj is %s' % repr(obj) + print self.output + if obj is None: return + self.info = getattr(obj, 'info', None) + + def __array_wrap__(self, out_arr, context=None): + self.output += 'In __array_wrap__:' + self.output += ' self is %s' % repr(self) + self.output += ' arr is %s' % repr(out_arr) + # then just call the parent + ret = np.ndarray.__array_wrap__(self, out_arr, context) + print 'wrap',self.output + return ret + + obj = MySubClass(np.arange(5), info='spam') + assert obj.output.startswith('In __array_finalize') + obj.output = '' + arr2 = np.arange(5)+1 + assert len(obj.output) < 1 + ret = np.add(arr2, obj) + print obj.output + assert obj.output.startswith('In __array_wrap') + assert 'finalize' not in obj.output + assert ret.info == 'spam' + ret = np.negative(obj) + assert ret.info == 'spam' + ret = obj.sum() + assert ret.info == 'spam' + assert False diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py --- a/pypy/module/micronumpy/ufuncs.py +++ b/pypy/module/micronumpy/ufuncs.py @@ -584,7 +584,6 @@ assert isinstance(w_rhs, W_NDimArray) new_shape = shape_agreement(space, w_lhs.get_shape(), w_rhs) new_shape = shape_agreement(space, new_shape, out, broadcast_down=False) - # XXX call __array_wrap__ if out was not provided return loop.call2(space, new_shape, self.func, calc_dtype, res_dtype, w_lhs, w_rhs, out) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit