Author: Alex Gaynor <alex.gay...@gmail.com> Branch: Changeset: r68391:e07994044752 Date: 2013-12-06 16:06 -0600 http://bitbucket.org/pypy/pypy/changeset/e07994044752/
Log: merged upstream diff --git a/lib-python/2.7/ctypes/test/test_python_api.py b/lib-python/2.7/ctypes/test/test_python_api.py --- a/lib-python/2.7/ctypes/test/test_python_api.py +++ b/lib-python/2.7/ctypes/test/test_python_api.py @@ -73,6 +73,7 @@ del pyobj self.assertEqual(grc(s), ref) + @xfail def test_PyOS_snprintf(self): PyOS_snprintf = pythonapi.PyOS_snprintf PyOS_snprintf.argtypes = POINTER(c_char), c_size_t, c_char_p diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst --- a/pypy/doc/cpython_differences.rst +++ b/pypy/doc/cpython_differences.rst @@ -83,7 +83,7 @@ _winreg -* Supported by being rewritten in pure Python (possibly using ``ctypes``): +* Supported by being rewritten in pure Python (possibly using ``cffi``): see the `lib_pypy/`_ directory. Examples of modules that we support this way: ``ctypes``, ``cPickle``, ``cmath``, ``dbm``, ``datetime``... Note that some modules are both in there and in the list above; @@ -316,5 +316,4 @@ type and vice versa. For builtin types, a dictionary will be returned that cannot be changed (but still looks and behaves like a normal dictionary). - .. include:: _ref.txt diff --git a/pypy/doc/ctypes-implementation.rst b/pypy/doc/ctypes-implementation.rst --- a/pypy/doc/ctypes-implementation.rst +++ b/pypy/doc/ctypes-implementation.rst @@ -72,7 +72,13 @@ Here is a list of the limitations and missing features of the current implementation: -* No support for ``PyXxx`` functions from ``libpython``, for obvious reasons. +* ``ctypes.pythonapi`` lets you access the CPython C API emulation layer + of PyPy, at your own risks and without doing anything sensible about + the GIL. Since PyPy 2.3, these functions are also named with an extra + "Py", for example ``PyPyInt_FromLong()``. Basically, don't use this, + but it might more or less work in simple cases if you do. (Obviously, + assuming the PyObject pointers you get have any particular fields in + any particular order is just going to crash.) * We copy Python strings instead of having pointers to raw buffers diff --git a/pypy/doc/extradoc.rst b/pypy/doc/extradoc.rst --- a/pypy/doc/extradoc.rst +++ b/pypy/doc/extradoc.rst @@ -72,13 +72,13 @@ .. _bibtex: https://bitbucket.org/pypy/extradoc/raw/tip/talk/bibtex.bib .. _`Runtime Feedback in a Meta-Tracing JIT for Efficient Dynamic Languages`: https://bitbucket.org/pypy/extradoc/raw/extradoc/talk/icooolps2011/jit-hints.pdf -.. _`Allocation Removal by Partial Evaluation in a Tracing JIT`: http://codespeak.net/svn/pypy/extradoc/talk/pepm2011/bolz-allocation-removal.pdf -.. _`Towards a Jitting VM for Prolog Execution`: http://www.stups.uni-duesseldorf.de/publications/bolz-prolog-jit.pdf +.. _`Allocation Removal by Partial Evaluation in a Tracing JIT`: https://bitbucket.org/pypy/extradoc/raw/extradoc/talk/pepm2011/bolz-allocation-removal.pdf +.. _`Towards a Jitting VM for Prolog Execution`: http://www.stups.uni-duesseldorf.de/mediawiki/images/a/a7/Pub-BoLeSch2010.pdf .. _`High performance implementation of Python for CLI/.NET with JIT compiler generation for dynamic languages`: http://buildbot.pypy.org/misc/antocuni-thesis.pdf .. _`How to *not* write Virtual Machines for Dynamic Languages`: https://bitbucket.org/pypy/extradoc/raw/tip/talk/dyla2007/dyla.pdf .. _`Tracing the Meta-Level: PyPy's Tracing JIT Compiler`: https://bitbucket.org/pypy/extradoc/raw/tip/talk/icooolps2009/bolz-tracing-jit.pdf .. _`Faster than C#: Efficient Implementation of Dynamic Languages on .NET`: https://bitbucket.org/pypy/extradoc/raw/tip/talk/icooolps2009-dotnet/cli-jit.pdf -.. _`Automatic JIT Compiler Generation with Runtime Partial Evaluation`: http://www.stups.uni-duesseldorf.de/thesis/final-master.pdf +.. _`Automatic JIT Compiler Generation with Runtime Partial Evaluation`: http://wwwold.cobra.cs.uni-duesseldorf.de/thesis/final-master.pdf .. _`RPython: A Step towards Reconciling Dynamically and Statically Typed OO Languages`: http://www.disi.unige.it/person/AnconaD/papers/Recent_abstracts.html#AACM-DLS07 .. _`EU Reports`: index-report.html .. _`Hardware Transactional Memory Support for Lightweight Dynamic Language Evolution`: http://sabi.net/nriley/pubs/dls6-riley.pdf 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 @@ -25,3 +25,17 @@ .. branch: less-stringly-ops Use subclasses of SpaceOperation instead of SpaceOperator objects. Random cleanups in flowspace and annotator. + +.. branch: ndarray-buffer +adds support for the buffer= argument to the ndarray ctor + +.. branch: better_ftime_detect2 +On OpenBSD do not pull in libcompat.a as it is about to be removed. +And more generally, if you have gettimeofday(2) you will not need ftime(3). + +.. branch: timeb_h +Remove dependency upon <sys/timeb.h> on OpenBSD. This will be disappearing +along with libcompat.a. + +.. branch: OlivierBlanvillain/fix-3-broken-links-on-pypy-published-pap-1386250839215 +Fix 3 broken links on PyPy published papers in docs. diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py --- a/pypy/interpreter/buffer.py +++ b/pypy/interpreter/buffer.py @@ -47,6 +47,9 @@ def get_raw_address(self): raise ValueError("no raw buffer") + def is_writable(self): + return False + # __________ app-level support __________ def descr_len(self, space): @@ -135,6 +138,9 @@ __slots__ = () # no extra slot here + def is_writable(self): + return True + def setitem(self, index, char): "Write a character into the buffer." raise NotImplementedError # Must be overriden. No bounds checks. diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py --- a/pypy/module/_cffi_backend/cbuffer.py +++ b/pypy/module/_cffi_backend/cbuffer.py @@ -59,6 +59,9 @@ def descr__buffer__(self, space): return self.buffer.descr__buffer__(space) + def descr_str(self, space): + return space.wrap(self.buffer.as_str()) + MiniBuffer.typedef = TypeDef( "buffer", @@ -68,6 +71,7 @@ __setitem__ = interp2app(MiniBuffer.descr_setitem), __buffer__ = interp2app(MiniBuffer.descr__buffer__), __weakref__ = make_weakref_descr(MiniBuffer), + __str__ = interp2app(MiniBuffer.descr_str), ) MiniBuffer.typedef.acceptable_as_base_class = False diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2143,7 +2143,13 @@ c = newp(BCharArray, b"hi there") # buf = buffer(c) - assert str(buf).startswith('<_cffi_backend.buffer object at 0x') + assert repr(buf).startswith('<_cffi_backend.buffer object at 0x') + assert bytes(buf) == b"hi there\x00" + if sys.version_info < (3,): + assert str(buf) == "hi there\x00" + assert unicode(buf) == u+"hi there\x00" + else: + assert str(buf) == repr(buf) # --mb_length-- assert len(buf) == len(b"hi there\x00") # --mb_item-- diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -400,16 +400,16 @@ '_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT', 'PyBuffer_FromMemory', 'PyBuffer_FromReadWriteMemory', 'PyBuffer_FromObject', - 'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', 'init_bufferobject', + 'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', '_Py_init_bufferobject', 'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 'PyCObject_AsVoidPtr', 'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr', - 'PyCObject_Type', 'init_pycobject', + 'PyCObject_Type', '_Py_init_pycobject', 'PyCapsule_New', 'PyCapsule_IsValid', 'PyCapsule_GetPointer', 'PyCapsule_GetName', 'PyCapsule_GetDestructor', 'PyCapsule_GetContext', 'PyCapsule_SetPointer', 'PyCapsule_SetName', 'PyCapsule_SetDestructor', - 'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', 'init_capsule', + 'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', '_Py_init_capsule', 'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer', @@ -687,11 +687,15 @@ globals()['va_get_%s' % name_no_star] = func def setup_init_functions(eci, translating): - init_buffer = rffi.llexternal('init_bufferobject', [], lltype.Void, + if translating: + prefix = 'PyPy' + else: + prefix = 'cpyexttest' + init_buffer = rffi.llexternal('_%s_init_bufferobject' % prefix, [], lltype.Void, compilation_info=eci, _nowrapper=True) - init_pycobject = rffi.llexternal('init_pycobject', [], lltype.Void, + init_pycobject = rffi.llexternal('_%s_init_pycobject' % prefix, [], lltype.Void, compilation_info=eci, _nowrapper=True) - init_capsule = rffi.llexternal('init_capsule', [], lltype.Void, + init_capsule = rffi.llexternal('_%s_init_capsule' % prefix, [], lltype.Void, compilation_info=eci, _nowrapper=True) INIT_FUNCTIONS.extend([ lambda space: init_buffer(), @@ -699,12 +703,8 @@ lambda space: init_capsule(), ]) from pypy.module.posix.interp_posix import add_fork_hook - if translating: - reinit_tls = rffi.llexternal('PyThread_ReInitTLS', [], lltype.Void, - compilation_info=eci) - else: - reinit_tls = rffi.llexternal('PyPyThread_ReInitTLS', [], lltype.Void, - compilation_info=eci) + reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [], lltype.Void, + compilation_info=eci) add_fork_hook('child', reinit_tls) def init_function(func): @@ -746,7 +746,7 @@ from rpython.translator.c.database import LowLevelDatabase db = LowLevelDatabase() - generate_macros(export_symbols, rename=True, do_deref=True) + generate_macros(export_symbols, prefix='cpyexttest') # Structure declaration code members = [] @@ -812,7 +812,7 @@ INTERPLEVEL_API[name] = w_obj - name = name.replace('Py', 'PyPy') + name = name.replace('Py', 'cpyexttest') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) if typ == 'PyObject*': @@ -824,7 +824,7 @@ ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): - if name.startswith('PyPyExc_'): + if name.startswith('PyPyExc_') or name.startswith('cpyexttestExc_'): # we already have the pointer in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) @@ -859,28 +859,27 @@ setup_init_functions(eci, translating=False) return modulename.new(ext='') -def generate_macros(export_symbols, rename=True, do_deref=True): +def mangle_name(prefix, name): + if name.startswith('Py'): + return prefix + name[2:] + elif name.startswith('_Py'): + return '_' + prefix + name[3:] + else: + return None + +def generate_macros(export_symbols, prefix): "NOT_RPYTHON" pypy_macros = [] renamed_symbols = [] for name in export_symbols: - if name.startswith("PyPy"): - renamed_symbols.append(name) - continue - if not rename: - continue name = name.replace("#", "") - newname = name.replace('Py', 'PyPy') - if not rename: - newname = name + newname = mangle_name(prefix, name) + assert newname, name pypy_macros.append('#define %s %s' % (name, newname)) if name.startswith("PyExc_"): pypy_macros.append('#define _%s _%s' % (name, newname)) renamed_symbols.append(newname) - if rename: - export_symbols[:] = renamed_symbols - else: - export_symbols[:] = [sym.replace("#", "") for sym in export_symbols] + export_symbols[:] = renamed_symbols # Generate defines for macro_name, size in [ @@ -1041,7 +1040,7 @@ from rpython.translator.c.database import LowLevelDatabase db = LowLevelDatabase() - generate_macros(export_symbols, rename=False, do_deref=False) + generate_macros(export_symbols, prefix='PyPy') functions = generate_decls_and_callbacks(db, [], api_struct=False) code = "#include <Python.h>\n" + "\n".join(functions) @@ -1071,7 +1070,8 @@ export_struct(name, struct) for name, func in FUNCTIONS.iteritems(): - deco = entrypoint_lowlevel("cpyext", func.argtypes, name, relax=True) + newname = mangle_name('PyPy', name) or name + deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, relax=True) deco(func.get_wrapper(space)) setup_init_functions(eci, translating=True) diff --git a/pypy/module/cpyext/include/bufferobject.h b/pypy/module/cpyext/include/bufferobject.h --- a/pypy/module/cpyext/include/bufferobject.h +++ b/pypy/module/cpyext/include/bufferobject.h @@ -37,7 +37,7 @@ PyObject* PyBuffer_New(Py_ssize_t size); -void init_bufferobject(void); +void _Py_init_bufferobject(void); #ifdef __cplusplus } diff --git a/pypy/module/cpyext/include/pycapsule.h b/pypy/module/cpyext/include/pycapsule.h --- a/pypy/module/cpyext/include/pycapsule.h +++ b/pypy/module/cpyext/include/pycapsule.h @@ -50,7 +50,7 @@ PyAPI_FUNC(void *) PyCapsule_Import(const char *name, int no_block); -void init_capsule(void); +void _Py_init_capsule(void); #ifdef __cplusplus } diff --git a/pypy/module/cpyext/include/pycobject.h b/pypy/module/cpyext/include/pycobject.h --- a/pypy/module/cpyext/include/pycobject.h +++ b/pypy/module/cpyext/include/pycobject.h @@ -48,7 +48,7 @@ } PyCObject; #endif -void init_pycobject(void); +void _Py_init_pycobject(void); #ifdef __cplusplus } diff --git a/pypy/module/cpyext/src/bufferobject.c b/pypy/module/cpyext/src/bufferobject.c --- a/pypy/module/cpyext/src/bufferobject.c +++ b/pypy/module/cpyext/src/bufferobject.c @@ -783,7 +783,7 @@ return size; } -void init_bufferobject(void) +void _Py_init_bufferobject(void) { PyType_Ready(&PyBuffer_Type); } diff --git a/pypy/module/cpyext/src/capsule.c b/pypy/module/cpyext/src/capsule.c --- a/pypy/module/cpyext/src/capsule.c +++ b/pypy/module/cpyext/src/capsule.c @@ -321,7 +321,7 @@ PyCapsule_Type__doc__ /*tp_doc*/ }; -void init_capsule() +void _Py_init_capsule() { PyType_Ready(&PyCapsule_Type); } diff --git a/pypy/module/cpyext/src/cobject.c b/pypy/module/cpyext/src/cobject.c --- a/pypy/module/cpyext/src/cobject.c +++ b/pypy/module/cpyext/src/cobject.c @@ -156,7 +156,7 @@ PyCObject_Type__doc__ /*tp_doc*/ }; -void init_pycobject() +void _Py_init_pycobject() { PyType_Ready(&PyCObject_Type); } diff --git a/pypy/module/cpyext/test/test_thread.py b/pypy/module/cpyext/test/test_thread.py --- a/pypy/module/cpyext/test/test_thread.py +++ b/pypy/module/cpyext/test/test_thread.py @@ -8,8 +8,10 @@ module = self.import_extension('foo', [ ("get_thread_ident", "METH_NOARGS", """ - /* Use the 'PyPy' prefix to ensure we access our functions */ - return PyInt_FromLong(PyPyThread_get_thread_ident()); +#ifndef PyThread_get_thread_ident +#error "seems we are not accessing PyPy's functions" +#endif + return PyInt_FromLong(PyThread_get_thread_ident()); """), ]) import thread, threading @@ -32,17 +34,19 @@ module = self.import_extension('foo', [ ("test_acquire_lock", "METH_NOARGS", """ - /* Use the 'PyPy' prefix to ensure we access our functions */ - PyThread_type_lock lock = PyPyThread_allocate_lock(); - if (PyPyThread_acquire_lock(lock, 1) != 1) { +#ifndef PyThread_allocate_lock +#error "seems we are not accessing PyPy's functions" +#endif + PyThread_type_lock lock = PyThread_allocate_lock(); + if (PyThread_acquire_lock(lock, 1) != 1) { PyErr_SetString(PyExc_AssertionError, "first acquire"); return NULL; } - if (PyPyThread_acquire_lock(lock, 0) != 0) { + if (PyThread_acquire_lock(lock, 0) != 0) { PyErr_SetString(PyExc_AssertionError, "second acquire"); return NULL; } - PyPyThread_free_lock(lock); + PyThread_free_lock(lock); Py_RETURN_NONE; """), @@ -53,15 +57,17 @@ module = self.import_extension('foo', [ ("test_release_lock", "METH_NOARGS", """ - /* Use the 'PyPy' prefix to ensure we access our functions */ - PyThread_type_lock lock = PyPyThread_allocate_lock(); - PyPyThread_acquire_lock(lock, 1); - PyPyThread_release_lock(lock); - if (PyPyThread_acquire_lock(lock, 0) != 1) { +#ifndef PyThread_release_lock +#error "seems we are not accessing PyPy's functions" +#endif + PyThread_type_lock lock = PyThread_allocate_lock(); + PyThread_acquire_lock(lock, 1); + PyThread_release_lock(lock); + if (PyThread_acquire_lock(lock, 0) != 1) { PyErr_SetString(PyExc_AssertionError, "first acquire"); return NULL; } - PyPyThread_free_lock(lock); + PyThread_free_lock(lock); Py_RETURN_NONE; """), 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 @@ -392,6 +392,21 @@ def __del__(self): free_raw_storage(self.storage, track_allocation=False) +class ConcreteArrayWithBase(ConcreteArrayNotOwning): + def __init__(self, shape, dtype, order, strides, backstrides, storage, orig_base): + ConcreteArrayNotOwning.__init__(self, shape, dtype, order, + strides, backstrides, storage) + self.orig_base = orig_base + + def base(self): + return self.orig_base + + +class ConcreteNonWritableArrayWithBase(ConcreteArrayWithBase): + 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 descr_setitem(self, space, orig_array, w_index, w_value): 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 @@ -49,11 +49,24 @@ return W_NDimArray(impl) @staticmethod - def from_shape_and_storage(space, shape, storage, dtype, order='C', owning=False, w_subtype=None): + def from_shape_and_storage(space, shape, storage, dtype, order='C', owning=False, + w_subtype=None, w_base=None, writable=True): from pypy.module.micronumpy.arrayimpl import concrete assert shape strides, backstrides = calc_strides(shape, dtype, order) - if owning: + if w_base is not None: + if owning: + raise OperationError(space.w_ValueError, + space.wrap("Cannot have owning=True when specifying a buffer")) + if writable: + impl = concrete.ConcreteArrayWithBase(shape, dtype, order, strides, + backstrides, storage, w_base) + else: + impl = concrete.ConcreteNonWritableArrayWithBase(shape, dtype, order, + strides, backstrides, + storage, w_base) + + elif owning: # Will free storage when GCd impl = concrete.ConcreteArray(shape, dtype, order, strides, backstrides, storage=storage) 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 @@ -1,3 +1,5 @@ +from rpython.rtyper.lltypesystem import rffi +from rpython.rlib.rawstorage import RAW_STORAGE_PTR from pypy.interpreter.error import operationerrfmt, OperationError from pypy.interpreter.typedef import TypeDef, GetSetProperty, make_weakref_descr from pypy.interpreter.gateway import interp2app, unwrap_spec, applevel, \ @@ -20,6 +22,7 @@ from rpython.rlib.rstring import StringBuilder from pypy.module.micronumpy.arrayimpl.base import BaseArrayImplementation from pypy.module.micronumpy.conversion_utils import order_converter, multi_axis_converter +from pypy.module.micronumpy import support from pypy.module.micronumpy.constants import * def _find_shape(space, w_size, dtype): @@ -1067,13 +1070,35 @@ offset=0, w_strides=None, order='C'): from pypy.module.micronumpy.arrayimpl.concrete import ConcreteArray from pypy.module.micronumpy.support import calc_strides - if (offset != 0 or not space.is_none(w_strides) or - not space.is_none(w_buffer)): - raise OperationError(space.w_NotImplementedError, - space.wrap("unsupported param")) dtype = space.interp_w(interp_dtype.W_Dtype, space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)) shape = _find_shape(space, w_shape, dtype) + + if not space.is_none(w_buffer): + if (not space.is_none(w_strides)): + raise OperationError(space.w_NotImplementedError, + space.wrap("unsupported param")) + + buf = space.buffer_w(w_buffer) + try: + raw_ptr = buf.get_raw_address() + except ValueError: + raise OperationError(space.w_TypeError, space.wrap( + "Only raw buffers are supported")) + if not shape: + raise OperationError(space.w_TypeError, space.wrap( + "numpy scalars from buffers not supported yet")) + totalsize = support.product(shape) * dtype.get_size() + if totalsize+offset > buf.getlength(): + raise OperationError(space.w_TypeError, space.wrap( + "buffer is too small for requested array")) + storage = rffi.cast(RAW_STORAGE_PTR, raw_ptr) + storage = rffi.ptradd(storage, offset) + return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype, + w_subtype=w_subtype, + w_base=w_buffer, + writable=buf.is_writable()) + if not shape: return W_NDimArray.new_scalar(space, dtype) if space.is_w(w_subtype, space.gettypefor(W_NDimArray)): @@ -1093,8 +1118,6 @@ Create an array from an existing buffer, given its address as int. PyPy-only implementation detail. """ - from rpython.rtyper.lltypesystem import rffi - from rpython.rlib.rawstorage import RAW_STORAGE_PTR storage = rffi.cast(RAW_STORAGE_PTR, addr) dtype = space.interp_w(interp_dtype.W_Dtype, space.call_function(space.gettypefor(interp_dtype.W_Dtype), 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 @@ -71,7 +71,6 @@ final_strides = arr.get_strides() + strides final_backstrides = arr.get_backstrides() + backstrides final_dtype = subdtype - print self.name,'strides',arr.get_strides(),strides if subdtype.subdtype: final_dtype = subdtype.subdtype return W_NDimArray.new_slice(space, arr.start + ofs, final_strides, 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 @@ -238,13 +238,16 @@ while not out_iter.done(): axis_reduce__driver.jit_merge_point(shapelen=shapelen, func=func, dtype=dtype) - w_val = arr_iter.getitem().convert_to(dtype) - if out_iter.first_line: - if identity is not None: - w_val = func(dtype, identity, w_val) + if arr_iter.done(): + w_val = identity else: - cur = temp_iter.getitem() - w_val = func(dtype, cur, w_val) + w_val = arr_iter.getitem().convert_to(dtype) + if out_iter.first_line: + if identity is not None: + w_val = func(dtype, identity, w_val) + else: + cur = temp_iter.getitem() + w_val = func(dtype, cur, w_val) out_iter.setitem(w_val) if cumulative: temp_iter.setitem(w_val) diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -219,6 +219,7 @@ class AppTestNumArray(BaseNumpyAppTest): spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"]) + def w_CustomIndexObject(self, index): class CustomIndexObject(object): def __init__(self, index): @@ -1299,6 +1300,9 @@ assert a.sum() == 105 assert a.max() == 14 assert array([]).sum() == 0.0 + assert array([]).reshape(0, 2).sum() == 0. + assert (array([]).reshape(0, 2).sum(0) == [0., 0.]).all() + assert (array([]).reshape(0, 2).prod(0) == [1., 1.]).all() raises(ValueError, 'array([]).max()') assert (a.sum(0) == [30, 35, 40]).all() assert (a.sum(axis=0) == [30, 35, 40]).all() @@ -2089,6 +2093,69 @@ a = np.ndarray([1], dtype=bool) assert a[0] == True + +class AppTestNumArrayFromBuffer(BaseNumpyAppTest): + spaceconfig = dict(usemodules=["micronumpy", "array", "mmap"]) + + def setup_class(cls): + from rpython.tool.udir import udir + BaseNumpyAppTest.setup_class.im_func(cls) + cls.w_tmpname = cls.space.wrap(str(udir.join('mmap-'))) + + def test_ndarray_from_buffer(self): + import numpypy as np + import array + buf = array.array('c', ['\x00']*2*3) + a = np.ndarray((3,), buffer=buf, dtype='i2') + a[0] = ord('b') + a[1] = ord('a') + a[2] = ord('r') + assert list(buf) == ['b', '\x00', 'a', '\x00', 'r', '\x00'] + assert a.base is buf + + def test_ndarray_subclass_from_buffer(self): + import numpypy as np + import array + buf = array.array('c', ['\x00']*2*3) + class X(np.ndarray): + pass + a = X((3,), buffer=buf, dtype='i2') + assert type(a) is X + + def test_ndarray_from_buffer_and_offset(self): + import numpypy as np + import array + buf = array.array('c', ['\x00']*7) + buf[0] = 'X' + a = np.ndarray((3,), buffer=buf, offset=1, dtype='i2') + a[0] = ord('b') + a[1] = ord('a') + a[2] = ord('r') + assert list(buf) == ['X', 'b', '\x00', 'a', '\x00', 'r', '\x00'] + + def test_ndarray_from_buffer_out_of_bounds(self): + import numpypy as np + import array + buf = array.array('c', ['\x00']*2*10) # 20 bytes + info = raises(TypeError, "np.ndarray((11,), buffer=buf, dtype='i2')") + assert str(info.value).startswith('buffer is too small') + info = raises(TypeError, "np.ndarray((5,), buffer=buf, offset=15, dtype='i2')") + assert str(info.value).startswith('buffer is too small') + + def test_ndarray_from_readonly_buffer(self): + import numpypy as np + from mmap import mmap, ACCESS_READ + f = open(self.tmpname, "w+") + f.write("hello") + f.flush() + buf = mmap(f.fileno(), 5, access=ACCESS_READ) + a = np.ndarray((5,), buffer=buf, dtype='c') + raises(ValueError, "a[0] = 'X'") + buf.close() + f.close() + + + class AppTestMultiDim(BaseNumpyAppTest): def test_init(self): import numpypy @@ -3060,9 +3127,6 @@ exc = raises(IndexError, "a[0][None]") assert exc.value.message == "invalid index" - exc = raises(IndexError, "a[0][None]") - assert exc.value.message == 'invalid index' - a[0]["x"][0] = 200 assert a[0]["x"][0] == 200 diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py --- a/pypy/module/mmap/interp_mmap.py +++ b/pypy/module/mmap/interp_mmap.py @@ -314,6 +314,14 @@ self.check_valid_writeable() self.mmap.setslice(start, string) + def is_writable(self): + try: + self.mmap.check_writeable() + except RMMapError: + return False + else: + return True + def get_raw_address(self): self.check_valid() return self.mmap.data diff --git a/pypy/testrunner_cfg.py b/pypy/testrunner_cfg.py --- a/pypy/testrunner_cfg.py +++ b/pypy/testrunner_cfg.py @@ -3,7 +3,7 @@ DIRS_SPLIT = [ 'translator/c', 'rlib', - 'rpython/memory', 'jit/metainterp', 'rpython/test', + 'memory/test', 'jit/metainterp', 'jit/backend/arm', 'jit/backend/x86', ] diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py --- a/rpython/flowspace/flowcontext.py +++ b/rpython/flowspace/flowcontext.py @@ -329,7 +329,7 @@ if closure is None: self.closure = [] else: - self.closure = [const(c.cell_contents) for c in closure] + self.closure = list(closure) assert len(self.closure) == len(self.pycode.co_freevars) def init_locals_stack(self, code): @@ -846,7 +846,13 @@ LOOKUP_METHOD = LOAD_ATTR def LOAD_DEREF(self, varindex): - self.pushvalue(self.closure[varindex]) + cell = self.closure[varindex] + try: + content = cell.cell_contents + except ValueError: + name = self.pycode.co_freevars[varindex] + raise FlowingError("Undefined closure variable '%s'" % name) + self.pushvalue(const(content)) def STORE_FAST(self, varindex): w_newvalue = self.popvalue() diff --git a/rpython/flowspace/test/test_objspace.py b/rpython/flowspace/test/test_objspace.py --- a/rpython/flowspace/test/test_objspace.py +++ b/rpython/flowspace/test/test_objspace.py @@ -1212,6 +1212,39 @@ graph = self.codetest(f) assert 'getattr' in self.all_operations(graph) + def test_empty_cell_unused(self): + def test(flag): + if flag: + b = 5 + def g(): + if flag: + return b + else: + return 1 + return g + g1 = test(False) + graph = self.codetest(g1) + assert not self.all_operations(graph) + g2 = test(True) + graph = self.codetest(g2) + assert not self.all_operations(graph) + + def test_empty_cell_error(self): + def test(flag): + if not flag: + b = 5 + def g(): + if flag: + return b + else: + return 1 + return g + g = test(True) + with py.test.raises(FlowingError) as excinfo: + graph = self.codetest(g) + assert "Undefined closure variable 'b'" in str(excinfo.value) + + DATA = {'x': 5, 'y': 6} diff --git a/rpython/rtyper/module/ll_time.py b/rpython/rtyper/module/ll_time.py --- a/rpython/rtyper/module/ll_time.py +++ b/rpython/rtyper/module/ll_time.py @@ -24,8 +24,12 @@ FTIME = 'ftime' STRUCT_TIMEB = 'struct timeb' includes = [TIME_H, 'time.h', 'errno.h', 'sys/select.h', - 'sys/types.h', 'unistd.h', 'sys/timeb.h', + 'sys/types.h', 'unistd.h', 'sys/time.h', 'sys/resource.h'] + + if not sys.platform.startswith("openbsd"): + includes.append('sys/timeb.h') + need_rusage = True @@ -86,16 +90,18 @@ c_gettimeofday = self.llexternal('gettimeofday', [self.TIMEVALP, rffi.VOIDP], rffi.INT, _nowrapper=True, releasegil=False) + c_ftime = None # We have gettimeofday(2), so force ftime(3) OFF. else: c_gettimeofday = None - if self.HAVE_FTIME: - self.configure(CConfigForFTime) - c_ftime = self.llexternal(FTIME, [lltype.Ptr(self.TIMEB)], - lltype.Void, - _nowrapper=True, releasegil=False) - else: - c_ftime = None # to not confuse the flow space + # Only look for ftime(3) if gettimeofday(2) was not found. + if self.HAVE_FTIME: + self.configure(CConfigForFTime) + c_ftime = self.llexternal(FTIME, [lltype.Ptr(self.TIMEB)], + lltype.Void, + _nowrapper=True, releasegil=False) + else: + c_ftime = None # to not confuse the flow space c_time = self.llexternal('time', [rffi.VOIDP], rffi.TIME_T, _nowrapper=True, releasegil=False) @@ -115,9 +121,9 @@ if rffi.cast(rffi.LONG, errcode) == 0: result = decode_timeval(t) lltype.free(t, flavor='raw') - if result != -1: - return result - if self.HAVE_FTIME: + if result != -1: + return result + else: # assume using ftime(3) t = lltype.malloc(self.TIMEB, flavor='raw') c_ftime(t) result = (float(intmask(t.c_time)) + diff --git a/rpython/translator/c/src/exception.h b/rpython/translator/c/src/exception.h --- a/rpython/translator/c/src/exception.h +++ b/rpython/translator/c/src/exception.h @@ -36,7 +36,6 @@ /* prototypes */ -#define RPyRaiseSimpleException(exc, msg) _RPyRaiseSimpleException(R##exc) void _RPyRaiseSimpleException(RPYTHON_EXCEPTION rexc); #endif diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h --- a/rpython/translator/c/src/support.h +++ b/rpython/translator/c/src/support.h @@ -5,13 +5,9 @@ #define RUNNING_ON_LLINTERP 0 #define OP_JIT_RECORD_KNOWN_CLASS(i, c, r) /* nothing */ -#define FAIL_EXCEPTION(exc, msg) \ - { \ - RPyRaiseSimpleException(exc, msg); \ - } -#define FAIL_OVF(msg) FAIL_EXCEPTION(PyExc_OverflowError, msg) -#define FAIL_VAL(msg) FAIL_EXCEPTION(PyExc_ValueError, msg) -#define FAIL_ZER(msg) FAIL_EXCEPTION(PyExc_ZeroDivisionError, msg) +#define FAIL_OVF(msg) _RPyRaiseSimpleException(RPyExc_OverflowError) +#define FAIL_VAL(msg) _RPyRaiseSimpleException(RPyExc_ValueError) +#define FAIL_ZER(msg) _RPyRaiseSimpleException(RPyExc_ZeroDivisionError) /* Extra checks can be enabled with the RPY_ASSERT or RPY_LL_ASSERT * macros. They differ in the level at which the tests are made. diff --git a/rpython/translator/platform/openbsd.py b/rpython/translator/platform/openbsd.py --- a/rpython/translator/platform/openbsd.py +++ b/rpython/translator/platform/openbsd.py @@ -13,7 +13,7 @@ ] + os.environ.get("CFLAGS", "").split() def _libs(self, libraries): - libraries=set(libraries + ("intl", "iconv", "compat")) + libraries=set(libraries + ("intl", "iconv")) return ['-l%s' % lib for lib in libraries if lib not in ["crypt", "dl", "rt"]] class OpenBSD_64(OpenBSD): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit