[pypy-commit] pypy ndarray-subtype: patch bomb for passing space into all calls of from_shape...() while noting which methods must be tested for subtypes

mattip noreply at buildbot.pypy.org
Thu Jul 4 21:32:10 CEST 2013


Author: Matti Picus <matti.picus at gmail.com>
Branch: ndarray-subtype
Changeset: r65184:fd71a983d387
Date: 2013-07-04 22:18 +0300
http://bitbucket.org/pypy/pypy/changeset/fd71a983d387/

Log:	patch bomb for passing space into all calls of from_shape...() while
	noting which methods must be tested for subtypes

diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -229,7 +229,7 @@
         except IndexError:
             # not a single result
             chunks = self._prepare_slice_args(space, w_index)
-            return chunks.apply(orig_arr)
+            return chunks.apply(space, orig_arr)
 
     def descr_setitem(self, space, orig_arr, w_index, w_value):
         try:
@@ -238,7 +238,7 @@
         except IndexError:
             w_value = convert_to_array(space, w_value)
             chunks = self._prepare_slice_args(space, w_index)
-            view = chunks.apply(orig_arr)
+            view = chunks.apply(space, orig_arr)
             view.implementation.setslice(space, w_value)
 
     def transpose(self, orig_array):
@@ -269,14 +269,14 @@
                                   shape, skip)
         return iter.MultiDimViewIterator(self, self.dtype, self.start, r[0], r[1], shape)
 
-    def swapaxes(self, orig_arr, axis1, axis2):
+    def swapaxes(self, space, orig_arr, axis1, axis2):
         shape = self.get_shape()[:]
         strides = self.get_strides()[:]
         backstrides = self.get_backstrides()[:]
         shape[axis1], shape[axis2] = shape[axis2], shape[axis1]
         strides[axis1], strides[axis2] = strides[axis2], strides[axis1]
         backstrides[axis1], backstrides[axis2] = backstrides[axis2], backstrides[axis1]
-        return W_NDimArray.new_slice(self.start, strides,
+        return W_NDimArray.new_slice(space, self.start, strides,
                                      backstrides, shape, self, orig_arr)
 
     def get_storage_as_int(self, space):
@@ -289,13 +289,16 @@
         return ArrayBuffer(self)
 
     def astype(self, space, dtype):
-        new_arr = W_NDimArray.from_shape(self.get_shape(), dtype)
+        strides, backstrides = support.calc_strides(self.get_shape(), dtype,
+                                                    self.order)
+        impl = ConcreteArray(self.get_shape(), dtype, self.order,
+                             strides, backstrides)
         if self.dtype.is_str_or_unicode() and not dtype.is_str_or_unicode():
             raise OperationError(space.w_NotImplementedError, space.wrap(
                 "astype(%s) not implemented yet" % self.dtype))
         else:
-            loop.setslice(space, new_arr.get_shape(), new_arr.implementation, self)
-        return new_arr
+            loop.setslice(space, impl.get_shape(), impl, self)
+        return impl
 
 
 class ConcreteArrayNotOwning(BaseConcreteArray):
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -139,7 +139,7 @@
         if not new_shape:
             return self
         if support.product(new_shape) == 1:
-            arr = W_NDimArray.from_shape(new_shape, self.dtype)
+            arr = W_NDimArray.from_shape(space, new_shape, self.dtype)
             arr_iter = arr.create_iter(new_shape)
             arr_iter.setitem(self.value)
             return arr.implementation
@@ -152,7 +152,7 @@
     def create_axis_iter(self, shape, dim, cum):
         raise Exception("axis iter should not happen on scalar")
 
-    def swapaxes(self, orig_array, axis1, axis2):
+    def swapaxes(self, space, orig_array, axis1, axis2):
         raise Exception("should not be called")
 
     def fill(self, w_value):
@@ -166,7 +166,7 @@
         return space.wrap(0)
 
     def astype(self, space, dtype):
-        return W_NDimArray.new_scalar(space, dtype, self.value)
+        raise Exception("should not be called")
 
     def base(self):
         return None
diff --git a/pypy/module/micronumpy/arrayimpl/sort.py b/pypy/module/micronumpy/arrayimpl/sort.py
--- a/pypy/module/micronumpy/arrayimpl/sort.py
+++ b/pypy/module/micronumpy/arrayimpl/sort.py
@@ -126,7 +126,7 @@
             axis = space.int_w(w_axis)
         # create array of indexes
         dtype = interp_dtype.get_dtype_cache(space).w_longdtype
-        index_arr = W_NDimArray.from_shape(arr.get_shape(), dtype)
+        index_arr = W_NDimArray.from_shape(space, arr.get_shape(), dtype)
         storage = index_arr.implementation.get_storage()
         if len(arr.get_shape()) == 1:
             for i in range(arr.get_size()):
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
@@ -31,7 +31,7 @@
         self.implementation = implementation
 
     @staticmethod
-    def from_shape(shape, dtype, order='C', subtype_and_space=(None, None)):
+    def from_shape(space, shape, dtype, order='C', subtype=None):
         from pypy.module.micronumpy.arrayimpl import concrete, scalar
 
         if not shape:
@@ -40,16 +40,14 @@
             strides, backstrides = calc_strides(shape, dtype.base, order)
             impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
                                       backstrides)
-        if subtype_and_space[0]:
-            space = subtype_and_space[1]
-            subtype = subtype_and_space[0]
+        if subtype:
             ret = space.allocate_instance(W_NDimArray, subtype)
             W_NDimArray.__init__(ret, impl)
             return ret
         return W_NDimArray(impl)
 
     @staticmethod
-    def from_shape_and_storage(shape, storage, dtype, order='C', owning=False, subtype_and_space=(None, None)):
+    def from_shape_and_storage(space, shape, storage, dtype, order='C', owning=False, subtype=None):
         from pypy.module.micronumpy.arrayimpl import concrete
         assert shape
         strides, backstrides = calc_strides(shape, dtype, order)
@@ -60,21 +58,19 @@
         else:
             impl = concrete.ConcreteArrayNotOwning(shape, dtype, order, strides,
                                                 backstrides, storage)
-        if subtype_and_space[0]:
-            space = subtype_and_space[1]
-            subtype = subtype_and_space[0]
+        if subtype:
             ret = space.allocate_instance(W_NDimArray, subtype)
             W_NDimArray.__init__(ret, impl)
             return ret
         return W_NDimArray(impl)
 
     @staticmethod
-    def new_slice(offset, strides, backstrides, shape, parent, orig_arr, dtype=None):
+    def new_slice(space, offset, strides, backstrides, shape, parent, orig_arr, dtype=None):
         from pypy.module.micronumpy.arrayimpl import concrete
 
         impl = concrete.SliceArray(offset, strides, backstrides, shape, parent,
                                    orig_arr, dtype)
-        return W_NDimArray(impl)
+        return wrap_impl(space, orig_arr, impl)
 
     @staticmethod
     def new_scalar(space, dtype, w_val=None):
diff --git a/pypy/module/micronumpy/interp_arrayops.py b/pypy/module/micronumpy/interp_arrayops.py
--- a/pypy/module/micronumpy/interp_arrayops.py
+++ b/pypy/module/micronumpy/interp_arrayops.py
@@ -88,7 +88,7 @@
                                                   y.get_dtype())
     shape = shape_agreement(space, arr.get_shape(), x)
     shape = shape_agreement(space, shape, y)
-    out = W_NDimArray.from_shape(shape, dtype)
+    out = W_NDimArray.from_shape(space, shape, dtype, subtype=arr)
     return loop.where(out, shape, arr, x, y, dtype)
 
 def dot(space, w_obj1, w_obj2):
@@ -131,7 +131,8 @@
                                                       arr.get_dtype())
         if _axis < 0 or len(arr.get_shape()) <= _axis:
             raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
