[pypy-commit] cffi release-1.12: hg merge default

arigo pypy.commits at gmail.com
Thu Apr 18 07:11:57 EDT 2019


Author: Armin Rigo <arigo at tunes.org>
Branch: release-1.12
Changeset: r3263:553702112a56
Date: 2019-04-18 13:11 +0200
http://bitbucket.org/cffi/cffi/changeset/553702112a56/

Log:	hg merge default

diff too long, truncating to 2000 out of 2146 lines

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -2,7 +2,7 @@
 #include <Python.h>
 #include "structmember.h"
 
-#define CFFI_VERSION  "1.12.2"
+#define CFFI_VERSION  "1.12.3"
 
 #ifdef MS_WIN32
 #include <windows.h>
@@ -174,7 +174,7 @@
 #define CT_IS_BOOL             0x00080000
 #define CT_IS_FILE             0x00100000
 #define CT_IS_VOID_PTR         0x00200000
-#define CT_WITH_VAR_ARRAY      0x00400000
+#define CT_WITH_VAR_ARRAY      0x00400000 /* with open-ended array, anywhere */
 /* unused                      0x00800000 */
 #define CT_LAZY_FIELD_LIST     0x01000000
 #define CT_WITH_PACKED_CHANGE  0x02000000
@@ -1331,6 +1331,29 @@
 }
 
 static int
+add_varsize_length(Py_ssize_t offset, Py_ssize_t itemsize,
+                   Py_ssize_t varsizelength, Py_ssize_t *optvarsize)
+{
+    /* update '*optvarsize' to account for an array of 'varsizelength'
+       elements, each of size 'itemsize', that starts at 'offset'. */
+    Py_ssize_t size = ADD_WRAPAROUND(offset,
+                              MUL_WRAPAROUND(itemsize, varsizelength));
+    if (size < 0 ||
+        ((size - offset) / itemsize) != varsizelength) {
+        PyErr_SetString(PyExc_OverflowError,
+                        "array size would overflow a Py_ssize_t");
+        return -1;
+    }
+    if (size > *optvarsize)
+        *optvarsize = size;
+    return 0;
+}
+
+static int
+convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init,
+                           Py_ssize_t *optvarsize);  /* forward */
+
+static int
 convert_vfield_from_object(char *data, CFieldObject *cf, PyObject *value,
                            Py_ssize_t *optvarsize)
 {
@@ -1343,20 +1366,11 @@
         if (optvarsize != NULL) {
             /* in this mode, the only purpose of this function is to compute
                the real size of the structure from a var-sized C99 array */
-            Py_ssize_t size, itemsize;
             assert(data == NULL);
-            itemsize = cf->cf_type->ct_itemdescr->ct_size;
-            size = ADD_WRAPAROUND(cf->cf_offset,
-                                  MUL_WRAPAROUND(itemsize, varsizelength));
-            if (size < 0 ||
-                ((size - cf->cf_offset) / itemsize) != varsizelength) {
-                PyErr_SetString(PyExc_OverflowError,
-                                "array size would overflow a Py_ssize_t");
-                return -1;
-            }
-            if (size > *optvarsize)
-                *optvarsize = size;
-            return 0;
+            return add_varsize_length(cf->cf_offset,
+                cf->cf_type->ct_itemdescr->ct_size,
+                varsizelength,
+                optvarsize);
         }
         /* if 'value' was only an integer, get_new_array_length() returns
            it and convert 'value' to be None.  Detect if this was the case,
@@ -1365,8 +1379,16 @@
         if (value == Py_None)
             return 0;
     }
-    if (optvarsize == NULL)
+    if (optvarsize == NULL) {
         return convert_field_from_object(data, cf, value);
+    }
+    else if ((cf->cf_type->ct_flags & CT_WITH_VAR_ARRAY) != 0 &&
+             !CData_Check(value)) {
+        Py_ssize_t subsize = cf->cf_type->ct_size;
+        if (convert_struct_from_object(NULL, cf->cf_type, value, &subsize) < 0)
+            return -1;
+        return add_varsize_length(cf->cf_offset, 1, subsize, optvarsize);
+    }
     else
         return 0;
 }
@@ -2171,7 +2193,10 @@
         return PyInt_FromLong(value);
     }
     if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED)) {
-        return convert_to_object(cd->c_data, cd->c_type);
+        PyObject *result = convert_to_object(cd->c_data, cd->c_type);
+        if (result != NULL && PyBool_Check(result))
+            result = PyInt_FromLong(PyInt_AsLong(result));
+        return result;
     }
     else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) {
         /*READ(cd->c_data, cd->c_type->ct_size)*/
@@ -4951,6 +4976,19 @@
                 goto error;
             }
         }
+        else if (ftype->ct_flags & (CT_STRUCT|CT_UNION)) {
+            if (force_lazy_struct(ftype) < 0)   /* for CT_WITH_VAR_ARRAY */
+                return NULL;
+
+            /* GCC (or maybe C99) accepts var-sized struct fields that are not
+               the last field of a larger struct.  That's why there is no
+               check here for "last field": we propagate the flag
+               CT_WITH_VAR_ARRAY to any struct that contains either an open-
+               ended array or another struct that recursively contains an
+               open-ended array. */
+            if (ftype->ct_flags & CT_WITH_VAR_ARRAY)
+                ct->ct_flags |= CT_WITH_VAR_ARRAY;
+        }
 
         if (is_union)
             boffset = 0;   /* reset each field at offset 0 */
@@ -6016,6 +6054,11 @@
 #endif
     if (closure == NULL) {
         Py_DECREF(infotuple);
+        PyErr_SetString(PyExc_MemoryError,
+            "Cannot allocate write+execute memory for ffi.callback(). "
+            "You might be running on a system that prevents this. "
+            "For more information, see "
+            "https://cffi.readthedocs.io/en/latest/using.html#callbacks");
         return NULL;
     }
     cd = PyObject_GC_New(CDataObject_closure, &CDataOwningGC_Type);
diff --git a/c/call_python.c b/c/call_python.c
--- a/c/call_python.c
+++ b/c/call_python.c
@@ -1,10 +1,18 @@
 #if PY_VERSION_HEX >= 0x03080000
-# define Py_BUILD_CORE
-/* for access to the fields of PyInterpreterState */
-#  include "internal/pycore_pystate.h"
-# undef Py_BUILD_CORE
+# define HAVE_PYINTERPSTATE_GETDICT
 #endif
 
+
+static PyObject *_current_interp_key(void)
+{
+    PyInterpreterState *interp = PyThreadState_GET()->interp;
+#ifdef HAVE_PYINTERPSTATE_GETDICT
+    return PyInterpreterState_GetDict(interp);   /* shared reference */
+#else
+    return interp->modules;
+#endif
+}
+
 static PyObject *_get_interpstate_dict(void)
 {
     /* Hack around to return a dict that is subinterpreter-local.
@@ -14,7 +22,7 @@
     */
     static PyObject *attr_name = NULL;
     PyThreadState *tstate;
-    PyObject *d, *builtins;
+    PyObject *d, *interpdict;
     int err;
 
     tstate = PyThreadState_GET();
@@ -23,8 +31,13 @@
         return NULL;
     }
 
