Author: Matti Picus <[email protected]>
Branch: ndarray-subtype
Changeset: r65187:31b9c2717719
Date: 2013-07-05 01:03 +0300
http://bitbucket.org/pypy/pypy/changeset/31b9c2717719/

Log:    first pass at differentiating types from instances and handling
        __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
@@ -11,12 +11,17 @@
             isinstance(w_obj, W_NDimArray))
 
 def wrap_impl(space, cls, impl):
-    if space.is_w(space.type(cls), space.gettypefor(W_NDimArray)):
+    if cls is None or space.is_w(space.type(cls), 
space.gettypefor(W_NDimArray)):
         ret = W_NDimArray(impl)
     else:
-        ret = space.allocate_instance(W_NDimArray, space.type(cls))
-        print 'created',space.type(ret)
+        if space.isinstance_w(cls, space.w_type):
+            #got type, either from __new__ or from view casting
+            ret = space.allocate_instance(W_NDimArray, cls)
+        else:
+            ret = space.allocate_instance(W_NDimArray, space.type(cls))
         W_NDimArray.__init__(ret, impl)
+        space.call_function(space.getattr(ret, 
space.wrap('__array_finalize__')),
+                        cls)
     return ret
 
 class ArrayArgumentException(Exception):
@@ -31,7 +36,7 @@
         self.implementation = implementation
 
     @staticmethod
-    def from_shape(space, shape, dtype, order='C', subtype=None):
+    def from_shape(space, shape, dtype, order='C', subtype=None, is_new=False):
         from pypy.module.micronumpy.arrayimpl import concrete, scalar
 
         if not shape:
@@ -42,12 +47,25 @@
                                       backstrides)
         if subtype:
             if space.isinstance_w(subtype, space.w_type):
-                #got type, probably from descr_XXX
+                #got type, either from __new__ or from view casting
                 ret = space.allocate_instance(W_NDimArray, subtype)
+                W_NDimArray.__init__(ret, impl)
+                if is_new:
+                    space.call_function(space.getattr(ret,
+                                    space.wrap('__array_finalize__')),
+                                    space.w_None)
+                else:
+                    # view casting, call finalize
+                    space.call_function(space.getattr(ret,
+                                    space.wrap('__array_finalize__')),
+                                    subtype)
             else:
                 #got instance
                 ret = space.allocate_instance(W_NDimArray, space.type(subtype))
-            W_NDimArray.__init__(ret, impl)
+                W_NDimArray.__init__(ret, impl)
+                space.call_function(space.getattr(ret,
+                                    space.wrap('__array_finalize__')),
+                                    subtype)
         else:
             ret = W_NDimArray(impl)
         return ret
@@ -68,10 +86,17 @@
             if space.isinstance_w(subtype, space.w_type):
                 #got type, probably from descr_XXX
                 ret = space.allocate_instance(W_NDimArray, subtype)
+                W_NDimArray.__init__(ret, impl)
+                space.call_function(space.getattr(ret,
+                                    space.wrap('__array_finalize__')),
+                                    space.w_None)
             else:
                 #got instance
                 ret = space.allocate_instance(W_NDimArray, space.type(subtype))
-            W_NDimArray.__init__(ret, impl)
+                W_NDimArray.__init__(ret, impl)
+                space.call_function(space.getattr(ret,
+                                    space.wrap('__array_finalize__')),
+                                    subtype)
             return ret
         return W_NDimArray(impl)
 
diff --git a/pypy/module/micronumpy/interp_numarray.py 
b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -664,12 +664,7 @@
                         "new type not compatible with array."))
                 new_shape[-1] = new_shape[-1] * old_itemsize / new_itemsize
         v = impl.get_view(self, dtype, new_shape)
-        if w_type is not None:
-            ret = space.allocate_instance(W_NDimArray, w_type)
-            W_NDimArray.__init__(ret, v)
-            return ret
-        return W_NDimArray(v)
-
+        return wrap_impl(space, w_type, v)
 
     # --------------------- operations ----------------------------
 
@@ -906,6 +901,8 @@
                 rffi.str2charp(space.str_w(storage), track_allocation=False),
                 dtype, owning=True).implementation
 
+    def descr___array_finalize__(self, space, w_obj):
+        pass
 
 @unwrap_spec(offset=int, order=str)
 def descr_new_array(space, w_subtype, w_shape, w_dtype=None, w_buffer=None,
@@ -921,7 +918,8 @@
         return W_NDimArray.new_scalar(space, dtype)
     if space.is_w(w_subtype, space.gettypefor(W_NDimArray)):
         return W_NDimArray.from_shape(space, shape, dtype, order)
-    return W_NDimArray.from_shape(space, shape, dtype, order, w_subtype)
+    ret = W_NDimArray.from_shape(space, shape, dtype, order, w_subtype, 
is_new=True)
+    return ret
 
 @unwrap_spec(addr=int)
 def descr__from_shape_and_storage(space, w_cls, w_shape, addr, w_dtype, 
w_subclass=None):
@@ -1068,6 +1066,7 @@
                                    W_NDimArray.fdel___pypy_data__),
     __reduce__ = interp2app(W_NDimArray.descr_reduce),
     __setstate__ = interp2app(W_NDimArray.descr_setstate),
+    __array_finalize__ = interp2app(W_NDimArray.descr___array_finalize__),
 )
 
 @unwrap_spec(ndmin=int, copy=bool, subok=bool)
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
@@ -4,8 +4,9 @@
 
 class AppTestSupport(BaseNumpyAppTest):
     def setup_class(cls):
+        BaseNumpyAppTest.setup_class.im_func(cls)
+        '''
         from numpypy import ndarray
-        BaseNumpyAppTest.setup_class.im_func(cls)
         class NoNew(ndarray):
             def __new__(cls):
                 raise ValueError('should not call __new__')
@@ -17,8 +18,42 @@
                 return cls
             def __array_finalize(self, obj):
                 self.called_finalize = True
-            cls.w_NoNew = cls.space.wrap(NoNew)
-            cls.w_SubType = cls.space.wrap(SubType)
+        cls.w_NoNew = cls.space.wrap(NoNew)
+        cls.w_SubType = cls.space.wrap(SubType)
+        '''
+
+    def test_finalize(self):
+        #taken from 
http://docs.scipy.org/doc/numpy/user/basics.subclassing.html#simple-example-adding-an-extra-attribute-to-ndarray
+        import numpypy as np
+        class InfoArray(np.ndarray):
+            def __new__(subtype, shape, dtype=float, buffer=None, offset=0,
+                          strides=None, order='C', info=None):
+                obj = np.ndarray.__new__(subtype, shape, dtype, buffer,
+                         offset, strides, order)
+                obj.info = info
+                return obj
+
+            def __array_finalize__(self, obj):
+                if obj is None:
+                    print 'finazlize with None'
+                    return
+                print 'finalize with something'
+                self.info = getattr(obj, 'info', None)
+        obj = InfoArray(shape=(3,))
+        assert isinstance(obj, InfoArray)
+        assert obj.info is None
+        obj = InfoArray(shape=(3,), info='information')
+        assert obj.info == 'information'
+        v = obj[1:]
+        assert isinstance(v, InfoArray)
+        assert v.base is obj
+        assert v.info == 'information'
+        arr = np.arange(10)
+        print '1'
+        cast_arr = arr.view(InfoArray)
+        assert isinstance(cast_arr, InfoArray)
+        assert cast_arr.base is arr
+        assert cast_arr.info is None
 
     def test_sub_where(self):
         from numpypy import where, ones, zeros, array
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to