-    res = W_NDimArray.from_shape(shape, dtype, 'C')
+    # concatenate does not handle ndarray subtypes, it always returns a ndarray
+    res = W_NDimArray.from_shape(space, shape, dtype, 'C')
     chunks = [Chunk(0, i, 1, i) for i in shape]
     axis_start = 0
     for arr in args_w:
@@ -139,7 +140,7 @@
             continue
         chunks[_axis] = Chunk(axis_start, axis_start + arr.get_shape()[_axis], 1,
                              arr.get_shape()[_axis])
-        Chunks(chunks).apply(res).implementation.setslice(space, arr)
+        Chunks(chunks).apply(space, res).implementation.setslice(space, arr)
         axis_start += arr.get_shape()[_axis]
     return res
 
@@ -150,21 +151,21 @@
         arr = arr.descr_flatten(space)
         orig_size = arr.get_shape()[0]
         shape = [arr.get_shape()[0] * repeats]
-        res = W_NDimArray.from_shape(shape, arr.get_dtype())
+        res = W_NDimArray.from_shape(space, shape, arr.get_dtype(), subtype=arr)
         for i in range(repeats):
             Chunks([Chunk(i, shape[0] - repeats + i, repeats,
-                          orig_size)]).apply(res).implementation.setslice(space, arr)
+                 orig_size)]).apply(space, res).implementation.setslice(space, arr)
     else:
         axis = space.int_w(w_axis)
         shape = arr.get_shape()[:]
         chunks = [Chunk(0, i, 1, i) for i in shape]
         orig_size = shape[axis]
         shape[axis] *= repeats
-        res = W_NDimArray.from_shape(shape, arr.get_dtype())
+        res = W_NDimArray.from_shape(space, shape, arr.get_dtype(), subtype=arr)
         for i in range(repeats):
             chunks[axis] = Chunk(i, shape[axis] - repeats + i, repeats,
                                  orig_size)
-            Chunks(chunks).apply(res).implementation.setslice(space, arr)
+            Chunks(chunks).apply(space, res).implementation.setslice(space, arr)
     return res
 
 def count_nonzero(space, w_obj):
@@ -261,7 +262,7 @@
     else:
         shape = (shape[:axis2] + shape[axis2 + 1:axis1] +
                  shape[axis1 + 1:] + [size])
-    out = W_NDimArray.from_shape(shape, dtype)
+    out = W_NDimArray.from_shape(space, shape, dtype)
     if size == 0:
         return out
     if shapelen == 2:
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -41,7 +41,7 @@
     dtype = w_arr_list[0].get_dtype()
     for w_arr in w_arr_list[1:]:
         dtype = find_binop_result_dtype(space, dtype, w_arr.get_dtype())
-    out = base.W_NDimArray.from_shape(shape, dtype)
+    out = base.W_NDimArray.from_shape(space, shape, dtype)
     return out
 
 
diff --git a/pypy/module/micronumpy/interp_flatiter.py b/pypy/module/micronumpy/interp_flatiter.py
--- a/pypy/module/micronumpy/interp_flatiter.py
+++ b/pypy/module/micronumpy/interp_flatiter.py
@@ -64,8 +64,8 @@
         base_iter.next_skip_x(start)
         if length == 1:
             return base_iter.getitem()
-        res = W_NDimArray.from_shape([length], base.get_dtype(),
-                                     base.get_order())
+        res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
+                                     base.get_order(), subtype=base)
         return loop.flatiter_getitem(res, base_iter, step)
 
     def descr_setitem(self, space, w_idx, w_value):
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
@@ -85,7 +85,7 @@
             res_shape = [size] + self.get_shape()[1:]
         else:
             res_shape = [size]
-        res = W_NDimArray.from_shape(res_shape, self.get_dtype())
+        res = W_NDimArray.from_shape(space, res_shape, self.get_dtype(), subtype=self)
         return loop.getitem_filter(res, self, arr)
 
     def setitem_filter(self, space, idx, val):
