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

Reply via email to