-    builtins = tstate->interp->builtins;
-    if (builtins == NULL) {
+    PyInterpreterState *interp = tstate->interp;
+#ifdef HAVE_PYINTERPSTATE_GETDICT
+    interpdict = PyInterpreterState_GetDict(interp);   /* shared reference */
+#else
+    interpdict = interp->builtins;
+#endif
+    if (interpdict == NULL) {
         /* subinterpreter was cleared already, or is being cleared right now,
            to a point that is too much for us to continue */
         return NULL;
@@ -38,13 +51,13 @@
             goto error;
     }
 
-    d = PyDict_GetItem(builtins, attr_name);
+    d = PyDict_GetItem(interpdict, attr_name);
     if (d == NULL) {
         d = PyDict_New();
         if (d == NULL)
             goto error;
-        err = PyDict_SetItem(builtins, attr_name, d);
-        Py_DECREF(d);    /* if successful, there is one ref left in builtins */
+        err = PyDict_SetItem(interpdict, attr_name, d);
+        Py_DECREF(d);   /* if successful, there is one ref left in interpdict */
         if (err < 0)
             goto error;
     }
@@ -163,7 +176,7 @@
     if (infotuple == NULL)
         return 3;    /* no ffi.def_extern() from this subinterpreter */
 
-    new1 = PyThreadState_GET()->interp->modules;
+    new1 = _current_interp_key();
     Py_INCREF(new1);
     Py_INCREF(infotuple);
     old1 = (PyObject *)externpy->reserved1;
@@ -252,7 +265,7 @@
     }
     else {
         PyGILState_STATE state = gil_ensure();
-        if (externpy->reserved1 != PyThreadState_GET()->interp->modules) {
+        if (externpy->reserved1 != _current_interp_key()) {
             /* Update the (reserved1, reserved2) cache.  This will fail
                if we didn't call @ffi.def_extern() in this particular
                subinterpreter. */
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -1,4 +1,6 @@
 import py
+import pytest
+
 def _setup_path():
     import os, sys
     if '__pypy__' in sys.builtin_module_names:
@@ -12,7 +14,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.12.2", ("This test_c.py file is for testing a version"
+assert __version__ == "1.12.3", ("This test_c.py file is for testing a version"
                                  " of cffi that differs from the one that we"
                                  " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
@@ -315,8 +317,10 @@
     assert p[0] == 0
     p = newp(BPtr, 5000)
     assert p[0] == 5000
-    py.test.raises(IndexError, "p[1]")
-    py.test.raises(IndexError, "p[-1]")
+    with pytest.raises(IndexError):
+        p[1]
+    with pytest.raises(IndexError):
+        p[-1]
 
 def test_reading_pointer_to_float():
     BFloat = new_primitive_type("float")
@@ -444,7 +448,8 @@
 def test_invalid_indexing():
     p = new_primitive_type("int")
     x = cast(p, 42)
-    py.test.raises(TypeError, "x[0]")
+    with pytest.raises(TypeError):
+        x[0]
 
 def test_default_str():
     BChar = new_primitive_type("char")
@@ -537,13 +542,16 @@
     assert len(a) == LENGTH
     for i in range(LENGTH):
         assert a[i] == 0
-    py.test.raises(IndexError, "a[LENGTH]")
-    py.test.raises(IndexError, "a[-1]")
+    with pytest.raises(IndexError):
+        a[LENGTH]
+    with pytest.raises(IndexError):
+        a[-1]
     for i in range(LENGTH):
         a[i] = i * i + 1
     for i in range(LENGTH):
         assert a[i] == i * i + 1
-    e = py.test.raises(IndexError, "a[LENGTH+100] = 500")
+    with pytest.raises(IndexError) as e:
+        a[LENGTH+100] = 500
     assert ('(expected %d < %d)' % (LENGTH+100, LENGTH)) in str(e.value)
     py.test.raises(TypeError, int, a)
 
@@ -558,10 +566,14 @@
         a[i] -= i
     for i in range(42):
         assert a[i] == -i
-    py.test.raises(IndexError, "a[42]")
-    py.test.raises(IndexError, "a[-1]")
-    py.test.raises(IndexError, "a[42] = 123")
-    py.test.raises(IndexError, "a[-1] = 456")
+    with pytest.raises(IndexError):
+        a[42]
+    with pytest.raises(IndexError):
+        a[-1]
+    with pytest.raises(IndexError):
+        a[42] = 123
+    with pytest.raises(IndexError):
+        a[-1] = 456
 
 def test_array_of_unknown_length_instance_with_initializer():
     p = new_primitive_type("int")
@@ -609,10 +621,14 @@
     assert a == (p - 1)
     BPtr = new_pointer_type(new_primitive_type("short"))
     q = newp(BPtr, None)
-    py.test.raises(TypeError, "p - q")
-    py.test.raises(TypeError, "q - p")
-    py.test.raises(TypeError, "a - q")
-    e = py.test.raises(TypeError, "q - a")
+    with pytest.raises(TypeError):
+        p - q
+    with pytest.raises(TypeError):
+        q - p
+    with pytest.raises(TypeError):
+        a - q
+    with pytest.raises(TypeError) as e:
+        q - a
     assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
 
 def test_ptr_sub_unaligned():
@@ -625,8 +641,10 @@
             assert b - a == (bi - 1240) // size_of_int()
             assert a - b == (1240 - bi) // size_of_int()
         else:
-            py.test.raises(ValueError, "b - a")
-            py.test.raises(ValueError, "a - b")
+            with pytest.raises(ValueError):
+                b - a
+            with pytest.raises(ValueError):
+                a - b
 
 def test_cast_primitive_from_cdata():
     p = new_primitive_type("int")
@@ -777,10 +795,12 @@
     BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     p = cast(BStructPtr, 42)
-    e = py.test.raises(AttributeError, "p.a1")    # opaque
+    with pytest.raises(AttributeError) as e:
+        p.a1    # opaque
     assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
                             "cannot read fields")
-    e = py.test.raises(AttributeError, "p.a1 = 10")    # opaque
+    with pytest.raises(AttributeError) as e:
+        p.a1 = 10    # opaque
     assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
                             "cannot write fields")
 
@@ -792,30 +812,41 @@
     s.a2 = 123
     assert s.a1 == 0
     assert s.a2 == 123
-    py.test.raises(OverflowError, "s.a1 = sys.maxsize+1")
+    with pytest.raises(OverflowError):
+        s.a1 = sys.maxsize+1
     assert s.a1 == 0
-    e = py.test.raises(AttributeError, "p.foobar")
+    with pytest.raises(AttributeError) as e:
+        p.foobar
     assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
-    e = py.test.raises(AttributeError, "p.foobar = 42")
+    with pytest.raises(AttributeError) as e:
+        p.foobar = 42
     assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
-    e = py.test.raises(AttributeError, "s.foobar")
+    with pytest.raises(AttributeError) as e:
+        s.foobar
     assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
-    e = py.test.raises(AttributeError, "s.foobar = 42")
+    with pytest.raises(AttributeError) as e:
+        s.foobar = 42
     assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
     j = cast(BInt, 42)
-    e = py.test.raises(AttributeError, "j.foobar")
+    with pytest.raises(AttributeError) as e:
+        j.foobar
     assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
-    e = py.test.raises(AttributeError, "j.foobar = 42")
+    with pytest.raises(AttributeError) as e:
+        j.foobar = 42
     assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
     j = cast(new_pointer_type(BInt), 42)
-    e = py.test.raises(AttributeError, "j.foobar")
+    with pytest.raises(AttributeError) as e:
+        j.foobar
     assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
-    e = py.test.raises(AttributeError, "j.foobar = 42")
+    with pytest.raises(AttributeError) as e:
+        j.foobar = 42
     assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
     pp = newp(new_pointer_type(BStructPtr), p)
-    e = py.test.raises(AttributeError, "pp.a1")
+    with pytest.raises(AttributeError) as e:
+        pp.a1
     assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
-    e = py.test.raises(AttributeError, "pp.a1 = 42")
+    with pytest.raises(AttributeError) as e:
+        pp.a1 = 42
     assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
 
 def test_union_instance():
@@ -1636,7 +1667,8 @@
     assert ("an integer is required" in msg or  # CPython
             "unsupported operand type for int(): 'NoneType'" in msg or  # old PyPys
             "expected integer, got NoneType object" in msg) # newer PyPys
-    py.test.raises(TypeError, 'p.a1 = "def"')
+    with pytest.raises(TypeError):
+        p.a1 = "def"
     if sys.version_info < (3,):
         BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt)
         assert string(cast(BEnum2, 5)) == 'abc'
@@ -1766,14 +1798,17 @@
     p.a1 = -1
     assert p.a1 == -1
     p.a1 = 0
-    py.test.raises(OverflowError, "p.a1 = 2")
+    with pytest.raises(OverflowError):
+        p.a1 = 2
     assert p.a1 == 0
     #
     p.a1 = -1
     p.a2 = 3
     p.a3 = -4
-    py.test.raises(OverflowError, "p.a3 = 4")
-    e = py.test.raises(OverflowError, "p.a3 = -5")
+    with pytest.raises(OverflowError):
+        p.a3 = 4
+    with pytest.raises(OverflowError) as e:
+        p.a3 = -5
     assert str(e.value) == ("value -5 outside the range allowed by the "
                             "bit field width: -4 <= x <= 3")
     assert p.a1 == -1 and p.a2 == 3 and p.a3 == -4
@@ -1782,7 +1817,8 @@
     # allows also setting the value "1" (it still gets read back as -1)
     p.a1 = 1
     assert p.a1 == -1
-    e = py.test.raises(OverflowError, "p.a1 = -2")
+    with pytest.raises(OverflowError) as e:
+        p.a1 = -2
     assert str(e.value) == ("value -2 outside the range allowed by the "
                             "bit field width: -1 <= x <= 1")
 
@@ -1842,14 +1878,17 @@
     assert string(a[2]) == b"."
     a[2] = b"12345"
     assert string(a[2]) == b"12345"
-    e = py.test.raises(IndexError, 'a[2] = b"123456"')
+    with pytest.raises(IndexError) as e:
+        a[2] = b"123456"
     assert 'char[5]' in str(e.value)
     assert 'got 6 characters' in str(e.value)
 
 def test_add_error():
     x = cast(new_primitive_type("int"), 42)
-    py.test.raises(TypeError, "x + 1")
-    py.test.raises(TypeError, "x - 1")
+    with pytest.raises(TypeError):
+        x + 1
+    with pytest.raises(TypeError):
+        x - 1
 
 def test_void_errors():
     py.test.raises(ValueError, alignof, new_void_type())
@@ -2181,8 +2220,10 @@
     s = newp(BStructPtr)
     s.a1 = u+'\x00'
     assert s.a1 == u+'\x00'
-    py.test.raises(TypeError, "s.a1 = b'a'")
-    py.test.raises(TypeError, "s.a1 = bytechr(0xFF)")
+    with pytest.raises(TypeError):
+        s.a1 = b'a'
+    with pytest.raises(TypeError):
+        s.a1 = bytechr(0xFF)
     s.a1 = u+'\u1234'
     assert s.a1 == u+'\u1234'
     if pyuni4:
@@ -2196,7 +2237,8 @@
             s.a1 = u+'\ud807\udf44'
             assert s.a1 == u+'\U00011f44'
     else:
-        py.test.raises(TypeError, "s.a1 = u+'\U00012345'")
+        with pytest.raises(TypeError):
+            s.a1 = u+'\U00012345'
     #
     BWCharArray = new_array_type(BWCharP, None)
     a = newp(BWCharArray, u+'hello \u1234 world')
@@ -2220,7 +2262,8 @@
         assert list(a) == expected
         got = [a[i] for i in range(4)]
         assert got == expected
-        py.test.raises(IndexError, 'a[4]')
+        with pytest.raises(IndexError):
+            a[4]
     #
     w = cast(BWChar, 'a')
     assert repr(w) == "<cdata '%s' %s'a'>" % (typename, mandatory_u_prefix)
@@ -2352,9 +2395,11 @@
 def test_cannot_dereference_void():
     BVoidP = new_pointer_type(new_void_type())
     p = cast(BVoidP, 123456)
-    py.test.raises(TypeError, "p[0]")
+    with pytest.raises(TypeError):
+        p[0]
     p = cast(BVoidP, 0)
-    py.test.raises((TypeError, RuntimeError), "p[0]")
+    with pytest.raises((TypeError, RuntimeError)):
+        p[0]
 
 def test_iter():
     BInt = new_primitive_type("int")
@@ -2377,12 +2422,12 @@
     assert (q == p) is False
     assert (q != p) is True
     if strict_compare:
-        py.test.raises(TypeError, "p < q")
-        py.test.raises(TypeError, "p <= q")
-        py.test.raises(TypeError, "q < p")
-        py.test.raises(TypeError, "q <= p")
-        py.test.raises(TypeError, "p > q")
-        py.test.raises(TypeError, "p >= q")
+        with pytest.raises(TypeError): p < q
+        with pytest.raises(TypeError): p <= q
+        with pytest.raises(TypeError): q < p
+        with pytest.raises(TypeError): q <= p
+        with pytest.raises(TypeError): p > q
+        with pytest.raises(TypeError): p >= q
     r = cast(BVoidP, p)
     assert (p <  r) is False
     assert (p <= r) is True
@@ -2428,7 +2473,8 @@
         try:
             expected = b"hi there\x00"[i]
         except IndexError:
-            py.test.raises(IndexError, "buf[i]")
+            with pytest.raises(IndexError):
+                buf[i]
         else:
             assert buf[i] == bitem2bchr(expected)
     # --mb_slice--
@@ -2455,15 +2501,18 @@
         try:
             expected[i] = bytechr(i & 0xff)
         except IndexError:
-            py.test.raises(IndexError, "buf[i] = bytechr(i & 0xff)")
+            with pytest.raises(IndexError):
+                buf[i] = bytechr(i & 0xff)
         else:
             buf[i] = bytechr(i & 0xff)
         assert list(buf) == expected
     # --mb_ass_slice--
     buf[:] = b"hi there\x00"
     assert list(buf) == list(c) == list(map(bitem2bchr, b"hi there\x00"))
-    py.test.raises(ValueError, 'buf[:] = b"shorter"')
-    py.test.raises(ValueError, 'buf[:] = b"this is much too long!"')
+    with pytest.raises(ValueError):
+        buf[:] = b"shorter"
+    with pytest.raises(ValueError):
+        buf[:] = b"this is much too long!"
     buf[4:2] = b""   # no effect, but should work
     assert buf[:] == b"hi there\x00"
     buf[:2] = b"HI"
@@ -2537,14 +2586,16 @@
     BChar = new_primitive_type("char")
     BCharP = new_pointer_type(BChar)
     x = newp(BCharP)
-    py.test.raises(TypeError, "del x[0]")
+    with pytest.raises(TypeError):
+        del x[0]
 
 def test_bug_delattr():
     BLong = new_primitive_type("long")
     BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a1', BLong, -1)])
     x = newp(new_pointer_type(BStruct))
-    py.test.raises(AttributeError, "del x.a1")
+    with pytest.raises(AttributeError):
+        del x.a1
 
 def test_variable_length_struct():
     py.test.skip("later")
@@ -2562,7 +2613,8 @@
     assert sizeof(x) == 6 * size_of_long()
     x[4] = 123
     assert x[4] == 123
-    py.test.raises(IndexError, "x[5]")
+    with pytest.raises(IndexError):
+        x[5]
     assert len(x.a2) == 5
     #
     py.test.raises(TypeError, newp, BStructP, [123])
@@ -2814,7 +2866,8 @@
     BCharP = new_pointer_type(new_primitive_type("char"))
     p = newp(BCharP, b'X')
     q = cast(BBoolP, p)
-    py.test.raises(ValueError, "q[0]")
+    with pytest.raises(ValueError):
+        q[0]
     py.test.raises(TypeError, newp, BBoolP, b'\x00')
     assert newp(BBoolP, 0)[0] is False
     assert newp(BBoolP, 1)[0] is True
@@ -3114,8 +3167,10 @@
     assert c[1] == 123
     assert c[3] == 456
     assert d[2] == 456
-    py.test.raises(IndexError, "d[3]")
-    py.test.raises(IndexError, "d[-1]")
+    with pytest.raises(IndexError):
+        d[3]
+    with pytest.raises(IndexError):
+        d[-1]
 
 def test_slice_ptr():
     BIntP = new_pointer_type(new_primitive_type("int"))
@@ -3133,7 +3188,8 @@
     c = newp(BIntArray, 5)
     c[0:5]
     assert len(c[5:5]) == 0
-    py.test.raises(IndexError, "c[-1:1]")
+    with pytest.raises(IndexError):
+        c[-1:1]
     cp = c + 0
     cp[-1:1]
 
@@ -3141,17 +3197,23 @@
     BIntP = new_pointer_type(new_primitive_type("int"))
     BIntArray = new_array_type(BIntP, None)
     c = newp(BIntArray, 5)
-    e = py.test.raises(IndexError, "c[:5]")
+    with pytest.raises(IndexError) as e:
+        c[:5]
     assert str(e.value) == "slice start must be specified"
-    e = py.test.raises(IndexError, "c[4:]")
+    with pytest.raises(IndexError) as e:
+        c[4:]
     assert str(e.value) == "slice stop must be specified"
-    e = py.test.raises(IndexError, "c[1:2:3]")
+    with pytest.raises(IndexError) as e:
+        c[1:2:3]
     assert str(e.value) == "slice with step not supported"
-    e = py.test.raises(IndexError, "c[1:2:1]")
+    with pytest.raises(IndexError) as e:
+        c[1:2:1]
     assert str(e.value) == "slice with step not supported"
-    e = py.test.raises(IndexError, "c[4:2]")
+    with pytest.raises(IndexError) as e:
+        c[4:2]
     assert str(e.value) == "slice start > stop"
-    e = py.test.raises(IndexError, "c[6:6]")
+    with pytest.raises(IndexError) as e:
+        c[6:6]
     assert str(e.value) == "index too large (expected 6 <= 5)"
 
 def test_setslice():
@@ -3165,9 +3227,11 @@
     assert list(c) == [0, 100, 300, 400, 0]
     cp[-1:1] = iter([500, 600])
     assert list(c) == [0, 100, 500, 600, 0]
-    py.test.raises(ValueError, "cp[-1:1] = [1000]")
+    with pytest.raises(ValueError):
+        cp[-1:1] = [1000]
     assert list(c) == [0, 100, 1000, 600, 0]
-    py.test.raises(ValueError, "cp[-1:1] = (700, 800, 900)")
+    with pytest.raises(ValueError):
+        cp[-1:1] = (700, 800, 900)
     assert list(c) == [0, 100, 700, 800, 0]
 
 def test_setslice_array():
@@ -3427,10 +3491,14 @@
     assert sizeof(q[0]) == sizeof(BStruct)
     #
     # error cases
-    py.test.raises(IndexError, "p.y[4]")
-    py.test.raises(TypeError, "p.y = cast(BIntP, 0)")
-    py.test.raises(TypeError, "p.y = 15")
-    py.test.raises(TypeError, "p.y = None")
+    with pytest.raises(IndexError):
+        p.y[4]
+    with pytest.raises(TypeError):
+        p.y = cast(BIntP, 0)
+    with pytest.raises(TypeError):
+        p.y = 15
+    with pytest.raises(TypeError):
+        p.y = None
     #
     # accepting this may be specified by the C99 standard,
     # or a GCC strangeness...
@@ -3452,6 +3520,15 @@
     assert p.a[1] == 20
     assert p.a[2] == 30
     assert p.a[3] == 0
+    #
+    # struct of struct of varsized array
+    BStruct2 = new_struct_type("bar")
+    complete_struct_or_union(BStruct2, [('head', BInt),
+                                        ('tail', BStruct)])
+    for i in range(2):   # try to detect heap overwrites
+        p = newp(new_pointer_type(BStruct2), [100, [200, list(range(50))]])
+        assert p.tail.y[49] == 49
+
 
 def test_struct_array_no_length_explicit_position():
     BInt = new_primitive_type("int")
@@ -3526,8 +3603,10 @@
     p[2:5] = [b"*", b"Z", b"T"]
     p[1:3] = b"XY"
     assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"]
-    py.test.raises(TypeError, "p[1:5] = u+'XYZT'")
-    py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]")
+    with pytest.raises(TypeError):
+        p[1:5] = u+'XYZT'
+    with pytest.raises(TypeError):
+        p[1:5] = [1, 2, 3, 4]
     #
     for typename in ["wchar_t", "char16_t", "char32_t"]:
         BUniChar = new_primitive_type(typename)
