[pypy-commit] pypy missing-ndarray-attributes: merge default

fijal noreply at buildbot.pypy.org
Wed Sep 19 21:09:09 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: missing-ndarray-attributes
Changeset: r57397:a618b4ba3c53
Date: 2012-09-19 17:42 +0200
http://bitbucket.org/pypy/pypy/changeset/a618b4ba3c53/

Log:	merge default

diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -81,7 +81,9 @@
         addr = self._buffer[0]
         if addr == 0:
             raise ValueError("NULL pointer access")
-        return self._type_.from_address(addr)
+        instance = self._type_.from_address(addr)
+        instance.__dict__['_base'] = self
+        return instance
 
     def setcontents(self, value):
         if not isinstance(value, self._type_):
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -590,10 +590,6 @@
                 w_exc = self.getitem(w_dic, w_name)
                 exc_types_w[name] = w_exc
                 setattr(self, "w_" + excname, w_exc)
-        # Make a prebuilt recursion error
-        w_msg = self.wrap("maximum recursion depth exceeded")
-        self.prebuilt_recursion_error = OperationError(self.w_RuntimeError,
-                                                       w_msg)
         return exc_types_w
 
     def install_mixedmodule(self, mixedname, installed_builtin_modules):
@@ -834,7 +830,8 @@
         return isinstance(obj, RequiredClass)
 
     def unpackiterable(self, w_iterable, expected_length=-1):
-        """Unpack an iterable object into a real (interpreter-level) list.
+        """Unpack an iterable into a real (interpreter-level) list.
+
         Raise an OperationError(w_ValueError) if the length is wrong."""
         w_iterator = self.iter(w_iterable)
         if expected_length == -1:
@@ -854,12 +851,10 @@
     def iteriterable(self, w_iterable):
         return W_InterpIterable(self, w_iterable)
 
-    @jit.dont_look_inside
     def _unpackiterable_unknown_length(self, w_iterator, w_iterable):
-        # Unpack a variable-size list of unknown length.
-        # The JIT does not look inside this function because it
-        # contains a loop (made explicit with the decorator above).
-        #
+        """Unpack an iterable of unknown length into an interp-level
+        list.
+        """
         # If we can guess the expected length we can preallocate.
         try:
             lgt_estimate = self.len_w(w_iterable)
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -651,7 +651,8 @@
             raise OperationError(space.w_MemoryError, space.w_None)
         except rstackovf.StackOverflow, e:
             rstackovf.check_stack_overflow()
-            raise space.prebuilt_recursion_error
+            raise OperationError(space.w_RuntimeError,
+                                space.wrap("maximum recursion depth exceeded"))
         except RuntimeError:   # not on top of py.py
             raise OperationError(space.w_RuntimeError, space.w_None)
 
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -104,9 +104,11 @@
             next_instr = self.handle_asynchronous_error(ec,
                 self.space.w_MemoryError)
         except rstackovf.StackOverflow, e:
+            # Note that this case catches AttributeError!
             rstackovf.check_stack_overflow()
-            w_err = self.space.prebuilt_recursion_error
-            next_instr = self.handle_operation_error(ec, w_err)
+            next_instr = self.handle_asynchronous_error(ec,
+                self.space.w_RuntimeError,
+                self.space.wrap("maximum recursion depth exceeded"))
         return next_instr
 
     def handle_asynchronous_error(self, ec, w_type, w_value=None):
@@ -966,6 +968,7 @@
                       isinstance(unroller, SApplicationException))
         if is_app_exc:
             operr = unroller.operr
+            self.last_exception = operr
             w_traceback = self.space.wrap(operr.get_traceback())
             w_suppress = self.call_contextmanager_exit_function(
                 w_exitfunc,
diff --git a/pypy/interpreter/test/test_syntax.py b/pypy/interpreter/test/test_syntax.py
--- a/pypy/interpreter/test/test_syntax.py
+++ b/pypy/interpreter/test/test_syntax.py
@@ -567,6 +567,24 @@
         import types
         assert isinstance(acontextfact.exit_params[2], types.TracebackType)
 
+    def test_with_reraise_exception(self):
+        class Context:
+            def __enter__(self):
+                self.calls = []
+            def __exit__(self, exc_type, exc_value, exc_tb):
+                self.calls.append('exit')
+                raise
+
+        c = Context()
+        try:
+            with c:
+                1 / 0
+        except ZeroDivisionError:
+            pass
+        else:
+            raise AssertionError('Should have reraised initial exception')
+        assert c.calls == ['exit']
+
     def test_with_break(self):
 
         s = """
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -994,6 +994,7 @@
                              ('p', lltype.Ptr(TP)))
         a_box, A = self.alloc_array_of(ITEM, 15)
         s_box, S = self.alloc_instance(TP)
+        vsdescr = self.cpu.interiorfielddescrof(A, 'vs')
         kdescr = self.cpu.interiorfielddescrof(A, 'k')
         pdescr = self.cpu.interiorfielddescrof(A, 'p')
         self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(3),
@@ -1045,6 +1046,13 @@
         r = self.execute_operation(rop.GETINTERIORFIELD_GC, [a_box, BoxInt(3)],
                                    'ref', descr=pdescr)
         assert r.getref_base() == s_box.getref_base()
+        #
+        # test a corner case that used to fail on x86
+        i4 = BoxInt(4)
+        self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, i4, i4],
+                               'void', descr=vsdescr)
+        r = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 4, vsdescr)
+        assert r == 4
 
     def test_string_basic(self):
         s_box = self.alloc_string("hello\xfe")
diff --git a/pypy/jit/backend/test/test_random.py b/pypy/jit/backend/test/test_random.py
--- a/pypy/jit/backend/test/test_random.py
+++ b/pypy/jit/backend/test/test_random.py
@@ -465,6 +465,16 @@
 
 # ____________________________________________________________
 
+def do_assert(condition, error_message):
+    if condition:
+        return
+    seed = pytest.config.option.randomseed
+    message = "%s\nPython: %s\nRandom seed: %r" % (
+        error_message,
+        sys.executable,
+        seed)
+    raise AssertionError(message)
+
 def Random():
     import random
     seed = pytest.config.option.randomseed
@@ -544,6 +554,7 @@
         self.startvars = startvars
         self.prebuilt_ptr_consts = []
         self.r = r
+        self.subloops = []
         self.build_random_loop(cpu, builder_factory, r, startvars, allow_delay)
 
     def build_random_loop(self, cpu, builder_factory, r, startvars, allow_delay):
@@ -668,13 +679,15 @@
 
         arguments = [box.value for box in self.loop.inputargs]
         fail = cpu.execute_token(self.runjitcelltoken(), *arguments)
-        assert fail is self.should_fail_by.getdescr()
+        do_assert(fail is self.should_fail_by.getdescr(),
+                  "Got %r, expected %r" % (fail,
+                                           self.should_fail_by.getdescr()))
         for i, v in enumerate(self.get_fail_args()):
             if isinstance(v, (BoxFloat, ConstFloat)):
                 value = cpu.get_latest_value_float(i)
             else:
                 value = cpu.get_latest_value_int(i)
