[pypy-commit] pypy py3k: (mjacob, plan_rich) merge default into py3k

plan_rich pypy.commits at gmail.com
Sun Feb 21 17:06:04 EST 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: py3k
Changeset: r82377:c87ebc4db701
Date: 2016-02-21 23:05 +0100
http://bitbucket.org/pypy/pypy/changeset/c87ebc4db701/

Log:	(mjacob, plan_rich) merge default into py3k

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -22,6 +22,7 @@
 ^pypy/module/cpyext/test/.+\.obj$
 ^pypy/module/cpyext/test/.+\.manifest$
 ^pypy/module/test_lib_pypy/ctypes_tests/.+\.o$
+^pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test\.o$
 ^pypy/module/cppyy/src/.+\.o$
 ^pypy/module/cppyy/bench/.+\.so$
 ^pypy/module/cppyy/bench/.+\.root$
@@ -35,7 +36,6 @@
 ^pypy/module/test_lib_pypy/cffi_tests/__pycache__.+$
 ^pypy/doc/.+\.html$
 ^pypy/doc/config/.+\.rst$
-^pypy/doc/basicblock\.asc$
 ^pypy/doc/.+\.svninfo$
 ^rpython/translator/c/src/libffi_msvc/.+\.obj$
 ^rpython/translator/c/src/libffi_msvc/.+\.dll$
@@ -45,53 +45,33 @@
 ^rpython/translator/c/src/cjkcodecs/.+\.obj$
 ^rpython/translator/c/src/stacklet/.+\.o$
 ^rpython/translator/c/src/.+\.o$
-^rpython/translator/jvm/\.project$
-^rpython/translator/jvm/\.classpath$
-^rpython/translator/jvm/eclipse-bin$
-^rpython/translator/jvm/src/pypy/.+\.class$
-^rpython/translator/benchmark/docutils$
-^rpython/translator/benchmark/templess$
-^rpython/translator/benchmark/gadfly$
-^rpython/translator/benchmark/mako$
-^rpython/translator/benchmark/bench-custom\.benchmark_result$
-^rpython/translator/benchmark/shootout_benchmarks$
+^rpython/translator/llvm/.+\.so$
 ^rpython/translator/goal/target.+-c$
 ^rpython/translator/goal/.+\.exe$
 ^rpython/translator/goal/.+\.dll$
 ^pypy/goal/pypy-translation-snapshot$
 ^pypy/goal/pypy-c
-^pypy/goal/pypy-jvm
-^pypy/goal/pypy-jvm.jar
 ^pypy/goal/.+\.exe$
 ^pypy/goal/.+\.dll$
 ^pypy/goal/.+\.lib$
 ^pypy/_cache$
-^pypy/doc/statistic/.+\.html$
-^pypy/doc/statistic/.+\.eps$
-^pypy/doc/statistic/.+\.pdf$
-^rpython/translator/cli/src/pypylib\.dll$
-^rpython/translator/cli/src/query\.exe$
-^rpython/translator/cli/src/main\.exe$
+^lib-python/2.7/lib2to3/.+\.pickle$
 ^lib_pypy/__pycache__$
 ^lib_pypy/ctypes_config_cache/_.+_cache\.py$
 ^lib_pypy/ctypes_config_cache/_.+_.+_\.py$
 ^lib_pypy/_libmpdec/.+.o$
-^rpython/translator/cli/query-descriptions$
 ^pypy/doc/discussion/.+\.html$
 ^include/.+\.h$
 ^include/.+\.inl$
 ^pypy/doc/_build/.*$
 ^pypy/doc/config/.+\.html$
 ^pypy/doc/config/style\.css$
-^pypy/doc/jit/.+\.html$
-^pypy/doc/jit/style\.css$
 ^pypy/doc/image/lattice1\.png$
 ^pypy/doc/image/lattice2\.png$
 ^pypy/doc/image/lattice3\.png$
 ^pypy/doc/image/stackless_informal\.png$
 ^pypy/doc/image/parsing_example.+\.png$
 ^rpython/doc/_build/.*$
-^pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test\.o$
 ^compiled
 ^.git/
 ^release/
diff --git a/pypy/interpreter/pyparser/pytokenizer.py b/pypy/interpreter/pyparser/pytokenizer.py
--- a/pypy/interpreter/pyparser/pytokenizer.py
+++ b/pypy/interpreter/pyparser/pytokenizer.py
@@ -106,6 +106,7 @@
     strstart = (0, 0, "")
     for line in lines:
         lnum = lnum + 1
+        line = universal_newline(line)
         pos, max = 0, len(line)
 
         if contstr:
@@ -296,3 +297,15 @@
 
     token_list.append((tokens.ENDMARKER, '', lnum, pos, line))
     return token_list
+
+def universal_newline(line):
+    if len(line) >= 2:
+        c0 = line[-2]
+        c1 = line[-1]
+        if c0 == '\r' and c1 == '\n':
+            return line[:-2] + '\n'
+    if len(line) >= 1:
+        c = line[-1]
+        if c == '\r':
+            return line[:-1] + '\n'
+    return line
diff --git a/pypy/interpreter/pyparser/test/test_pyparse.py b/pypy/interpreter/pyparser/test/test_pyparse.py
--- a/pypy/interpreter/pyparser/test/test_pyparse.py
+++ b/pypy/interpreter/pyparser/test/test_pyparse.py
@@ -139,6 +139,13 @@
     def test_print_function(self):
         self.parse("from __future__ import print_function\nx = print\n")
 