@@ -3536,8 +3615,10 @@
         p[2:5] = [u+"*", u+"Z", u+"T"]
         p[1:3] = u+"XY"
         assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"]
-        py.test.raises(TypeError, "p[1:5] = b'XYZT'")
-        py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]")
+        with pytest.raises(TypeError):
+            p[1:5] = b'XYZT'
+        with pytest.raises(TypeError):
+            p[1:5] = [1, 2, 3, 4]
 
 def test_void_p_arithmetic():
     BVoid = new_void_type()
@@ -3548,10 +3629,14 @@
     assert int(cast(BInt, p - (-42))) == 100042
     assert (p + 42) - p == 42
     q = cast(new_pointer_type(new_primitive_type("char")), 100000)
-    py.test.raises(TypeError, "p - q")
-    py.test.raises(TypeError, "q - p")
-    py.test.raises(TypeError, "p + cast(new_primitive_type('int'), 42)")
-    py.test.raises(TypeError, "p - cast(new_primitive_type('int'), 42)")
+    with pytest.raises(TypeError):
+        p - q
+    with pytest.raises(TypeError):
+        q - p
+    with pytest.raises(TypeError):
+        p + cast(new_primitive_type('int'), 42)
+    with pytest.raises(TypeError):
+        p - cast(new_primitive_type('int'), 42)
 
 def test_sizeof_sliced_array():
     BInt = new_primitive_type("int")
@@ -3766,8 +3851,10 @@
     assert p1[0] == lst[0]
     assert p1[1] == lst[1]
     assert p1[2] == lst[2]
-    py.test.raises(IndexError, "p1[3]")
-    py.test.raises(IndexError, "p1[-1]")
+    with pytest.raises(IndexError):
+        p1[3]
+    with pytest.raises(IndexError):
+        p1[-1]
     #
     py.test.raises(TypeError, from_buffer, BInt, bytestring)
     py.test.raises(TypeError, from_buffer, BIntP, bytestring)
@@ -3778,8 +3865,10 @@
     assert len(p2) == 2
     assert p2[0] == lst[0]
     assert p2[1] == lst[1]
-    py.test.raises(IndexError, "p2[2]")
-    py.test.raises(IndexError, "p2[-1]")
+    with pytest.raises(IndexError):
+        p2[2]
+    with pytest.raises(IndexError):
+        p2[-1]
     assert p2 == p1
     #
     BIntA4 = new_array_type(BIntP, 4)        # int[4]: too big
@@ -3795,7 +3884,8 @@
     assert typeof(p1) is BStructA
     assert p1[0].a1 == lst[0]
     assert p1[0].a2 == lst[1]
-    py.test.raises(IndexError, "p1[1]")
+    with pytest.raises(IndexError):
+        p1[1]
     #
     BEmptyStruct = new_struct_type("empty")
     complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0)
@@ -3887,10 +3977,14 @@
     BInt = new_primitive_type("int")
     BIntPtr = new_pointer_type(BInt)
     p = cast(BIntPtr, 0)
-    py.test.raises(RuntimeError, "p[0]")
-    py.test.raises(RuntimeError, "p[0] = 42")
-    py.test.raises(RuntimeError, "p[42]")
-    py.test.raises(RuntimeError, "p[42] = -1")
+    with pytest.raises(RuntimeError):
+        p[0]
+    with pytest.raises(RuntimeError):
+        p[0] = 42
+    with pytest.raises(RuntimeError):
+        p[42]
+    with pytest.raises(RuntimeError):
+        p[42] = -1
 
 def test_mixup():
     BStruct1 = new_struct_type("foo")
@@ -3906,10 +4000,12 @@
     pp2 = newp(BStruct2PtrPtr)
     pp3 = newp(BStruct3PtrPtr)
     pp1[0] = pp1[0]
-    e = py.test.raises(TypeError, "pp3[0] = pp1[0]")
+    with pytest.raises(TypeError) as e:
+        pp3[0] = pp1[0]
     assert str(e.value).startswith("initializer for ctype 'bar *' must be a ")
     assert str(e.value).endswith(", not cdata 'foo *'")
-    e = py.test.raises(TypeError, "pp2[0] = pp1[0]")
+    with pytest.raises(TypeError) as e:
+        pp2[0] = pp1[0]
     assert str(e.value) == ("initializer for ctype 'foo *' appears indeed to "
                             "be 'foo *', but the types are different (check "
                             "that you are not e.g. mixing up different ffi "
@@ -4098,14 +4194,14 @@
         assert (a != b) is True
         assert (b != a) is True
         if strict_compare:
-            py.test.raises(TypeError, "a < b")
-            py.test.raises(TypeError, "a <= b")
-            py.test.raises(TypeError, "a > b")
-            py.test.raises(TypeError, "a >= b")
-            py.test.raises(TypeError, "b < a")
-            py.test.raises(TypeError, "b <= a")
-            py.test.raises(TypeError, "b > a")
-            py.test.raises(TypeError, "b >= a")
+            with pytest.raises(TypeError): a < b
+            with pytest.raises(TypeError): a <= b
+            with pytest.raises(TypeError): a > b
+            with pytest.raises(TypeError): a >= b
+            with pytest.raises(TypeError): b < a
+            with pytest.raises(TypeError): b <= a
+            with pytest.raises(TypeError): b > a
+            with pytest.raises(TypeError): b >= a
         elif a < b:
             assert_lt(a, b)
         else:
@@ -4151,7 +4247,8 @@
     BIntP = new_pointer_type(new_primitive_type("int"))
     p = newp(BIntP)
     p[0] = 42
-    py.test.raises(IndexError, "p[1]")
+    with pytest.raises(IndexError):
+        p[1]
     release(p)
     # here, reading p[0] might give garbage or segfault...
     release(p)   # no effect
@@ -4187,8 +4284,12 @@
 def test_explicit_release_badtype_contextmgr():
     BIntP = new_pointer_type(new_primitive_type("int"))
     p = cast(BIntP, 12345)
-    py.test.raises(ValueError, "with p: pass")
-    py.test.raises(ValueError, "with p: pass")
+    with pytest.raises(ValueError):
+        with p:
+            pass
+    with pytest.raises(ValueError):
+        with p:
+            pass
 
 def test_explicit_release_gc():
     BIntP = new_pointer_type(new_primitive_type("int"))
@@ -4248,9 +4349,21 @@
     BCharA = new_array_type(BCharP, None)
     a += b't' * 10
     p = from_buffer(BCharA, a)
-    py.test.raises(BufferError, "a += b'u' * 100")
+    with pytest.raises(BufferError):
+        a += b'u' * 100
     release(p)
     a += b'v' * 100
     release(p)   # no effect
     a += b'w' * 1000
     assert a == bytearray(b"xyz" + b't' * 10 + b'v' * 100 + b'w' * 1000)
+
+def test_int_doesnt_give_bool():
+    BBool = new_primitive_type("_Bool")
+    x = int(cast(BBool, 42))
+    assert type(x) is int and x == 1
+    x = long(cast(BBool, 42))
+    assert type(x) is long and x == 1
+    with pytest.raises(TypeError):
+        float(cast(BBool, 42))
+    with pytest.raises(TypeError):
+        complex(cast(BBool, 42))
diff --git a/cffi/__init__.py b/cffi/__init__.py
--- a/cffi/__init__.py
+++ b/cffi/__init__.py
@@ -5,8 +5,8 @@
 from .error import CDefError, FFIError, VerificationError, VerificationMissing
 from .error import PkgConfigError
 
-__version__ = "1.12.2"
-__version_info__ = (1, 12, 2)
+__version__ = "1.12.3"
+__version_info__ = (1, 12, 3)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/cffi/_embedding.h b/cffi/_embedding.h
--- a/cffi/_embedding.h
+++ b/cffi/_embedding.h
@@ -169,8 +169,10 @@
     global_dict = PyDict_New();
     if (global_dict == NULL)
         goto error;
-    if (PyDict_SetItemString(global_dict, "__builtins__",
-                             PyThreadState_GET()->interp->builtins) < 0)
+    PyObject *builtins = PyEval_GetBuiltins();
+    if (builtins == NULL)
+        goto error;
+    if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0)
         goto error;
     x = PyEval_EvalCode(
 #if PY_MAJOR_VERSION < 3
@@ -221,7 +223,7 @@
 
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.12.2"
+                               "\ncompiled with cffi version: 1.12.3"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
@@ -263,23 +265,33 @@
        So we use a global variable as a simple spin lock.  This global
        variable must be from 'libpythonX.Y.so', not from this
        cffi-based extension module, because it must be shared from
-       different cffi-based extension modules.  We choose
+       different cffi-based extension modules.
+
+       In Python < 3.8, we choose
        _PyParser_TokenNames[0] as a completely arbitrary pointer value
        that is never written to.  The default is to point to the
        string "ENDMARKER".  We change it temporarily to point to the
        next character in that string.  (Yes, I know it's REALLY
        obscure.)
+
+       In Python >= 3.8, this string array is no longer writable, so
+       instead we pick PyCapsuleType.tp_version_tag.  We can't change
+       Python < 3.8 because someone might use a mixture of cffi
+       embedded modules, some of which were compiled before this file
+       changed.
     */
 
 #ifdef WITH_THREAD
+# if PY_VERSION_HEX < 0x03080000
     char *volatile *lock = (char *volatile *)_PyParser_TokenNames;
-    char *old_value;
+    char *old_value, *locked_value;
 
     while (1) {    /* spin loop */
         old_value = *lock;
+        locked_value = old_value + 1;
         if (old_value[0] == 'E') {
             assert(old_value[1] == 'N');
-            if (cffi_compare_and_swap(lock, old_value, old_value + 1))
+            if (cffi_compare_and_swap(lock, old_value, locked_value))
                 break;
         }
         else {
@@ -290,6 +302,27 @@
                this is only run at start-up anyway. */
         }
     }
+# else
+    int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag;
+    int old_value, locked_value;
+    assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG));
+
+    while (1) {    /* spin loop */
+        old_value = *lock;
+        locked_value = -42;
+        if (old_value == 0) {
+            if (cffi_compare_and_swap(lock, old_value, locked_value))
+                break;
+        }
+        else {
+            assert(old_value == locked_value);
+            /* should ideally do a spin loop instruction here, but
+               hard to do it portably and doesn't really matter I
+               think: PyEval_InitThreads() should be very fast, and
+               this is only run at start-up anyway. */
+        }
+    }
+# endif
 #endif
 
     /* call Py_InitializeEx() */
