[pypy-commit] pypy py3.5: hg merge default

arigo pypy.commits at gmail.com
Tue Oct 18 04:47:16 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r87853:48faf85ce555
Date: 2016-10-18 10:46 +0200
http://bitbucket.org/pypy/pypy/changeset/48faf85ce555/

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
@@ -73,11 +73,16 @@
 Make optimiseopt iterative instead of recursive so it can be reasoned about
 more easily and debugging is faster.
 
-.. branch: stdlib-2.7.11
+.. branch: Tiberiumk/fix-2412-1476011166874
+.. branch: redirect-assembler-jitlog
 
-Update stdlib to version 2.7.11
 
-.. branch: vendor/stdlib
+
 .. branch: stdlib-2.7.12
 
 Update stdlib to version 2.7.12
+
+.. branch: buffer-interface2
+
+Improve support for new buffer interface in cpyext, bf_getbuffer on built-in
+types still missing
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -225,7 +225,12 @@
         return self._buffer(space, flags).buffer_w_ex(space, flags)
 
     def _buffer(self, space, flags):
-        w_impl = space.lookup(self, '__buffer__')
+        if flags & space.BUF_WRITABLE:
+            w_impl = space.lookup(self, '__wbuffer__')
+        else:
+            w_impl = space.lookup(self, '__rbuffer__')
+        if w_impl is None:
+            w_impl = space.lookup(self, '__buffer__')
         if w_impl is not None:
             w_result = space.get_and_call_function(w_impl, self,
                                                    space.newint(flags))
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -133,7 +133,7 @@
 
 /* Py3k buffer interface, adapted for PyPy */
 #define Py_MAX_NDIMS 32
-#define Py_MAX_FMT 5
+#define Py_MAX_FMT 128
 typedef struct bufferinfo {
     void *buf;
     PyObject *obj;        /* owned reference */
diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -4,6 +4,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rlib.rarithmetic import widen
 from pypy.objspace.std.memoryobject import W_MemoryView
+from pypy.module.cpyext.import_ import PyImport_Import
 
 from pypy.interpreter.error import oefmt
 from pypy.module.cpyext.pyobject import PyObject, from_ref
@@ -18,23 +19,32 @@
     view.c_itemsize = buf.getitemsize()
     rffi.setintfield(view, 'c_ndim', ndim)
     view.c_format = rffi.cast(rffi.CCHARP, view.c__format)
-    view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape)
-    view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides)
     fmt = buf.getformat()
     n = Py_MAX_FMT - 1 # NULL terminated buffer
     if len(fmt) > n:
-        ### WARN?
-        pass
+        w_message = space.newbytes("PyPy specific Py_MAX_FMT is %d which is too "
+                           "small for buffer format, %d needed" % (
+                           Py_MAX_FMT, len(fmt)))
+        w_stacklevel = space.newint(1)
+        w_module = PyImport_Import(space, space.newbytes("warnings"))
+        w_warn = space.getattr(w_module, space.newbytes("warn"))
+        space.call_function(w_warn, w_message, space.w_None, w_stacklevel)
     else:
         n = len(fmt)
     for i in range(n):
         view.c_format[i] = fmt[i]
     view.c_format[n] = '\x00'
-    shape = buf.getshape()
-    strides = buf.getstrides()
-    for i in range(ndim):
-        view.c_shape[i] = shape[i]
-        view.c_strides[i] = strides[i]
+    if ndim > 0:
+        view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape)
+        view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides)
+        shape = buf.getshape()
+        strides = buf.getstrides()
+        for i in range(ndim):
+            view.c_shape[i] = shape[i]
+            view.c_strides[i] = strides[i]
+    else:
+        view.c_shape = lltype.nullptr(Py_ssize_tP.TO)
+        view.c_strides = lltype.nullptr(Py_ssize_tP.TO)
     view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO)
     view.c_internal = lltype.nullptr(rffi.VOIDP.TO)
     return 0
