[pypy-commit] pypy fix-result-types: hg merge default

rlamy noreply at buildbot.pypy.org
Tue May 19 19:07:28 CEST 2015


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: fix-result-types
Changeset: r77396:593186bc7eee
Date: 2015-05-19 17:37 +0100
http://bitbucket.org/pypy/pypy/changeset/593186bc7eee/

Log:	hg merge default

diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -109,3 +109,8 @@
 
 branch pythonoptimize-env
 Implement PYTHONOPTIMIZE environment variable, fixing issue #2044
+
+.. branch: numpy-flags
+
+branch numpy-flags
+Finish implementation of ndarray.flags, including str() and repr()
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
@@ -22,6 +22,9 @@
     """Base class for ndarrays and scalars (aka boxes)."""
     _attrs_ = []
 
+    def get_flags(self):
+        return 0
+
 
 class W_NDimArray(W_NumpyObject):
     __metaclass__ = extendabletype
@@ -134,6 +137,9 @@
     def get_start(self):
         return self.implementation.start
 
+    def get_flags(self):
+        return self.implementation.flags
+
     def ndims(self):
         return len(self.get_shape())
     ndims._always_inline_ = True
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -143,6 +143,10 @@
     def get_scalar_value(self):
         return self
 
+    def get_flags(self):
+        return (NPY.ARRAY_C_CONTIGUOUS | NPY.ARRAY_F_CONTIGUOUS | 
+                NPY.ARRAY_WRITEABLE | NPY.ARRAY_OWNDATA)
+
     def item(self, space):
         return self.get_dtype(space).itemtype.to_builtin_type(space, self)
 
diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -7,11 +7,12 @@
 from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
 from pypy.module.micronumpy import support, loop, constants as NPY
 from pypy.module.micronumpy.base import convert_to_array, W_NDimArray, \
-    ArrayArgumentException
+    ArrayArgumentException, W_NumpyObject
 from pypy.module.micronumpy.iterators import ArrayIter
 from pypy.module.micronumpy.strides import (Chunk, Chunks, NewAxisChunk,
     RecordChunk, calc_strides, calc_new_strides, shape_agreement,
-    calculate_broadcast_strides, calc_backstrides, calc_start)
+    calculate_broadcast_strides, calc_backstrides, calc_start, is_c_contiguous,
+    is_f_contiguous)
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rtyper.annlowlevel import cast_gcref_to_instance
 from pypy.interpreter.baseobjspace import W_Root
@@ -19,7 +20,8 @@
 
 class BaseConcreteArray(object):
     _immutable_fields_ = ['dtype?', 'storage', 'start', 'size', 'shape[*]',
-                          'strides[*]', 'backstrides[*]', 'order', 'gcstruct']
+                          'strides[*]', 'backstrides[*]', 'order', 'gcstruct',
+                          'flags']
     start = 0
     parent = None
     flags = 0
@@ -443,6 +445,11 @@
         ConcreteArrayNotOwning.__init__(self, shape, dtype, order, strides, backstrides,
                                         storage, start=start)
         self.gcstruct = gcstruct
+        self.flags = NPY.ARRAY_ALIGNED | NPY.ARRAY_WRITEABLE
+        if is_c_contiguous(self):
+            self.flags |= NPY.ARRAY_C_CONTIGUOUS
+        if is_f_contiguous(self):
+            self.flags |= NPY.ARRAY_F_CONTIGUOUS
 
     def __del__(self):
         if self.gcstruct:
@@ -456,18 +463,39 @@
         ConcreteArrayNotOwning.__init__(self, shape, dtype, order,
                                         strides, backstrides, storage, start)
         self.orig_base = orig_base
+        if isinstance(orig_base, W_NumpyObject):
+            self.flags = orig_base.get_flags() & NPY.ARRAY_ALIGNED
+            self.flags |=  orig_base.get_flags() & NPY.ARRAY_WRITEABLE
+        else:
+            self.flags = 0
+        if is_c_contiguous(self):
+            self.flags |= NPY.ARRAY_C_CONTIGUOUS
+        if is_f_contiguous(self):
+            self.flags |= NPY.ARRAY_F_CONTIGUOUS
 
     def base(self):
         return self.orig_base
 
 
 class ConcreteNonWritableArrayWithBase(ConcreteArrayWithBase):
+    def __init__(self, shape, dtype, order, strides, backstrides, storage,
+                 orig_base, start=0):
+        ConcreteArrayWithBase.__init__(self, shape, dtype, order, strides,
+                backstrides, storage, orig_base, start)
+        self.flags &= ~ NPY.ARRAY_WRITEABLE
+
     def descr_setitem(self, space, orig_array, w_index, w_value):
         raise OperationError(space.w_ValueError, space.wrap(
             "assignment destination is read-only"))
 
 
 class NonWritableArray(ConcreteArray):
+    def __init__(self, shape, dtype, order, strides, backstrides,
+                 storage=lltype.nullptr(RAW_STORAGE), zero=True):
+        ConcreteArray.__init__(self, shape, dtype, order, strides, backstrides,
+                    storage, zero)
+        self.flags &= ~ NPY.ARRAY_WRITEABLE
+        
     def descr_setitem(self, space, orig_array, w_index, w_value):
         raise OperationError(space.w_ValueError, space.wrap(
             "assignment destination is read-only"))
@@ -491,6 +519,12 @@
         self.size = support.product(shape) * self.dtype.elsize
         self.start = start
         self.orig_arr = orig_arr
+        self.flags = parent.flags & NPY.ARRAY_ALIGNED
+        self.flags |= parent.flags & NPY.ARRAY_WRITEABLE
+        if is_c_contiguous(self):
+            self.flags |= NPY.ARRAY_C_CONTIGUOUS
+        if is_f_contiguous(self):
+            self.flags |= NPY.ARRAY_F_CONTIGUOUS
 
     def base(self):
         return self.orig_arr
@@ -538,6 +572,12 @@
         return sort_array(self, space, w_axis, w_order)
 
 class NonWritableSliceArray(SliceArray):
+    def __init__(self, start, strides, backstrides, shape, parent, orig_arr,
+                 dtype=None):
+        SliceArray.__init__(self, start, strides, backstrides, shape, parent,
+                        orig_arr, dtype)
+        self.flags &= ~NPY.ARRAY_WRITEABLE
+
     def descr_setitem(self, space, orig_array, w_index, w_value):
         raise OperationError(space.w_ValueError, space.wrap(
             "assignment destination is read-only"))
@@ -549,6 +589,8 @@
         self.gcstruct = V_OBJECTSTORE
         self.dtype = dtype
         self.size = size
+        self.flags = (NPY.ARRAY_C_CONTIGUOUS | NPY.ARRAY_F_CONTIGUOUS |
+                     NPY.ARRAY_WRITEABLE | NPY.ARRAY_ALIGNED)
 
     def __del__(self):
         free_raw_storage(self.storage)
diff --git a/pypy/module/micronumpy/constants.py b/pypy/module/micronumpy/constants.py
--- a/pypy/module/micronumpy/constants.py
+++ b/pypy/module/micronumpy/constants.py
@@ -77,8 +77,20 @@
 WRAP = 1
 RAISE = 2
 
+# These can be requested in constructor functions and tested for
 ARRAY_C_CONTIGUOUS = 0x0001
 ARRAY_F_CONTIGUOUS = 0x0002
+ARRAY_ALIGNED      = 0x0100
+ARRAY_WRITEABLE    = 0x0400
+ARRAY_UPDATEIFCOPY = 0x1000 # base contains a ref to an array, update it too
+# These can be tested for
+ARRAY_OWNDATA     = 0x004
+# These can be requested in constructor functions
+ARRAY_FORECAST    = 0x0010 # causes a cast to occur even if not safe to do so
+ARRAY_ENSURECOPY  = 0x0020 # returned array will be CONTIGUOUS, ALIGNED, WRITEABLE
+ARRAY_ENSUREARRAY = 0x0040 # return only ndarray, not subtype
+ARRAY_ELEMENTSTRIDES = 0x0080 # strides  are units of the dtype element size
+ARRAY_NOTSWAPPED  = 0x0200 #native byte order
 
 LITTLE = '<'
 BIG = '>'
diff --git a/pypy/module/micronumpy/flagsobj.py b/pypy/module/micronumpy/flagsobj.py
--- a/pypy/module/micronumpy/flagsobj.py
+++ b/pypy/module/micronumpy/flagsobj.py
@@ -1,4 +1,5 @@
 from rpython.rlib import jit
+from rpython.rlib.rstring import StringBuilder
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError
@@ -13,54 +14,55 @@
 def clear_flags(arr, flags):
     arr.flags &= ~flags
 
-def _update_contiguous_flags(arr):
-    is_c_contig = is_c_contiguous(arr)
-    if is_c_contig:
-        enable_flags(arr, NPY.ARRAY_C_CONTIGUOUS)
-    else:
-        clear_flags(arr, NPY.ARRAY_C_CONTIGUOUS)
-
-    is_f_contig = is_f_contiguous(arr)
-    if is_f_contig:
-        enable_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
-    else:
-        clear_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
-
+def get_tf_str(flags, key):
+    if flags & key:
+        return 'True'
+    return 'False'
 
 class W_FlagsObject(W_Root):
     def __init__(self, arr):