@@ -306,7 +339,7 @@
 
 #ifdef WITH_THREAD
     /* release the lock */
-    while (!cffi_compare_and_swap(lock, old_value + 1, old_value))
+    while (!cffi_compare_and_swap(lock, locked_value, old_value))
         ;
 #endif
 
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -817,12 +817,20 @@
         # or positive/negative number
         if isinstance(exprnode, pycparser.c_ast.Constant):
             s = exprnode.value
-            if s.startswith('0'):
-                if s.startswith('0x') or s.startswith('0X'):
-                    return int(s, 16)
-                return int(s, 8)
-            elif '1' <= s[0] <= '9':
-                return int(s, 10)
+            if '0' <= s[0] <= '9':
+                s = s.rstrip('uUlL')
+                try:
+                    if s.startswith('0'):
+                        return int(s, 8)
+                    else:
+                        return int(s, 10)
+                except ValueError:
+                    if len(s) > 1:
+                        if s.lower()[0:2] == '0x':
+                            return int(s, 16)
+                        elif s.lower()[0:2] == '0b':
+                            return int(s, 2)
+                raise CDefError("invalid constant %r" % (s,))
             elif s[0] == "'" and s[-1] == "'" and (
                     len(s) == 3 or (len(s) == 4 and s[1] == "\\")):
                 return ord(s[-2])
diff --git a/doc/source/conf.py b/doc/source/conf.py
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -47,7 +47,7 @@
 # The short X.Y version.
 version = '1.12'
 # The full version, including alpha/beta/rc tags.
-release = '1.12.2'
+release = '1.12.3'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/doc/source/installation.rst b/doc/source/installation.rst
--- a/doc/source/installation.rst
+++ b/doc/source/installation.rst
@@ -52,13 +52,13 @@
 
 * https://pypi.python.org/pypi/cffi
 
-* Checksums of the "source" package version 1.12.2:
+* Checksums of the "source" package version 1.12.3:
 
-   - MD5: 4d7dcb6c7c738c15d2ece9bd4c5f86da
+   - MD5: ...
 
-   - SHA: 5f579d4980cbcc8aac592721f714ef6a64370ab1
+   - SHA: ...
 
-   - SHA256: e113878a446c6228669144ae8a56e268c91b7f1fafae927adc4879d9849e0ea7
+   - SHA256: ...
 
 * Or grab the most current version from the `Bitbucket page`_:
   ``hg clone https://bitbucket.org/cffi/cffi``
diff --git a/doc/source/using.rst b/doc/source/using.rst
--- a/doc/source/using.rst
+++ b/doc/source/using.rst
@@ -876,11 +876,27 @@
       protections can interfere (for example, on SELinux you need to
       run with ``deny_execmem`` set to ``off``).
 
-    Note also that a cffi fix for the latter issue was attempted---see
+    - `On Mac OS X,`__ you need to give your application the entitlement
+      ``com.apple.security.cs.allow-unsigned-executable-memory``.
+
+    Note also that a cffi fix for this issue was attempted---see
     the ``ffi_closure_alloc`` branch---but was not merged because it
     creates potential `memory corruption`__ with ``fork()``.
 
+    In other words: yes, it is dangerous to allow write+execute memory in your
+    program; that's why the various "hardening" options above exist.  But at
+    the same time, these options open wide the door to another attack: if the
+    program forks and then attempts to call any of the ``ffi.callback()``, then
+    this immediately results in a crash---or, with a minimal amount of work
+    from an attacker, arbitrary code execution.  To me it sounds even more
+    dangerous than the original problem, and that's why cffi is not playing
+    along.
+
+    To fix the issue once and for all on the affected platforms, you need
+    to refactor the involved code so that it no longer uses ``ffi.callback()``.
+
 .. __: https://github.com/pyca/pyopenssl/issues/596
+.. __: https://bitbucket.org/cffi/cffi/issues/391/
 .. __: https://bugzilla.redhat.com/show_bug.cgi?id=1249685
 
 Warning: like ffi.new(), ffi.callback() returns a cdata that has
diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst
--- a/doc/source/whatsnew.rst
+++ b/doc/source/whatsnew.rst
@@ -3,6 +3,17 @@
 ======================
 
 