+    def test_universal_newlines(self):
+        fmt = 'stuff = """hello%sworld"""'
+        expected_tree = self.parse(fmt % '\n')
+        for linefeed in ["\r\n","\r"]:
+            tree = self.parse(fmt % linefeed)
+            assert expected_tree == tree
+
     def test_py3k_reject_old_binary_literal(self):
         py.test.raises(SyntaxError, self.parse, '0777')
 
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -156,20 +156,6 @@
 get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"
 _subclass_cache = {}
 
-def enum_interplevel_subclasses(config, cls):
-    """Return a list of all the extra interp-level subclasses of 'cls' that
-    can be built by get_unique_interplevel_subclass()."""
-    result = []
-    for flag1 in (False, True):
-        for flag2 in (False, True):
-            for flag3 in (False, True):
-                for flag4 in (False, True):
-                    result.append(get_unique_interplevel_subclass(
-                        config, cls, flag1, flag2, flag3, flag4))
-    result = dict.fromkeys(result)
-    assert len(result) <= 6
-    return result.keys()
-
 def _getusercls(config, cls, wants_dict, wants_slots, wants_del, weakrefable):
     typedef = cls.typedef
     if wants_dict and typedef.hasdict:
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -196,6 +196,10 @@
     def newfloat(self, f):
         return self.float(f)
 
+    def newslice(self, start, stop, step):
+        return SliceObject(self.int_w(start), self.int_w(stop),
+                           self.int_w(step))
+
     def le(self, w_obj1, w_obj2):
         assert isinstance(w_obj1, boxes.W_GenericBox)
         assert isinstance(w_obj2, boxes.W_GenericBox)
diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -12,8 +12,8 @@
     ArrayArgumentException, W_NumpyObject
 from pypy.module.micronumpy.iterators import ArrayIter
 from pypy.module.micronumpy.strides import (
-    IntegerChunk, SliceChunk, NewAxisChunk, EllipsisChunk, new_view,
-    calc_strides, calc_new_strides, shape_agreement,
+    IntegerChunk, SliceChunk, NewAxisChunk, EllipsisChunk, BooleanChunk,
+    new_view, calc_strides, calc_new_strides, shape_agreement,
     calculate_broadcast_strides, calc_backstrides, calc_start, is_c_contiguous,
     is_f_contiguous)
 from rpython.rlib.objectmodel import keepalive_until_here
@@ -236,6 +236,7 @@
 
     @jit.unroll_safe
     def _prepare_slice_args(self, space, w_idx):
+        from pypy.module.micronumpy import boxes
         if space.isinstance_w(w_idx, space.w_str):
             raise oefmt(space.w_IndexError, "only integers, slices (`:`), "
                 "ellipsis (`...`), numpy.newaxis (`None`) and integer or "
@@ -258,6 +259,7 @@
         result = []
         i = 0
         has_ellipsis = False
+        has_filter = False
         for w_item in space.fixedview(w_idx):
             if space.is_w(w_item, space.w_Ellipsis):
                 if has_ellipsis:
@@ -272,6 +274,16 @@
             elif space.isinstance_w(w_item, space.w_slice):
                 result.append(SliceChunk(w_item))
                 i += 1
+            elif isinstance(w_item, W_NDimArray) and w_item.get_dtype().is_bool():
+                if has_filter:
+                    # in CNumPy, the support for this is incomplete
+                    raise oefmt(space.w_ValueError,
+                        "an index can only have a single boolean mask; "
+                        "use np.take or create a sinlge mask array")
+                has_filter = True
+                result.append(BooleanChunk(w_item))
+            elif isinstance(w_item, boxes.W_GenericBox):
+                result.append(IntegerChunk(w_item.descr_int(space)))
             else:
                 result.append(IntegerChunk(w_item))
                 i += 1
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -107,8 +107,9 @@
             arr = W_NDimArray(self.implementation.transpose(self, None))
         return space.wrap(loop.tostring(space, arr))
 
-    def getitem_filter(self, space, arr):
-        if arr.ndims() > 1 and arr.get_shape() != self.get_shape():
+    def getitem_filter(self, space, arr, axis=0):
+        shape = self.get_shape()
+        if arr.ndims() > 1 and arr.get_shape() != shape:
             raise OperationError(space.w_IndexError, space.wrap(
                 "boolean index array should have 1 dimension"))
         if arr.get_size() > self.get_size():
@@ -116,14 +117,14 @@
                 "index out of range for array"))
         size = loop.count_all_true(arr)
         if arr.ndims() == 1:
-            if self.ndims() > 1 and arr.get_shape()[0] != self.get_shape()[0]:
+            if self.ndims() > 1 and arr.get_shape()[0] != shape[axis]:
                 msg = ("boolean index did not match indexed array along"
-                      " dimension 0; dimension is %d but corresponding"
-                      " boolean dimension is %d" % (self.get_shape()[0],
+                      " dimension %d; dimension is %d but corresponding"
+                      " boolean dimension is %d" % (axis, shape[axis],
                       arr.get_shape()[0]))
                 #warning = space.gettypefor(support.W_VisibleDeprecationWarning)
                 space.warn(space.wrap(msg), space.w_VisibleDeprecationWarning)
-            res_shape = [size] + self.get_shape()[1:]
+            res_shape = shape[:axis] + [size] + shape[axis+1:]
         else:
             res_shape = [size]
         w_res = W_NDimArray.from_shape(space, res_shape, self.get_dtype(),
@@ -149,6 +150,8 @@
     def _prepare_array_index(self, space, w_index):
         if isinstance(w_index, W_NDimArray):
             return [], w_index.get_shape(), w_index.get_shape(), [w_index]
+        if isinstance(w_index, boxes.W_GenericBox):
+            return [], [1], [1], [w_index]
         w_lst = space.listview(w_index)
         for w_item in w_lst:
             if not (space.isinstance_w(w_item, space.w_int) or space.isinstance_w(w_item, space.w_float)):
@@ -162,7 +165,14 @@
         arr_index_in_shape = False
         prefix = []
         for i, w_item in enumerate(w_lst):
-            if (isinstance(w_item, W_NDimArray) or
+            if isinstance(w_item, W_NDimArray) and w_item.get_dtype().is_bool():
+                if w_item.ndims() > 0:
+                    indexes_w[i] = w_item
+                else:
+                    raise oefmt(space.w_IndexError,
+                        "in the future, 0-d boolean arrays will be "
+                        "interpreted as a valid boolean index")
+            elif (isinstance(w_item, W_NDimArray) or
                     space.isinstance_w(w_item, space.w_list)):
                 w_item = convert_to_array(space, w_item)
                 if shape is None:
@@ -232,6 +242,8 @@
                 raise oefmt(space.w_IndexError,
                         "in the future, 0-d boolean arrays will be "
                         "interpreted as a valid boolean index")
+        elif isinstance(w_idx, boxes.W_GenericBox):
+            w_ret = self.getitem_array_int(space, w_idx)
         else:
             try:
                 w_ret = self.implementation.descr_getitem(space, self, w_idx)
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -77,14 +77,42 @@
         backstride = base_stride * max(0, base_length - 1)
         return 0, base_length, base_stride, backstride
 
+class BooleanChunk(BaseChunk):
+    input_dim = 1
+    out_dim = 1
+    def __init__(self, w_idx):
+        self.w_idx = w_idx
+
+    def compute(self, space, base_length, base_stride):
+        raise oefmt(space.w_NotImplementedError, 'cannot reach')
 
 def new_view(space, w_arr, chunks):
     arr = w_arr.implementation
-    r = calculate_slice_strides(space, arr.shape, arr.start, arr.get_strides(),
-                                arr.get_backstrides(), chunks)
+    dim = -1
+    for i, c in enumerate(chunks):
+        if isinstance(c, BooleanChunk):
+            dim = i
+            break
+    if dim >= 0:
+        # filter by axis dim
+        filtr = chunks[dim]
+        assert isinstance(filtr, BooleanChunk) 
+        w_arr = w_arr.getitem_filter(space, filtr.w_idx, axis=dim)
+        arr = w_arr.implementation
+        chunks[dim] = SliceChunk(space.newslice(space.wrap(0), 
+                                 space.wrap(-1), space.w_None))
+        r = calculate_slice_strides(space, arr.shape, arr.start,
+                 arr.get_strides(), arr.get_backstrides(), chunks)
+    else:
+        r = calculate_slice_strides(space, arr.shape, arr.start,
+                     arr.get_strides(), arr.get_backstrides(), chunks)
     shape, start, strides, backstrides = r
-    return W_NDimArray.new_slice(space, start, strides[:], backstrides[:],
+    w_ret = W_NDimArray.new_slice(space, start, strides[:], backstrides[:],
                                  shape[:], arr, w_arr)
+    if dim == 0:
+        # Do not return a view
+        return w_ret.descr_copy(space, space.wrap(w_ret.get_order()))
+    return w_ret
 
 @jit.unroll_safe
 def _extend_shape(old_shape, chunks):
@@ -127,7 +155,7 @@
                      jit.isconstant(len(chunks)))
 def calculate_slice_strides(space, shape, start, strides, backstrides, chunks):
     """
-    Note: `chunks` must contain exactly one EllipsisChunk object.
+    Note: `chunks` can contain at most one EllipsisChunk object.
     """
     size = 0
     used_dims = 0
diff --git a/pypy/module/micronumpy/test/test_deprecations.py b/pypy/module/micronumpy/test/test_deprecations.py
--- a/pypy/module/micronumpy/test/test_deprecations.py
+++ b/pypy/module/micronumpy/test/test_deprecations.py
@@ -24,7 +24,7 @@
                 # boolean indexing matches the dims in index
                 # to the first index.ndims in arr, not implemented in pypy yet
                 raises(IndexError, arr.__getitem__, index)
-                raises(TypeError, arr.__getitem__, (slice(None), index))
+                raises(IndexError, arr.__getitem__, (slice(None), index))
             else:
                 raises(np.VisibleDeprecationWarning, arr.__getitem__, index)
                 raises(np.VisibleDeprecationWarning, arr.__getitem__, (slice(None), index))
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -2532,6 +2532,25 @@
         a[b] = np.array([[4.]])
         assert (a == [[4., 4., 4.]]).all()
 
+    def test_indexing_by_boolean(self):
+        import numpy as np
+        a = np.arange(6).reshape(2,3)
+        assert (a[[True, False], :] == [[3, 4, 5], [0, 1, 2]]).all()
+        b = a[np.array([True, False]), :]
+        assert (b == [[0, 1, 2]]).all()
+        assert b.base is None
+        b = a[:, np.array([True, False, True])]
+        assert b.base is not None
+        b = a[np.array([True, False]), 0]
+        assert (b ==[0]).all()
+
+    def test_scalar_indexing(self):
+        import numpy as np
+        a = np.arange(6).reshape(2,3)
+        i = np.dtype('int32').type(0)
+        assert (a[0] == a[i]).all()
+        
+
     def test_ellipsis_indexing(self):
         import numpy as np
         import sys
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -7,7 +7,7 @@
 from pypy.interpreter.astcompiler.misc import mangle
 
 from rpython.rlib.jit import (promote, elidable_promote, we_are_jitted,
-     promote_string, elidable, dont_look_inside, unroll_safe)
+     elidable, dont_look_inside, unroll_safe)
 from rpython.rlib.objectmodel import current_object_addr_as_int, compute_hash
 from rpython.rlib.rarithmetic import intmask, r_uint
 
@@ -400,7 +400,6 @@
         if version_tag is None:
             tup = w_self._lookup_where(name)
             return tup
-        name = promote_string(name)
         tup_w = w_self._pure_lookup_where_with_method_cache(name, version_tag)
         w_class, w_value = tup_w
         if (space.config.objspace.std.withtypeversion and
diff --git a/rpython/jit/codewriter/support.py b/rpython/jit/codewriter/support.py
--- a/rpython/jit/codewriter/support.py
+++ b/rpython/jit/codewriter/support.py
@@ -246,12 +246,12 @@
 def _ll_2_int_floordiv_ovf_zer(x, y):
     if y == 0:
         raise ZeroDivisionError
-    if x == -sys.maxint - 1 and y == -1:
-        raise OverflowError
-    return llop.int_floordiv(lltype.Signed, x, y)
+    return _ll_2_int_floordiv_ovf(x, y)
 
 def _ll_2_int_floordiv_ovf(x, y):
-    if x == -sys.maxint - 1 and y == -1:
+    # intentionally not short-circuited to produce only one guard
+    # and to remove the check fully if one of the arguments is known
+    if (x == -sys.maxint - 1) & (y == -1):
         raise OverflowError
     return llop.int_floordiv(lltype.Signed, x, y)
 
@@ -263,12 +263,11 @@
 def _ll_2_int_mod_ovf_zer(x, y):
     if y == 0:
         raise ZeroDivisionError
-    if x == -sys.maxint - 1 and y == -1:
-        raise OverflowError
-    return llop.int_mod(lltype.Signed, x, y)
+    return _ll_2_int_mod_ovf(x, y)
 
 def _ll_2_int_mod_ovf(x, y):
-    if x == -sys.maxint - 1 and y == -1:
+    #see comment in _ll_2_int_floordiv_ovf
+    if (x == -sys.maxint - 1) & (y == -1):
         raise OverflowError
     return llop.int_mod(lltype.Signed, x, y)
 
diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py
--- a/rpython/jit/metainterp/test/test_ajit.py
+++ b/rpython/jit/metainterp/test/test_ajit.py
@@ -1199,6 +1199,31 @@
                        (-sys.maxint-1) // (-6) +
                        100 * 8)
 
+    def test_overflow_fold_if_divisor_constant(self):
+        import sys
+        from rpython.rtyper.lltypesystem.lloperation import llop
+        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
+        def f(x, y):
+            res = 0
+            while y > 0:
+                myjitdriver.can_enter_jit(x=x, y=y, res=res)
+                myjitdriver.jit_merge_point(x=x, y=y, res=res)
+                try:
+                    res += llop.int_floordiv_ovf(lltype.Signed,
+                                                 x, 2)
+                    res += llop.int_mod_ovf(lltype.Signed,
+                                                 x, 2)
+                    x += 5
+                except OverflowError:
+                    res += 100
+                y -= 1
+            return res
+        res = self.meta_interp(f, [-41, 8])
+        # the guard_true are for the loop condition
+        # the guard_false needed to check whether an overflow can occur have
+        # been folded away
+        self.check_resops(guard_true=2, guard_false=0)
+
     def test_isinstance(self):
         class A:
             pass
diff --git a/rpython/jit/metainterp/test/test_tlc.py b/rpython/jit/metainterp/test/test_tlc.py
--- a/rpython/jit/metainterp/test/test_tlc.py
+++ b/rpython/jit/metainterp/test/test_tlc.py
@@ -1,5 +1,4 @@
 import py
-from rpython.rtyper.module.support import LLSupport
 
 from rpython.jit.tl import tlc
 
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -3,7 +3,6 @@
 import errno
 from rpython.rtyper.lltypesystem.rffi import CConstant, CExternVariable, INT
 from rpython.rtyper.lltypesystem import lltype, ll2ctypes, rffi
-from rpython.rtyper.module.support import StringTraits, UnicodeTraits
 from rpython.rtyper.tool import rffi_platform
 from rpython.tool.sourcetools import func_renamer
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -12,7 +11,7 @@
     specialize, enforceargs, register_replacement_for, NOT_CONSTANT)
 from rpython.rlib.signature import signature
 from rpython.rlib import types
-from rpython.annotator.model import s_Str0
+from rpython.annotator.model import s_Str0, s_Unicode0
 from rpython.rlib import jit
 from rpython.translator.platform import platform
 from rpython.rlib import rstring
@@ -342,6 +341,87 @@
     rstring.check_str0(res)
     return res
 
+
+class StringTraits:
+    str = str
+    str0 = s_Str0
+    CHAR = rffi.CHAR
+    CCHARP = rffi.CCHARP
+    charp2str = staticmethod(rffi.charp2str)
+    charpsize2str = staticmethod(rffi.charpsize2str)
+    scoped_str2charp = staticmethod(rffi.scoped_str2charp)
+    str2charp = staticmethod(rffi.str2charp)
+    free_charp = staticmethod(rffi.free_charp)
+    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
+
+    @staticmethod
+    def posix_function_name(name):
+        return UNDERSCORE_ON_WIN32 + name
+
+    @staticmethod
+    def ll_os_name(name):
+        return 'll_os.ll_os_' + name
+
+    @staticmethod
+    @specialize.argtype(0)
+    def as_str(path):
+        assert path is not None
+        if isinstance(path, str):
+            return path
+        elif isinstance(path, unicode):
+            # This never happens in PyPy's Python interpreter!
+            # Only in raw RPython code that uses unicode strings.
+            # We implement python2 behavior: silently convert to ascii.
+            return path.encode('ascii')
+        else:
+            return path.as_bytes()    
+
+    @staticmethod
+    @specialize.argtype(0)
+    def as_str0(path):
+        res = StringTraits.as_str(path)
+        rstring.check_str0(res)
+        return res
+
+
+class UnicodeTraits:
+    str = unicode
+    str0 = s_Unicode0
+    CHAR = rffi.WCHAR_T
+    CCHARP = rffi.CWCHARP
+    charp2str = staticmethod(rffi.wcharp2unicode)
+    charpsize2str = staticmethod(rffi.wcharpsize2unicode)
+    str2charp = staticmethod(rffi.unicode2wcharp)
+    scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp)
+    free_charp = staticmethod(rffi.free_wcharp)
+    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
+
+    @staticmethod
+    def posix_function_name(name):
+        return UNDERSCORE_ON_WIN32 + 'w' + name
+
+    @staticmethod
+    @specialize.argtype(0)
+    def ll_os_name(name):
+        return 'll_os.ll_os_w' + name
+
+    @staticmethod
+    @specialize.argtype(0)
+    def as_str(path):
+        assert path is not None
+        if isinstance(path, unicode):
+            return path
+        else:
+            return path.as_unicode()
+    
+    @staticmethod
+    @specialize.argtype(0)
+    def as_str0(path):
+        res = UnicodeTraits.as_str(path)
+        rstring.check_str0(res)
+        return res
+
+
 # Returns True when the unicode function should be called:
 # - on Windows
 # - if the path is Unicode.
diff --git a/rpython/rlib/rposix_environ.py b/rpython/rlib/rposix_environ.py
--- a/rpython/rlib/rposix_environ.py
+++ b/rpython/rlib/rposix_environ.py
@@ -2,10 +2,10 @@
 import sys
 from rpython.annotator import model as annmodel
 from rpython.rlib.objectmodel import enforceargs
+from rpython.rlib.rposix import _WIN32, StringTraits, UnicodeTraits
 from rpython.rtyper.controllerentry import Controller
 from rpython.rtyper.extfunc import register_external
 from rpython.rtyper.lltypesystem import rffi, lltype
-from rpython.rtyper.module.support import _WIN32, StringTraits, UnicodeTraits
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
 str0 = annmodel.s_Str0
diff --git a/rpython/rtyper/module/test/test_posix.py b/rpython/rlib/test/test_posix.py
rename from rpython/rtyper/module/test/test_posix.py
rename to rpython/rlib/test/test_posix.py
diff --git a/rpython/rlib/test/test_rerased.py b/rpython/rlib/test/test_rerased.py
--- a/rpython/rlib/test/test_rerased.py
+++ b/rpython/rlib/test/test_rerased.py
@@ -192,7 +192,7 @@
 
     def interpret(self, *args, **kwargs):
         kwargs["taggedpointers"] = True