-        self.flags = 0
+        if arr:
+            self.flags = arr.get_flags()
+        else:
+            self.flags = (NPY.ARRAY_C_CONTIGUOUS | NPY.ARRAY_F_CONTIGUOUS |
+                          NPY.ARRAY_OWNDATA | NPY.ARRAY_ALIGNED)
 
     def descr__new__(space, w_subtype):
         self = space.allocate_instance(W_FlagsObject, w_subtype)
         W_FlagsObject.__init__(self, None)
         return self
 
-    def descr_get_contiguous(self, space):
-        return space.w_True
+    def descr_c_contiguous(self, space):
+        return space.wrap(bool(self.flags & NPY.ARRAY_C_CONTIGUOUS))
 
-    def descr_get_fortran(self, space):
-        return space.w_False
+    def descr_f_contiguous(self, space):
+        return space.wrap(bool(self.flags & NPY.ARRAY_F_CONTIGUOUS))
 
     def descr_get_writeable(self, space):
-        return space.w_True
+        return space.wrap(bool(self.flags & NPY.ARRAY_WRITEABLE))
+
+    def descr_get_owndata(self, space):
+        return space.wrap(bool(self.flags & NPY.ARRAY_OWNDATA))
+
+    def descr_get_aligned(self, space):
+        return space.wrap(bool(self.flags & NPY.ARRAY_ALIGNED))
 
     def descr_get_fnc(self, space):
-        return space.wrap(
-            space.is_true(self.descr_get_fortran(space)) and not
-            space.is_true(self.descr_get_contiguous(space)))
+        return space.wrap(bool(
+            self.flags & NPY.ARRAY_F_CONTIGUOUS and not
+            self.flags & NPY.ARRAY_C_CONTIGUOUS ))
 
     def descr_get_forc(self, space):
-        return space.wrap(
-            space.is_true(self.descr_get_fortran(space)) or
-            space.is_true(self.descr_get_contiguous(space)))
+        return space.wrap(bool(
+            self.flags & NPY.ARRAY_F_CONTIGUOUS or
+            self.flags & NPY.ARRAY_C_CONTIGUOUS ))
 
     def descr_getitem(self, space, w_item):
         key = space.str_w(w_item)
         if key == "C" or key == "CONTIGUOUS" or key == "C_CONTIGUOUS":
-            return self.descr_get_contiguous(space)
+            return self.descr_c_contiguous(space)
         if key == "F" or key == "FORTRAN" or key == "F_CONTIGUOUS":
-            return self.descr_get_fortran(space)
+            return self.descr_f_contiguous(space)
         if key == "W" or key == "WRITEABLE":
             return self.descr_get_writeable(space)
         if key == "FNC":
@@ -85,6 +87,22 @@
     def descr_ne(self, space, w_other):
         return space.wrap(not self.eq(space, w_other))
 
+    def descr___str__(self, space):
+        s = StringBuilder()
+        s.append('  C_CONTIGUOUS : ')
+        s.append(get_tf_str(self.flags, NPY.ARRAY_C_CONTIGUOUS))
+        s.append('\n  F_CONTIGUOUS : ')
+        s.append(get_tf_str(self.flags, NPY.ARRAY_F_CONTIGUOUS))
+        s.append('\n  OWNDATA : ')
+        s.append(get_tf_str(self.flags, NPY.ARRAY_OWNDATA))
+        s.append('\n  WRITEABLE : ')
+        s.append(get_tf_str(self.flags, NPY.ARRAY_WRITEABLE))
+        s.append('\n  ALIGNED : ')
+        s.append(get_tf_str(self.flags, NPY.ARRAY_ALIGNED))
+        s.append('\n  UPDATEIFCOPY : ')
+        s.append(get_tf_str(self.flags, NPY.ARRAY_UPDATEIFCOPY))
+        return space.wrap(s.build())
+
 W_FlagsObject.typedef = TypeDef("numpy.flagsobj",
     __new__ = interp2app(W_FlagsObject.descr__new__.im_func),
 
@@ -92,12 +110,16 @@
     __setitem__ = interp2app(W_FlagsObject.descr_setitem),
     __eq__ = interp2app(W_FlagsObject.descr_eq),
     __ne__ = interp2app(W_FlagsObject.descr_ne),
+    __str__ = interp2app(W_FlagsObject.descr___str__),
+    __repr__ = interp2app(W_FlagsObject.descr___str__),
 
-    contiguous = GetSetProperty(W_FlagsObject.descr_get_contiguous),
-    c_contiguous = GetSetProperty(W_FlagsObject.descr_get_contiguous),
-    f_contiguous = GetSetProperty(W_FlagsObject.descr_get_fortran),
-    fortran = GetSetProperty(W_FlagsObject.descr_get_fortran),
+    contiguous = GetSetProperty(W_FlagsObject.descr_c_contiguous),
+    c_contiguous = GetSetProperty(W_FlagsObject.descr_c_contiguous),
+    f_contiguous = GetSetProperty(W_FlagsObject.descr_f_contiguous),
+    fortran = GetSetProperty(W_FlagsObject.descr_f_contiguous),
     writeable = GetSetProperty(W_FlagsObject.descr_get_writeable),
+    owndata = GetSetProperty(W_FlagsObject.descr_get_owndata),
+    aligned = GetSetProperty(W_FlagsObject.descr_get_aligned),
     fnc = GetSetProperty(W_FlagsObject.descr_get_fnc),
     forc = GetSetProperty(W_FlagsObject.descr_get_forc),
 )
