Author: Antonio Cuni <anto.c...@gmail.com> Branch: ndarray-buffer Changeset: r68316:eda923010bdb Date: 2013-11-25 11:44 +0100 http://bitbucket.org/pypy/pypy/changeset/eda923010bdb/
Log: hg merge default diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py --- a/lib-python/2.7/socket.py +++ b/lib-python/2.7/socket.py @@ -335,9 +335,10 @@ s = self._sock self._sock = None if s is not None: - s._drop() if self._close: s.close() + else: + s._drop() def __del__(self): try: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -63,3 +63,6 @@ except KeyboardInterrupt: console.write("\nKeyboardInterrupt\n") console.resetbuffer() + except MemoryError: + console.write("\nMemoryError\n") + console.resetbuffer() 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 @@ -15,3 +15,6 @@ .. branch: armhf-singlefloat JIT support for singlefloats on ARM using the hardfloat ABI + +.. branch: voidtype_strformat +Better support for record numpy arrays 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 @@ -26,6 +26,7 @@ from pypy.module.__builtin__.descriptor import W_Property from pypy.module.__builtin__.interp_classobj import W_ClassObject from pypy.module.__builtin__.interp_memoryview import W_MemoryView +from pypy.module.micronumpy.base import W_NDimArray from rpython.rlib.entrypoint import entrypoint_lowlevel from rpython.rlib.rposix import is_valid_fd, validate_fd from rpython.rlib.unroll import unrolling_iterable @@ -469,6 +470,7 @@ "Complex": "space.w_complex", "ByteArray": "space.w_bytearray", "MemoryView": "space.gettypeobject(W_MemoryView.typedef)", + "Array": "space.gettypeobject(W_NDimArray.typedef)", "BaseObject": "space.w_object", 'None': 'space.type(space.w_None)', 'NotImplemented': 'space.type(space.w_NotImplemented)', diff --git a/pypy/module/cpyext/include/pyconfig.h b/pypy/module/cpyext/include/pyconfig.h --- a/pypy/module/cpyext/include/pyconfig.h +++ b/pypy/module/cpyext/include/pyconfig.h @@ -25,6 +25,22 @@ #define Py_UNICODE_SIZE 2 #endif +#ifndef Py_BUILD_CORE /* not building the core - must be an ext */ +# if defined(_MSC_VER) + /* So MSVC users need not specify the .lib file in + * their Makefile (other compilers are generally + * taken care of by distutils.) */ +# ifdef _DEBUG +# error("debug first with cpython") +# pragma comment(lib,"python27.lib") +# else +# pragma comment(lib,"python27.lib") +# endif /* _DEBUG */ +# endif +#endif /* _MSC_VER */ + + + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/src/ndarrayobject.c b/pypy/module/cpyext/src/ndarrayobject.c --- a/pypy/module/cpyext/src/ndarrayobject.c +++ b/pypy/module/cpyext/src/ndarrayobject.c @@ -3,8 +3,6 @@ #include "numpy/arrayobject.h" #include <string.h> /* memset, memcpy */ -PyTypeObject PyArray_Type; - void _PyArray_FILLWBYTE(PyObject* obj, int val) { memset(PyArray_DATA(obj), val, PyArray_NBYTES(obj)); diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py b/pypy/module/cpyext/test/test_ndarrayobject.py --- a/pypy/module/cpyext/test/test_ndarrayobject.py +++ b/pypy/module/cpyext/test/test_ndarrayobject.py @@ -286,3 +286,19 @@ assert dt.num == 11 + def test_pass_ndarray_object_to_c(self): + from _numpypy.multiarray import ndarray + mod = self.import_extension('foo', [ + ("check_array", "METH_VARARGS", + ''' + PyObject* obj; + if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &obj)) + return NULL; + Py_INCREF(obj); + return obj; + '''), + ], prologue='#include <numpy/arrayobject.h>') + array = ndarray((3, 4), dtype='d') + assert mod.check_array(array) is array + raises(TypeError, "mod.check_array(42)") + diff --git a/pypy/module/itertools/interp_itertools.py b/pypy/module/itertools/interp_itertools.py --- a/pypy/module/itertools/interp_itertools.py +++ b/pypy/module/itertools/interp_itertools.py @@ -342,10 +342,8 @@ if space.is_w(w_startstop, space.w_None): start = 0 else: - start = space.int_w(w_startstop) - if start < 0: - raise OperationError(space.w_ValueError, space.wrap( - "Indicies for islice() must be non-negative integers.")) + start = self.arg_int_w(w_startstop, 0, + "Indicies for islice() must be None or non-negative integers") w_stop = args_w[0] else: raise OperationError(space.w_TypeError, space.wrap("islice() takes at most 4 arguments (" + str(num_args) + " given)")) @@ -353,10 +351,8 @@ if space.is_w(w_stop, space.w_None): stop = -1 else: - stop = space.int_w(w_stop) - if stop < 0: - raise OperationError(space.w_ValueError, space.wrap( - "Stop argument must be a non-negative integer or None.")) + stop = self.arg_int_w(w_stop, 0, + "Stop argument must be a non-negative integer or None.") stop = max(start, stop) # for obscure CPython compatibility if num_args == 2: @@ -364,10 +360,8 @@ if space.is_w(w_step, space.w_None): step = 1 else: - step = space.int_w(w_step) - if step < 1: - raise OperationError(space.w_ValueError, space.wrap( - "Step must be one or lager for islice().")) + step = self.arg_int_w(w_step, 1, + "Step for islice() must be a positive integer or None") else: step = 1 @@ -375,6 +369,18 @@ self.start = start self.stop = stop + def arg_int_w(self, w_obj, minimum, errormsg): + space = self.space + try: + result = space.int_w(w_obj) + except OperationError, e: + if e.async(space): + raise + result = -1 + if result < minimum: + raise OperationError(space.w_ValueError, space.wrap(errormsg)) + return result + def iter_w(self): return self.space.wrap(self) diff --git a/pypy/module/itertools/test/test_itertools.py b/pypy/module/itertools/test/test_itertools.py --- a/pypy/module/itertools/test/test_itertools.py +++ b/pypy/module/itertools/test/test_itertools.py @@ -304,6 +304,11 @@ raises(TypeError, itertools.islice, [], 0, 0, 0, 0) + # why not TypeError? Because CPython + raises(ValueError, itertools.islice, [], "a", 1, 2) + raises(ValueError, itertools.islice, [], 0, "a", 2) + raises(ValueError, itertools.islice, [], 0, 1, "a") + def test_chain(self): import itertools diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -56,6 +56,8 @@ self.aliases = aliases self.float_type = float_type self.fields = fields + if fieldnames is None: + fieldnames = [] self.fieldnames = fieldnames self.shape = list(shape) self.subdtype = subdtype @@ -214,15 +216,15 @@ self.name = "void" + str(8 * self.get_size()) def descr_get_names(self, space): - if self.fieldnames is None: + if len(self.fieldnames) == 0: return space.w_None return space.newtuple([space.wrap(name) for name in self.fieldnames]) def set_names(self, space, w_names): + self.fieldnames = [] if w_names == space.w_None: - self.fieldnames = None + return else: - self.fieldnames = [] iter = space.iter(w_names) while True: try: 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 @@ -252,12 +252,13 @@ return space.wrap(self.dump_data()) return space.call_function(cache.w_array_str, self) - def dump_data(self): + def dump_data(self, prefix='array(', suffix=')'): i = self.create_iter() first = True dtype = self.get_dtype() s = StringBuilder() - s.append('array([') + s.append(prefix) + s.append('[') while not i.done(): if first: first = False @@ -265,7 +266,8 @@ s.append(', ') s.append(dtype.itemtype.str_format(i.getitem())) i.next() - s.append('])') + s.append(']') + s.append(suffix) return s.build() def create_iter(self, shape=None, backward_broadcast=False, require_index=False): 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 @@ -61,10 +61,22 @@ def apply(self, space, orig_arr): arr = orig_arr.implementation ofs, subdtype = arr.dtype.fields[self.name] - # strides backstrides are identical, ofs only changes start - return W_NDimArray.new_slice(space, arr.start + ofs, arr.get_strides(), - arr.get_backstrides(), - arr.shape, arr, orig_arr, subdtype) + # ofs only changes start + # create a view of the original array by extending + # the shape, strides, backstrides of the array + from pypy.module.micronumpy.support import calc_strides + strides, backstrides = calc_strides(subdtype.shape, + subdtype.subdtype, arr.order) + final_shape = arr.shape + subdtype.shape + 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, + final_backstrides, + final_shape, arr, orig_arr, final_dtype) class Chunks(BaseChunk): def __init__(self, l): 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 @@ -3138,7 +3138,9 @@ ] h = np.array(buf, dtype=descr) assert len(h) == 2 - skip('broken') # XXX + assert h['x'].shape == (2, 2) + assert h['y'].strides == (41, 16, 8) + assert h['z'].shape == (2,) for v in (h, h[0], h['x']): repr(v) # check for crash in repr assert (h['x'] == np.array([buf[0][0], @@ -3169,6 +3171,22 @@ assert len(list(a[0])) == 2 + def test_3d_record(self): + from numpypy import dtype, array + dt = dtype([('name', 'S4'), ('x', float), ('y', float), + ('block', int, (2, 2, 3))]) + a = array([('aaaa', 1.0, 8.0, [[[1, 2, 3], [4, 5, 6]], + [[7, 8, 9], [10, 11, 12]]])], + dtype=dt) + s = str(a) + i = a.item() + assert isinstance(i, tuple) + assert len(i) == 4 + skip('incorrect formatting via dump_data') + assert s.endswith("[('aaaa', 1.0, 8.0, [[[1, 2, 3], [4, 5, 6]], " + "[[7, 8, 9], [10, 11, 12]]])]") + + def test_issue_1589(self): import numpypy as numpy c = numpy.array([[(1, 2, 'a'), (3, 4, 'b')], [(5, 6, 'c'), (7, 8, 'd')]], diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -1789,6 +1789,40 @@ dtype.subdtype) return W_NDimArray(implementation) + def read(self, arr, i, offset, dtype=None): + if dtype is None: + dtype = arr.dtype + return interp_boxes.W_VoidBox(arr, i + offset, dtype) + + @jit.unroll_safe + def str_format(self, box): + assert isinstance(box, interp_boxes.W_VoidBox) + arr = self.readarray(box.arr, box.ofs, 0, box.dtype) + return arr.dump_data(prefix='', suffix='') + + def to_builtin_type(self, space, item): + ''' From the documentation of ndarray.item(): + "Void arrays return a buffer object for item(), + unless fields are defined, in which case a tuple is returned." + ''' + assert isinstance(item, interp_boxes.W_VoidBox) + dt = item.arr.dtype + ret_unwrapped = [] + for name in dt.fieldnames: + ofs, dtype = dt.fields[name] + if isinstance(dtype.itemtype, VoidType): + read_val = dtype.itemtype.readarray(item.arr, ofs, 0, dtype) + else: + read_val = dtype.itemtype.read(item.arr, ofs, 0, dtype) + if isinstance (read_val, interp_boxes.W_StringBox): + # StringType returns a str + read_val = space.wrap(dtype.itemtype.to_str(read_val)) + ret_unwrapped = ret_unwrapped + [read_val,] + if len(ret_unwrapped) == 0: + raise OperationError(space.w_NotImplementedError, space.wrap( + "item() for Void aray with no fields not implemented")) + return space.newtuple(ret_unwrapped) + class RecordType(FlexibleType): T = lltype.Char @@ -1848,7 +1882,8 @@ first = False else: pieces.append(", ") - pieces.append(tp.str_format(tp.read(box.arr, box.ofs, ofs))) + val = tp.read(box.arr, box.ofs, ofs, subdtype) + pieces.append(tp.str_format(val)) pieces.append(")") return "".join(pieces) diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py --- a/rpython/annotator/bookkeeper.py +++ b/rpython/annotator/bookkeeper.py @@ -371,15 +371,19 @@ listdef.generalize(self.immutablevalue(e, False)) result = SomeList(listdef) elif tp is dict or tp is r_dict or tp is SomeOrderedDict.knowntype: + if tp is SomeOrderedDict.knowntype: + cls = SomeOrderedDict + else: + cls = SomeDict if need_const: key = Constant(x) try: return self.immutable_cache[key] except KeyError: - result = SomeDict(DictDef(self, - s_ImpossibleValue, - s_ImpossibleValue, - is_r_dict = tp is r_dict)) + result = cls(DictDef(self, + s_ImpossibleValue, + s_ImpossibleValue, + is_r_dict = tp is r_dict)) self.immutable_cache[key] = result if tp is r_dict: s_eqfn = self.immutablevalue(x.key_eq) @@ -412,10 +416,7 @@ dictdef.generalize_key(self.immutablevalue(ek, False)) dictdef.generalize_value(self.immutablevalue(ev, False)) dictdef.seen_prebuilt_key(ek) - if tp is SomeOrderedDict.knowntype: - result = SomeOrderedDict(dictdef) - else: - result = SomeDict(dictdef) + result = cls(dictdef) elif tp is weakref.ReferenceType: x1 = x() if x1 is None: diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py --- a/rpython/annotator/test/test_annrpython.py +++ b/rpython/annotator/test/test_annrpython.py @@ -4148,6 +4148,19 @@ a.build_types(f, [str, str]) assert ("format() is not RPython" in exc.value.msg) + def test_prebuilt_ordered_dict(self): + try: + from collections import OrderedDict + except ImportError: + py.test.skip("Please upgrade to python 2.7") + d = OrderedDict([("aa", 1)]) + + def f(): + return d + + a = self.RPythonAnnotator() + assert isinstance(a.build_types(f, []), annmodel.SomeOrderedDict) + def g(n): return [0, 1, 2, n] diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -460,13 +460,13 @@ check_negative_slice(start, end, "count") return SomeInteger(nonneg=True) - def method_strip(str, chr): + def method_strip(str, chr=None): return str.basestringclass(no_nul=str.no_nul) - def method_lstrip(str, chr): + def method_lstrip(str, chr=None): return str.basestringclass(no_nul=str.no_nul) - def method_rstrip(str, chr): + def method_rstrip(str, chr=None): return str.basestringclass(no_nul=str.no_nul) def method_join(str, s_list): diff --git a/rpython/jit/backend/x86/test/test_ztranslation_basic.py b/rpython/jit/backend/x86/test/test_ztranslation_basic.py --- a/rpython/jit/backend/x86/test/test_ztranslation_basic.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_basic.py @@ -1,11 +1,11 @@ from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTest from rpython.jit.backend.x86.arch import WORD +import sys class TestTranslationX86(TranslationTest): def _check_cbuilder(self, cbuilder): - # We assume here that we have sse2. If not, the CPUClass - # needs to be changed to CPU386_NO_SSE2, but well. - if WORD == 4: + # msse2 and sse are always on on x86-64 + if WORD == 4 and sys.platform != 'win32': assert '-msse2' in cbuilder.eci.compile_extra assert '-mfpmath=sse' in cbuilder.eci.compile_extra diff --git a/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py b/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py --- a/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py @@ -1,11 +1,13 @@ from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTestCallAssembler from rpython.translator.translator import TranslationContext from rpython.config.translationoption import DEFL_GC - +from rpython.jit.backend.x86.arch import WORD +import sys class TestTranslationCallAssemblerX86(TranslationTestCallAssembler): def _check_cbuilder(self, cbuilder): - # We assume here that we have sse2. If not, the CPUClass + #We assume here that we have sse2. If not, the CPUClass # needs to be changed to CPU386_NO_SSE2, but well. - assert '-msse2' in cbuilder.eci.compile_extra - assert '-mfpmath=sse' in cbuilder.eci.compile_extra \ No newline at end of file + if WORD == 4 and sys.platform != 'win32': + assert '-msse2' in cbuilder.eci.compile_extra + assert '-mfpmath=sse' in cbuilder.eci.compile_extra diff --git a/rpython/jit/backend/x86/test/test_ztranslation_jit_stats.py b/rpython/jit/backend/x86/test/test_ztranslation_jit_stats.py --- a/rpython/jit/backend/x86/test/test_ztranslation_jit_stats.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_jit_stats.py @@ -1,11 +1,14 @@ from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTestJITStats from rpython.translator.translator import TranslationContext from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.x86.arch import WORD +import sys class TestTranslationJITStatsX86(TranslationTestJITStats): def _check_cbuilder(self, cbuilder): - # We assume here that we have sse2. If not, the CPUClass + #We assume here that we have sse2. If not, the CPUClass # needs to be changed to CPU386_NO_SSE2, but well. - assert '-msse2' in cbuilder.eci.compile_extra - assert '-mfpmath=sse' in cbuilder.eci.compile_extra \ No newline at end of file + if WORD == 4 and sys.platform != 'win32': + assert '-msse2' in cbuilder.eci.compile_extra + assert '-mfpmath=sse' in cbuilder.eci.compile_extra diff --git a/rpython/rlib/rdtoa.py b/rpython/rlib/rdtoa.py --- a/rpython/rlib/rdtoa.py +++ b/rpython/rlib/rdtoa.py @@ -38,6 +38,10 @@ ], ) +# dtoa.c is limited to 'int', so we refuse to pass it +# strings or integer arguments bigger than ~2GB +_INT_LIMIT = 0x7ffff000 + dg_strtod = rffi.llexternal( '_PyPy_dg_strtod', [rffi.CCHARP, rffi.CCHARPP], rffi.DOUBLE, compilation_info=eci, sandboxsafe=True) @@ -52,6 +56,8 @@ compilation_info=eci, sandboxsafe=True) def strtod(input): + if len(input) > _INT_LIMIT: + raise MemoryError end_ptr = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw') try: ll_input = rffi.str2charp(input) @@ -232,6 +238,8 @@ def dtoa(value, code='r', mode=0, precision=0, flags=0, special_strings=lower_special_strings, upper=False): + if precision > _INT_LIMIT: + raise MemoryError decpt_ptr = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') try: sign_ptr = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') diff --git a/rpython/rlib/rdynload.py b/rpython/rlib/rdynload.py --- a/rpython/rlib/rdynload.py +++ b/rpython/rlib/rdynload.py @@ -4,7 +4,6 @@ from rpython.rtyper.tool import rffi_platform from rpython.rtyper.lltypesystem import rffi from rpython.rlib.rarithmetic import r_uint -from rpython.rlib.objectmodel import we_are_translated from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform @@ -80,38 +79,6 @@ RTLD_NOW = cConfig.RTLD_NOW RTLD_LAZY = cConfig.RTLD_LAZY - _t_opened = {} - - def t_dlopen(name): - # for direct execution: can't use the regular way on FreeBSD :-( - # http://factor-language.blogspot.de/2009/02/note-about-libdl-functions-on-netbsd.html - import ctypes - if name: - name = rffi.charp2str(name) - else: - name = None - try: - res = ctypes.cdll.LoadLibrary(name) - except OSError, e: - raise DLOpenError(str(e)) - h = rffi.cast(rffi.VOIDP, res._handle) - _t_opened[rffi.cast(rffi.LONG, h)] = res - return h - - def t_dlclose(handle): - _t_opened.pop(rffi.cast(rffi.LONG, handle)) - return rffi.cast(rffi.INT, 0) - - def t_dldym(handle, name): - import ctypes - lib = _t_opened[rffi.cast(rffi.LONG, handle)] - try: - symbol = lib[name] - except AttributeError: - raise KeyError(name) - res = ctypes.cast(symbol, ctypes.c_void_p) - return rffi.cast(rffi.VOIDP, res.value or 0) - def dlerror(): # XXX this would never work on top of ll2ctypes, because # ctypes are calling dlerror itself, unsure if I can do much in this @@ -124,8 +91,6 @@ def dlopen(name, mode=-1): """ Wrapper around C-level dlopen """ - if not we_are_translated(): - return t_dlopen(name) if mode == -1: if RTLD_LOCAL is not None: mode = RTLD_LOCAL @@ -139,16 +104,11 @@ raise DLOpenError(err) return res - def dlclose(handle): - if not we_are_translated(): - return t_dlclose(handle) - return c_dlclose(handle) + dlclose = c_dlclose def dlsym(libhandle, name): """ Wrapper around C-level dlsym """ - if not we_are_translated(): - return t_dldym(libhandle, name) res = c_dlsym(libhandle, name) if not res: raise KeyError(name) diff --git a/rpython/rlib/test/test_rdynload.py b/rpython/rlib/test/test_rdynload.py --- a/rpython/rlib/test/test_rdynload.py +++ b/rpython/rlib/test/test_rdynload.py @@ -21,4 +21,3 @@ lltype.Signed)), dlsym(lib, 'abs')) assert 1 == handle(1) assert 1 == handle(-1) - dlclose(lib) diff --git a/rpython/rtyper/lltypesystem/rstr.py b/rpython/rtyper/lltypesystem/rstr.py --- a/rpython/rtyper/lltypesystem/rstr.py +++ b/rpython/rtyper/lltypesystem/rstr.py @@ -9,6 +9,7 @@ from rpython.rlib.rarithmetic import ovfcheck from rpython.rtyper.error import TyperError from rpython.rtyper.lltypesystem import ll_str, llmemory +from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rtyper.lltypesystem.lltype import (GcStruct, Signed, Array, Char, UniChar, Ptr, malloc, Bool, Void, GcArray, nullptr, cast_primitive, typeOf, staticAdtMethod, GcForwardReference) @@ -402,6 +403,46 @@ return result @jit.elidable + def ll_strip_default(s, left, right): + s_len = len(s.chars) + if s_len == 0: + return s.empty() + lpos = 0 + rpos = s_len - 1 + if left: + while lpos < rpos and s.chars[lpos].isspace(): + lpos += 1 + if right: + while lpos < rpos + 1 and s.chars[rpos].isspace(): + rpos -= 1 + if rpos < lpos: + return s.empty() + r_len = rpos - lpos + 1 + result = s.malloc(r_len) + s.copy_contents(s, result, lpos, 0, r_len) + return result + + @jit.elidable + def ll_strip_multiple(s, s2, left, right): + s_len = len(s.chars) + if s_len == 0: + return s.empty() + lpos = 0 + rpos = s_len - 1 + if left: + while lpos < rpos and LLHelpers.ll_contains(s2, s.chars[lpos]): + lpos += 1 + if right: + while lpos < rpos + 1 and LLHelpers.ll_contains(s2, s.chars[rpos]): + rpos -= 1 + if rpos < lpos: + return s.empty() + r_len = rpos - lpos + 1 + result = s.malloc(r_len) + s.copy_contents(s, result, lpos, 0, r_len) + return result + + @jit.elidable def ll_upper(s): s_chars = s.chars s_len = len(s_chars) diff --git a/rpython/rtyper/rstr.py b/rpython/rtyper/rstr.py --- a/rpython/rtyper/rstr.py +++ b/rpython/rtyper/rstr.py @@ -231,11 +231,22 @@ def rtype_method_strip(self, hop, left=True, right=True): rstr = hop.args_r[0].repr v_str = hop.inputarg(rstr.repr, arg=0) - v_char = hop.inputarg(rstr.char_repr, arg=1) - v_left = hop.inputconst(Bool, left) - v_right = hop.inputconst(Bool, right) + args_v = [v_str] + if len(hop.args_s) == 2: + if isinstance(hop.args_s[1], annmodel.SomeString): + v_stripstr = hop.inputarg(rstr.repr, arg=1) + args_v.append(v_stripstr) + func = self.ll.ll_strip_multiple + else: + v_char = hop.inputarg(rstr.char_repr, arg=1) + args_v.append(v_char) + func = self.ll.ll_strip + else: + func = self.ll.ll_strip_default + args_v.append(hop.inputconst(Bool, left)) + args_v.append(hop.inputconst(Bool, right)) hop.exception_is_here() - return hop.gendirectcall(self.ll.ll_strip, v_str, v_char, v_left, v_right) + return hop.gendirectcall(func, *args_v) def rtype_method_lstrip(self, hop): return self.rtype_method_strip(hop, left=True, right=False) diff --git a/rpython/rtyper/test/test_rstr.py b/rpython/rtyper/test/test_rstr.py --- a/rpython/rtyper/test/test_rstr.py +++ b/rpython/rtyper/test/test_rstr.py @@ -9,6 +9,7 @@ from rpython.rtyper.rstr import AbstractLLHelpers from rpython.rtyper.rtyper import TyperError from rpython.rtyper.test.tool import BaseRtypingTest +from rpython.rtyper.annlowlevel import llstr, hlstr def test_parse_fmt(): @@ -457,6 +458,29 @@ res = self.interpret(left2, []) assert self.ll_to_string(res) == const('a') + def test_strip_multiple_chars(self): + const = self.const + def both(): + return const('!ab!').strip(const('!a')) + def left(): + return const('!+ab!').lstrip(const('!+')) + def right(): + return const('!ab!+').rstrip(const('!+')) + def empty(): + return const(' \t\t ').strip('\t ') + def left2(): + return const('a ').strip(' \t') + res = self.interpret(both, []) + assert self.ll_to_string(res) == const('b') + res = self.interpret(left, []) + assert self.ll_to_string(res) == const('ab!') + res = self.interpret(right, []) + assert self.ll_to_string(res) == const('!ab') + res = self.interpret(empty, []) + assert self.ll_to_string(res) == const('') + res = self.interpret(left2, []) + assert self.ll_to_string(res) == const('a') + def test_upper(self): const = self.const constchar = self.constchar @@ -1143,3 +1167,16 @@ self.interpret(f, [array, 4]) assert list(array) == list('abc'*4) lltype.free(array, flavor='raw') + + def test_strip_no_arg(self): + strings = [" xyz ", "", "\t\vx"] + + def f(i): + return strings[i].strip() + + res = self.interpret(f, [0]) + assert hlstr(res) == "xyz" + res = self.interpret(f, [1]) + assert hlstr(res) == "" + res = self.interpret(f, [2]) + assert hlstr(res) == "x" diff --git a/rpython/rtyper/test/test_runicode.py b/rpython/rtyper/test/test_runicode.py --- a/rpython/rtyper/test/test_runicode.py +++ b/rpython/rtyper/test/test_runicode.py @@ -282,6 +282,7 @@ test_int_valueerror = unsupported test_float = unsupported test_hlstr = unsupported + test_strip_multiple_chars = unsupported def test_hash_via_type(self): from rpython.rlib.objectmodel import compute_hash diff --git a/rpython/tool/runsubprocess.py b/rpython/tool/runsubprocess.py --- a/rpython/tool/runsubprocess.py +++ b/rpython/tool/runsubprocess.py @@ -49,7 +49,7 @@ sys.stdout.flush() -if sys.platform != 'win32' and hasattr(os, 'fork'): +if sys.platform != 'win32' and hasattr(os, 'fork') and not os.getenv("PYPY_DONT_RUN_SUBPROCESS", None): # do this at import-time, when the process is still tiny _source = os.path.dirname(os.path.abspath(__file__)) _source = os.path.join(_source, 'runsubprocess.py') # and not e.g. '.pyc' diff --git a/rpython/translator/c/src/dtoa.c b/rpython/translator/c/src/dtoa.c --- a/rpython/translator/c/src/dtoa.c +++ b/rpython/translator/c/src/dtoa.c @@ -2329,7 +2329,7 @@ static char * __Py_dg_dtoa(double dd, int mode, int ndigits, - Signed *decpt, Signed *sign, char **rve) + int *decpt, int *sign, char **rve) { /* Arguments ndigits, decpt, sign are similar to those of ecvt and fcvt; trailing zeros are suppressed from @@ -2952,7 +2952,7 @@ } char * _PyPy_dg_dtoa(double dd, int mode, int ndigits, - Signed *decpt, Signed *sign, char **rve) + int *decpt, int *sign, char **rve) { char* result; _PyPy_SET_53BIT_PRECISION_HEADER; diff --git a/rpython/translator/c/src/dtoa.h b/rpython/translator/c/src/dtoa.h --- a/rpython/translator/c/src/dtoa.h +++ b/rpython/translator/c/src/dtoa.h @@ -2,6 +2,6 @@ double _PyPy_dg_strtod(const char *str, char **ptr); char * _PyPy_dg_dtoa(double d, int mode, int ndigits, - Signed *decpt, Signed *sign, char **rve); + int *decpt, int *sign, char **rve); void _PyPy_dg_freedtoa(char *s); diff --git a/rpython/translator/c/test/test_exception.py b/rpython/translator/c/test/test_exception.py --- a/rpython/translator/c/test/test_exception.py +++ b/rpython/translator/c/test/test_exception.py @@ -156,3 +156,20 @@ assert res == 42 res = f1(0) assert res == 100 + +def test_dict_keyerror_inside_try_finally(): + class CtxMgr: + def __enter__(self): + return 42 + def __exit__(self, *args): + pass + def fn(x): + d = {5: x} + with CtxMgr() as forty_two: + try: + return d[x] + except KeyError: + return forty_two + f1 = getcompiledopt(fn, [int]) + res = f1(100) + assert res == 42 diff --git a/rpython/translator/c/test/test_genc.py b/rpython/translator/c/test/test_genc.py --- a/rpython/translator/c/test/test_genc.py +++ b/rpython/translator/c/test/test_genc.py @@ -574,6 +574,22 @@ fn = compile(chooser, [bool]) assert fn(True) +def test_ordered_dict(): + try: + from collections import OrderedDict + except ImportError: + py.test.skip("Please update to Python 2.7") + + expected = [('ea', 1), ('bb', 2), ('c', 3), ('d', 4), ('e', 5), + ('ef', 6)] + d = OrderedDict(expected) + + def f(): + assert d.items() == expected + + fn = compile(f, []) + fn() + def test_inhibit_tail_call(): def foobar_fn(n): return 42 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit