Author: Armin Rigo <ar...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit