[pypy-commit] pypy default: extend matrix test to expose indexing error since reshape() call subtype __array_finalize__, fix.

mattip noreply at buildbot.pypy.org
Sat Feb 7 20:51:54 CET 2015


Author: mattip <matti.picus at gmail.com>
Branch: 
Changeset: r75757:07ae676d67c6
Date: 2015-02-06 08:30 +0200
http://bitbucket.org/pypy/pypy/changeset/07ae676d67c6/

Log:	extend matrix test to expose indexing error since reshape() call
	subtype __array_finalize__, fix.

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
@@ -81,7 +81,10 @@
                 return w_object.descr_copy(space, w_order)
             elif not copy and (subok or type(w_object) is W_NDimArray):
                 return w_object
-        # we have a ndarray, but need to copy or change dtype or create W_NDimArray
+        if subok:
+            raise oefmt(space.w_NotImplementedError, 
+                "array(..., subok=True) only partially implemented")
+        # we have a ndarray, but need to copy or change dtype 
         if dtype is None:
             dtype = w_object.get_dtype()
         if dtype != w_object.get_dtype():
@@ -89,13 +92,12 @@
             copy = True
         if copy:
             shape = w_object.get_shape()
-            _elems_w = w_object.reshape(space, space.wrap(-1))
             elems_w = [None] * w_object.get_size()
-            for i in range(len(elems_w)):
-                elems_w[i] = _elems_w.descr_getitem(space, space.wrap(i))
-        elif subok:
-            raise oefmt(space.w_NotImplementedError, 
-                "array(...copy=False, subok=True) not implemented yet")
+            elsize = w_object.get_dtype().elsize
+            # TODO - use w_object.implementation without copying to a list
+            # unfortunately that causes a union error in translation
+            for i in range(w_object.get_size()):
+                elems_w[i] = w_object.implementation.getitem(i * elsize)
         else:
             sz = support.product(w_object.get_shape()) * dtype.elsize
             return W_NDimArray.from_shape_and_storage(space,
@@ -113,7 +115,7 @@
             dtype = descriptor.variable_dtype(space, dtype.char + '1')
 
     w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
-    if len(elems_w) == 1:
+    if support.product(shape) < 2:
         w_arr.set_scalar_value(dtype.coerce(space, elems_w[0]))
     else:
         loop.assign(space, w_arr, elems_w)
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
@@ -272,40 +272,103 @@
         import numpy as N
         # numpy's matrix class caused an infinite loop
         class matrix(N.ndarray):
-            getcnt = 0
             def __new__(subtype, data, dtype=None, copy=True):
+                print('matrix __new__')
+                if isinstance(data, matrix):
+                    dtype2 = data.dtype
+                    if (dtype is None):
+                        dtype = dtype2
+                    if (dtype2 == dtype) and (not copy):
+                        return data
+                    return data.astype(dtype)
+
+                if isinstance(data, N.ndarray):
+                    if dtype is None:
+                        intype = data.dtype
+                    else:
+                        intype = N.dtype(dtype)
+                    new = data.view(subtype)
+                    if intype != data.dtype:
+                        return new.astype(intype)
+                    if copy: return new.copy()
+                    else: return new
+
+                if isinstance(data, str):
+                    data = _convert_from_string(data)
+
+                # now convert data to an array
                 arr = N.array(data, dtype=dtype, copy=copy)
+                ndim = arr.ndim
                 shape = arr.shape
+                if (ndim > 2):
+                    raise ValueError("matrix must be 2-dimensional")
+                elif ndim == 0:
+                    shape = (1, 1)
+                elif ndim == 1:
+                    shape = (1, shape[0])
+
+                order = False
+                if (ndim == 2) and arr.flags.fortran:
+                    order = True
+
+                if not (order or arr.flags.contiguous):
+                    arr = arr.copy()
 
                 ret = N.ndarray.__new__(subtype, shape, arr.dtype,
                                         buffer=arr,
-                                        order=True)
+                                        order=order)
                 return ret
 
+            def __array_finalize__(self, obj):
+                print('matrix __array_finalize__')
+                self._getitem = False
+                if (isinstance(obj, matrix) and obj._getitem): return
+                ndim = self.ndim
+                if (ndim == 2):
+                    return
+                if (ndim > 2):
+                    newshape = tuple([x for x in self.shape if x > 1])
+                    ndim = len(newshape)
+                    if ndim == 2:
+                        self.shape = newshape
+                        return
+                    elif (ndim > 2):
+                        raise ValueError("shape too large to be a matrix.")
+                else:
+                    newshape = self.shape
+                if ndim == 0:
+                    self.shape = (1, 1)
+                elif ndim == 1:
+                    self.shape = (1, newshape[0])
+                return
+
             def __getitem__(self, index):
-                matrix.getcnt += 1
-                if matrix.getcnt > 10:
-                    # XXX strides.find_shape_and_elems is sensitive
-                    # to shape modification
-                    xxx
-                out = N.ndarray.__getitem__(self, index)
+                print('matrix __getitem__')
+                self._getitem = True
+
+                try:
+                    out = N.ndarray.__getitem__(self, index)
+                finally:
+                    self._getitem = False
 
                 if not isinstance(out, N.ndarray):
                     return out
+
+                if out.ndim == 0:
+                    return out[()]
+                if out.ndim == 1:
+                    sh = out.shape[0]
                     # Determine when we should have a column array
-                old_shape = out.shape
-                if out.ndim < 2:
-                    sh = out.shape[0]
                     try:
                         n = len(index)
                     except:
                         n = 0
-                    if n > 1:
+                    if n > 1 and isscalar(index[1]):
                         out.shape = (sh, 1)
                     else:
                         out.shape = (1, sh)
-                #print 'out, shape was',old_shape,'now',out.shape,'out',out
                 return out
+
         a = matrix([[1., 2.], [3., 4.]])
         b = N.array([a])
         assert (b == a).all()
@@ -318,6 +381,17 @@
         assert len(b.shape) == 2
         assert (b == a).all()
 
+        b = N.array(a, copy=True, dtype=int)
+        assert len(b.shape) == 2
+        assert (b == a).all()
+
+        c = matrix(a, copy=False)
+        assert c.base is not None
+        c[0, 0] = 100
+        assert a[0, 0] == 100
+        b = N.array(c, copy=True)
+        assert (b == a).all()
+
     def test_setstate_no_version(self):
         # Some subclasses of ndarray, like MaskedArray, do not use
         # version in __setstare__


More information about the pypy-commit mailing list