-            assert value == self.expected[v], (
+            do_assert(value == self.expected[v],
                 "Got %r, expected %r for value #%d" % (value,
                                                        self.expected[v],
                                                        i)
@@ -683,9 +696,11 @@
         if (self.guard_op is not None and
             self.guard_op.is_guard_exception()):
             if self.guard_op.getopnum() == rop.GUARD_NO_EXCEPTION:
-                assert exc
+                do_assert(exc,
+                          "grab_exc_value() should not be %r" % (exc,))
         else:
-            assert not exc
+            do_assert(not exc,
+                      "unexpected grab_exc_value(): %r" % (exc,))
 
     def build_bridge(self):
         def exc_handling(guard_op):
@@ -710,6 +725,7 @@
             return False
         # generate the branch: a sequence of operations that ends in a FINISH
         subloop = DummyLoop([])
+        self.subloops.append(subloop)   # keep around for debugging
         if guard_op.is_guard_exception():
             subloop.operations.append(exc_handling(guard_op))
         bridge_builder = self.builder.fork(self.builder.cpu, subloop,
@@ -746,9 +762,6 @@
             args = [x.clonebox() for x in subset]
             rl = RandomLoop(self.builder.cpu, self.builder.fork,
                                      r, args)
-            dump(rl.loop)
-            self.cpu.compile_loop(rl.loop.inputargs, rl.loop.operations,
-                                  rl.loop._jitcelltoken)
             # done
             self.should_fail_by = rl.should_fail_by
             self.expected = rl.expected
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -1003,14 +1003,18 @@
         # If 'index_loc' is not an immediate, then we need a 'temp_loc' that
         # is a register whose value will be destroyed.  It's fine to destroy
         # the same register as 'index_loc', but not the other ones.
-        self.rm.possibly_free_var(box_index)
         if not isinstance(index_loc, ImmedLoc):
+            # ...that is, except in a corner case where 'index_loc' would be
+            # in the same register as 'value_loc'...
+            if index_loc is not value_loc:
+                self.rm.possibly_free_var(box_index)
             tempvar = TempBox()
             temp_loc = self.rm.force_allocate_reg(tempvar, [box_base,
                                                             box_value])
             self.rm.possibly_free_var(tempvar)
         else:
             temp_loc = None
+        self.rm.possibly_free_var(box_index)
         self.rm.possibly_free_var(box_base)
         self.possibly_free_var(box_value)
         self.PerformDiscard(op, [base_loc, ofs, itemsize, fieldsize,
diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py
--- a/pypy/jit/backend/x86/rx86.py
+++ b/pypy/jit/backend/x86/rx86.py
@@ -576,7 +576,7 @@
     J_il8 = insn(immediate(1, 'o'), '\x70', immediate(2, 'b'))
     J_il = insn('\x0F', immediate(1,'o'), '\x80', relative(2))
 
-    SET_ir = insn(rex_w, '\x0F', immediate(1,'o'),'\x90', byte_register(2), '\xC0')
+    SET_ir = insn(rex_fw, '\x0F', immediate(1,'o'),'\x90', byte_register(2), '\xC0')
 
     # The 64-bit version of this, CQO, is defined in X86_64_CodeBuilder
     CDQ = insn(rex_nw, '\x99')
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -27,7 +27,8 @@
         'alignof': 'func.alignof',
         'sizeof': 'func.sizeof',
         'typeof': 'func.typeof',
-        'offsetof': 'func.offsetof',
+        'typeoffsetof': 'func.typeoffsetof',
+        'rawaddressof': 'func.rawaddressof',
         '_getfields': 'func._getfields',
         'getcname': 'func.getcname',
         '_get_types': 'func._get_types',
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -134,14 +134,22 @@
                               "ctype '%s' is of unknown alignment",
                               self.name)
 
-    def offsetof(self, fieldname):
+    def typeoffsetof(self, fieldname):
         space = self.space
-        raise OperationError(space.w_TypeError,
-                             space.wrap("not a struct or union ctype"))
+        if fieldname is None:
+            msg = "expected a struct or union ctype"
+        else:
+            msg = "expected a struct or union ctype, or a pointer to one"
+        raise OperationError(space.w_TypeError, space.wrap(msg))
 
     def _getfields(self):
         return None
 
+    def rawaddressof(self, cdata, offset):
+        space = self.space
+        raise OperationError(space.w_TypeError,
+                             space.wrap("expected a pointer ctype"))
+
     def call(self, funcaddr, args_w):
         space = self.space
         raise operationerrfmt(space.w_TypeError,
diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -52,19 +52,25 @@
         if (isinstance(ob, cdataobj.W_CData) and
                isinstance(ob.ctype, ctypeptr.W_CTypePtrOrArray)):
             value = rffi.cast(lltype.Signed, ob._cdata)
-            value = r_ulonglong(value)
+            value = self._cast_result(value)
         elif space.isinstance_w(w_ob, space.w_str):
             value = self.cast_str(w_ob)
-            value = r_ulonglong(value)
+            value = self._cast_result(value)
         elif space.isinstance_w(w_ob, space.w_unicode):
             value = self.cast_unicode(w_ob)
-            value = r_ulonglong(value)
+            value = self._cast_result(value)
         else:
-            value = misc.as_unsigned_long_long(space, w_ob, strict=False)
+            value = self._cast_generic(w_ob)
         w_cdata = cdataobj.W_CDataMem(space, self.size, self)
         w_cdata.write_raw_integer_data(value)
         return w_cdata
 
+    def _cast_result(self, intvalue):
+        return r_ulonglong(intvalue)
+
+    def _cast_generic(self, w_ob):
+        return misc.as_unsigned_long_long(self.space, w_ob, strict=False)
+
     def _overflow(self, w_ob):
         space = self.space
         s = space.str_w(space.str(w_ob))
@@ -163,13 +169,9 @@
             self.vrangemax = (r_ulonglong(1) << sh) - 1
 
     def int(self, cdata):
-        if self.value_fits_long:
-            # this case is to handle enums, but also serves as a slight
-            # performance improvement for some other primitive types
-            value = misc.read_raw_long_data(cdata, self.size)
-            return self.space.wrap(value)
-        else:
-            return self.convert_to_object(cdata)
+        # enums: really call convert_to_object() just below,
+        # and not the one overridden in W_CTypeEnum.
+        return W_CTypePrimitiveSigned.convert_to_object(self, cdata)
 
     def convert_to_object(self, cdata):
         if self.value_fits_long:
@@ -203,8 +205,11 @@
         W_CTypePrimitive.__init__(self, *args)
         self.value_fits_long = self.size < rffi.sizeof(lltype.Signed)
         if self.size < rffi.sizeof(lltype.SignedLongLong):
-            sh = self.size * 8
-            self.vrangemax = (r_ulonglong(1) << sh) - 1
+            self.vrangemax = self._compute_vrange_max()
+
+    def _compute_vrange_max(self):
+        sh = self.size * 8
+        return (r_ulonglong(1) << sh) - 1
 
     def int(self, cdata):
         return self.convert_to_object(cdata)
@@ -231,6 +236,23 @@
         return self
 
 
+class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned):
+    _attrs_ = []
+
+    def _compute_vrange_max(self):
+        return r_ulonglong(1)
+
+    def _cast_result(self, intvalue):
+        return r_ulonglong(intvalue != 0)
+
+    def _cast_generic(self, w_ob):
+        return misc.object_as_bool(self.space, w_ob)
+
+    def string(self, cdataobj, maxlen):
+        # bypass the method 'string' implemented in W_CTypePrimitive
+        return W_CType.string(self, cdataobj, maxlen)
+
+
 class W_CTypePrimitiveFloat(W_CTypePrimitive):
     _attrs_ = []
 
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -274,18 +274,26 @@
             return True
         else:
             set_mustfree_flag(cdata, False)
-            try:
-                self.convert_from_object(cdata, w_ob)
-            except OperationError:
-                if (self.is_struct_ptr and isinstance(ob, cdataobj.W_CData)
-                    and ob.ctype is self.ctitem):
-                    # special case to make the life of verifier.py easier:
-                    # if the formal argument type is 'struct foo *' but
-                    # we pass a 'struct foo', then get a pointer to it
-                    rffi.cast(rffi.CCHARPP, cdata)[0] = ob._cdata
-                else:
-                    raise
+            self.convert_from_object(cdata, w_ob)
             return False
 
     def getcfield(self, attr):
         return self.ctitem.getcfield(attr)
+
+    def typeoffsetof(self, fieldname):
+        if fieldname is None:
+            return W_CTypePtrBase.typeoffsetof(self, fieldname)
+        else:
+            return self.ctitem.typeoffsetof(fieldname)
+
+    def rawaddressof(self, cdata, offset):
+        from pypy.module._cffi_backend.ctypestruct import W_CTypeStructOrUnion
+        space = self.space
+        ctype2 = cdata.ctype
+        if (isinstance(ctype2, W_CTypeStructOrUnion) or
+            (isinstance(ctype2, W_CTypePtrOrArray) and ctype2.is_struct_ptr)):
+            ptrdata = rffi.ptradd(cdata._cdata, offset)
+            return cdataobj.W_CData(space, ptrdata, self)
+        else:
+            raise OperationError(space.w_TypeError,
+                     space.wrap("expected a 'cdata struct-or-union' object"))
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -61,14 +61,19 @@
         keepalive_until_here(ob)
         return ob
 
-    def offsetof(self, fieldname):
+    def typeoffsetof(self, fieldname):
+        if fieldname is None:
+            return (self, 0)
         self.check_complete()
+        space = self.space
         try:
             cfield = self.fields_dict[fieldname]
         except KeyError:
-            space = self.space
             raise OperationError(space.w_KeyError, space.wrap(fieldname))
-        return cfield.offset
+        if cfield.bitshift >= 0:
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("not supported for bitfields"))
+        return (cfield.ctype, cfield.offset)
 
     def _copy_from_same(self, cdata, w_ob):
         space = self.space
diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -53,15 +53,19 @@
     align = ctype.alignof()
     return space.wrap(align)
 
- at unwrap_spec(ctype=ctypeobj.W_CType, fieldname=str)
-def offsetof(space, ctype, fieldname):
-    ofs = ctype.offsetof(fieldname)
-    return space.wrap(ofs)
+ at unwrap_spec(ctype=ctypeobj.W_CType, fieldname="str_or_None")
+def typeoffsetof(space, ctype, fieldname):
+    ctype, offset = ctype.typeoffsetof(fieldname)
+    return space.newtuple([space.wrap(ctype), space.wrap(offset)])
 
 @unwrap_spec(ctype=ctypeobj.W_CType)
 def _getfields(space, ctype):
     return ctype._getfields()
 
+ at unwrap_spec(ctype=ctypeobj.W_CType, cdata=cdataobj.W_CData, offset=int)
+def rawaddressof(space, ctype, cdata, offset=0):
+    return ctype.rawaddressof(cdata, offset)
+
 # ____________________________________________________________
 
 @unwrap_spec(ctype=ctypeobj.W_CType, replace_with=str)
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -3,7 +3,9 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rlib.rarithmetic import r_ulonglong
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib import jit
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
 # ____________________________________________________________
 
@@ -121,6 +123,14 @@
 
 # ____________________________________________________________
 
+def _is_a_float(space, w_ob):
+    from pypy.module._cffi_backend.cdataobj import W_CData
+    from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveFloat
+    ob = space.interpclass_w(w_ob)
+    if isinstance(ob, W_CData):
+        return isinstance(ob.ctype, W_CTypePrimitiveFloat)
+    return space.isinstance_w(w_ob, space.w_float)
+
 def as_long_long(space, w_ob):
     # (possibly) convert and cast a Python object to a long long.
     # This version accepts a Python int too, and does convertions from
@@ -132,7 +142,7 @@
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
-        if space.isinstance_w(w_ob, space.w_float):
+        if _is_a_float(space, w_ob):
             raise
         bigint = space.bigint_w(space.int(w_ob))
     try:
@@ -155,7 +165,7 @@
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
-        if strict and space.isinstance_w(w_ob, space.w_float):
+        if strict and _is_a_float(space, w_ob):
             raise
         bigint = space.bigint_w(space.int(w_ob))
     if strict:
@@ -173,6 +183,61 @@
 
 # ____________________________________________________________
 
+class _NotStandardObject(Exception):
+    pass
+
+def _standard_object_as_bool(space, w_ob):
+    if space.isinstance_w(w_ob, space.w_int):
+        return space.int_w(w_ob) != 0
+    if space.isinstance_w(w_ob, space.w_long):
+        return space.bigint_w(w_ob).tobool()
+    if space.isinstance_w(w_ob, space.w_float):
+        return space.float_w(w_ob) != 0.0
+    raise _NotStandardObject
+
+# hackish, but the most straightforward way to know if a LONGDOUBLE object
+# contains the value 0 or not.
+eci = ExternalCompilationInfo(post_include_bits=["""
+#define pypy__is_nonnull_longdouble(x)  ((x) != 0.0)
+"""])
+is_nonnull_longdouble = rffi.llexternal(
+    "pypy__is_nonnull_longdouble", [rffi.LONGDOUBLE], lltype.Bool,
+    compilation_info=eci, _nowrapper=True, elidable_function=True,
+    sandboxsafe=True)
+
+def object_as_bool(space, w_ob):
+    # convert and cast a Python object to a boolean.  Accept an integer
+    # or a float object, up to a CData 'long double'.
+    try:
+        return _standard_object_as_bool(space, w_ob)
+    except _NotStandardObject:
+        pass
+    #
+    from pypy.module._cffi_backend.cdataobj import W_CData
+    from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveFloat
+    from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveLongDouble
+    ob = space.interpclass_w(w_ob)
+    is_cdata = isinstance(ob, W_CData)
+    if is_cdata and isinstance(ob.ctype, W_CTypePrimitiveFloat):
+        if isinstance(ob.ctype, W_CTypePrimitiveLongDouble):
+            result = is_nonnull_longdouble(read_raw_longdouble_data(ob._cdata))
+        else:
+            result = read_raw_float_data(ob._cdata, ob.ctype.size) != 0.0
+        keepalive_until_here(ob)
+        return result
+    #
+    if not is_cdata and space.lookup(w_ob, '__float__') is not None:
+        w_io = space.float(w_ob)
+    else:
+        w_io = space.int(w_ob)
+    try:
+        return _standard_object_as_bool(space, w_io)
+    except _NotStandardObject:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("integer/float expected"))
+
+# ____________________________________________________________
+
 def _raw_memcopy(source, dest, size):
     if jit.isconstant(size):
         # for the JIT: first handle the case where 'size' is known to be
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -38,6 +38,7 @@
 eptype("float",  rffi.FLOAT,  ctypeprim.W_CTypePrimitiveFloat)
 eptype("double", rffi.DOUBLE, ctypeprim.W_CTypePrimitiveFloat)
 eptype("long double", rffi.LONGDOUBLE, ctypeprim.W_CTypePrimitiveLongDouble)
+eptype("_Bool",  lltype.Bool,          ctypeprim.W_CTypePrimitiveBool)
 
 @unwrap_spec(name=str)
 def new_primitive_type(space, name):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -741,6 +741,8 @@
     assert repr(s.a1).startswith("<cdata 'int[5]' 0x")
 
 def test_offsetof():
+    def offsetof(BType, fieldname):
+        return typeoffsetof(BType, fieldname)[1]
     BInt = new_primitive_type("int")
     BStruct = new_struct_type("foo")
     py.test.raises(TypeError, offsetof, BInt, "abc")
@@ -749,6 +751,7 @@
     assert offsetof(BStruct, 'abc') == 0
     assert offsetof(BStruct, 'def') == size_of_int()
     py.test.raises(KeyError, offsetof, BStruct, "ghi")
+    assert offsetof(new_pointer_type(BStruct), "def") == size_of_int()
 
 def test_function_type():
     BInt = new_primitive_type("int")
@@ -888,11 +891,8 @@
     BFunc20 = new_function_type((BStructPtr,), BShort, False)
     f = cast(BFunc20, _testfunc(20))
     x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
-    # test the exception that allows us to pass a 'struct foo' where the
-    # function really expects a 'struct foo *'.
-    res = f(x[0])
-    assert res == -4042 + ord(b'A')
-    assert res == f(x)
+    # can't pass a 'struct foo'
+    py.test.raises(TypeError, f, x[0])
 
 def test_call_function_21():
     BInt = new_primitive_type("int")
@@ -2076,3 +2076,88 @@
     assert not isinstance(nullchr, CType)
     assert not isinstance(chrref, CType)
     assert isinstance(BChar, CType)
+
+def test_no_cdata_float():
+    BInt = new_primitive_type("int")
+    BIntP = new_pointer_type(BInt)
+    BUInt = new_primitive_type("unsigned int")
+    BUIntP = new_pointer_type(BUInt)
+    BFloat = new_primitive_type("float")
+    py.test.raises(TypeError, newp, BIntP, cast(BFloat, 0.0))
+    py.test.raises(TypeError, newp, BUIntP, cast(BFloat, 0.0))
+
+def test_bool():
+    BBool = new_primitive_type("_Bool")
+    BBoolP = new_pointer_type(BBool)
+    assert int(cast(BBool, False)) == 0
+    assert int(cast(BBool, True)) == 1
+    assert bool(cast(BBool, False)) is True    # warning!
+    assert int(cast(BBool, 3)) == 1
+    assert int(cast(BBool, long(3))) == 1
+    assert int(cast(BBool, long(10)**4000)) == 1
+    assert int(cast(BBool, -0.1)) == 1
+    assert int(cast(BBool, -0.0)) == 0
+    assert int(cast(BBool, '\x00')) == 0
+    assert int(cast(BBool, '\xff')) == 1
+    assert newp(BBoolP, False)[0] == 0
+    assert newp(BBoolP, True)[0] == 1
+    assert newp(BBoolP, 0)[0] == 0
+    assert newp(BBoolP, 1)[0] == 1
+    py.test.raises(TypeError, newp, BBoolP, 1.0)
+    py.test.raises(TypeError, newp, BBoolP, '\x00')
+    py.test.raises(OverflowError, newp, BBoolP, 2)
+    py.test.raises(OverflowError, newp, BBoolP, -1)
+    BCharP = new_pointer_type(new_primitive_type("char"))
+    p = newp(BCharP, 'X')
+    q = cast(BBoolP, p)
+    assert q[0] == ord('X')
+    py.test.raises(TypeError, string, cast(BBool, False))
+    BDouble = new_primitive_type("double")
+    assert int(cast(BBool, cast(BDouble, 0.1))) == 1
+    assert int(cast(BBool, cast(BDouble, 0.0))) == 0
+
+def test_typeoffsetof():
+    BChar = new_primitive_type("char")
+    BStruct = new_struct_type("foo")
+    BStructPtr = new_pointer_type(BStruct)
+    complete_struct_or_union(BStruct, [('a1', BChar, -1),
+                                       ('a2', BChar, -1),
+                                       ('a3', BChar, -1)])
+    py.test.raises(TypeError, typeoffsetof, BStructPtr, None)
+    assert typeoffsetof(BStruct, None) == (BStruct, 0)
+    assert typeoffsetof(BStructPtr, 'a1') == (BChar, 0)
+    assert typeoffsetof(BStruct, 'a1') == (BChar, 0)
+    assert typeoffsetof(BStructPtr, 'a2') == (BChar, 1)
+    assert typeoffsetof(BStruct, 'a3') == (BChar, 2)
+    py.test.raises(KeyError, typeoffsetof, BStructPtr, 'a4')
+    py.test.raises(KeyError, typeoffsetof, BStruct, 'a5')
+
+def test_typeoffsetof_no_bitfield():
+    BInt = new_primitive_type("int")
+    BStruct = new_struct_type("foo")
+    complete_struct_or_union(BStruct, [('a1', BInt, 4)])
+    py.test.raises(TypeError, typeoffsetof, BStruct, 'a1')
+
+def test_rawaddressof():
+    BChar = new_primitive_type("char")
+    BCharP = new_pointer_type(BChar)
+    BStruct = new_struct_type("foo")
+    BStructPtr = new_pointer_type(BStruct)
+    complete_struct_or_union(BStruct, [('a1', BChar, -1),
+                                       ('a2', BChar, -1),
+                                       ('a3', BChar, -1)])
+    p = newp(BStructPtr)
+    assert repr(p) == "<cdata 'struct foo *' owning 3 bytes>"
+    s = p[0]
+    assert repr(s) == "<cdata 'struct foo' owning 3 bytes>"
+    a = rawaddressof(BStructPtr, s)
+    assert repr(a).startswith("<cdata 'struct foo *' 0x")
+    py.test.raises(TypeError, rawaddressof, BStruct, s)
+    b = rawaddressof(BCharP, s)
+    assert b == cast(BCharP, p)
+    c = rawaddressof(BStructPtr, a)
+    assert c == a
+    py.test.raises(TypeError, rawaddressof, BStructPtr, cast(BChar, '?'))
+    #
+    d = rawaddressof(BCharP, s, 1)
+    assert d == cast(BCharP, p) + 1
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
@@ -636,9 +636,12 @@
         globals()['va_get_%s' % name_no_star] = func
 
 def setup_init_functions(eci):
-    init_buffer = rffi.llexternal('init_bufferobject', [], lltype.Void, compilation_info=eci)
-    init_pycobject = rffi.llexternal('init_pycobject', [], lltype.Void, compilation_info=eci)
-    init_capsule = rffi.llexternal('init_capsule', [], lltype.Void, compilation_info=eci)
+    init_buffer = rffi.llexternal('init_bufferobject', [], lltype.Void,
+                                  compilation_info=eci, _nowrapper=True)
+    init_pycobject = rffi.llexternal('init_pycobject', [], lltype.Void,
+                                     compilation_info=eci, _nowrapper=True)
+    init_capsule = rffi.llexternal('init_capsule', [], lltype.Void,
+                                   compilation_info=eci, _nowrapper=True)
     INIT_FUNCTIONS.extend([
         lambda space: init_buffer(),
         lambda space: init_pycobject(),
diff --git a/pypy/module/cpyext/pystate.py b/pypy/module/cpyext/pystate.py
--- a/pypy/module/cpyext/pystate.py
+++ b/pypy/module/cpyext/pystate.py
@@ -23,10 +23,10 @@
     the current thread must have acquired it.  (This function is available even
     when thread support is disabled at compile time.)"""
     state = space.fromcache(InterpreterState)
+    tstate = state.swap_thread_state(
+        space, lltype.nullptr(PyThreadState.TO))
     if rffi.aroundstate.before:
         rffi.aroundstate.before()
-    tstate = state.swap_thread_state(
-        space, lltype.nullptr(PyThreadState.TO))
     return tstate
 
 @cpython_api([PyThreadState], lltype.Void)
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -1,21 +1,9 @@
 from pypy.interpreter.mixedmodule import MixedModule
 
 
-class PyPyModule(MixedModule):
-    interpleveldefs = {
-        'debug_repr': 'interp_extras.debug_repr',
-        'remove_invalidates': 'interp_extras.remove_invalidates',
-        'set_invalidation': 'interp_extras.set_invalidation',
-    }
-    appleveldefs = {}
-
 class Module(MixedModule):
     applevel_name = '_numpypy'
 
-    submodules = {
-        'pypy': PyPyModule
-    }
-
     interpleveldefs = {
         'ndarray': 'interp_numarray.W_NDimArray',
         'dtype': 'interp_dtype.W_Dtype',
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -1,7 +1,8 @@
 
 from pypy.module.micronumpy.arrayimpl import base
 from pypy.module.micronumpy import support, loop
-from pypy.module.micronumpy.base import convert_to_array, W_NDimArray
+from pypy.module.micronumpy.base import convert_to_array, W_NDimArray,\
+     ArrayArgumentException
 from pypy.module.micronumpy.strides import calc_new_strides, shape_agreement,\
      calculate_broadcast_strides, calculate_dot_strides
 from pypy.module.micronumpy.iter import Chunk, Chunks, NewAxisChunk, RecordChunk
@@ -223,6 +224,26 @@
             item += idx * self.strides[i]
         return item
 
+    @jit.unroll_safe
+    def _lookup_by_unwrapped_index(self, space, lst):
+        item = self.start
+        assert len(lst) == len(self.shape)
+        for i, idx in enumerate(lst):
+            if idx < 0:
+                idx = self.shape[i] + idx
+            if idx < 0 or idx >= self.shape[i]:
+                raise operationerrfmt(space.w_IndexError,
+                      "index (%d) out of range (0<=index<%d", i, self.shape[i],
+                )
+            item += idx * self.strides[i]
+        return item
+
+    def getitem_index(self, space, index):
+        return self.getitem(self._lookup_by_unwrapped_index(space, index))
+
+    def setitem_index(self, space, index, value):
+        self.setitem(self._lookup_by_unwrapped_index(space, index), value)
+
     def _single_item_index(self, space, w_idx):
         """ Return an index of single item if possible, otherwise raises
         IndexError
@@ -231,10 +252,16 @@
             space.isinstance_w(w_idx, space.w_slice) or
             space.is_w(w_idx, space.w_None)):
             raise IndexError
+        if isinstance(w_idx, W_NDimArray):
+            raise ArrayArgumentException
         shape_len = len(self.shape)
         if shape_len == 0:
             raise OperationError(space.w_IndexError, space.wrap(
                 "0-d arrays can't be indexed"))
+        view_w = None
+        if (space.isinstance_w(w_idx, space.w_list) or
+            isinstance(w_idx, W_NDimArray)):
+            raise ArrayArgumentException
         if space.isinstance_w(w_idx, space.w_tuple):
             view_w = space.fixedview(w_idx)
             if len(view_w) < shape_len:
@@ -249,6 +276,11 @@
                     raise IndexError # but it's still not a single item
                 raise OperationError(space.w_IndexError,
                                      space.wrap("invalid index"))
+            # check for arrays
+            for w_item in view_w:
+                if (isinstance(w_item, W_NDimArray) or
+                    space.isinstance_w(w_item, space.w_list)):
+                    raise ArrayArgumentException
             return self._lookup_by_index(space, view_w)
         if shape_len > 1:
             raise IndexError
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -58,10 +58,17 @@
         raise OperationError(space.w_IndexError,
                              space.wrap("scalars cannot be indexed"))
 
+    def getitem_index(self, space, idx):
+        raise OperationError(space.w_IndexError,
+                             space.wrap("scalars cannot be indexed"))
+
     def descr_setitem(self, space, w_idx, w_val):
         raise OperationError(space.w_IndexError,
                              space.wrap("scalars cannot be indexed"))
         
+    def setitem_index(self, space, idx, w_val):
+        raise OperationError(space.w_IndexError,
+                             space.wrap("scalars cannot be indexed"))
     def set_shape(self, space, new_shape):
         if not new_shape:
             return self
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -3,6 +3,9 @@
 from pypy.tool.pairtype import extendabletype
 from pypy.module.micronumpy.support import calc_strides
 
+class ArrayArgumentException(Exception):
+    pass
+
 class W_NDimArray(Wrappable):
     __metaclass__ = extendabletype
 
diff --git a/pypy/module/micronumpy/interp_extras.py b/pypy/module/micronumpy/interp_extras.py
deleted file mode 100644
--- a/pypy/module/micronumpy/interp_extras.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_numarray import BaseArray, get_numarray_cache
-
-
- at unwrap_spec(array=BaseArray)
-def debug_repr(space, array):
-    return space.wrap(array.find_sig().debug_repr())
-
- at unwrap_spec(array=BaseArray)
-def remove_invalidates(space, array):
-    """ Array modification will no longer invalidate any of it's
-    potential children. Use only for performance debugging
-    """
-    del array.invalidates[:]
-    return space.w_None
-
- at unwrap_spec(arg=bool)
-def set_invalidation(space, arg):
-    get_numarray_cache(space).enable_invalidation = arg
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
@@ -2,10 +2,11 @@
 from pypy.interpreter.error import operationerrfmt, OperationError
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.module.micronumpy.base import W_NDimArray, convert_to_array
+from pypy.module.micronumpy.base import W_NDimArray, convert_to_array,\
+     ArrayArgumentException
 from pypy.module.micronumpy import interp_dtype, interp_ufuncs, interp_boxes
 from pypy.module.micronumpy.strides import find_shape_and_elems,\
-     get_shape_from_iterable, to_coords
+     get_shape_from_iterable, to_coords, shape_agreement
 from pypy.module.micronumpy.interp_flatiter import W_FlatIterator
 from pypy.module.micronumpy.interp_support import unwrap_axis_arg
 from pypy.module.micronumpy.appbridge import get_appbridge_cache
@@ -63,30 +64,101 @@
 
     def getitem_filter(self, space, arr):
         if arr.get_size() > self.get_size():
-            raise OperationError(space.w_IndexError,
+            raise OperationError(space.w_ValueError,
                                  space.wrap("index out of range for array"))
         size = loop.count_all_true(arr)
         res = W_NDimArray.from_shape([size], self.get_dtype())
         return loop.getitem_filter(res, self, arr)
 
     def setitem_filter(self, space, idx, val):
+        if idx.get_size() > self.get_size():
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("index out of range for array"))
         loop.setitem_filter(self, idx, val)
 
+    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]
+        w_lst = space.listview(w_index)
+        for w_item in w_lst:
+            if not space.isinstance_w(w_item, space.w_int):
+                break
+        else:
+            arr = convert_to_array(space, w_index)
+            return [], arr.get_shape(), arr.get_shape(), [arr]
+        shape = None
+        indexes_w = [None] * len(w_lst)
+        res_shape = []
+        arr_index_in_shape = False
+        prefix = []
+        for i, w_item in enumerate(w_lst):
+            if (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:
+                    shape = w_item.get_shape()
+                else:
+                    shape = shape_agreement(space, shape, w_item)
+                indexes_w[i] = w_item
+                if not arr_index_in_shape:
+                    res_shape.append(-1)
+                    arr_index_in_shape = True
+            else:
+                if space.isinstance_w(w_item, space.w_slice):
+                    _, _, _, lgt = space.decode_index4(w_item, self.get_shape()[i])
+                    if not arr_index_in_shape:
+                        prefix.append(w_item)
+                    res_shape.append(lgt)
+                indexes_w[i] = w_item
+        real_shape = []
+        for i in res_shape:
+            if i == -1:
+                real_shape += shape
+            else:
+                real_shape.append(i)
+        return prefix, real_shape[:], shape, indexes_w
+
+    def getitem_array_int(self, space, w_index):
+        prefix, res_shape, iter_shape, indexes = \
+                self._prepare_array_index(space, w_index)
+        shape = res_shape + self.get_shape()[len(indexes):]
+        res = W_NDimArray.from_shape(shape, self.get_dtype(), self.get_order())
+        return loop.getitem_array_int(space, self, res, iter_shape, indexes,
+                                      prefix)
+
+    def setitem_array_int(self, space, w_index, w_value):
+        val_arr = convert_to_array(space, w_value)
+        prefix, _, iter_shape, indexes = \
+                self._prepare_array_index(space, w_index)
+        return loop.setitem_array_int(space, self, iter_shape, indexes, val_arr,
+                                      prefix)
+
     def descr_getitem(self, space, w_idx):
-        if (isinstance(w_idx, W_NDimArray) and w_idx.get_shape() == self.get_shape() and
+        if (isinstance(w_idx, W_NDimArray) and
             w_idx.get_dtype().is_bool_type()):
             return self.getitem_filter(space, w_idx)
         try:
             return self.implementation.descr_getitem(space, w_idx)
+        except ArrayArgumentException:
+            return self.getitem_array_int(space, w_idx)
         except OperationError:
             raise OperationError(space.w_IndexError, space.wrap("wrong index"))
 
+    def getitem(self, space, index_list):
+        return self.implementation.getitem_index(space, index_list)
+
+    def setitem(self, space, index_list, w_value):
+        self.implementation.setitem_index(space, index_list, w_value)
+
     def descr_setitem(self, space, w_idx, w_value):
-        if (isinstance(w_idx, W_NDimArray) and w_idx.get_shape() == self.get_shape() and
+        if (isinstance(w_idx, W_NDimArray) and
             w_idx.get_dtype().is_bool_type()):
             return self.setitem_filter(space, w_idx,
                                        convert_to_array(space, w_value))
-        self.implementation.descr_setitem(space, w_idx, w_value)
+        try:
+            self.implementation.descr_setitem(space, w_idx, w_value)
+        except ArrayArgumentException:
+            self.setitem_array_int(space, w_idx, w_value)
 
     def descr_len(self, space):
         shape = self.get_shape()
@@ -265,9 +337,8 @@
             if self.is_scalar():
                 return self.get_scalar_value().item(space)
             if self.get_size() == 1:
-                w_obj = self.descr_getitem(space,
-                                           space.newtuple([space.wrap(0) for i
-                                      in range(len(self.get_shape()))]))
+                w_obj = self.getitem(space,
+                                     [0] * len(self.get_shape()))
                 assert isinstance(w_obj, interp_boxes.W_GenericBox)
                 return w_obj.item(space)
             raise OperationError(space.w_IndexError,
@@ -277,8 +348,7 @@
                 raise OperationError(space.w_IndexError,
                                      space.wrap("index out of bounds"))
             i = self.to_coords(space, w_arg)
-            item = self.descr_getitem(space, space.newtuple([space.wrap(x)
-                                             for x in i]))
+            item = self.getitem(space, i)
             assert isinstance(item, interp_boxes.W_GenericBox)
             return item.item(space)
         raise OperationError(space.w_NotImplementedError, space.wrap(
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -4,9 +4,10 @@
 """
 
 from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rstring import StringBuilder
+from pypy.rlib import jit
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.module.micronumpy.base import W_NDimArray
-from pypy.rlib.rstring import StringBuilder
-from pypy.rpython.lltypesystem import lltype, rffi
 
 def call2(shape, func, name, calc_dtype, res_dtype, w_lhs, w_rhs, out):
     if out is None:
@@ -244,3 +245,67 @@
             builder.append(res_str_casted[i])
         iter.next()
     return builder.build()
+
+class PureShapeIterator(object):
+    def __init__(self, shape, idx_w):
+        self.shape = shape
+        self.shapelen = len(shape)
+        self.indexes = [0] * len(shape)
+        self._done = False
+        self.idx_w = [None] * len(idx_w)
+        for i, w_idx in enumerate(idx_w):
+            if isinstance(w_idx, W_NDimArray):
+                self.idx_w[i] = w_idx.create_iter(shape)
+
+    def done(self):
+        return self._done
+
+    @jit.unroll_safe
+    def next(self):
+        for w_idx in self.idx_w:
+            if w_idx is not None:
+                w_idx.next()
+        for i in range(self.shapelen - 1, -1, -1):
+            if self.indexes[i] < self.shape[i] - 1:
+                self.indexes[i] += 1
+                break
+            else:
+                self.indexes[i] = 0
+        else:
+            self._done = True
+
+    def get_index(self, space):
+        return [space.wrap(i) for i in self.indexes]
+
+def getitem_array_int(space, arr, res, iter_shape, indexes_w, prefix_w):
+    iter = PureShapeIterator(iter_shape, indexes_w)
+    while not iter.done():
+        # prepare the index
+        index_w = [None] * len(indexes_w)
+        for i in range(len(indexes_w)):
+            if iter.idx_w[i] is not None:
+                index_w[i] = iter.idx_w[i].getitem()
+            else:
+                index_w[i] = indexes_w[i]
+        res.descr_setitem(space, space.newtuple(prefix_w +
+                                                iter.get_index(space)),
+                          arr.descr_getitem(space, space.newtuple(index_w)))
+        iter.next()
+    return res
+
+def setitem_array_int(space, arr, iter_shape, indexes_w, val_arr,
+                      prefix_w):
+    iter = PureShapeIterator(iter_shape, indexes_w)
+    while not iter.done():
+        # prepare the index
+        index_w = [None] * len(indexes_w)
+        for i in range(len(indexes_w)):
+            if iter.idx_w[i] is not None:
+                index_w[i] = iter.idx_w[i].getitem()
+            else:
+                index_w[i] = indexes_w[i]
+        w_idx = space.newtuple(prefix_w + iter.get_index(space))
+        arr.descr_setitem(space, space.newtuple(index_w),
+                          val_arr.descr_getitem(space, w_idx))
+        iter.next()
+
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
@@ -1517,7 +1517,38 @@
         a = array([1.0,-1.0])
         a[a<0] = -a[a<0]
         assert (a == [1, 1]).all()
-                        
+
+    def test_int_array_index(self):
+        from numpypy import array, arange
+        b = arange(10)[array([3, 2, 1, 5])]
+        assert (b == [3, 2, 1, 5]).all()
+        raises(IndexError, "arange(10)[array([10])]")
+        assert (arange(10)[[-5, -3]] == [5, 7]).all()
+        raises(IndexError, "arange(10)[[-11]]")
+
+    def test_int_array_index_setitem(self):
+        from numpypy import array, arange, zeros
+        a = arange(10)
+        a[[3, 2, 1, 5]] = zeros(4, dtype=int)
+        assert (a == [0, 0, 0, 0, 4, 0, 6, 7, 8, 9]).all()
+        a[[-9, -8]] = [1, 1]
+        assert (a == [0, 1, 1, 0, 4, 0, 6, 7, 8, 9]).all()
+        raises(IndexError, "arange(10)[array([10])] = 3")
+        raises(IndexError, "arange(10)[[-11]] = 3")
+
+    def test_bool_array_index(self):
+        from numpypy import arange, array
+        b = arange(10)
+        assert (b[array([True, False, True])] == [0, 2]).all()
+        raises(ValueError, "array([1, 2])[array([True, True, True])]")
+
+    def test_bool_array_index_setitem(self):
+        from numpypy import arange, array
+        b = arange(5)
+        b[array([True, False, True])] = [20, 21]
+        assert (b == [20, 1, 21, 3, 4]).all() 
+        raises(ValueError, "array([1, 2])[array([True, False, True])] = [1, 2, 3]")
+
 class AppTestMultiDim(BaseNumpyAppTest):
     def test_init(self):
         import _numpypy
@@ -1943,7 +1974,7 @@
         assert (a.compress([1, 0, 13.5]) == [0, 2]).all()
         a = arange(10).reshape(2, 5)
         assert (a.compress([True, False, True]) == [0, 2]).all()
-        raises(IndexError, "a.compress([1] * 100)")
+        raises((IndexError, ValueError), "a.compress([1] * 100)")
 
     def test_item(self):
         from _numpypy import array
@@ -1961,7 +1992,27 @@
         assert (a + a).item(1) == 4
         raises(IndexError, "array(5).item(1)")
         assert array([1]).item() == 1
- 
+
+    def test_int_array_index(self):
+        from _numpypy import array
+        a = array([[1, 2], [3, 4], [5, 6]])
+        assert (a[slice(0, 3), [0, 0]] == [[1, 1], [3, 3], [5, 5]]).all()
+        assert (a[array([0, 2]), slice(0, 2)] == [[1, 2], [5, 6]]).all()
+        b = a[array([0, 0])]
+        assert (b == [[1, 2], [1, 2]]).all()
+        assert (a[[[0, 1], [0, 0]]] == array([1, 3])).all()
+        assert (a[array([0, 2])] == [[1, 2], [5, 6]]).all()
+        assert (a[array([0, 2]), 1] == [2, 6]).all()
+        assert (a[array([0, 2]), array([1])] == [2, 6]).all()
+
+    def test_int_array_index_setitem(self):
+        from _numpypy import array
+        a = array([[1, 2], [3, 4], [5, 6]])
+        a[slice(0, 3), [0, 0]] = [[0, 0], [0, 0], [0, 0]]
+        assert (a == [[0, 2], [0, 4], [0, 6]]).all()
+        a = array([[1, 2], [3, 4], [5, 6]])
+        a[array([0, 2]), slice(0, 2)] = [[10, 11], [12, 13]]
+        assert (a == [[10, 11], [3, 4], [12, 13]]).all()
 
 class AppTestSupport(BaseNumpyAppTest):
     def setup_class(cls):
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
@@ -433,6 +433,14 @@
         obj = X()
         assert isinstance(obj.items, Array)
 
+    def test_b_base(self):
+        # _b_base_ used to be None here in PyPy
+        class X(Structure):
+            _fields_ = [('x', c_int)]
+        obj = X()
+        p = pointer(obj)
+        assert p.contents._b_base_ is p
+
 class TestPointerMember(BaseCTypesTestChecker):
 
     def test_1(self):
diff --git a/pypy/rlib/parsing/test/test_tree.py b/pypy/rlib/parsing/test/test_tree.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/parsing/test/test_tree.py
@@ -0,0 +1,90 @@
+import py
+
+from pypy.rlib.parsing.tree import Nonterminal, Symbol
+from pypy.rlib.parsing.lexer import Token, SourcePos
+
+class TestTreeAppLevel(object):
+
+    def test_nonterminal_simple(self):
+        pos = SourcePos(1,2,3)
+        tree = Nonterminal(symbol="a", 
+            children=[
+                Symbol(symbol="b", 
+                    additional_info="b", 
+                    token=Token(name="B",
+                        source="b",
+                        source_pos=pos))])
+        assert tree.getsourcepos() == pos
+        
+    def test_nonterminal_nested(self):
+        pos = SourcePos(1,2,3)
+        tree = Nonterminal(symbol="a", 
+            children=[
+                Nonterminal(symbol="c",
+                    children=[
+                       Symbol(symbol="b", 
+                            additional_info="b", 
+                            token=Token(name="B",
+                                source="b",
+                                source_pos=pos))])])
+        assert tree.getsourcepos() == pos
+    
+    def test_nonterminal_simple_empty(self):
+        tree = Nonterminal(symbol="a", 
+            children=[])
+        assert len(tree.children) == 0 # trivial
+        py.test.raises(IndexError, tree.getsourcepos)
+
+    def test_nonterminal_nested_empty(self):
+        tree = Nonterminal(symbol="a", 
+            children=[Nonterminal(symbol="c",
+            children=[Nonterminal(symbol="c",
+            children=[Nonterminal(symbol="c",
+            children=[Nonterminal(symbol="c",
+            children=[Nonterminal(symbol="c",
+            children=[Nonterminal(symbol="c",
+            children=[])])])])])])])
+        assert len(tree.children) != 0 # the not-so-trivial part.
+        py.test.raises(IndexError, tree.getsourcepos)
+
+class BaseTestTreeTranslated(object):
+    
+    def compile(self, f):
+        raise NotImplementedError
+    
+    def test_nonterminal_simple_empty(self):
+        def foo():
+            tree = Nonterminal(symbol="a", 
+                children=[])
+            return tree.getsourcepos()
+        f = self.compile(foo)
+        py.test.raises(IndexError, f)    
+
+    def test_nonterminal_nested_empty(self):
+        def foo():
+            tree = Nonterminal(symbol="a", 
+                children=[Nonterminal(symbol="c",
+                children=[Nonterminal(symbol="c",
+                children=[Nonterminal(symbol="c",
+                children=[Nonterminal(symbol="c",
+                children=[Nonterminal(symbol="c",
+                children=[Nonterminal(symbol="c",
+                children=[])])])])])])])
+            return tree.getsourcepos()
+        f = self.compile(foo)
+        py.test.raises(IndexError, f)    
+
+
+class TestTreeTranslatedLLType(BaseTestTreeTranslated):
+
+    def compile(self, f):
+        from pypy.translator.c.test.test_genc import compile
+        return compile(f, [])
+
+class TestTreeTranslatedOOType(BaseTestTreeTranslated):
+    
+    def compile(self, f):
+        from pypy.translator.cli.test.runtest import compile_function
+        return compile_function(f, [], auto_raise_exc=True, exctrans=True)
+
+
diff --git a/pypy/rlib/parsing/tree.py b/pypy/rlib/parsing/tree.py
--- a/pypy/rlib/parsing/tree.py
+++ b/pypy/rlib/parsing/tree.py
@@ -53,7 +53,10 @@
         self.symbol = symbol
 
     def getsourcepos(self):
-        return self.children[0].getsourcepos()
+        try:
+            return self.children[0].getsourcepos()
+        except IndexError:
+            raise
 
     def __str__(self):
         return "%s(%s)" % (self.symbol, ", ".join([str(c) for c in self.children]))
diff --git a/pypy/rlib/rsocket.py b/pypy/rlib/rsocket.py
--- a/pypy/rlib/rsocket.py
+++ b/pypy/rlib/rsocket.py
@@ -810,23 +810,19 @@
             errno = _c.geterrno()
             if self.timeout > 0.0 and res < 0 and errno == _c.EINPROGRESS:
                 timeout = self._select(True)
-                errno = _c.geterrno()
                 if timeout == 0:
-                    addr = address.lock()
-                    res = _c.socketconnect(self.fd, addr, address.addrlen)
-                    address.unlock()
-                    if res < 0:
-                        errno = _c.geterrno()
-                        if errno == _c.EISCONN:
-                            res = 0
+                    res = self.getsockopt_int(_c.SOL_SOCKET, _c.SO_ERROR)
+                    if res == _c.EISCONN:
+                        res = 0
+                    errno = res
                 elif timeout == -1:
-                    return (errno, False)
+                    return (_c.geterrno(), False)
                 else:
                     return (_c.EWOULDBLOCK, True)
 
-            if res == 0:
-                errno = 0
-            return (errno, False)
+            if res < 0:
+                res = errno
+            return (res, False)
         
     def connect(self, address):
         """Connect the socket to a remote address."""
diff --git a/pypy/rlib/streamio.py b/pypy/rlib/streamio.py
--- a/pypy/rlib/streamio.py
+++ b/pypy/rlib/streamio.py
@@ -295,12 +295,23 @@
 
     def read(self, n):
         assert isinstance(n, int)
-        return os.read(self.fd, n)
+        while True:
+            try:
+                return os.read(self.fd, n)
+            except OSError, e:
+                if e.errno != errno.EINTR:
+                    raise
+                # else try again
 
     def write(self, data):
         while data:
-            n = os.write(self.fd, data)
-            data = data[n:]
+            try:
+                n = os.write(self.fd, data)
+            except OSError, e:
+                if e.errno != errno.EINTR:
+                    raise
+            else:
+                data = data[n:]
 
     def close(self):
         os.close(self.fd)
diff --git a/pypy/rlib/test/test_rsocket.py b/pypy/rlib/test/test_rsocket.py
--- a/pypy/rlib/test/test_rsocket.py
+++ b/pypy/rlib/test/test_rsocket.py
@@ -159,6 +159,7 @@
     assert addr.eq(sock.getsockname())
     sock.listen(1)
     s2 = RSocket(AF_INET, SOCK_STREAM)
+    s2.settimeout(10.0) # test one side with timeouts so select is used, shouldn't affect test
     def connecting():
         s2.connect(addr)
         lock.release()
@@ -209,6 +210,7 @@
     addr = INETAddress('127.0.0.1', port)
     assert addr.eq(s1.getsockname())
     s2 = RSocket(AF_INET, SOCK_DGRAM)
+    s2.settimeout(10.0) # test one side with timeouts so select is used, shouldn't affect test
     s2.bind(INETAddress('127.0.0.1', INADDR_ANY))
     addr2 = s2.getsockname()
 
@@ -325,6 +327,18 @@
     if errcodesok:
         assert err in (errno.ECONNREFUSED, errno.EADDRNOTAVAIL)
 
+def test_connect_with_timeout_fail():
+    s = RSocket()
+    s.settimeout(0.1)
+    with py.test.raises(SocketTimeout):
+        s.connect(INETAddress('240.240.240.240', 12345))
+    s.close()
+
+def test_connect_with_timeout_succeed():
+    s = RSocket()
+    s.settimeout(10.0)
+    s.connect(INETAddress('python.org', 80))
+    s.close()
 
 def test_getsetsockopt():
     import struct
diff --git a/pypy/rlib/test/test_streamio.py b/pypy/rlib/test/test_streamio.py
--- a/pypy/rlib/test/test_streamio.py
+++ b/pypy/rlib/test/test_streamio.py
@@ -1078,6 +1078,49 @@
         assert r == ''
 
 
+class TestDiskFile:
+    def test_read_interrupted(self):
+        try:
+            from signal import alarm, signal, SIG_DFL, SIGALRM
+        except:
+            skip('no alarm on this platform')
+        try:
+            read_fd, write_fd = os.pipe()
+            file = streamio.DiskFile(read_fd)
+            def handler(*a):
+                os.write(write_fd, "hello")
+            signal(SIGALRM, handler)
+            alarm(1)
+            assert file.read(10) == "hello"
+        finally:
+            signal(SIGALRM, SIG_DFL)
+
+    def test_write_interrupted(self):
+        try:
+            from signal import alarm, signal, SIG_DFL, SIGALRM
+        except:
+            skip('no alarm on this platform')
+        try:
+            read_fd, write_fd = os.pipe()
+            file = streamio.DiskFile(write_fd)
+            def handler(*a):
+                os.read(read_fd, 2000)
+                alarm(1)
+            signal(SIGALRM, handler)
+            alarm(1)
+            # Write to the pipe until it is full
+            buf = "FILL THE PIPE" * 1000
+            while True:
+                if os.write(write_fd, buf) < len(buf):
+                    break
+            # Write more, this should block, the write() syscall is
+            # interrupted, signal handler is called, and next write()
+            # can succeed.
+            file.write("hello")
+        finally:
+            signal(SIGALRM, SIG_DFL)
+
+
 # Speed test
 
 FN = "BIG"
diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py
--- a/pypy/translator/c/genc.py
+++ b/pypy/translator/c/genc.py
@@ -17,14 +17,23 @@
 
 _CYGWIN = sys.platform == 'cygwin'
 
-def import_module_from_directory(dir, modname):
-    file, pathname, description = imp.find_module(modname, [str(dir)])
-    try:
-        mod = imp.load_module(modname, file, pathname, description)
-    finally:
-        if file:
-            file.close()
-    return mod
+_CPYTHON_RE = py.std.re.compile('^Python 2.[567]')
+
+def get_recent_cpython_executable():
+
+    if sys.platform == 'win32':
+        python = sys.executable.replace('\\', '/') + ' '
+    else:
+        python = sys.executable + ' '
+
+    # Is there a command 'python' that runs python 2.5-2.7?
+    # If there is, then we can use it instead of sys.executable
+    returncode, stdout, stderr = runsubprocess.run_subprocess(
+        "python", "-V")
+    if _CPYTHON_RE.match(stdout) or _CPYTHON_RE.match(stderr):
+        python = 'python '
+    return python
+
 
 class ProfOpt(object):
     #XXX assuming gcc style flags for now
@@ -574,18 +583,7 @@
             else:
                 mk.definition('PYPY_MAIN_FUNCTION', "main")
 
-            if sys.platform == 'win32':
-                python = sys.executable.replace('\\', '/') + ' '
-            else:
-                python = sys.executable + ' '
-
-            # Is there a command 'python' that runs python 2.5-2.7?
-            # If there is, then we can use it instead of sys.executable
-            returncode, stdout, stderr = runsubprocess.run_subprocess(
-                "python", "-V")
-            if (stdout.startswith('Python 2.') or
-                stderr.startswith('Python 2.')):
-                python = 'python '
+            python = get_recent_cpython_executable()
 
             if self.translator.platform.name == 'msvc':
                 lblofiles = []


More information about the pypy-commit mailing list