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

Reply via email to