+v1.12.3
+=======
+
+* Fix for nested struct types that end in a var-sized array (#405).
+
+* Add support for using ``U`` and ``L`` characters at the end of integer
+  constants in ``ffi.cdef()`` (thanks Guillaume).
+
+* More 3.8 fixes.
+
+
 v1.12.2
 =======
 
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -198,7 +198,7 @@
 
 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
 """,
-        version='1.12.2',
+        version='1.12.3',
         packages=['cffi'] if cpython else [],
         package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h', 
                                '_embedding.h', '_cffi_errors.h']}
diff --git a/testing/cffi0/backend_tests.py b/testing/cffi0/backend_tests.py
--- a/testing/cffi0/backend_tests.py
+++ b/testing/cffi0/backend_tests.py
@@ -1,4 +1,5 @@
 import py
+import pytest
 import platform
 import sys, ctypes
 from cffi import FFI, CDefError, FFIError, VerificationMissing
@@ -112,10 +113,14 @@
         p[9] = 43
         assert p[0] == 42
         assert p[9] == 43
-        py.test.raises(IndexError, "p[10]")
-        py.test.raises(IndexError, "p[10] = 44")
-        py.test.raises(IndexError, "p[-1]")
-        py.test.raises(IndexError, "p[-1] = 44")
+        with pytest.raises(IndexError):
+            p[10]
+        with pytest.raises(IndexError):
+            p[10] = 44
+        with pytest.raises(IndexError):
+            p[-1]
+        with pytest.raises(IndexError):
+            p[-1] = 44
 
     def test_new_array_args(self):
         ffi = FFI(backend=self.Backend())
@@ -140,18 +145,21 @@
         ffi = FFI(backend=self.Backend())
         p = ffi.new("int[]", 10)     # a single integer is the length
         assert p[9] == 0
-        py.test.raises(IndexError, "p[10]")
+        with pytest.raises(IndexError):
+            p[10]
         #
         py.test.raises(TypeError, ffi.new, "int[]")
         #
         p = ffi.new("int[]", [-6, -7])    # a list is all the items, like C
         assert p[0] == -6
         assert p[1] == -7
-        py.test.raises(IndexError, "p[2]")
+        with pytest.raises(IndexError):
+            p[2]
         assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
         #
         p = ffi.new("int[]", 0)
-        py.test.raises(IndexError, "p[0]")
+        with pytest.raises(IndexError):
+            p[0]
         py.test.raises(ValueError, ffi.new, "int[]", -1)
         assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
 
@@ -259,7 +267,8 @@
         p[2][3] = 33
         assert p[0][0] == 10
         assert p[2][3] == 33
-        py.test.raises(IndexError, "p[1][-1]")
+        with pytest.raises(IndexError):
+            p[1][-1]
 
     def test_constructor_array_of_array(self):
         ffi = FFI(backend=self.Backend())
@@ -386,7 +395,8 @@
         n = ffi.new("int*", 99)
         p = ffi.new("int*[]", [n])
         assert p[0][0] == 99
-        py.test.raises(TypeError, "p[0] = None")
+        with pytest.raises(TypeError):
+            p[0] = None
         p[0] = ffi.NULL
         assert p[0] == ffi.NULL
 
@@ -422,13 +432,15 @@
         assert s.a == s.b == s.c == 0
         s.b = -23
         assert s.b == -23
-        py.test.raises(OverflowError, "s.b = 32768")
+        with pytest.raises(OverflowError):
+            s.b = 32768
         #
         s = ffi.new("struct foo*", [-2, -3])
         assert s.a == -2
         assert s.b == -3
         assert s.c == 0
-        py.test.raises((AttributeError, TypeError), "del s.a")
+        with pytest.raises((AttributeError, TypeError)):
+            del s.a
         assert repr(s) == "<cdata 'struct foo *' owning %d bytes>" % (
             SIZE_OF_INT + 2 * SIZE_OF_SHORT)
         #
@@ -450,8 +462,10 @@
         assert s[0].a == s[0].b == s[0].c == 0
         s[0].b = -23
         assert s[0].b == s.b == -23
-        py.test.raises(OverflowError, "s[0].b = -32769")
-        py.test.raises(IndexError, "s[1]")
+        with pytest.raises(OverflowError):
+            s[0].b = -32769
+        with pytest.raises(IndexError):
+            s[1]
 
     def test_struct_opaque(self):
         ffi = FFI(backend=self.Backend())
@@ -511,11 +525,13 @@
         u.b = -23
         assert u.b == -23
         assert u.a != 0
-        py.test.raises(OverflowError, "u.b = 32768")
+        with pytest.raises(OverflowError):
+            u.b = 32768
         #
         u = ffi.new("union foo*", [-2])
         assert u.a == -2
-        py.test.raises((AttributeError, TypeError), "del u.a")
+        with pytest.raises((AttributeError, TypeError)):
+            del u.a
         assert repr(u) == "<cdata 'union foo *' owning %d bytes>" % SIZE_OF_INT
 
     def test_union_opaque(self):
@@ -591,7 +607,8 @@
         p[3] = b'\x00'
         assert ffi.string(p) == b"hel"
         assert ffi.string(p, 2) == b"he"
-        py.test.raises(IndexError, "p[7] = b'X'")
+        with pytest.raises(IndexError):
+            p[7] = b'X'
         #
         a = ffi.new("char[]", b"hello\x00world")
         assert len(a) == 12
@@ -615,7 +632,8 @@
         p[3] = u+'\x00'
         assert ffi.string(p) == u+"hel"
         assert ffi.string(p, 123) == u+"hel"
-        py.test.raises(IndexError, "p[7] = u+'X'")
+        with pytest.raises(IndexError):
+            p[7] = u+'X'
         #
         a = ffi.new("wchar_t[]", u+"hello\x00world")
         assert len(a) == 12
@@ -633,7 +651,8 @@
         s = ffi.new("struct foo*", [t])
         assert type(s.name) not in (bytes, str, unicode)
         assert ffi.string(s.name) == b"testing"
-        py.test.raises(TypeError, "s.name = None")
+        with pytest.raises(TypeError):
+            s.name = None
         s.name = ffi.NULL
         assert s.name == ffi.NULL
 
@@ -657,18 +676,21 @@
         a = ffi.new("int[]", [10, 11, 12])
         p = ffi.new("void **", a)
         vp = p[0]
-        py.test.raises(TypeError, "vp[0]")
+        with pytest.raises(TypeError):
+            vp[0]
         py.test.raises(TypeError, ffi.new, "short **", a)
         #
         ffi.cdef("struct foo { void *p; int *q; short *r; };")
         s = ffi.new("struct foo *")
         s.p = a    # works
         s.q = a    # works
-        py.test.raises(TypeError, "s.r = a")    # fails
+        with pytest.raises(TypeError):
+            s.r = a    # fails
         b = ffi.cast("int *", a)
         s.p = b    # works
         s.q = b    # works
-        py.test.raises(TypeError, "s.r = b")    # fails
+        with pytest.raises(TypeError):
+            s.r = b    # fails
 
     def test_functionptr_simple(self):
         ffi = FFI(backend=self.Backend())
@@ -687,7 +709,8 @@
         q = ffi.new("int(**)(int)", p)
         assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
             SIZE_OF_PTR)
-        py.test.raises(TypeError, "q(43)")
+        with pytest.raises(TypeError):
+            q(43)
         res = q[0](43)
         assert res == 44
         q = ffi.cast("int(*)(int)", p)
@@ -912,10 +935,14 @@
         assert s.e == 4294967295
         assert s[0].e == 4294967295
         s.e = s.e
-        py.test.raises(TypeError, "s.e = 'B'")
-        py.test.raises(TypeError, "s.e = '2'")
-        py.test.raises(TypeError, "s.e = '#2'")
-        py.test.raises(TypeError, "s.e = '#7'")
+        with pytest.raises(TypeError):
+            s.e = 'B'
+        with pytest.raises(TypeError):
+            s.e = '2'
+        with pytest.raises(TypeError):
+            s.e = '#2'
+        with pytest.raises(TypeError):
+            s.e = '#7'
 
     def test_enum_non_contiguous(self):
         ffi = FFI(backend=self.Backend())
@@ -950,11 +977,14 @@
         ffi = FFI(backend=self.Backend())
         ffi.cdef("struct foo { int a, b; };")
         s = ffi.new("struct foo[1]")
-        py.test.raises(AttributeError, 's.b')
-        py.test.raises(AttributeError, 's.b = 412')
+        with pytest.raises(AttributeError):
+            s.b
+        with pytest.raises(AttributeError):
+            s.b = 412
         s[0].b = 412
         assert s[0].b == 412
-        py.test.raises(IndexError, 's[1]')
+        with pytest.raises(IndexError):
+            s[1]
 
     def test_pointer_to_array(self):
         ffi = FFI(backend=self.Backend())
@@ -1011,17 +1041,23 @@
         assert ffi.sizeof("struct foo") == 8
         s = ffi.new("struct foo *")
         s.a = 511
-        py.test.raises(OverflowError, "s.a = 512")
-        py.test.raises(OverflowError, "s[0].a = 512")
+        with pytest.raises(OverflowError):
+            s.a = 512
+        with pytest.raises(OverflowError):
+            s[0].a = 512
         assert s.a == 511
         s.a = -512
-        py.test.raises(OverflowError, "s.a = -513")
-        py.test.raises(OverflowError, "s[0].a = -513")
+        with pytest.raises(OverflowError):
+            s.a = -513
+        with pytest.raises(OverflowError):
+            s[0].a = -513
         assert s.a == -512
         s.c = 3
         assert s.c == 3
-        py.test.raises(OverflowError, "s.c = 4")
-        py.test.raises(OverflowError, "s[0].c = 4")
+        with pytest.raises(OverflowError):
+            s.c = 4
+        with pytest.raises(OverflowError):
+            s[0].c = 4
         s.c = -4
         assert s.c == -4
 
@@ -1279,7 +1315,8 @@
         p = ffi.new("struct foo_s *", 10)     # a single integer is the length
         assert p.len == 0
         assert p.data[9] == 0
-        py.test.raises(IndexError, "p.data[10]")
+        with pytest.raises(IndexError):
+            p.data[10]
 
     def test_ffi_typeof_getcname(self):
         ffi = FFI(backend=self.Backend())
diff --git a/testing/cffi0/test_ffi_backend.py b/testing/cffi0/test_ffi_backend.py
--- a/testing/cffi0/test_ffi_backend.py
+++ b/testing/cffi0/test_ffi_backend.py
@@ -129,6 +129,36 @@
         alloc5 = ffi.new_allocator(myalloc5)
         py.test.raises(MemoryError, alloc5, "int[5]")
 
+    def test_new_struct_containing_struct_containing_array_varsize(self):
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""
+            struct foo_s { int len[100]; short data[]; };
+            struct bar_s { int abc[100]; struct foo_s tail; };
+        """)
+        # loop to try to detect heap overwrites, if the size allocated
+        # is too small
+        for i in range(1, 501, 100):
+            p = ffi.new("struct bar_s *", [[10], [[20], [3,4,5,6,7,8,9] * i]])
+            assert p.abc[0] == 10
+            assert p.tail.len[0] == 20
+            assert p.tail.data[0] == 3
+            assert p.tail.data[6] == 9
+            assert p.tail.data[7 * i - 1] == 9
+
+    def test_bogus_struct_containing_struct_containing_array_varsize(self):
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""
+            struct foo_s { signed char len; signed char data[]; };
+            struct bar_s { struct foo_s foo; int bcd; };
+        """)
+        p = ffi.new("struct bar_s *", [[123, [45, 56, 67, 78]], 9999999])
+        assert p.foo.len == 123
+        assert p.foo.data[0] == 45
+        assert p.foo.data[1] == 56
+        assert p.foo.data[2] == 67
+        assert p.bcd == 9999999
+        assert p.foo.data[3] != 78   # has been overwritten with 9999999
+
 
 class TestBitfield:
     def check(self, source, expected_ofs_y, expected_align, expected_size):
@@ -268,12 +298,15 @@
 
     def test_error_cases(self):
         ffi = FFI()
-        py.test.raises(TypeError,
-            'ffi.cdef("struct s1 { float x:1; };"); ffi.new("struct s1 *")')
-        py.test.raises(TypeError,
-            'ffi.cdef("struct s2 { char x:0; };"); ffi.new("struct s2 *")')
-        py.test.raises(TypeError,
-            'ffi.cdef("struct s3 { char x:9; };"); ffi.new("struct s3 *")')
+        ffi.cdef("struct s1 { float x:1; };")
+        with pytest.raises(TypeError):
+            ffi.new("struct s1 *")
+        ffi.cdef("struct s2 { char x:0; };")
+        with pytest.raises(TypeError):
+            ffi.new("struct s2 *")
+        ffi.cdef("struct s3 { char x:9; };")
+        with pytest.raises(TypeError):
+            ffi.new("struct s3 *")
 
     def test_struct_with_typedef(self):
         ffi = FFI()
diff --git a/testing/cffi0/test_function.py b/testing/cffi0/test_function.py
--- a/testing/cffi0/test_function.py
+++ b/testing/cffi0/test_function.py
@@ -1,4 +1,5 @@
 import py
+import pytest
 from cffi import FFI, CDefError
 import math, os, sys
 import ctypes.util
@@ -90,7 +91,8 @@
         """)
         m = ffi.dlopen(lib_m)
         assert m.FOOBAR == 42
-        py.test.raises(NotImplementedError, "m.baz")
+        with pytest.raises(NotImplementedError):
+            m.baz
 
     def test_tlsalloc(self):
         if sys.platform != 'win32':
diff --git a/testing/cffi0/test_parsing.py b/testing/cffi0/test_parsing.py
--- a/testing/cffi0/test_parsing.py
+++ b/testing/cffi0/test_parsing.py
@@ -466,3 +466,40 @@
     e = py.test.raises(CDefError, ffi.cdef, 'void foo(void) {}')
     assert str(e.value) == ('<cdef source string>:1: unexpected <FuncDef>: '
                             'this construct is valid C but not valid in cdef()')