-        return BaseRtypingTest.interpret(self, *args, **kwargs)
+        return BaseRtypingTest.interpret(*args, **kwargs)
     def test_rtype_1(self):
         def f():
             return eraseX(X())
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -463,6 +463,9 @@
 
 def remove_regular_struct_content(container):
     STRUCT = container._TYPE
+    if isinstance(STRUCT, lltype.FixedSizeArray):
+        del container._items
+        return
     for field_name in STRUCT._names:
         FIELDTYPE = getattr(STRUCT, field_name)
         if not isinstance(FIELDTYPE, lltype.ContainerType):
@@ -642,6 +645,12 @@
             cobj = lltype2ctypes(value)
             setattr(self._storage.contents, field_name, cobj)
 
+    def getitem(self, index, uninitialized_ok=False):
+        return getattr(self, "item%s" % index)
+
+    def setitem(self, index, value):
+        setattr(self, "item%s" % index, value)
+
 class _array_mixin(_parentable_mixin):
     """Mixin added to _array containers when they become ctypes-based."""
     __slots__ = ()
diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py
--- a/rpython/rtyper/lltypesystem/lltype.py
+++ b/rpython/rtyper/lltypesystem/lltype.py
@@ -1761,7 +1761,10 @@
 
     def __new__(self, TYPE, n=None, initialization=None, parent=None,
                 parentindex=None):