@@ -145,9 +145,10 @@
         if iter_shape is None:
             # w_index is a list of slices, return a view
             chunks = self.implementation._prepare_slice_args(space, w_index)
-            return chunks.apply(self)
+            return chunks.apply(space, self)
         shape = res_shape + self.get_shape()[len(indexes):]
-        res = W_NDimArray.from_shape(shape, self.get_dtype(), self.get_order())
+        res = W_NDimArray.from_shape(space, shape, self.get_dtype(),
+                                     self.get_order(), subtype=self)
         if not res.get_size():
             return res
         return loop.getitem_array_int(space, self, res, iter_shape, indexes,
@@ -161,7 +162,7 @@
             # w_index is a list of slices
             w_value = convert_to_array(space, w_value)
             chunks = self.implementation._prepare_slice_args(space, w_index)
-            view = chunks.apply(self)
+            view = chunks.apply(space, self)
             view.implementation.setslice(space, w_value)
             return
         loop.setitem_array_int(space, self, iter_shape, indexes, val_arr,
@@ -259,14 +260,14 @@
         return self.implementation.get_scalar_value()
 
     def descr_copy(self, space):
-        return W_NDimArray(self.implementation.copy(space))
+        return wrap_impl(space, self, self.implementation.copy(space))
 
     def descr_get_real(self, space):
-        return W_NDimArray(self.implementation.get_real(self))
+        return wrap_impl(space, self, self.implementation.get_real(self))
 
     def descr_get_imag(self, space):
         ret = self.implementation.get_imag(self)
-        return W_NDimArray(ret)
+        return wrap_impl(space, self, ret)
 
     def descr_set_real(self, space, w_value):
         # copy (broadcast) values into self
@@ -326,7 +327,7 @@
         """
         if self.is_scalar():
             return self
-        return self.implementation.swapaxes(self, axis1, axis2)
+        return self.implementation.swapaxes(space, self, axis1, axis2)
 
     def descr_tolist(self, space):
         if len(self.get_shape()) == 0:
@@ -446,17 +447,25 @@
         # we must do that, because we need a working set. otherwise
         # we would modify the array in-place. Use this to our advantage
         # by converting nonnative byte order.
+        if self.is_scalar():
+            return space.wrap(0)
         s = self.get_dtype().name
         if not self.get_dtype().native:
             s = s[1:]
         dtype = interp_dtype.get_dtype_cache(space).dtypes_by_name[s]
         contig = self.implementation.astype(space, dtype)
+        assert isinstance(contig, W_NDimArray)
         return contig.implementation.argsort(space, w_axis)
 
     def descr_astype(self, space, w_dtype):
         dtype = space.interp_w(interp_dtype.W_Dtype,
           space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
-        return self.implementation.astype(space, dtype)
+        impl = self.implementation
+        if isinstance(impl, scalar.Scalar):
+            return W_NDimArray.new_scalar(space, dtype, impl.value)
+        else:
+            new_impl = impl.astype(space, dtype)
+            return wrap_impl(space, self, new_impl)
 
     def descr_get_base(self, space):
         impl = self.implementation
@@ -471,7 +480,7 @@
             loop.byteswap(self.implementation, self.implementation)
             return self
         else:
-            res = W_NDimArray.from_shape(self.get_shape(), self.get_dtype())
+            res = W_NDimArray.from_shape(space, self.get_shape(), self.get_dtype(), subtype=self)
             loop.byteswap(self.implementation, res.implementation)
             return res
 
@@ -564,7 +573,7 @@
         if space.is_none(w_out):
             if self.get_dtype().is_bool_type():
                 #numpy promotes bool.round() to float16. Go figure.
-                w_out = W_NDimArray.from_shape(self.get_shape(),
+                w_out = W_NDimArray.from_shape(space, self.get_shape(),
                        interp_dtype.get_dtype_cache(space).w_float16dtype)
             else:
                 w_out = None
@@ -765,7 +774,7 @@
             return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
         # Do the dims match?
         out_shape, other_critical_dim = match_dot_shapes(space, self, other)
-        result = W_NDimArray.from_shape(out_shape, dtype)
+        result = W_NDimArray.from_shape(space, out_shape, dtype, subtype=self)
         # This is the place to add fpypy and blas
         return loop.multidim_dot(space, self, other,  result, dtype,
                                  other_critical_dim)
@@ -889,7 +898,10 @@
         isfortran = space.getitem(w_state, space.wrap(3))
         storage = space.getitem(w_state, space.wrap(4))
 
-        self.implementation = W_NDimArray.from_shape_and_storage([space.int_w(i) for i in space.listview(shape)], rffi.str2charp(space.str_w(storage), track_allocation=False), dtype, owning=True).implementation
+        self.implementation = W_NDimArray.from_shape_and_storage(space,
+                [space.int_w(i) for i in space.listview(shape)],
+                rffi.str2charp(space.str_w(storage), track_allocation=False),
+                dtype, owning=True).implementation
 
 
 @unwrap_spec(offset=int, order=str)
@@ -905,8 +917,8 @@
     if not shape:
         return W_NDimArray.new_scalar(space, dtype)
     if space.is_w(w_subtype, space.gettypefor(W_NDimArray)):
-        return W_NDimArray.from_shape(shape, dtype, order)
-    return W_NDimArray.from_shape(shape, dtype, order, (w_subtype, space))
+        return W_NDimArray.from_shape(space, shape, dtype, order)
+    return W_NDimArray.from_shape(space, shape, dtype, order, w_subtype)
 
 @unwrap_spec(addr=int)
 def descr__from_shape_and_storage(space, w_cls, w_shape, addr, w_dtype, w_subclass=None):
@@ -922,10 +934,10 @@
                              w_dtype))
     shape = _find_shape(space, w_shape, dtype)
     if w_subclass:
-        return W_NDimArray.from_shape_and_storage(shape, storage, dtype, 'C',
-                            False, (w_subclass, space))
+        return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
+                             'C', False, w_subclass)
     else:
-        return W_NDimArray.from_shape_and_storage(shape, storage, dtype)
+        return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype)
 
 W_NDimArray.typedef = TypeDef(
     "ndarray",
@@ -1105,7 +1117,7 @@
         dtype = interp_dtype.variable_dtype(space, dtype.char + '1')
     if ndmin > len(shape):
         shape = [1] * (ndmin - len(shape)) + shape
-    arr = W_NDimArray.from_shape(shape, dtype, order=order)
+    arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
     arr_iter = arr.create_iter()
     for w_elem in elems_w:
         arr_iter.setitem(dtype.coerce(space, w_elem))
@@ -1120,7 +1132,7 @@
     shape = _find_shape(space, w_shape, dtype)
     if not shape:
         return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
-    return space.wrap(W_NDimArray.from_shape(shape, dtype=dtype, order=order))
+    return space.wrap(W_NDimArray.from_shape(space, shape, dtype=dtype, order=order))
 
 @unwrap_spec(order=str)
 def ones(space, w_shape, w_dtype=None, order='C'):
@@ -1130,7 +1142,7 @@
     shape = _find_shape(space, w_shape, dtype)
     if not shape:
         return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
-    arr = W_NDimArray.from_shape(shape, dtype=dtype, order=order)
+    arr = W_NDimArray.from_shape(space, shape, dtype=dtype, order=order)
     one = dtype.box(1)
     arr.fill(one)
     return space.wrap(arr)
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -50,7 +50,7 @@
         raise OperationError(space.w_ValueError, space.wrap(
             "string is smaller than requested size"))
 
-    a = W_NDimArray.from_shape([num_items], dtype=dtype)
+    a = W_NDimArray.from_shape(space, [num_items], dtype=dtype)
     ai = a.create_iter()
     for val in items:
         ai.setitem(val)
@@ -71,7 +71,7 @@
         raise OperationError(space.w_ValueError, space.wrap(
             "string is smaller than requested size"))
 
-    a = W_NDimArray.from_shape([count], dtype=dtype)
+    a = W_NDimArray.from_shape(space, [count], dtype=dtype)
     loop.fromstring_loop(a, dtype, itemsize, s)
     return space.wrap(a)
 
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -181,7 +181,8 @@
                 temp_shape = obj_shape[:axis] + obj_shape[axis + 1:]
                 if out:
                     dtype = out.get_dtype()
-                temp = W_NDimArray.from_shape(temp_shape, dtype)
+                temp = W_NDimArray.from_shape(space, temp_shape, dtype,
+                                                subtype=self)
             elif keepdims:
                 shape = obj_shape[:axis] + [1] + obj_shape[axis + 1:]
             else:
@@ -207,7 +208,7 @@
                         )
                 dtype = out.get_dtype()
             else:
-                out = W_NDimArray.from_shape(shape, dtype)
+                out = W_NDimArray.from_shape(space, shape, dtype, subtype=self)
             return loop.do_axis_reduce(shape, self.func, obj, dtype, axis, out,
                                        self.identity, cumultative, temp)
         if cumultative:
@@ -216,7 +217,7 @@
                     raise OperationError(space.w_ValueError, space.wrap(
                         "out of incompatible size"))
             else:
-                out = W_NDimArray.from_shape([obj.get_size()], dtype)
+                out = W_NDimArray.from_shape(space, [obj.get_size()], dtype, subtype=self)
             loop.compute_reduce_cumultative(obj, out, dtype, self.func,
                                             self.identity)
             return out
@@ -295,7 +296,7 @@
             return out
         shape = shape_agreement(space, w_obj.get_shape(), out,
                                 broadcast_down=False)
-        return loop.call1(shape, self.func, calc_dtype, res_dtype,
+        return loop.call1(space, shape, self.func, calc_dtype, res_dtype,
                           w_obj, out)
 
 
@@ -370,7 +371,7 @@
             return out
         new_shape = shape_agreement(space, w_lhs.get_shape(), w_rhs)
         new_shape = shape_agreement(space, new_shape, out, broadcast_down=False)
-        return loop.call2(new_shape, self.func, calc_dtype,
+        return loop.call2(space, new_shape, self.func, calc_dtype,
                           res_dtype, w_lhs, w_rhs, out)
 
 
@@ -450,7 +451,7 @@
                 return dt2
             return dt1
         return dt2
-    else:    
+    else:
         # increase to the next signed type
         dtypenum = dt2.num + 1
     newdtype = interp_dtype.get_dtype_cache(space).dtypes_by_num[dtypenum]
diff --git a/pypy/module/micronumpy/iter.py b/pypy/module/micronumpy/iter.py
--- a/pypy/module/micronumpy/iter.py
+++ b/pypy/module/micronumpy/iter.py
@@ -58,11 +58,11 @@
     def __init__(self, name):
         self.name = name
 
-    def apply(self, orig_arr):
+    def apply(self, space, orig_arr):
         arr = orig_arr.implementation
         ofs, subdtype = arr.dtype.fields[self.name]
         # strides backstrides are identical, ofs only changes start
-        return W_NDimArray.new_slice(arr.start + ofs, arr.get_strides(),
+        return W_NDimArray.new_slice(space, arr.start + ofs, arr.get_strides(),
                                      arr.get_backstrides(),
                                      arr.shape, arr, orig_arr, subdtype)
 
@@ -81,13 +81,13 @@
         assert s >= 0
         return shape[:] + old_shape[s:]
 
-    def apply(self, orig_arr):
+    def apply(self, space, orig_arr):
         arr = orig_arr.implementation
         shape = self.extend_shape(arr.shape)
         r = calculate_slice_strides(arr.shape, arr.start, arr.get_strides(),
                                     arr.get_backstrides(), self.l)
         _, start, strides, backstrides = r
-        return W_NDimArray.new_slice(start, strides[:], backstrides[:],
+        return W_NDimArray.new_slice(space, start, strides[:], backstrides[:],
                                      shape[:], arr, orig_arr)
 
 
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
@@ -19,9 +19,9 @@
                              reds = ['shape', 'w_lhs', 'w_rhs', 'out',
                                      'left_iter', 'right_iter', 'out_iter'])
 
-def call2(shape, func, calc_dtype, res_dtype, w_lhs, w_rhs, out):
+def call2(space, shape, func, calc_dtype, res_dtype, w_lhs, w_rhs, out):
     if out is None:
-        out = W_NDimArray.from_shape(shape, res_dtype)
+        out = W_NDimArray.from_shape(space, shape, res_dtype)
     left_iter = w_lhs.create_iter(shape)
     right_iter = w_rhs.create_iter(shape)
     out_iter = out.create_iter(shape)
@@ -48,9 +48,9 @@
                              reds = ['shape', 'w_obj', 'out', 'obj_iter',
                                      'out_iter'])
 
-def call1(shape, func, calc_dtype, res_dtype, w_obj, out):
+def call1(space, shape, func, calc_dtype, res_dtype, w_obj, out):
     if out is None:
-        out = W_NDimArray.from_shape(shape, res_dtype)
+        out = W_NDimArray.from_shape(space, shape, res_dtype, subtype=w_obj)
     obj_iter = w_obj.create_iter(shape)
     out_iter = out.create_iter(shape)
     shapelen = len(shape)
@@ -437,7 +437,7 @@
 def tostring(space, arr):
     builder = StringBuilder()
     iter = arr.create_iter()
-    res_str = W_NDimArray.from_shape([1], arr.get_dtype(), order='C')
+    res_str = W_NDimArray.from_shape(space, [1], arr.get_dtype(), order='C')
     itemsize = arr.get_dtype().itemtype.get_element_size()
     res_str_casted = rffi.cast(rffi.CArrayPtr(lltype.Char),
                                res_str.implementation.get_storage_as_int(space))
diff --git a/pypy/module/micronumpy/test/test_subtype.py b/pypy/module/micronumpy/test/test_subtype.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_subtype.py
@@ -0,0 +1,72 @@
+import py
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestSupport(BaseNumpyAppTest):
+    def setup_class(cls):
+        from numpypy import ndarray
+        BaseNumpyAppTest.setup_class.im_func(cls)
+        class NoNew(ndarray):
+            def __new__(cls):
+                raise ValueError('should not call __new__')
+            def __array_finalize(self, obj):
+                self.called_finalize = True
+        class SubType(ndarray):
+            def __new__(cls):
+                cls.called_new = True
+                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)
+
+    def test_sub_where(self):
+        from numpypy import where, ones, zeros, array
+        a = array([1, 2, 3, 0, -3])
+        v = a.view(self.NoNew)
+        assert False
+
+    def test_repeat(self):
+        assert False
+
+    def test_flatiter(self):
+        assert False
+
+    def test_getitem_filter(self):
+        assert False
+
+    def test_getitem_array_int(self):
+        assert False
+
+    def test_round(self):
+        from numpypy import array
+        a = array(range(10), dtype=float).view(self.NoNew)
+        # numpy compatibility
+        b = a.round(decimal=0)
+        assert isinstance(b, self.NoNew)
+        b = a.round(decimal=1)
+        assert not isinstance(b, self.NoNew)
+        b = a.round(decimal=-1)
+        assert not isinstance(b, self.NoNew)
+
+    def test_dot(self):
+        # the returned type is that of the first argument
+        assert False
+
+    def test_reduce(self):
+        # i.e. sum, max
+        # test for out as well
+        assert False
+
+    def test_call2(self):
+        # c + a vs. a + c, what about array priority?
+        assert False
+
+    def test_call1(self):
+        assert False
+
+    def test_astype(self):
+        assert False
+
+    def test_reshape(self):
+        assert False


More information about the pypy-commit mailing list