+
+def test_unsigned_int_suffix_for_constant():
+    ffi = FFI()
+    ffi.cdef("""enum e {
+                    bin_0=0b10,
+                    bin_1=0b10u,
+                    bin_2=0b10U,
+                    bin_3=0b10l,
+                    bin_4=0b10L,
+                    bin_5=0b10ll,
+                    bin_6=0b10LL,
+                    oct_0=010,
+                    oct_1=010u,
+                    oct_2=010U,
+                    oct_3=010l,
+                    oct_4=010L,
+                    oct_5=010ll,
+                    oct_6=010LL,
+                    dec_0=10,
+                    dec_1=10u,
+                    dec_2=10U,
+                    dec_3=10l,
+                    dec_4=10L,
+                    dec_5=10ll,
+                    dec_6=10LL,
+                    hex_0=0x10,
+                    hex_1=0x10u,
+                    hex_2=0x10U,
+                    hex_3=0x10l,
+                    hex_4=0x10L,
+                    hex_5=0x10ll,
+                    hex_6=0x10LL,};""")
+    needs_dlopen_none()
+    C = ffi.dlopen(None)
+    for base, expected_result in (('bin', 2), ('oct', 8), ('dec', 10), ('hex', 16)):
+        for index in range(7):
+            assert getattr(C, '{base}_{index}'.format(base=base, index=index)) == expected_result
diff --git a/testing/cffi0/test_verify.py b/testing/cffi0/test_verify.py
--- a/testing/cffi0/test_verify.py
+++ b/testing/cffi0/test_verify.py
@@ -1,4 +1,5 @@
 import py, re
+import pytest
 import sys, os, math, weakref
 from cffi import FFI, VerificationError, VerificationMissing, model, FFIError
 from testing.support import *
@@ -20,7 +21,8 @@
         extra_compile_args.append('-Qunused-arguments')
     else:
         # assume a standard gcc
-        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
+        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion',
+                              '-Wno-unused-parameter']
 
     class FFI(FFI):
         def verify(self, *args, **kwds):
@@ -589,7 +591,8 @@
     assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
     s = ffi.new("struct foo_s *")
     assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
-    py.test.raises(IndexError, 's.a[17]')
+    with pytest.raises(IndexError):
+        s.a[17]
 
 def test_struct_array_c99_1():
     if sys.platform == 'win32':
@@ -647,7 +650,8 @@
     ffi.verify("struct foo_s { int a:2, b:3; };")
     s = ffi.new("struct foo_s *")
     s.b = 3
-    py.test.raises(OverflowError, "s.b = 4")
+    with pytest.raises(OverflowError):
+        s.b = 4
     assert s.b == 3
 
 def test_struct_with_bitfield_enum():
@@ -1463,8 +1467,10 @@
     p = ffi.new("struct foo_s *")
     p.x = 1
     assert p.x is True
-    py.test.raises(OverflowError, "p.x = -1")
-    py.test.raises(TypeError, "p.x = 0.0")
+    with pytest.raises(OverflowError):
+        p.x = -1
+    with pytest.raises(TypeError):
+        p.x = 0.0
     assert lib.foop(1) is False
     assert lib.foop(True) is False
     assert lib.foop(0) is True
@@ -1532,7 +1538,8 @@
                 }
             """ % (type, type))
             p = ffi.new("struct foo_s *")
-            py.test.raises(TypeError, "p.x = 0.0")
+            with pytest.raises(TypeError):
+                p.x = 0.0
             assert lib.foo(42) == 0
             assert lib.foo(0) == 1
             py.test.raises(TypeError, lib.foo, 0.0)
@@ -2098,6 +2105,11 @@
             raise errors[0][1]
 
 def test_errno_working_even_with_pypys_jit():
+    # NOTE: on some platforms, to work correctly, this test needs to be
+    # compiled with -pthread.  Otherwise, the accesses to errno done from f()
+    # are compiled by assuming this small library won't be used from multiple
+    # threads, which is wrong.  If you see failures _and_ if you pass your
+    # own CFLAGS environment variable, please make sure "-pthread" is in it.
     ffi = FFI()
     ffi.cdef("int f(int);")
     lib = ffi.verify("""
diff --git a/testing/cffi1/test_ffi_obj.py b/testing/cffi1/test_ffi_obj.py
--- a/testing/cffi1/test_ffi_obj.py
+++ b/testing/cffi1/test_ffi_obj.py
@@ -1,4 +1,5 @@
 import py, sys
+import pytest
 import _cffi_backend as _cffi1_backend
 
 
@@ -85,9 +86,12 @@
 
 def test_ffi_no_attr():
     ffi = _cffi1_backend.FFI()
-    py.test.raises(AttributeError, "ffi.no_such_name")
-    py.test.raises(AttributeError, "ffi.no_such_name = 42")
-    py.test.raises(AttributeError, "del ffi.no_such_name")
+    with pytest.raises(AttributeError):
+        ffi.no_such_name
+    with pytest.raises(AttributeError):
+        ffi.no_such_name = 42
+    with pytest.raises(AttributeError):
+        del ffi.no_such_name
 
 def test_ffi_string():
     ffi = _cffi1_backend.FFI()
diff --git a/testing/cffi1/test_new_ffi_1.py b/testing/cffi1/test_new_ffi_1.py
--- a/testing/cffi1/test_new_ffi_1.py
+++ b/testing/cffi1/test_new_ffi_1.py
@@ -1,4 +1,5 @@
 import py
+import pytest
 import platform, imp
 import sys, os, ctypes
 import cffi
@@ -186,10 +187,14 @@
         p[9] = 43
         assert p[0] == 42
         assert p[9] == 43
-        py.test.raises(IndexError, "p[10]")
-        py.test.raises(IndexError, "p[10] = 44")
-        py.test.raises(IndexError, "p[-1]")
-        py.test.raises(IndexError, "p[-1] = 44")
+        with pytest.raises(IndexError):
+            p[10]
+        with pytest.raises(IndexError):
+            p[10] = 44
+        with pytest.raises(IndexError):
+            p[-1]
+        with pytest.raises(IndexError):
+            p[-1] = 44
 
     def test_new_array_args(self):
         # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
@@ -212,18 +217,21 @@
     def test_new_array_varsize(self):
         p = ffi.new("int[]", 10)     # a single integer is the length
         assert p[9] == 0
-        py.test.raises(IndexError, "p[10]")
+        with pytest.raises(IndexError):
+            p[10]
         #
         py.test.raises(TypeError, ffi.new, "int[]")
         #
         p = ffi.new("int[]", [-6, -7])    # a list is all the items, like C
         assert p[0] == -6
         assert p[1] == -7
-        py.test.raises(IndexError, "p[2]")
+        with pytest.raises(IndexError):
+            p[2]
         assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
         #
         p = ffi.new("int[]", 0)
-        py.test.raises(IndexError, "p[0]")
+        with pytest.raises(IndexError):
+            p[0]
         py.test.raises(ValueError, ffi.new, "int[]", -1)
         assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
 
@@ -324,7 +332,8 @@
         p[2][3] = 33
         assert p[0][0] == 10
         assert p[2][3] == 33
-        py.test.raises(IndexError, "p[1][-1]")
+        with pytest.raises(IndexError):
+            p[1][-1]
 
     def test_constructor_array_of_array(self):
         p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]])
@@ -445,7 +454,8 @@
         n = ffi.new("int*", 99)
         p = ffi.new("int*[]", [n])
         assert p[0][0] == 99
-        py.test.raises(TypeError, "p[0] = None")
+        with pytest.raises(TypeError):
+            p[0] = None
         p[0] = ffi.NULL
         assert p[0] == ffi.NULL
 
@@ -478,13 +488,15 @@
         assert s.a == s.b == s.c == 0
         s.b = -23
         assert s.b == -23
-        py.test.raises(OverflowError, "s.b = 32768")
+        with pytest.raises(OverflowError):
+            s.b = 32768
         #
         s = ffi.new("struct simple*", [-2, -3])
         assert s.a == -2
         assert s.b == -3
         assert s.c == 0
-        py.test.raises((AttributeError, TypeError), "del s.a")
+        with pytest.raises((AttributeError, TypeError)):
+            del s.a
         assert repr(s) == "<cdata 'struct simple *' owning %d bytes>" % (
             SIZE_OF_INT + 2 * SIZE_OF_SHORT)
         #
@@ -502,8 +514,10 @@
         assert s[0].a == s[0].b == s[0].c == 0
         s[0].b = -23
         assert s[0].b == s.b == -23
-        py.test.raises(OverflowError, "s[0].b = -32769")
-        py.test.raises(IndexError, "s[1]")
+        with pytest.raises(OverflowError):
+            s[0].b = -32769
+        with pytest.raises(IndexError):
+            s[1]
 
     def test_struct_opaque(self):
         py.test.raises(ffi.error, ffi.new, "struct baz*")
@@ -555,11 +569,13 @@
         u.b = -23
         assert u.b == -23
         assert u.a != 0
-        py.test.raises(OverflowError, "u.b = 32768")
+        with pytest.raises(OverflowError):
+            u.b = 32768
         #
         u = ffi.new("union simple_u*", [-2])
         assert u.a == -2
-        py.test.raises((AttributeError, TypeError), "del u.a")
+        with pytest.raises((AttributeError, TypeError)):
+            del u.a
         assert repr(u) == "<cdata 'union simple_u *' owning %d bytes>" % (
             SIZE_OF_INT,)
 
@@ -625,7 +641,8 @@
         p[3] = b'\x00'
         assert ffi.string(p) == b"hel"
         assert ffi.string(p, 2) == b"he"
-        py.test.raises(IndexError, "p[7] = b'X'")
+        with pytest.raises(IndexError):
+            p[7] = b'X'
         #
         a = ffi.new("char[]", b"hello\x00world")
         assert len(a) == 12
@@ -648,7 +665,8 @@
         p[3] = u+'\x00'
         assert ffi.string(p) == u+"hel"
         assert ffi.string(p, 123) == u+"hel"