@@ -77,12 +87,12 @@
 
 @cpython_api([lltype.Ptr(Py_buffer), lltype.Char], rffi.INT_real, error=CANNOT_FAIL)
 def PyBuffer_IsContiguous(space, view, fort):
-    """Return 1 if the memory defined by the view is C-style (fortran is
-    'C') or Fortran-style (fortran is 'F') contiguous or either one
-    (fortran is 'A').  Return 0 otherwise."""
+    """Return 1 if the memory defined by the view is C-style (fort is
+    'C') or Fortran-style (fort is 'F') contiguous or either one
+    (fort is 'A').  Return 0 otherwise."""
     # traverse the strides, checking for consistent stride increases from
     # right-to-left (c) or left-to-right (fortran). Copied from cpython
-    if not view.c_suboffsets:
+    if view.c_suboffsets:
         return 0
     if (fort == 'C'):
         return _IsCContiguous(view)
@@ -114,6 +124,7 @@
     if ndim >= Py_MAX_NDIMS:
         # XXX warn?
         return view
+    fill_Py_buffer(space, w_obj.buf, view)
     try:
         view.c_buf = rffi.cast(rffi.VOIDP, w_obj.buf.get_raw_address())
         view.c_obj = make_ref(space, w_obj)
@@ -122,9 +133,9 @@
     except ValueError:
         w_s = w_obj.descr_tobytes(space)
         view.c_obj = make_ref(space, w_s)
+        view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(space.str_w(w_s), track_allocation=False))
         rffi.setintfield(view, 'c_readonly', 1)
         isstr = True
-    fill_Py_buffer(space, w_obj.buf, view)
     return view
 
 @cpython_api([lltype.Ptr(Py_buffer)], PyObject)
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -21,7 +21,7 @@
 @cpython_api([PyObject, CONST_STRING], lltype.Void)
 def PyErr_SetString(space, w_type, message_ptr):
     message = rffi.charp2str(message_ptr)
-    PyErr_SetObject(space, w_type, space.wrap(message))
+    PyErr_SetObject(space, w_type, space.newbytes(message))
 
 @cpython_api([PyObject], lltype.Void, error=CANNOT_FAIL)
 def PyErr_SetNone(space, w_type):
@@ -146,12 +146,12 @@
     Return value: always NULL."""
     # XXX Doesn't actually do anything with PyErr_CheckSignals.
     if llfilename:
-        w_filename = rffi.charp2str(llfilename)
-        filename = space.wrap(w_filename)
+        filename = rffi.charp2str(llfilename)
+        w_filename = space.newbytes(filename)
     else:
-        filename = space.w_None
+        w_filename = space.w_None
 
-    PyErr_SetFromErrnoWithFilenameObject(space, w_type, filename)
+    PyErr_SetFromErrnoWithFilenameObject(space, w_type, w_filename)
 
 @cpython_api([PyObject, PyObject], PyObject)
 @jit.dont_look_inside       # direct use of _get_errno()
@@ -166,13 +166,13 @@
     msg = _strerror(errno)
     if w_value:
         w_error = space.call_function(w_type,
-                                      space.wrap(errno),
-                                      space.wrap(msg),
+                                      space.newint(errno),
+                                      space.newbytes(msg),
                                       w_value)
     else:
         w_error = space.call_function(w_type,
-                                      space.wrap(errno),
-                                      space.wrap(msg))
+                                      space.newint(errno),
+                                      space.newbytes(msg))
     raise OperationError(w_type, w_error)
 
 @cpython_api([], rffi.INT_real, error=-1)
@@ -250,11 +250,11 @@
     documentation.  There is no C API for warning control."""
     if w_category is None:
         w_category = space.w_None
-    w_message = space.wrap(rffi.charp2str(message_ptr))
-    w_stacklevel = space.wrap(rffi.cast(lltype.Signed, stacklevel))
+    w_message = space.newbytes(rffi.charp2str(message_ptr))
+    w_stacklevel = space.newint(rffi.cast(lltype.Signed, stacklevel))
 
-    w_module = PyImport_Import(space, space.wrap("warnings"))
-    w_warn = space.getattr(w_module, space.wrap("warn"))
+    w_module = PyImport_Import(space, space.newbytes("warnings"))
+    w_warn = space.getattr(w_module, space.newbytes("warn"))
     space.call_function(w_warn, w_message, w_category, w_stacklevel)
     return 0
 
@@ -315,10 +315,10 @@
 
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
 def PyTraceBack_Print(space, w_tb, w_file):
-    space.call_method(w_file, "write", space.wrap(
+    space.call_method(w_file, "write", space.newbytes(
         'Traceback (most recent call last):\n'))
     w_traceback = space.call_method(space.builtin, '__import__',
-                                    space.wrap("traceback"))
+                                    space.newbytes("traceback"))
     space.call_method(w_traceback, "print_tb", w_tb, space.w_None, w_file)
     return 0
 
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -14,6 +14,7 @@
     getbufferproc, ssizessizeobjargproc)
 from pypy.module.cpyext.pyobject import from_ref, make_ref, Py_DecRef
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
+from pypy.module.cpyext.memoryobject import fill_Py_buffer
 from pypy.module.cpyext.state import State
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.argument import Arguments
@@ -340,6 +341,10 @@
     def getndim(self):
         return self.ndim
 
+    def setitem(self, index, char):
+        # absolutely no safety checks, what could go wrong?
+        self.ptr[index] = char
+
 def wrap_getbuffer(space, w_self, w_args, func):
     func_target = rffi.cast(getbufferproc, func)
     with lltype.scoped_alloc(Py_buffer) as pybuf:
@@ -589,13 +594,27 @@
         @cpython_api([PyObject, Py_bufferP, rffi.INT_real],
                 rffi.INT_real, header=None, error=-1)
         @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
-        def buff_w(space, w_self, pybuf, flags):
-            # XXX this is wrong, needs a test
-            raise oefmt(space.w_NotImplemented,
-                "calling bf_getbuffer on a builtin type not supported yet")
-            #args = Arguments(space, [w_self],
-            #                 w_stararg=w_args, w_starstararg=w_kwds)
-            #return space.call_args(space.get(buff_fn, w_self), args)
+        def buff_w(space, w_self, view, flags):
+            args = Arguments(space, [space.newint(flags)])
+            w_obj = space.call_args(space.get(buff_fn, w_self), args)
+            if view:
+                #like PyObject_GetBuffer
+                flags = widen(flags)
+                buf = space.buffer_w(w_obj, flags)
+                try:
+                    view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address())
+                    view.c_obj = make_ref(space, w_obj)
+                except ValueError:
+                    w_s = space.newbytes(buf.as_str())
+                    view.c_obj = make_ref(space, w_s)
+                    view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(
+                                    space.str_w(w_s), track_allocation=False))
+                    rffi.setintfield(view, 'c_readonly', 1)
+                ret = fill_Py_buffer(space, buf, view)
+                return ret
+            return 0
+        # XXX remove this when it no longer crashes a translated PyPy
+        return
         api_func = buff_w.api_func
     else:
         # missing: tp_as_number.nb_nonzero, tp_as_number.nb_coerce
@@ -874,13 +893,13 @@
 slotdefs = eval(slotdefs_str)
 # PyPy addition
 slotdefs += (
-    # XXX that might not be what we want!
     TPSLOT("__buffer__", "tp_as_buffer.c_bf_getbuffer", None, "wrap_getbuffer", ""),
 )
 
 if not PY3:
     slotdefs += (
-        TPSLOT("__buffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
+        TPSLOT("__rbuffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
+        TPSLOT("__wbuffer__", "tp_as_buffer.c_bf_getwritebuffer", None, "wrap_getwritebuffer", ""),
     )
 
 
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2856,15 +2856,30 @@
     (iternextfunc)arrayiter_next,               /* tp_iternext */
     0,                                          /* tp_methods */
 };
+static PyObject *
+readbuffer_as_string(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    const void *ptr;
+    Py_ssize_t size;
+
+    if (!PyArg_ParseTuple(args, "O", &obj)) {
+        return NULL;
+    }
+    if (PyObject_AsReadBuffer(obj, &ptr, &size) < 0)
+        return NULL;
+    return PyString_FromStringAndSize((char*)ptr, size);
+}
+
 
 
 /*********************** Install Module **************************/
 
-/* No functions in array module. */
 static PyMethodDef a_methods[] = {
     {"_array_reconstructor", array_reconstructor, METH_VARARGS,
      PyDoc_STR("Internal. Used for pickling support.")},
     {"switch_multiply",   (PyCFunction)switch_multiply, METH_NOARGS, NULL},
+    {"readbuffer_as_string",   (PyCFunction)readbuffer_as_string, METH_VARARGS, NULL},
     {NULL, NULL, 0, NULL}        /* Sentinel */
 };
 
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -1,8 +1,17 @@
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
-
+from pypy.conftest import option
 
 class AppTestArrayModule(AppTestCpythonExtensionBase):
-    enable_leak_checking = False
+    enable_leak_checking = True
+
+    def setup_class(cls):
+        from rpython.tool.udir import udir
+        AppTestCpythonExtensionBase.setup_class.im_func(cls)
+        if option.runappdirect:
+            cls.w_udir = str(udir)
+        else:
+            cls.w_udir = cls.space.wrap(str(udir))
+
 
     def test_basic(self):
         module = self.import_module(name='array')
@@ -80,6 +89,7 @@
         assert res == [2, 4, 6]
 
     def test_subclass(self):
+        import struct
         module = self.import_module(name='array')
         class Sub(module.array):
             pass
@@ -88,3 +98,37 @@
         res = [1, 2, 3] * arr
         assert res == [1, 2, 3, 1, 2, 3]
 
+        val = module.readbuffer_as_string(arr)
+        assert val == struct.pack('i', 2)
+
+    def test_unicode_readbuffer(self):
+        # Not really part of array, refactor
+        import struct
+        module = self.import_module(name='array')
+        val = module.readbuffer_as_string('abcd')
+        assert val == 'abcd'
+        val = module.readbuffer_as_string(u'\u03a3')
+        assert val is not None
+
+    def test_readinto(self):
+        module = self.import_module(name='array')
+        a = module.array('c')
+        a.fromstring('0123456789')
+        filename = self.udir + "/_test_file"
+        f = open(filename, 'w+b')
+        f.write('foobar')
+        f.seek(0)
+        n = f.readinto(a)
+        f.close()
+        assert n == 6
+        assert len(a) == 10
+        assert a.tostring() == 'foobar6789'
+
+    def test_iowrite(self):
+        module = self.import_module(name='array')
+        from io import BytesIO
+        a = module.array('c')
+        a.fromstring('0123456789')
+        fd = BytesIO()
+        # only test that it works
+        fd.write(a)
diff --git a/pypy/module/cpyext/test/test_getargs.py b/pypy/module/cpyext/test/test_getargs.py
--- a/pypy/module/cpyext/test/test_getargs.py
+++ b/pypy/module/cpyext/test/test_getargs.py
@@ -123,9 +123,10 @@
             return result;
             ''')
         assert b'foo\0bar\0baz' == pybuffer(b'foo\0bar\0baz')
-        return  # XXX
+        #return  # XXX?
         assert b'foo\0bar\0baz' == pybuffer(bytearray(b'foo\0bar\0baz'))
 
+
     def test_pyarg_parse_string_fails(self):
         """
         Test the failing case of PyArg_ParseTuple(): it must not keep
diff --git a/pypy/module/cpyext/test/test_memoryobject.py b/pypy/module/cpyext/test/test_memoryobject.py
--- a/pypy/module/cpyext/test/test_memoryobject.py
+++ b/pypy/module/cpyext/test/test_memoryobject.py
@@ -1,10 +1,14 @@
 import pytest
+
 from rpython.rtyper.lltypesystem import rffi
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from rpython.rlib.buffer import StringBuffer
 
+only_pypy ="config.option.runappdirect and '__pypy__' not in sys.builtin_module_names" 
+
 class TestMemoryViewObject(BaseApiTest):
+    skip('needs c_bf_getbuffer wrapper from slotdefs')
     def test_fromobject(self, space, api):
         w_hello = space.newbytes("hello")
         assert api.PyObject_CheckBuffer(w_hello)
@@ -24,6 +28,8 @@
         assert w_view.c_shape[0] == 5
         assert w_view.c_strides[0] == 1
         assert w_view.c_len == 5
+        o = rffi.charp2str(w_view.c_buf)
+        assert o == 'hello'
 
 class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
     def test_fillWithObject(self):
@@ -80,8 +86,12 @@
         assert viewlen == y.itemsize * len(y)
 
     @pytest.mark.skipif(True, reason="no _numpypy on py3k")
+    #@pytest.mark.skipif(only_pypy, reason='pypy only test')
     def test_buffer_info(self):
-        from _numpypy import multiarray as np
+        try:
+            from _numpypy import multiarray as np
+        except ImportError:
+            skip('pypy built without _numpypy')
         module = self.import_module(name='buffer_test')
         get_buffer_info = module.get_buffer_info
         raises(ValueError, get_buffer_info, np.arange(5)[::2], ('SIMPLE',))
@@ -91,3 +101,29 @@
         arr = np.zeros((10, 1), order='C')
         shape, strides = get_buffer_info(arr, ['C_CONTIGUOUS'])
         assert strides[-1] == 8
+        dt1 = np.dtype(
+             [('a', 'b'), ('b', 'i'), 
+              ('sub0', np.dtype('b,i')), 
+              ('sub1', np.dtype('b,i')), 
+              ('sub2', np.dtype('b,i')), 
+              ('sub3', np.dtype('b,i')), 
+              ('sub4', np.dtype('b,i')), 
+              ('sub5', np.dtype('b,i')), 
+              ('sub6', np.dtype('b,i')), 
+              ('sub7', np.dtype('b,i')), 
+              ('c', 'i')],
+             )
+        x = np.arange(dt1.itemsize, dtype='int8').view(dt1)
+        # pytest can catch warnings from v2.8 and up, we ship 2.5
+        import warnings
+        warnings.filterwarnings("error")
+        try:
+            try:
+                y = get_buffer_info(x, ['SIMPLE'])
+            except UserWarning as e:
+                pass
+            else:
+                assert False ,"PyPy-specific UserWarning not raised" \
+                          " on too long format string"
+        finally:
+            warnings.resetwarnings()
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -610,7 +610,7 @@
     # uninitialized fields:
     # c_tp_print
     # XXX implement
-    # c_tp_compare and the following fields (see http://docs.python.org/c-api/typeobj.html )
+    # c_tp_compare and more?
     w_base = best_base(space, w_type.bases_w)
     pto.c_tp_base = rffi.cast(PyTypeObjectPtr, make_ref(space, w_base))
 
@@ -668,7 +668,6 @@
     return find_best_base(bases_w)
 
 def inherit_slots(space, pto, w_base):
-    # XXX missing: nearly everything
     base_pyo = make_ref(space, w_base)
     try:
         base = rffi.cast(PyTypeObjectPtr, base_pyo)
@@ -687,6 +686,15 @@
             pto.c_tp_getattro = base.c_tp_getattro
         if not pto.c_tp_as_buffer:
             pto.c_tp_as_buffer = base.c_tp_as_buffer
+        if base.c_tp_as_buffer:
+            # inherit base.c_tp_as_buffer functions not inherited from w_type
+            # note: builtin types are handled in setup_buffer_procs
+            pto_as = pto.c_tp_as_buffer
+            base_as = base.c_tp_as_buffer
+            if not pto_as.c_bf_getbuffer:
+                pto_as.c_bf_getbuffer = base_as.c_bf_getbuffer
+            if not pto_as.c_bf_releasebuffer:
+                pto_as.c_bf_releasebuffer = base_as.c_bf_releasebuffer
     finally:
         Py_DecRef(space, base_pyo)
 
@@ -716,21 +724,22 @@
 
     w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype)
     track_reference(space, py_obj, w_obj)
-    w_obj.__init__(space, py_type)
+    # __init__ wraps all slotdefs functions from py_type via add_operators
+    w_obj.__init__(space, py_type) 
     w_obj.ready()
 
     finish_type_2(space, py_type, w_obj)
-    # inheriting tp_as_* slots
     base = py_type.c_tp_base
     if base:
-        if not py_type.c_tp_as_number:
+        # XXX refactor - parts of this are done in finish_type_2 -> inherit_slots
+        if not py_type.c_tp_as_number: 
             py_type.c_tp_as_number = base.c_tp_as_number
             py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
         if not py_type.c_tp_as_sequence:
             py_type.c_tp_as_sequence = base.c_tp_as_sequence
             py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
         if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping
-        if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer
+        #if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer
 
     return w_obj
 
diff --git a/pypy/module/micronumpy/test/dummy_module.py b/pypy/module/micronumpy/test/dummy_module.py
--- a/pypy/module/micronumpy/test/dummy_module.py
+++ b/pypy/module/micronumpy/test/dummy_module.py
@@ -29,7 +29,8 @@
 globals()['uint'] = dtype('uint').type
 
 types = ['Generic', 'Number', 'Integer', 'SignedInteger', 'UnsignedInteger',
-         'Inexact', 'Floating', 'ComplexFloating', 'Flexible', 'Character']
+         'Inexact', 'Floating', 'ComplexFloating', 'Flexible', 'Character',
+        ]
 for t in types:
     globals()[t.lower()] = typeinfo[t]
 
@@ -42,4 +43,4 @@
     return a
 
 def isscalar(a):
-    return type(a) in [typeinfo[t] for t in types]
+    return any([isinstance(a, typeinfo[t]) for t in types])
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
@@ -1486,7 +1486,7 @@
         assert d[1] == 12
 
     def test_sum(self):
-        from numpy import array, zeros, float16, complex64, str_
+        from numpy import array, zeros, float16, complex64, str_, isscalar, add
         a = array(range(5))
         assert a.sum() == 10
         assert a[:4].sum() == 6
@@ -1515,6 +1515,13 @@
 
         assert list(zeros((0, 2)).sum(axis=1)) == []
 
+        a = array([1, 2, 3, 4]).sum()
+        s = isscalar(a)
+        assert s is True
+        a = add.reduce([1.0, 2, 3, 4])
+        s = isscalar(a)
+        assert s is True,'%r is not a scalar' % type(a)
+
     def test_reduce_nd(self):
         from numpy import arange, array
         a = arange(15).reshape(5, 3)
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
@@ -288,10 +288,8 @@
 
         _, dtype, _ = self.find_specialization(space, dtype, dtype, out,
                                                    casting='unsafe')
-        call__array_wrap__ = True
         if shapelen == len(axes):
             if out:
-                call__array_wrap__ = False
                 if out.ndims() > 0:
                     raise oefmt(space.w_ValueError,
                                 "output parameter for reduction operation %s has "
@@ -302,15 +300,20 @@
             if out:
                 out.set_scalar_value(res)
                 return out
+            w_NDimArray = space.gettypefor(W_NDimArray)
+            call__array_wrap__ = False
             if keepdims:
                 shape = [1] * len(obj_shape)
                 out = W_NDimArray.from_shape(space, shape, dtype, w_instance=obj)
                 out.implementation.setitem(0, res)
+                call__array_wrap__ = True
                 res = out
-            elif not space.is_w(space.type(w_obj), space.gettypefor(W_NDimArray)):
+            elif (space.issubtype_w(space.type(w_obj), w_NDimArray) and 
+                  not space.is_w(space.type(w_obj), w_NDimArray)):
                 # subtypes return a ndarray subtype, not a scalar
                 out = W_NDimArray.from_shape(space, [1], dtype, w_instance=obj)
                 out.implementation.setitem(0, res)
+                call__array_wrap__ = True
                 res = out
             if call__array_wrap__:
                 res = space.call_method(obj, '__array_wrap__', res, space.w_None)
@@ -359,8 +362,7 @@
                 return out
             loop.reduce(
                 space, self.func, obj, axis_flags, dtype, out, self.identity)
-            if call__array_wrap__:
-                out = space.call_method(obj, '__array_wrap__', out, space.w_None)
+            out = space.call_method(obj, '__array_wrap__', out, space.w_None)
             return out
 
     def descr_outer(self, space, args_w):
diff --git a/pypy/module/operator/test/test_operator.py b/pypy/module/operator/test/test_operator.py
--- a/pypy/module/operator/test/test_operator.py
+++ b/pypy/module/operator/test/test_operator.py
@@ -203,6 +203,13 @@
                 return 13289
         assert operator.index(myint(7)) == 7
 
+    def test_index_int_subclass(self):
+        import operator
+        class myint(int):
+            def __index__(self):
+                return 13289
+        assert operator.index(myint(7)) == 7
+
     def test_compare_digest(self):
         import _operator as operator
 
diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -409,10 +409,14 @@
 
     def w_get_shape(self, space):
         self._check_released(space)
+        if self.buf.getndim() == 0:
+            return space.w_None
         return space.newtuple([space.wrap(x) for x in self.getshape()])
 
     def w_get_strides(self, space):
         self._check_released(space)
+        if self.buf.getndim() == 0:
+            return space.w_None
         return space.newtuple([space.wrap(x) for x in self.getstrides()])
 
     def w_get_suboffsets(self, space):
diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py
--- a/rpython/jit/backend/detect_cpu.py
+++ b/rpython/jit/backend/detect_cpu.py
@@ -61,6 +61,7 @@
             'i86pc': MODEL_X86,    # Solaris/Intel
             'x86': MODEL_X86,      # Apple
             'Power Macintosh': MODEL_PPC_64,
+            'powerpc': MODEL_PPC_64, # freebsd
             'ppc64': MODEL_PPC_64,
             'ppc64le': MODEL_PPC_64,
             'x86_64': MODEL_X86,
diff --git a/rpython/translator/c/src/asm.c b/rpython/translator/c/src/asm.c
--- a/rpython/translator/c/src/asm.c
+++ b/rpython/translator/c/src/asm.c
@@ -8,10 +8,6 @@
 /* #  include "src/asm_gcc_x86_64.c" */
 #endif
 
-#if defined(__GNUC__) && defined(__ppc__)
-#  include "src/asm_ppc.c"
-#endif
-
 #if defined(_MSC_VER)
 #  include "src/asm_msvc.c"
 #endif
diff --git a/rpython/translator/c/src/asm.h b/rpython/translator/c/src/asm.h
--- a/rpython/translator/c/src/asm.h
+++ b/rpython/translator/c/src/asm.h
@@ -10,10 +10,6 @@
 #  include "src/asm_gcc_x86_64.h"
 #endif
 
-#if defined(__GNUC__) && defined(__ppc__)
-#  include "src/asm_ppc.h"
-#endif
-
 #if defined(MS_WINDOWS) && defined(_MSC_VER)
 #  include "src/asm_msvc.h"
 #endif


More information about the pypy-commit mailing list