-        my_variety = _struct_variety(TYPE._names)
+        if isinstance(TYPE, FixedSizeArray):
+            my_variety = _fixedsizearray
+        else:
+            my_variety = _struct_variety(TYPE._names)
         return object.__new__(my_variety)
 
     def __init__(self, TYPE, n=None, initialization=None, parent=None,
@@ -1771,7 +1774,6 @@
             raise TypeError("%r is not variable-sized" % (TYPE,))
         if n is None and TYPE._arrayfld is not None:
             raise TypeError("%r is variable-sized" % (TYPE,))
-        first, FIRSTTYPE = TYPE._first_struct()
         for fld, typ in TYPE._flds.items():
             if fld == TYPE._arrayfld:
                 value = _array(typ, n, initialization=initialization,
@@ -1814,23 +1816,48 @@
             raise UninitializedMemoryAccess("%r.%s"%(self, field_name))
         return r
 
-    # for FixedSizeArray kind of structs:
+
+class _fixedsizearray(_struct):
+    def __init__(self, TYPE, n=None, initialization=None, parent=None,
+                 parentindex=None):
+        _parentable.__init__(self, TYPE)
+        if n is not None:
+            raise TypeError("%r is not variable-sized" % (TYPE,))
+        typ = TYPE.OF
+        storage = []
+        for i, fld in enumerate(TYPE._names):
+            value = typ._allocate(initialization=initialization,
+                                  parent=self, parentindex=fld)
+            storage.append(value)
+        self._items = storage
+        if parent is not None:
+            self._setparentstructure(parent, parentindex)
 
     def getlength(self):
-        assert isinstance(self._TYPE, FixedSizeArray)
         return self._TYPE.length
 
     def getbounds(self):
         return 0, self.getlength()
 
     def getitem(self, index, uninitialized_ok=False):
-        assert isinstance(self._TYPE, FixedSizeArray)
-        return self._getattr('item%d' % index, uninitialized_ok)
+        assert 0 <= index < self.getlength()
+        return self._items[index]
 
     def setitem(self, index, value):
-        assert isinstance(self._TYPE, FixedSizeArray)
-        setattr(self, 'item%d' % index, value)
+        assert 0 <= index < self.getlength()
+        self._items[index] = value
 
+    def __getattr__(self, name):
+        # obscure
+        if name.startswith("item"):
+            return self.getitem(int(name[len('item'):]))
+        return _struct.__getattr__(self, name)
+
+    def __setattr__(self, name, value):
+        if name.startswith("item"):
+            self.setitem(int(name[len('item'):]), value)
+            return
+        _struct.__setattr__(self, name, value)
 
 class _array(_parentable):
     _kind = "array"
diff --git a/rpython/rtyper/lltypesystem/module/ll_math.py b/rpython/rtyper/lltypesystem/module/ll_math.py
--- a/rpython/rtyper/lltypesystem/module/ll_math.py
+++ b/rpython/rtyper/lltypesystem/module/ll_math.py
@@ -6,8 +6,8 @@
 from rpython.translator import cdir
 from rpython.rlib import jit, rposix
 from rpython.rlib.rfloat import INFINITY, NAN, isfinite, isinf, isnan
+from rpython.rlib.rposix import UNDERSCORE_ON_WIN32
 from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.rtyper.module.support import UNDERSCORE_ON_WIN32
 from rpython.tool.sourcetools import func_with_new_name
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.translator.platform import platform
diff --git a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
@@ -11,12 +11,12 @@
 from rpython.rtyper.lltypesystem.ll2ctypes import _llgcopaque
 from rpython.rtyper.annlowlevel import llhelper
 from rpython.rlib import rposix
+from rpython.rlib.rposix import UNDERSCORE_ON_WIN32
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.translator import cdir
 from rpython.tool.udir import udir
 from rpython.rtyper.test.test_llinterp import interpret
 from rpython.annotator.annrpython import RPythonAnnotator
-from rpython.rtyper.module.support import UNDERSCORE_ON_WIN32
 from rpython.rtyper.rtyper import RPythonTyper
 from rpython.rlib.rarithmetic import r_uint, get_long_pattern, is_emulated_long
 from rpython.rlib.rarithmetic import is_valid_int
diff --git a/rpython/rtyper/module/__init__.py b/rpython/rtyper/module/__init__.py
deleted file mode 100644
--- a/rpython/rtyper/module/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-#
diff --git a/rpython/rtyper/module/support.py b/rpython/rtyper/module/support.py
deleted file mode 100644
--- a/rpython/rtyper/module/support.py
+++ /dev/null
@@ -1,139 +0,0 @@
-import sys
-
-from rpython.annotator import model as annmodel
-from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.rlib.objectmodel import specialize
-from rpython.rlib import rstring
-
-_WIN32 = sys.platform.startswith('win')
-UNDERSCORE_ON_WIN32 = '_' if _WIN32 else ''
-
-# utility conversion functions
-class LLSupport:
-    _mixin_ = True
-
-    def to_rstr(s):
-        from rpython.rtyper.lltypesystem.rstr import STR, mallocstr
-        if s is None:
-            return lltype.nullptr(STR)
-        p = mallocstr(len(s))
-        for i in range(len(s)):
-            p.chars[i] = s[i]
-        return p
-    to_rstr = staticmethod(to_rstr)
-
-    def to_runicode(s):
-        from rpython.rtyper.lltypesystem.rstr import UNICODE, mallocunicode
-        if s is None:
-            return lltype.nullptr(UNICODE)
-        p = mallocunicode(len(s))
-        for i in range(len(s)):
-            p.chars[i] = s[i]
-        return p
-    to_runicode = staticmethod(to_runicode)
-
-    def from_rstr(rs):
-        if not rs:   # null pointer
-            return None
-        else:
-            return ''.join([rs.chars[i] for i in range(len(rs.chars))])
-    from_rstr = staticmethod(from_rstr)
-
-    def from_rstr_nonnull(rs):
-        assert rs
-        return ''.join([rs.chars[i] for i in range(len(rs.chars))])
-    from_rstr_nonnull = staticmethod(from_rstr_nonnull)
-
-
-class StringTraits:
-    str = str
-    str0 = annmodel.s_Str0
-    CHAR = rffi.CHAR
-    CCHARP = rffi.CCHARP
-    charp2str = staticmethod(rffi.charp2str)
-    charpsize2str = staticmethod(rffi.charpsize2str)
-    scoped_str2charp = staticmethod(rffi.scoped_str2charp)
-    str2charp = staticmethod(rffi.str2charp)
-    free_charp = staticmethod(rffi.free_charp)
-    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
-
-    @staticmethod
-    def posix_function_name(name):
-        return UNDERSCORE_ON_WIN32 + name
-
-    @staticmethod
-    def ll_os_name(name):
-        return 'll_os.ll_os_' + name
-
-    @staticmethod
-    @specialize.argtype(0)
-    def as_str(path):
-        assert path is not None
-        if isinstance(path, str):
-            return path
-        elif isinstance(path, unicode):
-            # This never happens in PyPy's Python interpreter!
-            # Only in raw RPython code that uses unicode strings.
-            # We implement python2 behavior: silently convert to ascii.
-            return path.encode('ascii')
-        else:
-            return path.as_bytes()    
-
-    @staticmethod
-    @specialize.argtype(0)
-    def as_str0(path):
-        res = StringTraits.as_str(path)
-        rstring.check_str0(res)
-        return res
-
-class UnicodeTraits:
-    str = unicode
-    str0 = annmodel.s_Unicode0
-    CHAR = rffi.WCHAR_T
-    CCHARP = rffi.CWCHARP
-    charp2str = staticmethod(rffi.wcharp2unicode)
-    charpsize2str = staticmethod(rffi.wcharpsize2unicode)
-    str2charp = staticmethod(rffi.unicode2wcharp)
-    scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp)
-    free_charp = staticmethod(rffi.free_wcharp)
-    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
-
-    @staticmethod
-    def posix_function_name(name):
-        return UNDERSCORE_ON_WIN32 + 'w' + name
-
-    @staticmethod
-    @specialize.argtype(0)
-    def ll_os_name(name):
-        return 'll_os.ll_os_w' + name
-
-    @staticmethod
-    @specialize.argtype(0)
-    def as_str(path):
-        assert path is not None
-        if isinstance(path, unicode):
-            return path
-        else:
-            return path.as_unicode()
-    
-    @staticmethod
-    @specialize.argtype(0)
-    def as_str0(path):
-        res = UnicodeTraits.as_str(path)
-        rstring.check_str0(res)
-        return res
-
-def ll_strcpy(dst_s, src_s, n):
-    dstchars = dst_s.chars
-    srcchars = src_s.chars
-    i = 0
-    while i < n:
-        dstchars[i] = srcchars[i]
-        i += 1
-
-def _ll_strfill(dst_s, srcchars, n):
-    dstchars = dst_s.chars
-    i = 0
-    while i < n:
-        dstchars[i] = srcchars[i]
-        i += 1
diff --git a/rpython/rtyper/module/test/__init__.py b/rpython/rtyper/module/test/__init__.py
deleted file mode 100644
--- a/rpython/rtyper/module/test/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-#
diff --git a/rpython/rtyper/module/test/test_ll_strtod.py b/rpython/rtyper/module/test/test_ll_strtod.py
deleted file mode 100644
--- a/rpython/rtyper/module/test/test_ll_strtod.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import py
-
-from rpython.rtyper.test.tool import BaseRtypingTest
-from rpython.rlib import rfloat
-
-class TestStrtod(BaseRtypingTest):
-    def test_formatd(self):
-        for flags in [0,
-                      rfloat.DTSF_ADD_DOT_0]:
-            def f(y):
-                return rfloat.formatd(y, 'g', 2, flags)
-
-            assert self.ll_to_string(self.interpret(f, [3.0])) == f(3.0)
diff --git a/rpython/rtyper/test/test_rfloat.py b/rpython/rtyper/test/test_rfloat.py
--- a/rpython/rtyper/test/test_rfloat.py
+++ b/rpython/rtyper/test/test_rfloat.py
@@ -204,6 +204,14 @@
         res = self.ll_to_string(self.interpret(f, [10/3.0]))
         assert res == '3.33'
 
+    def test_formatd_g(self):
+        from rpython.rlib import rfloat
+        for flags in [0, rfloat.DTSF_ADD_DOT_0]:
+            def f(y):
+                return rfloat.formatd(y, 'g', 2, flags)
+
+            assert self.ll_to_string(self.interpret(f, [3.0])) == f(3.0)
+
     def test_formatd_repr(self):
         from rpython.rlib.rfloat import formatd
         def f(x):
diff --git a/rpython/rtyper/test/test_rpbc.py b/rpython/rtyper/test/test_rpbc.py
--- a/rpython/rtyper/test/test_rpbc.py
+++ b/rpython/rtyper/test/test_rpbc.py
@@ -1945,7 +1945,7 @@
 
     def interpret(self, fn, args, **kwds):
         kwds['config'] = self.config
-        return TestRPBC.interpret(self, fn, args, **kwds)
+        return TestRPBC.interpret(fn, args, **kwds)
 
 def test_smallfuncsets_basic():
     from rpython.translator.translator import TranslationContext, graphof
diff --git a/rpython/rtyper/test/tool.py b/rpython/rtyper/test/tool.py
--- a/rpython/rtyper/test/tool.py
+++ b/rpython/rtyper/test/tool.py
@@ -5,22 +5,27 @@
 class BaseRtypingTest(object):
     FLOAT_PRECISION = 8
 
-    def gengraph(self, func, argtypes=[], viewbefore='auto', policy=None,
+    @staticmethod
+    def gengraph(func, argtypes=[], viewbefore='auto', policy=None,
              backendopt=False, config=None):
         return gengraph(func, argtypes, viewbefore, policy,
                         backendopt=backendopt, config=config)
 
-    def interpret(self, fn, args, **kwds):
+    @staticmethod
+    def interpret(fn, args, **kwds):
         return interpret(fn, args, **kwds)
 
-    def interpret_raises(self, exc, fn, args, **kwds):
+    @staticmethod
+    def interpret_raises(exc, fn, args, **kwds):
         return interpret_raises(exc, fn, args, **kwds)
 
-    def float_eq(self, x, y):
+    @staticmethod
+    def float_eq(x, y):
         return x == y
 
-    def float_eq_approx(self, x, y):
-        maxError = 10**-self.FLOAT_PRECISION
+    @classmethod
+    def float_eq_approx(cls, x, y):
+        maxError = 10**-cls.FLOAT_PRECISION
         if abs(x-y) < maxError:
             return True
 
@@ -31,45 +36,66 @@
 
         return relativeError < maxError
 
-    def is_of_type(self, x, type_):
+    @staticmethod
+    def is_of_type(x, type_):
         return type(x) is type_
 
-    def _skip_llinterpreter(self, reason):
+    @staticmethod
+    def _skip_llinterpreter(reason):
         py.test.skip("lltypesystem doesn't support %s, yet" % reason)
 
-    def ll_to_string(self, s):
+    @staticmethod
+    def ll_to_string(s):
         if not s:
             return None
         return ''.join(s.chars)
 
-    def ll_to_unicode(self, s):
+    @staticmethod
+    def ll_to_unicode(s):
         return u''.join(s.chars)
 
-    def string_to_ll(self, s):
-        from rpython.rtyper.module.support import LLSupport
-        return LLSupport.to_rstr(s)
+    @staticmethod
+    def string_to_ll(s):
+        from rpython.rtyper.lltypesystem.rstr import STR, mallocstr
+        if s is None:
+            return lltype.nullptr(STR)
+        p = mallocstr(len(s))
+        for i in range(len(s)):
+            p.chars[i] = s[i]
+        return p
 
-    def unicode_to_ll(self, s):
-        from rpython.rtyper.module.support import LLSupport
-        return LLSupport.to_runicode(s)
+    @staticmethod
+    def unicode_to_ll(s):
+        from rpython.rtyper.lltypesystem.rstr import UNICODE, mallocunicode
+        if s is None:
+            return lltype.nullptr(UNICODE)
+        p = mallocunicode(len(s))
+        for i in range(len(s)):
+            p.chars[i] = s[i]
+        return p
 
-    def ll_to_list(self, l):
+    @staticmethod
+    def ll_to_list(l):
         r = []
         items = l.ll_items()
         for i in range(l.ll_length()):
             r.append(items[i])
         return r
 
-    def ll_unpack_tuple(self, t, length):
+    @staticmethod
+    def ll_unpack_tuple(t, length):
         return tuple([getattr(t, 'item%d' % i) for i in range(length)])
 
-    def get_callable(self, fnptr):
+    @staticmethod
+    def get_callable(fnptr):
         return fnptr._obj._callable
 
-    def class_name(self, value):
+    @staticmethod
+    def class_name(value):
         return ''.join(value.super.typeptr.name.chars)
 
-    def read_attr(self, value, attr_name):
+    @staticmethod
+    def read_attr(value, attr_name):
         value = value._obj
         while value is not None:
             attr = getattr(value, "inst_" + attr_name, None)
@@ -79,6 +105,7 @@
                 return attr
         raise AttributeError()
 
-    def is_of_instance_type(self, val):
+    @staticmethod
+    def is_of_instance_type(val):
         T = lltype.typeOf(val)
         return isinstance(T, lltype.Ptr) and isinstance(T.TO, lltype.GcStruct)


More information about the pypy-commit mailing list