-        py.test.raises(IndexError, "p[7] = u+'X'")
+        with pytest.raises(IndexError):
+            p[7] = u+'X'
         #
         a = ffi.new("wchar_t[]", u+"hello\x00world")
         assert len(a) == 12
@@ -664,7 +682,8 @@
         s = ffi.new("struct string*", [t])
         assert type(s.name) not in (bytes, str, unicode)
         assert ffi.string(s.name) == b"testing"
-        py.test.raises(TypeError, "s.name = None")
+        with pytest.raises(TypeError):
+            s.name = None
         s.name = ffi.NULL
         assert s.name == ffi.NULL
 
@@ -685,17 +704,20 @@
         a = ffi.new("int[]", [10, 11, 12])
         p = ffi.new("void **", a)
         vp = p[0]
-        py.test.raises(TypeError, "vp[0]")
+        with pytest.raises(TypeError):
+            vp[0]
         py.test.raises(TypeError, ffi.new, "short **", a)
         #
         s = ffi.new("struct voidp *")
         s.p = a    # works
         s.q = a    # works
-        py.test.raises(TypeError, "s.r = a")    # fails
+        with pytest.raises(TypeError):
+            s.r = a    # fails
         b = ffi.cast("int *", a)
         s.p = b    # works
         s.q = b    # works
-        py.test.raises(TypeError, "s.r = b")    # fails
+        with pytest.raises(TypeError):
+            s.r = b    # fails
 
     def test_functionptr_simple(self):
         py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
@@ -713,7 +735,8 @@
         q = ffi.new("int(**)(int)", p)
         assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
             SIZE_OF_PTR)
-        py.test.raises(TypeError, "q(43)")
+        with pytest.raises(TypeError):
+            q(43)
         res = q[0](43)
         assert res == 44
         q = ffi.cast("int(*)(int)", p)
@@ -922,10 +945,14 @@
         assert s.e in (4294967295, -1)     # two choices
         assert s[0].e in (4294967295, -1)
         s.e = s.e
-        py.test.raises(TypeError, "s.e = 'B3'")
-        py.test.raises(TypeError, "s.e = '2'")
-        py.test.raises(TypeError, "s.e = '#2'")
-        py.test.raises(TypeError, "s.e = '#7'")
+        with pytest.raises(TypeError):
+            s.e = 'B3'
+        with pytest.raises(TypeError):
+            s.e = '2'
+        with pytest.raises(TypeError):
+            s.e = '#2'
+        with pytest.raises(TypeError):
+            s.e = '#7'
 
     def test_enum_non_contiguous(self):
         # enum noncont { A4, B4=42, C4 };
@@ -947,11 +974,14 @@
 
     def test_array_of_struct(self):
         s = ffi.new("struct ab[1]")
-        py.test.raises(AttributeError, 's.b')
-        py.test.raises(AttributeError, 's.b = 412')
+        with pytest.raises(AttributeError):
+            s.b
+        with pytest.raises(AttributeError):
+            s.b = 412
         s[0].b = 412
         assert s[0].b == 412
-        py.test.raises(IndexError, 's[1]')
+        with pytest.raises(IndexError):
+            s[1]
 
     def test_pointer_to_array(self):
         p = ffi.new("int(**)[5]")
@@ -1000,17 +1030,23 @@
         assert ffi.sizeof("struct bitfield") == 8
         s = ffi.new("struct bitfield *")
         s.a = 511
-        py.test.raises(OverflowError, "s.a = 512")
-        py.test.raises(OverflowError, "s[0].a = 512")
+        with pytest.raises(OverflowError):
+            s.a = 512
+        with pytest.raises(OverflowError):
+            s[0].a = 512
         assert s.a == 511
         s.a = -512
-        py.test.raises(OverflowError, "s.a = -513")
-        py.test.raises(OverflowError, "s[0].a = -513")
+        with pytest.raises(OverflowError):
+            s.a = -513
+        with pytest.raises(OverflowError):
+            s[0].a = -513
         assert s.a == -512
         s.c = 3
         assert s.c == 3
-        py.test.raises(OverflowError, "s.c = 4")
-        py.test.raises(OverflowError, "s[0].c = 4")
+        with pytest.raises(OverflowError):
+            s.c = 4
+        with pytest.raises(OverflowError):
+            s[0].c = 4
         s.c = -4
         assert s.c == -4
 
@@ -1235,7 +1271,8 @@
         p = ffi.new("struct foo_s *", 10)     # a single integer is the length
         assert p.len == 0
         assert p.data[9] == 0
-        py.test.raises(IndexError, "p.data[10]")
+        with pytest.raises(IndexError):
+            p.data[10]
 
     def test_ffi_typeof_getcname(self):
         assert ffi.getctype("int") == "int"
@@ -1752,7 +1789,8 @@
         assert MYFOO == 42
         assert myfunc(43) == 44
         assert myvar == -5     # but can't be changed, so not very useful
-        py.test.raises(ImportError, "from _test_import_from_lib.lib import bar")
+        with pytest.raises(ImportError):
+            from _test_import_from_lib.lib import bar
         d = {}
         exec("from _test_import_from_lib.lib import *", d)
         assert (set(key for key in d if not key.startswith('_')) ==
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -1,5 +1,6 @@
 
 import sys, os, py
+import pytest
 from cffi import FFI, VerificationError, FFIError, CDefError
 from cffi import recompiler
 from testing.udir import udir
@@ -188,20 +189,26 @@
     assert lib.a == -2
     lib.a = -2147483648
     assert lib.a == -2147483648
-    py.test.raises(OverflowError, "lib.a = 2147483648")
-    py.test.raises(OverflowError, "lib.a = -2147483649")
+    with pytest.raises(OverflowError):
+        lib.a = 2147483648
+    with pytest.raises(OverflowError):
+        lib.a = -2147483649
     lib.b = 525      # try with the first access being in setattr, too
     assert lib.b == 525
-    py.test.raises(AttributeError, "del lib.a")
-    py.test.raises(AttributeError, "del lib.c")
-    py.test.raises(AttributeError, "del lib.foobarbaz")
+    with pytest.raises(AttributeError):
+        del lib.a
+    with pytest.raises(AttributeError):
+        del lib.c
+    with pytest.raises(AttributeError):
+        del lib.foobarbaz
 
 def test_macro():
     ffi = FFI()
     ffi.cdef("#define FOOBAR ...")
     lib = verify(ffi, 'test_macro', "#define FOOBAR (-6912)")
     assert lib.FOOBAR == -6912
-    py.test.raises(AttributeError, "lib.FOOBAR = 2")
+    with pytest.raises(AttributeError):
+        lib.FOOBAR = 2
 
 def test_macro_check_value():
     # the value '-0x80000000' in C sources does not have a clear meaning
@@ -247,7 +254,8 @@
     ffi.cdef("static const int FOOBAR;")
     lib = verify(ffi, 'test_constant', "#define FOOBAR (-6912)")
     assert lib.FOOBAR == -6912
-    py.test.raises(AttributeError, "lib.FOOBAR = 2")
+    with pytest.raises(AttributeError):
+        lib.FOOBAR = 2
 
 def test_check_value_of_static_const():
     ffi = FFI()
@@ -263,7 +271,8 @@
     ffi.cdef("static const double FOOBAR;")
     lib = verify(ffi, 'test_constant_nonint', "#define FOOBAR (-6912.5)")
     assert lib.FOOBAR == -6912.5
-    py.test.raises(AttributeError, "lib.FOOBAR = 2")
+    with pytest.raises(AttributeError):
+        lib.FOOBAR = 2
 
 def test_constant_ptr():
     ffi = FFI()
@@ -315,8 +324,10 @@
     p = ffi.new("struct foo_s *", {'a': -32768, 'b': -2147483648})
     assert p.a == -32768
     assert p.b == -2147483648
-    py.test.raises(OverflowError, "p.a -= 1")
-    py.test.raises(OverflowError, "p.b -= 1")
+    with pytest.raises(OverflowError):
+        p.a -= 1
+    with pytest.raises(OverflowError):
+        p.b -= 1
     q = ffi.new("struct bar_s *", {'f': p})
     assert q.f == p
     #
@@ -387,8 +398,10 @@
     assert ffi.sizeof("struct foo_s") == (42 + 11) * 4
     p = ffi.new("struct foo_s *")
     assert p.a[41] == p.b[10] == 0
-    py.test.raises(IndexError, "p.a[42]")
-    py.test.raises(IndexError, "p.b[11]")
+    with pytest.raises(IndexError):
+        p.a[42]
+    with pytest.raises(IndexError):
+        p.b[11]
 
 def test_dotdotdot_global_array():
     ffi = FFI()
@@ -398,8 +411,10 @@
     assert ffi.sizeof(lib.aa) == 41 * 4
     assert ffi.sizeof(lib.bb) == 12 * 4
     assert lib.aa[40] == lib.bb[11] == 0
-    py.test.raises(IndexError, "lib.aa[41]")
-    py.test.raises(IndexError, "lib.bb[12]")
+    with pytest.raises(IndexError):
+        lib.aa[41]
+    with pytest.raises(IndexError):
+        lib.bb[12]
 
 def test_misdeclared_field_1():
     ffi = FFI()
@@ -1020,8 +1035,10 @@
     assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
     assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int')
     assert s.a[4][7] == 0
-    py.test.raises(IndexError, 's.a[4][8]')
-    py.test.raises(IndexError, 's.a[5][0]')
+    with pytest.raises(IndexError):
+        s.a[4][8]


More information about the pypy-commit mailing list