diff --git a/pypy/module/micronumpy/iterators.py b/pypy/module/micronumpy/iterators.py
--- a/pypy/module/micronumpy/iterators.py
+++ b/pypy/module/micronumpy/iterators.py
@@ -39,8 +39,6 @@
 from rpython.rlib import jit
 from pypy.module.micronumpy import support, constants as NPY
 from pypy.module.micronumpy.base import W_NDimArray
-from pypy.module.micronumpy.flagsobj import _update_contiguous_flags
-
 
 class PureShapeIter(object):
     def __init__(self, shape, idx_w):
@@ -96,7 +94,6 @@
     @jit.unroll_safe
     def __init__(self, array, size, shape, strides, backstrides):
         assert len(shape) == len(strides) == len(backstrides)
-        _update_contiguous_flags(array)
         self.contiguous = (array.flags & NPY.ARRAY_C_CONTIGUOUS and
                            array.shape == shape and array.strides == strides)
 
diff --git a/pypy/module/micronumpy/nditer.py b/pypy/module/micronumpy/nditer.py
--- a/pypy/module/micronumpy/nditer.py
+++ b/pypy/module/micronumpy/nditer.py
@@ -4,7 +4,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.module.micronumpy import support, concrete
-from pypy.module.micronumpy.base import W_NDimArray, convert_to_array
+from pypy.module.micronumpy.base import W_NDimArray, convert_to_array, W_NumpyObject
 from pypy.module.micronumpy.descriptor import decode_w_dtype
 from pypy.module.micronumpy.iterators import ArrayIter
 from pypy.module.micronumpy.strides import (calculate_broadcast_strides,
@@ -364,7 +364,7 @@
         return ret
 
 
-class W_NDIter(W_Root):
+class W_NDIter(W_NumpyObject):
     _immutable_fields_ = ['ndim', ]
     def __init__(self, space, w_seq, w_flags, w_op_flags, w_op_dtypes,
                  w_casting, w_op_axes, w_itershape, buffersize=0, order='K'):
diff --git a/pypy/module/micronumpy/test/test_flagsobj.py b/pypy/module/micronumpy/test/test_flagsobj.py
--- a/pypy/module/micronumpy/test/test_flagsobj.py
+++ b/pypy/module/micronumpy/test/test_flagsobj.py
@@ -9,6 +9,10 @@
         b = type(a.flags)()
         assert b is not a.flags
         assert b['C'] is True
+        s = str(b)
+        assert s == '%s' %('  C_CONTIGUOUS : True\n  F_CONTIGUOUS : True'
+                         '\n  OWNDATA : True\n  WRITEABLE : False'
+                         '\n  ALIGNED : True\n  UPDATEIFCOPY : False')
 
     def test_repr(self):
         import numpy as np
diff --git a/pypy/module/micronumpy/test/test_iterators.py b/pypy/module/micronumpy/test/test_iterators.py
--- a/pypy/module/micronumpy/test/test_iterators.py
+++ b/pypy/module/micronumpy/test/test_iterators.py
@@ -1,5 +1,7 @@
 from pypy.module.micronumpy import support
 from pypy.module.micronumpy.iterators import ArrayIter
+from pypy.module.micronumpy.strides import is_c_contiguous, is_f_contiguous
+from pypy.module.micronumpy import constants as NPY
 
 
 class MockArray(object):
@@ -12,6 +14,10 @@
         self.shape = shape
         self.strides = strides
         self.start = start
+        if is_c_contiguous(self):
+            self.flags |= NPY.ARRAY_C_CONTIGUOUS
+        if is_f_contiguous(self):
+            self.flags |= NPY.ARRAY_F_CONTIGUOUS
 
     def get_shape(self):
         return self.shape
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -258,17 +258,6 @@
         # test uninitialized value crash?
         assert len(str(a)) > 0
 
-        import sys
-        for order in [False, True, 'C', 'F']:
-            a = ndarray.__new__(ndarray, (2, 3), float, order=order)
-            assert a.shape == (2, 3)
-            if order in [True, 'F'] and '__pypy__' not in sys.builtin_module_names:
-                assert a.flags['F']
-                assert not a.flags['C']
-            else:
-                assert a.flags['C']
-                assert not a.flags['F']
-
         x = array([[0, 2], [1, 1], [2, 0]])
         y = array(x.T, dtype=float)
         assert (y == x.T).all()
@@ -2588,6 +2577,18 @@
         assert a[0][1][1] == 13
         assert a[1][2][1] == 15
 
+    def test_create_order(self):
+        import sys, numpy as np
+        for order in [False, True, 'C', 'F']:
+            a = np.empty((2, 3), float, order=order)
+            assert a.shape == (2, 3)
+            if order in [True, 'F'] and '__pypy__' not in sys.builtin_module_names:
+                assert a.flags['F']
+                assert not a.flags['C']
+            else:
+                assert a.flags['C'], "flags['C'] False for %r" % order
+                assert not a.flags['F']
+
     def test_setitem_slice(self):
         import numpy
         a = numpy.zeros((3, 4))
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -759,9 +759,26 @@
     noninplacespacemethod = specialname[3:-2]
     if noninplacespacemethod in ['or', 'and']:
         noninplacespacemethod += '_'     # not too clean
+    seq_bug_compat = (symbol == '+=' or symbol == '*=')
+    rhs_method = '__r' + specialname[3:]
+
     def inplace_impl(space, w_lhs, w_rhs):
         w_impl = space.lookup(w_lhs, specialname)
         if w_impl is not None:
+            # 'seq_bug_compat' is for cpython bug-to-bug compatibility:
+            # see objspace/test/test_descrobject.*rmul_overrides.
+            # For cases like "list += object-overriding-__radd__".
+            if (seq_bug_compat and space.type(w_lhs).flag_sequence_bug_compat
+                           and not space.type(w_rhs).flag_sequence_bug_compat):
+                w_res = _invoke_binop(space, space.lookup(w_rhs, rhs_method),
+                                      w_rhs, w_lhs)
+                if w_res is not None:
+                    return w_res
+                # xxx if __radd__ is defined but returns NotImplemented,
+                # then it might be called again below.  Oh well, too bad.
+                # Anyway that's a case where we're likely to end up in
+                # a TypeError.
+            #
             w_res = space.get_and_call_function(w_impl, w_lhs, w_rhs)
             if _check_notimplemented(space, w_res):
                 return w_res
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -759,6 +759,12 @@
         assert bytearray('2') * oops() == 42
         assert 1000 * oops() == 42
         assert '2'.__mul__(oops()) == '222'
+        x = '2'
+        x *= oops()
+        assert x == 42
+        x = [2]
+        x *= oops()
+        assert x == 42
 
     def test_sequence_rmul_overrides_oldstyle(self):
         class oops:
@@ -783,6 +789,12 @@
         assert [2] + A1([3]) == [2, 3]
         assert type([2] + A1([3])) is list
         assert [2] + A2([3]) == 42
+        x = "2"
+        x += A2([3])
+        assert x == 42
+        x = [2]
+        x += A2([3])
+        assert x == 42
 
     def test_data_descriptor_without_delete(self):
         class D(object):
diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py
--- a/rpython/jit/metainterp/test/test_fficall.py
+++ b/rpython/jit/metainterp/test/test_fficall.py
@@ -53,15 +53,12 @@
 
         cif_description = get_description(atypes, rtype)
 
-        expected_args = []
-        for avalue in avalues:
-            if lltype.typeOf(avalue) == rffi.ULONG:
-                avalue = intmask(avalue)
-            expected_args.append(avalue)
-        expected_args = tuple(expected_args)
-
         def verify(*args):
-            assert args == expected_args
+            for a, exp_a in zip(args, avalues):
+                if (lltype.typeOf(exp_a) == rffi.ULONG and
+                    lltype.typeOf(a) == lltype.Signed):
+                    a = rffi.cast(rffi.ULONG, a)
+                assert a == exp_a
             return rvalue
         FUNC = lltype.FuncType([lltype.typeOf(avalue) for avalue in avalues],
                                lltype.typeOf(rvalue))


More information about the pypy-commit mailing list