Hello community,

here is the log from the commit of package python3-cffi for openSUSE:Factory 
checked in at 2015-06-16 14:05:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python3-cffi (Old)
 and      /work/SRC/openSUSE:Factory/.python3-cffi.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python3-cffi"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python3-cffi/python3-cffi.changes        
2015-06-02 10:04:07.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python3-cffi.new/python3-cffi.changes   
2015-06-16 14:05:59.000000000 +0200
@@ -1,0 +2,18 @@
+Mon Jun 15 02:13:07 UTC 2015 - a...@gmx.de
+
+- update to version 1.1.2:
+  * ffi.gc(): fixed a race condition in multithreaded programs
+    introduced in 1.1.1
+
+- changes from version 1.1.1:
+  * Out-of-line mode: ffi.string(), ffi.buffer() and ffi.getwinerror()
+    didn't accept their arguments as keyword arguments, unlike their
+    in-line mode equivalent. (It worked in PyPy.)
+  * Out-of-line ABI mode: documented a restriction of ffi.dlopen()
+    when compared to the in-line mode.
+  * ffi.gc(): when called several times with equal pointers, it was
+    accidentally registering only the last destructor, or even none at
+    all depending on details. (It was correctly registering all of
+    them only in PyPy, and only with the out-of-line FFIs.)
+
+-------------------------------------------------------------------

Old:
----
  cffi-1.1.0.tar.gz

New:
----
  cffi-1.1.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python3-cffi.spec ++++++
--- /var/tmp/diff_new_pack.eQaebf/_old  2015-06-16 14:06:00.000000000 +0200
+++ /var/tmp/diff_new_pack.eQaebf/_new  2015-06-16 14:06:00.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python3-cffi
-Version:        1.1.0
+Version:        1.1.2
 Release:        0
 Summary:        Foreign Function Interface for Python calling C code
 License:        MIT

++++++ cffi-1.1.0.tar.gz -> cffi-1.1.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/PKG-INFO new/cffi-1.1.2/PKG-INFO
--- old/cffi-1.1.0/PKG-INFO     2015-05-30 21:48:01.000000000 +0200
+++ new/cffi-1.1.2/PKG-INFO     2015-06-09 12:04:16.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.1.0
+Version: 1.1.2
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/c/_cffi_backend.c 
new/cffi-1.1.2/c/_cffi_backend.c
--- old/cffi-1.1.0/c/_cffi_backend.c    2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/c/_cffi_backend.c    2015-06-09 12:04:10.000000000 +0200
@@ -5158,12 +5158,14 @@
     return PyText_FromStringAndSize(s, namelen + replacelen);
 }
 
-static PyObject *b_string(PyObject *self, PyObject *args)
+static PyObject *b_string(PyObject *self, PyObject *args, PyObject *kwds)
 {
     CDataObject *cd;
     Py_ssize_t maxlen = -1;
-    if (!PyArg_ParseTuple(args, "O!|n:string",
-                          &CData_Type, &cd, &maxlen))
+    static char *keywords[] = {"cdata", "maxlen", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|n:string", keywords,
+                                     &CData_Type, &cd, &maxlen))
         return NULL;
 
     if (cd->c_type->ct_itemdescr != NULL &&
@@ -5246,12 +5248,14 @@
     return NULL;
 }
 
-static PyObject *b_buffer(PyObject *self, PyObject *args)
+static PyObject *b_buffer(PyObject *self, PyObject *args, PyObject *kwds)
 {
     CDataObject *cd;
     Py_ssize_t size = -1;
-    if (!PyArg_ParseTuple(args, "O!|n:buffer",
-                          &CData_Type, &cd, &size))
+    static char *keywords[] = {"cdata", "size", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|n:buffer", keywords,
+                                     &CData_Type, &cd, &size))
         return NULL;
 
     if (cd->c_type->ct_flags & CT_POINTER) {
@@ -5351,6 +5355,12 @@
         return NULL;
     }
     x = (PyObject *)(raw + 42);
+    if (Py_REFCNT(x) <= 0) {
+        Py_FatalError("ffi.from_handle() detected that the address passed "
+                      "points to garbage. If it is really the result of "
+                      "ffi.new_handle(), then the Python object has already "
+                      "been garbage collected");
+    }
     Py_INCREF(x);
     return x;
 }
@@ -5790,15 +5800,15 @@
     {"typeoffsetof", b_typeoffsetof, METH_VARARGS},
     {"rawaddressof", b_rawaddressof, METH_VARARGS},
     {"getcname", b_getcname, METH_VARARGS},
-    {"string", b_string, METH_VARARGS},
-    {"buffer", b_buffer, METH_VARARGS},
+    {"string", (PyCFunction)b_string, METH_VARARGS | METH_KEYWORDS},
+    {"buffer", (PyCFunction)b_buffer, METH_VARARGS | METH_KEYWORDS},
     {"get_errno", b_get_errno, METH_NOARGS},
     {"set_errno", b_set_errno, METH_O},
     {"newp_handle", b_newp_handle, METH_VARARGS},
     {"from_handle", b_from_handle, METH_O},
     {"from_buffer", b_from_buffer, METH_VARARGS},
 #ifdef MS_WIN32
-    {"getwinerror", b_getwinerror, METH_VARARGS},
+    {"getwinerror", (PyCFunction)b_getwinerror, METH_VARARGS | METH_KEYWORDS},
 #endif
     {"_get_types", b__get_types, METH_NOARGS},
     {"_testfunc", b__testfunc, METH_VARARGS},
@@ -6053,7 +6063,7 @@
     if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0)
         INITERROR;
 
-    v = PyText_FromString("1.1.0");
+    v = PyText_FromString("1.1.2");
     if (v == NULL || PyModule_AddObject(m, "__version__", v) < 0)
         INITERROR;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/c/cgc.c new/cffi-1.1.2/c/cgc.c
--- old/cffi-1.1.0/c/cgc.c      2015-05-30 21:45:20.000000000 +0200
+++ new/cffi-1.1.2/c/cgc.c      2015-06-09 12:04:07.000000000 +0200
@@ -2,79 +2,121 @@
 /* translated to C from cffi/gc_weakref.py */
 
 
-static PyObject *const_name_pop;
-
-static PyObject *gc_wref_remove(PyObject *ffi_wref_data, PyObject *arg)
+static PyObject *gc_wref_remove(PyObject *ffi_wref_tup, PyObject *key)
 {
-    PyObject *destructor, *cdata, *x;
-    PyObject *res = PyObject_CallMethodObjArgs(ffi_wref_data,
-                                               const_name_pop, arg, NULL);
-    if (res == NULL)
-        return NULL;
-
-    assert(PyTuple_Check(res));
-    destructor = PyTuple_GET_ITEM(res, 0);
-    cdata = PyTuple_GET_ITEM(res, 1);
-    x = PyObject_CallFunctionObjArgs(destructor, cdata, NULL);
-    Py_DECREF(res);
-    if (x == NULL)
-        return NULL;
-    Py_DECREF(x);
-
-    Py_INCREF(Py_None);
-    return Py_None;
+    FFIObject *ffi;
+    PyObject *indexobj, *destructor, *cdata, *freelist, *result;
+    Py_ssize_t index;
+
+    /* here, tup is a 4-tuple (ffi, destructor, cdata, index) */
+    if (!PyTuple_Check(ffi_wref_tup))
+        goto oops;    /* should never occur */
+
+    ffi = (FFIObject *)PyTuple_GET_ITEM(ffi_wref_tup, 0);
+    destructor = PyTuple_GET_ITEM(ffi_wref_tup, 1);
+    cdata = PyTuple_GET_ITEM(ffi_wref_tup, 2);
+    indexobj = PyTuple_GET_ITEM(ffi_wref_tup, 3);
+
+    index = PyInt_AsSsize_t(indexobj);
+    if (index < 0)
+        goto oops;    /* should never occur */
+
+    /* assert gc_wrefs[index] is key */
+    if (PyList_GET_ITEM(ffi->gc_wrefs, index) != key)
+        goto oops;    /* should never occur */
+
+    /* gc_wrefs[index] = freelist */
+    /* transfer ownership of 'freelist' to 'gc_wrefs[index]' */
+    freelist = ffi->gc_wrefs_freelist;
+    PyList_SET_ITEM(ffi->gc_wrefs, index, freelist);
+
+    /* freelist = index */
+    ffi->gc_wrefs_freelist = indexobj;
+    Py_INCREF(indexobj);
+
+    /* destructor(cdata) */
+    result = PyObject_CallFunctionObjArgs(destructor, cdata, NULL);
+
+    Py_DECREF(key);    /* free the reference that was in 'gc_wrefs[index]' */
+    return result;
+
+ oops:
+    PyErr_SetString(PyExc_SystemError, "cgc: internal inconsistency");
+    /* random leaks may follow */
+    return NULL;
 }
 
 static PyMethodDef remove_callback = {
     "gc_wref_remove", (PyCFunction)gc_wref_remove, METH_O
 };
 
-static PyObject *gc_weakrefs_build(FFIObject *ffi, CDataObject *cd,
+static PyObject *gc_weakrefs_build(FFIObject *ffi, CDataObject *cdata,
                                    PyObject *destructor)
 {
-    PyObject *new_cdata, *ref = NULL, *tup = NULL;
+    PyObject *new_cdata, *ref = NULL, *tup = NULL, *remove_fn = NULL;
+    Py_ssize_t index;
+    PyObject *datalist;
 
     if (ffi->gc_wrefs == NULL) {
         /* initialize */
-        PyObject *data;
-
-        if (const_name_pop == NULL) {
-            const_name_pop = PyText_InternFromString("pop");
-            if (const_name_pop == NULL)
-                return NULL;
-        }
-        data = PyDict_New();
-        if (data == NULL)
-            return NULL;
-        ffi->gc_wrefs = PyCFunction_New(&remove_callback, data);
-        Py_DECREF(data);
-        if (ffi->gc_wrefs == NULL)
+        datalist = PyList_New(0);
+        if (datalist == NULL)
             return NULL;
+        ffi->gc_wrefs = datalist;
+        assert(ffi->gc_wrefs_freelist == NULL);
+        ffi->gc_wrefs_freelist = Py_None;
+        Py_INCREF(Py_None);
     }
 
-    new_cdata = do_cast(cd->c_type, (PyObject *)cd);
+    /* new_cdata = self.ffi.cast(typeof(cdata), cdata) */
+    new_cdata = do_cast(cdata->c_type, (PyObject *)cdata);
     if (new_cdata == NULL)
         goto error;
 
-    ref = PyWeakref_NewRef(new_cdata, ffi->gc_wrefs);
-    if (ref == NULL)
+    /* if freelist is None: */
+    datalist = ffi->gc_wrefs;
+    if (ffi->gc_wrefs_freelist == Py_None) {
+        /* index = len(gc_wrefs) */
+        index = PyList_GET_SIZE(datalist);
+        /* gc_wrefs.append(None) */
+        if (PyList_Append(datalist, Py_None) < 0)
+            goto error;
+        tup = Py_BuildValue("OOOn", ffi, destructor, cdata, index);
+    }
+    else {
+        /* index = freelist */
+        index = PyInt_AsSsize_t(ffi->gc_wrefs_freelist);
+        if (index < 0)
+            goto error;   /* should not occur */
+        tup = PyTuple_Pack(4, ffi, destructor, cdata, ffi->gc_wrefs_freelist);
+    }
+    if (tup == NULL)
         goto error;
 
-    tup = PyTuple_Pack(2, destructor, cd);
-    if (tup == NULL)
+    remove_fn = PyCFunction_New(&remove_callback, tup);
+    if (remove_fn == NULL)
         goto error;
 
-    /* the 'self' of the function 'gc_wrefs' is actually the data dict */
-    if (PyDict_SetItem(PyCFunction_GET_SELF(ffi->gc_wrefs), ref, tup) < 0)
+    ref = PyWeakref_NewRef(new_cdata, remove_fn);
+    if (ref == NULL)
         goto error;
 
+    /* freelist = gc_wrefs[index] (which is None if we just did append(None)) 
*/
+    /* transfer ownership of 'datalist[index]' into gc_wrefs_freelist */
+    Py_DECREF(ffi->gc_wrefs_freelist);
+    ffi->gc_wrefs_freelist = PyList_GET_ITEM(datalist, index);
+    /* gc_wrefs[index] = ref */
+    /* transfer ownership of 'ref' into 'datalist[index]' */
+    PyList_SET_ITEM(datalist, index, ref);
+    Py_DECREF(remove_fn);
     Py_DECREF(tup);
-    Py_DECREF(ref);
+
     return new_cdata;
 
  error:
     Py_XDECREF(new_cdata);
     Py_XDECREF(ref);
     Py_XDECREF(tup);
+    Py_XDECREF(remove_fn);
     return NULL;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/c/ffi_obj.c new/cffi-1.1.2/c/ffi_obj.c
--- old/cffi-1.1.0/c/ffi_obj.c  2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/c/ffi_obj.c  2015-06-09 12:04:07.000000000 +0200
@@ -23,7 +23,7 @@
 
 struct FFIObject_s {
     PyObject_HEAD
-    PyObject *gc_wrefs;
+    PyObject *gc_wrefs, *gc_wrefs_freelist;
     struct _cffi_parse_info_s info;
     char ctx_is_static, ctx_is_nonempty;
     builder_c_t types_builder;
@@ -51,6 +51,7 @@
         return NULL;
     }
     ffi->gc_wrefs = NULL;
+    ffi->gc_wrefs_freelist = NULL;
     ffi->info.ctx = &ffi->types_builder.ctx;
     ffi->info.output = internal_output;
     ffi->info.output_size = FFI_COMPLEXITY_OUTPUT;
@@ -63,6 +64,7 @@
 {
     PyObject_GC_UnTrack(ffi);
     Py_XDECREF(ffi->gc_wrefs);
+    Py_XDECREF(ffi->gc_wrefs_freelist);
 
     free_builder_c(&ffi->types_builder, ffi->ctx_is_static);
 
@@ -140,6 +142,38 @@
 #define ACCEPT_ALL      (ACCEPT_STRING | ACCEPT_CTYPE | ACCEPT_CDATA)
 #define CONSIDER_FN_AS_FNPTR  8
 
+static CTypeDescrObject *_ffi_bad_type(FFIObject *ffi, char *input_text)
+{
+    size_t length = strlen(input_text);
+    char *extra;
+
+    if (length > 500) {
+        extra = "";
+    }
+    else {
+        char *p;
+        size_t i, num_spaces = ffi->info.error_location;
+        extra = alloca(length + num_spaces + 4);
+        p = extra;
+        *p++ = '\n';
+        for (i = 0; i < length; i++) {
+            if (' ' <= input_text[i] && input_text[i] < 0x7f)
+                *p++ = input_text[i];
+            else if (input_text[i] == '\t' || input_text[i] == '\n')
+                *p++ = ' ';
+            else
+                *p++ = '?';
+        }
+        *p++ = '\n';
+        memset(p, ' ', num_spaces);
+        p += num_spaces;
+        *p++ = '^';
+        *p++ = 0;
+    }
+    PyErr_Format(FFIError, "%s%s", ffi->info.error_message, extra);
+    return NULL;
+}
+
 static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg,
                                    int accept)
 {
@@ -153,15 +187,9 @@
         if (x == NULL) {
             char *input_text = PyText_AS_UTF8(arg);
             int err, index = parse_c_type(&ffi->info, input_text);
-            if (index < 0) {
-                size_t num_spaces = ffi->info.error_location;
-                char *spaces = alloca(num_spaces + 1);
-                memset(spaces, ' ', num_spaces);
-                spaces[num_spaces] = '\0';
-                PyErr_Format(FFIError, "%s\n%s\n%s^", ffi->info.error_message,
-                             input_text, spaces);
-                return NULL;
-            }
+            if (index < 0)
+                return _ffi_bad_type(ffi, input_text);
+
             x = realize_c_type_or_func(&ffi->types_builder,
                                        ffi->info.output, index);
             if (x == NULL)
@@ -774,7 +802,7 @@
 static PyMethodDef ffi_methods[] = {
  {"addressof",  (PyCFunction)ffi_addressof,  METH_VARARGS, ffi_addressof_doc},
  {"alignof",    (PyCFunction)ffi_alignof,    METH_O,       ffi_alignof_doc},
- {"buffer",     (PyCFunction)ffi_buffer,     METH_VARARGS, ffi_buffer_doc},
+ {"buffer",     (PyCFunction)ffi_buffer,     METH_VKW,     ffi_buffer_doc},
  {"callback",   (PyCFunction)ffi_callback,   METH_VKW,     ffi_callback_doc},
  {"cast",       (PyCFunction)ffi_cast,       METH_VARARGS, ffi_cast_doc},
  {"dlclose",    (PyCFunction)ffi_dlclose,    METH_VARARGS, ffi_dlclose_doc},
@@ -784,14 +812,14 @@
  {"gc",         (PyCFunction)ffi_gc,         METH_VKW,     ffi_gc_doc},
  {"getctype",   (PyCFunction)ffi_getctype,   METH_VKW,     ffi_getctype_doc},
 #ifdef MS_WIN32
- {"getwinerror",(PyCFunction)ffi_getwinerror,METH_VARARGS, 
ffi_getwinerror_doc},
+ {"getwinerror",(PyCFunction)ffi_getwinerror,METH_VKW,     
ffi_getwinerror_doc},
 #endif
  {"integer_const",(PyCFunction)ffi_int_const,METH_VKW,     ffi_int_const_doc},
  {"new",        (PyCFunction)ffi_new,        METH_VKW,     ffi_new_doc},
  {"new_handle", (PyCFunction)ffi_new_handle, METH_O,       ffi_new_handle_doc},
  {"offsetof",   (PyCFunction)ffi_offsetof,   METH_VARARGS, ffi_offsetof_doc},
  {"sizeof",     (PyCFunction)ffi_sizeof,     METH_O,       ffi_sizeof_doc},
- {"string",     (PyCFunction)ffi_string,     METH_VARARGS, ffi_string_doc},
+ {"string",     (PyCFunction)ffi_string,     METH_VKW,     ffi_string_doc},
  {"typeof",     (PyCFunction)ffi_typeof,     METH_O,       ffi_typeof_doc},
  {NULL}
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/c/lib_obj.c new/cffi-1.1.2/c/lib_obj.c
--- old/cffi-1.1.0/c/lib_obj.c  2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/c/lib_obj.c  2015-06-09 12:04:07.000000000 +0200
@@ -300,7 +300,7 @@
     case _CFFI_OP_GLOBAL_VAR:
     {
         /* global variable of the exact type specified here */
-        size_t g_size = (size_t)g->size_or_direct_fn;
+        Py_ssize_t g_size = (Py_ssize_t)g->size_or_direct_fn;
         ct = realize_c_type(types_builder, types_builder->ctx.types,
                             _CFFI_GETARG(g->type_op));
         if (ct == NULL)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/c/misc_win32.h 
new/cffi-1.1.2/c/misc_win32.h
--- old/cffi-1.1.0/c/misc_win32.h       2015-05-30 21:45:20.000000000 +0200
+++ new/cffi-1.1.2/c/misc_win32.h       2015-06-09 12:04:07.000000000 +0200
@@ -82,14 +82,15 @@
 }
 
 #if PY_MAJOR_VERSION >= 3
-static PyObject *b_getwinerror(PyObject *self, PyObject *args)
+static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
 {
     int err = -1;
     int len;
     WCHAR *s_buf = NULL; /* Free via LocalFree */
     PyObject *v, *message;
+    static char *keywords[] = {"code", NULL};
 
-    if (!PyArg_ParseTuple(args, "|i", &err))
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err))
         return NULL;
 
     if (err == -1) {
@@ -129,7 +130,7 @@
     return v;
 }
 #else
-static PyObject *b_getwinerror(PyObject *self, PyObject *args)
+static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
 {
     int err = -1;
     int len;
@@ -137,8 +138,9 @@
     char *s_buf = NULL; /* Free via LocalFree */
     char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
     PyObject *v;
+    static char *keywords[] = {"code", NULL};
 
-    if (!PyArg_ParseTuple(args, "|i", &err))
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err))
         return NULL;
 
     if (err == -1) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/c/realize_c_type.c 
new/cffi-1.1.2/c/realize_c_type.c
--- old/cffi-1.1.0/c/realize_c_type.c   2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/c/realize_c_type.c   2015-06-09 12:04:07.000000000 +0200
@@ -60,7 +60,7 @@
 static void free_builder_c(builder_c_t *builder, int ctx_is_static)
 {
     if (!ctx_is_static) {
-        int i;
+        size_t i;
         const void *mem[] = {builder->ctx.types,
                              builder->ctx.globals,
                              builder->ctx.struct_unions,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/c/test_c.py new/cffi-1.1.2/c/test_c.py
--- old/cffi-1.1.0/c/test_c.py  2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/c/test_c.py  2015-06-09 12:04:10.000000000 +0200
@@ -3346,4 +3346,4 @@
 
 def test_version():
     # this test is here mostly for PyPy
-    assert __version__ == "1.1.0"
+    assert __version__ == "1.1.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/cffi/__init__.py 
new/cffi-1.1.2/cffi/__init__.py
--- old/cffi-1.1.0/cffi/__init__.py     2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/cffi/__init__.py     2015-06-09 12:04:10.000000000 +0200
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.1.0"
-__version_info__ = (1, 1, 0)
+__version__ = "1.1.2"
+__version_info__ = (1, 1, 2)
 
 # 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/cffi/gc_weakref.py 
new/cffi-1.1.2/cffi/gc_weakref.py
--- old/cffi-1.1.0/cffi/gc_weakref.py   2015-05-30 21:45:20.000000000 +0200
+++ new/cffi-1.1.2/cffi/gc_weakref.py   2015-06-09 12:04:07.000000000 +0200
@@ -2,18 +2,23 @@
 
 
 class GcWeakrefs(object):
-    # code copied and adapted from WeakKeyDictionary.
-
     def __init__(self, ffi):
         self.ffi = ffi
-        self.data = data = {}
-        def remove(k):
-            destructor, cdata = data.pop(k)
-            destructor(cdata)
-        self.remove = remove
+        self.data = {}
+        self.nextindex = 0
 
     def build(self, cdata, destructor):
         # make a new cdata of the same type as the original one
         new_cdata = self.ffi.cast(self.ffi._backend.typeof(cdata), cdata)
-        self.data[ref(new_cdata, self.remove)] = destructor, cdata
+        #
+        def remove(key):
+            # careful, this function is not protected by any lock
+            old_key = self.data.pop(index)
+            assert old_key is key
+            destructor(cdata)
+        #
+        key = ref(new_cdata, remove)
+        index = self.nextindex
+        self.nextindex = index + 1     # we're protected by the lock here
+        self.data[index] = key
         return new_cdata
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/cffi/recompiler.py 
new/cffi-1.1.2/cffi/recompiler.py
--- old/cffi-1.1.0/cffi/recompiler.py   2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/cffi/recompiler.py   2015-06-09 12:04:10.000000000 +0200
@@ -775,7 +775,8 @@
             try:
                 if ftype.is_integer_type() or fbitsize >= 0:
                     # accept all integers, but complain on float or double
-                    prnt('  (void)((p->%s) << 1);' % fname)
+                    prnt("  (void)((p->%s) << 1);  /* check that '%s.%s' is "
+                         "an integer */" % (fname, cname, fname))
                     continue
                 # only accept exactly the type declared, except that '[]'
                 # is interpreted as a '*' and so will match any array length.
@@ -949,7 +950,7 @@
             prnt('{')
             prnt('  int n = (%s) <= 0;' % (name,))
             prnt('  *o = (unsigned long long)((%s) << 0);'
-                 '  /* check that we get an integer */' % (name,))
+                 '  /* check that %s is an integer */' % (name, name))
             if check_value is not None:
                 if check_value > 0:
                     check_value = '%dU' % (check_value,)
@@ -1088,8 +1089,9 @@
         self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index)
 
     def _emit_bytecode_UnknownIntegerType(self, tp, index):
-        s = '_cffi_prim_int(sizeof(%s), (((%s)-1) << 0) <= 0)' % (
-            tp.name, tp.name)
+        s = ('_cffi_prim_int(sizeof(%s), (\n'
+             '           ((%s)-1) << 0 /* check that %s is an integer type 
*/\n'
+             '         ) <= 0)' % (tp.name, tp.name, tp.name))
         self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s)
 
     def _emit_bytecode_RawFunctionType(self, tp, index):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/cffi/setuptools_ext.py 
new/cffi-1.1.2/cffi/setuptools_ext.py
--- old/cffi-1.1.0/cffi/setuptools_ext.py       2015-05-30 21:45:50.000000000 
+0200
+++ new/cffi-1.1.2/cffi/setuptools_ext.py       2015-06-09 12:04:07.000000000 
+0200
@@ -18,7 +18,9 @@
     # __init__.py files may already try to import the file that
     # we are generating.
     with open(filename) as f:
-        code = compile(f.read(), filename, 'exec')
+        src = f.read()
+    src += '\n'      # Python 2.6 compatibility
+    code = compile(src, filename, 'exec')
     exec(code, glob, glob)
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/cffi/vengine_gen.py 
new/cffi-1.1.2/cffi/vengine_gen.py
--- old/cffi-1.1.0/cffi/vengine_gen.py  2015-05-30 21:45:20.000000000 +0200
+++ new/cffi-1.1.2/cffi/vengine_gen.py  2015-06-09 12:04:07.000000000 +0200
@@ -402,12 +402,16 @@
         else:
             assert tp is not None
             assert check_value is None
-            prnt(tp.get_c_name(' %s(void)' % funcname, name),)
-            prnt('{')
             if category == 'var':
                 ampersand = '&'
             else:
                 ampersand = ''
+            extra = ''
+            if category == 'const' and isinstance(tp, model.StructOrUnion):
+                extra = 'const *'
+                ampersand = '&'
+            prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name))
+            prnt('{')
             prnt('  return (%s%s);' % (ampersand, name))
             prnt('}')
         prnt()
@@ -436,9 +440,14 @@
                 value += (1 << (8*self.ffi.sizeof(BLongLong)))
         else:
             assert check_value is None
-            BFunc = self.ffi._typeof_locked(tp.get_c_name('(*)(void)', 
name))[0]
+            fntypeextra = '(*)(void)'
+            if isinstance(tp, model.StructOrUnion):
+                fntypeextra = '*' + fntypeextra
+            BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, 
name))[0]
             function = module.load_function(BFunc, funcname)
             value = function()
+            if isinstance(tp, model.StructOrUnion):
+                value = value[0]
         return value
 
     def _loaded_gen_constant(self, tp, name, module, library):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/cffi.egg-info/PKG-INFO 
new/cffi-1.1.2/cffi.egg-info/PKG-INFO
--- old/cffi-1.1.0/cffi.egg-info/PKG-INFO       2015-05-30 21:48:01.000000000 
+0200
+++ new/cffi-1.1.2/cffi.egg-info/PKG-INFO       2015-06-09 12:04:15.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.1.0
+Version: 1.1.2
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/doc/source/cdef.rst 
new/cffi-1.1.2/doc/source/cdef.rst
--- old/cffi-1.1.0/doc/source/cdef.rst  2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/doc/source/cdef.rst  2015-06-09 12:04:10.000000000 +0200
@@ -278,6 +278,18 @@
 needed.  (Alternatively, the out-of-line FFIs have a method
 ``ffi.dlclose(lib)``.)
 
+.. _dlopen-note:
+
+Note: the old version of ``ffi.dlopen()`` from the in-line ABI mode
+tries to use ``ctypes.util.find_library()`` if it cannot directly find
+the library.  The newer out-of-line ``ffi.dlopen()`` no longer does it
+automatically; it simply passes the argument it receives to the
+underlying ``dlopen()`` or ``LoadLibrary()`` function.  If needed, it
+is up to you to use ``ctypes.util.find_library()`` or any other way to
+look for the library's filename.  This also means that
+``ffi.dlopen(None)`` no longer work on Windows; try instead
+``ffi.dlopen(ctypes.util.find_library('c'))``.
+
 
 ffi.set_source(): preparing out-of-line modules
 -----------------------------------------------
@@ -375,7 +387,7 @@
 
 *  *New in version 1.1:* integer types: the syntax "``typedef
    int... foo_t;``" declares the type ``foo_t`` as an integer type
-   whose exact size and signness is not specified.  The compiler will
+   whose exact size and signedness is not specified.  The compiler will
    figure it out.  (Note that this requires ``set_source()``; it does
    not work with ``verify()``.)  The ``int...`` can be replaced with
    ``long...`` or ``unsigned long long...`` or any other primitive
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/doc/source/conf.py 
new/cffi-1.1.2/doc/source/conf.py
--- old/cffi-1.1.0/doc/source/conf.py   2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/doc/source/conf.py   2015-06-09 12:04:10.000000000 +0200
@@ -47,7 +47,7 @@
 # The short X.Y version.
 version = '1.1'
 # The full version, including alpha/beta/rc tags.
-release = '1.1.0'
+release = '1.1.2'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/doc/source/installation.rst 
new/cffi-1.1.2/doc/source/installation.rst
--- old/cffi-1.1.0/doc/source/installation.rst  2015-05-30 21:45:50.000000000 
+0200
+++ new/cffi-1.1.2/doc/source/installation.rst  2015-06-09 12:04:10.000000000 
+0200
@@ -51,7 +51,7 @@
 
 Download and Installation:
 
-* http://pypi.python.org/packages/source/c/cffi/cffi-1.1.0.tar.gz
+* http://pypi.python.org/packages/source/c/cffi/cffi-1.1.2.tar.gz
 
    - Or grab the most current version by following the instructions below.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/doc/source/overview.rst 
new/cffi-1.1.2/doc/source/overview.rst
--- old/cffi-1.1.0/doc/source/overview.rst      2015-05-30 21:45:20.000000000 
+0200
+++ new/cffi-1.1.2/doc/source/overview.rst      2015-06-09 12:04:07.000000000 
+0200
@@ -82,9 +82,21 @@
 
     from _simple_example import ffi
 
-    lib = ffi.dlopen(None)         # or path to a library
+    lib = ffi.dlopen(None)      # Unix: open the standard C library
+    #import ctypes.util         # or, try this on Windows:
+    #lib = ffi.dlopen(ctypes.util.find_library("c"))
+
     lib.printf(b"hi there, number %d\n", ffi.cast("int", 2))
 
+Note that this ``ffi.dlopen()``, unlike the one from in-line mode,
+does not invoke any additional magic to locate the library: it must be
+a path name (with or without a directory), as required by the C
+``dlopen()`` or ``LoadLibrary()`` functions.  This means that
+``ffi.dlopen("libfoo.so")`` is ok, but ``ffi.dlopen("foo")`` is not.
+In the latter case, you could replace it with
+``ffi.dlopen(ctypes.util.find_library("foo"))``.  Also, None is only
+recognized on Unix to open the standard C library.
+
 For distribution purposes, remember that there is a new
 ``_simple_example.py`` file generated.  You can either include it
 statically within your project's source files, or, with Setuptools,
@@ -202,6 +214,13 @@
 .. _struct: http://docs.python.org/library/struct.html
 .. _array: http://docs.python.org/library/array.html
 
+This example also admits an out-of-line equivalent.  It is similar to
+`Out-of-line example (ABI level, out-of-line)`_ above, but without any
+call to ``ffi.dlopen()``.  In the main program, you write ``from
+_simple_example import ffi`` and then the same content as the in-line
+example above starting from the line ``image = ffi.new("pixel_t[]",
+800*600)``.
+
 
 .. _performance:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/doc/source/whatsnew.rst 
new/cffi-1.1.2/doc/source/whatsnew.rst
--- old/cffi-1.1.0/doc/source/whatsnew.rst      2015-05-30 21:45:50.000000000 
+0200
+++ new/cffi-1.1.2/doc/source/whatsnew.rst      2015-06-09 12:04:10.000000000 
+0200
@@ -3,11 +3,36 @@
 ======================
 
 
+1.1.2
+=====
+
+* ``ffi.gc()``: fixed a race condition in multithreaded programs
+  introduced in 1.1.1
+
+
+1.1.1
+=====
+
+* Out-of-line mode: ``ffi.string()``, ``ffi.buffer()`` and
+  ``ffi.getwinerror()`` didn't accept their arguments as keyword
+  arguments, unlike their in-line mode equivalent.  (It worked in PyPy.)
+
+* Out-of-line ABI mode: documented a restriction__ of ``ffi.dlopen()``
+  when compared to the in-line mode.
+
+* ``ffi.gc()``: when called several times with equal pointers, it was
+  accidentally registering only the last destructor, or even none at
+  all depending on details.  (It was correctly registering all of them
+  only in PyPy, and only with the out-of-line FFIs.)
+
+.. __: cdef.html#dlopen-note
+
+
 1.1.0
 =====
 
 * Out-of-line API mode: we can now declare integer types with
-  ``typedef int... foo_t;``.  The exact size and signness of ``foo_t``
+  ``typedef int... foo_t;``.  The exact size and signedness of ``foo_t``
   is figured out by the compiler.
 
 * Out-of-line API mode: we can now declare multidimensional arrays
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/setup.py new/cffi-1.1.2/setup.py
--- old/cffi-1.1.0/setup.py     2015-05-30 21:45:50.000000000 +0200
+++ new/cffi-1.1.2/setup.py     2015-06-09 12:04:10.000000000 +0200
@@ -144,7 +144,7 @@
 
 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
 """,
-        version='1.1.0',
+        version='1.1.2',
         packages=['cffi'] if cpython else [],
         package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h']}
                      if cpython else {},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi0/backend_tests.py 
new/cffi-1.1.2/testing/cffi0/backend_tests.py
--- old/cffi-1.1.0/testing/cffi0/backend_tests.py       2015-05-30 
21:45:20.000000000 +0200
+++ new/cffi-1.1.2/testing/cffi0/backend_tests.py       2015-06-09 
12:04:07.000000000 +0200
@@ -1457,6 +1457,63 @@
         import gc; gc.collect(); gc.collect(); gc.collect()
         assert seen == [1]
 
+    def test_gc_2(self):
+        ffi = FFI(backend=self.Backend())
+        p = ffi.new("int *", 123)
+        seen = []
+        q1 = ffi.gc(p, lambda p: seen.append(1))
+        q2 = ffi.gc(q1, lambda p: seen.append(2))
+        import gc; gc.collect()
+        assert seen == []
+        del q1, q2
+        import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
+        assert seen == [2, 1]
+
+    def test_gc_3(self):
+        ffi = FFI(backend=self.Backend())
+        p = ffi.new("int *", 123)
+        r = ffi.new("int *", 123)
+        seen = []
+        seen_r = []
+        q1 = ffi.gc(p, lambda p: seen.append(1))
+        s1 = ffi.gc(r, lambda r: seen_r.append(4))
+        q2 = ffi.gc(q1, lambda p: seen.append(2))
+        s2 = ffi.gc(s1, lambda r: seen_r.append(5))
+        q3 = ffi.gc(q2, lambda p: seen.append(3))
+        import gc; gc.collect()
+        assert seen == []
+        assert seen_r == []
+        del q1, q2, q3, s2, s1
+        import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
+        assert seen == [3, 2, 1]
+        assert seen_r == [5, 4]
+
+    def test_gc_4(self):
+        ffi = FFI(backend=self.Backend())
+        p = ffi.new("int *", 123)
+        seen = []
+        q1 = ffi.gc(p, lambda p: seen.append(1))
+        q2 = ffi.gc(q1, lambda p: seen.append(2))
+        q3 = ffi.gc(q2, lambda p: seen.append(3))
+        import gc; gc.collect()
+        assert seen == []
+        del q1, q3     # q2 remains, and has a hard ref to q1
+        import gc; gc.collect(); gc.collect(); gc.collect()
+        assert seen == [3]
+
+    def test_gc_finite_list(self):
+        ffi = FFI(backend=self.Backend())
+        p = ffi.new("int *", 123)
+        keepalive = []
+        for i in range(10):
+            keepalive.append(ffi.gc(p, lambda p: None))
+            assert len(ffi.gc_weakrefs.data) == i + 1  #should be a private 
attr
+        del keepalive[:]
+        import gc; gc.collect(); gc.collect()
+        for i in range(10):
+            keepalive.append(ffi.gc(p, lambda p: None))
+        assert len(ffi.gc_weakrefs.data) == 10
+
     def test_CData_CType(self):
         ffi = FFI(backend=self.Backend())
         assert isinstance(ffi.cast("int", 0), ffi.CData)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi0/test_verify.py 
new/cffi-1.1.2/testing/cffi0/test_verify.py
--- old/cffi-1.1.0/testing/cffi0/test_verify.py 2015-05-30 21:45:20.000000000 
+0200
+++ new/cffi-1.1.2/testing/cffi0/test_verify.py 2015-06-09 12:04:07.000000000 
+0200
@@ -2227,3 +2227,11 @@
     ffi.cdef("static const int FOO = 123;")
     e = py.test.raises(VerificationError, ffi.verify, "#define FOO 124")
     assert str(e.value).endswith("FOO has the real value 124, not 123")
+
+def test_const_struct_global():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int x; ...; } T; const T myglob;")
+    lib = ffi.verify("typedef struct { double y; int x; } T;"
+                     "const T myglob = { 0.1, 42 };")
+    assert ffi.typeof(lib.myglob) == ffi.typeof("T")
+    assert lib.myglob.x == 42
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi0/test_zintegration.py 
new/cffi-1.1.2/testing/cffi0/test_zintegration.py
--- old/cffi-1.1.0/testing/cffi0/test_zintegration.py   2015-05-30 
21:45:20.000000000 +0200
+++ new/cffi-1.1.2/testing/cffi0/test_zintegration.py   2015-06-09 
12:04:07.000000000 +0200
@@ -1,5 +1,4 @@
 import py, os, sys, shutil
-import imp
 import subprocess
 from testing.udir import udir
 
@@ -15,28 +14,12 @@
     except OSError as e:
         py.test.skip("Cannot execute virtualenv: %s" % (e,))
 
-    try:
-        deepcopy = os.symlink
-    except:
-        import shutil, errno
-        def deepcopy(src, dst):
-            try:
-                shutil.copytree(src, dst)
-            except OSError as e:
-                if e.errno in (errno.ENOTDIR, errno.EINVAL):
-                    shutil.copy(src, dst)
-                else:
-                    print('got errno')
-                    print(e.errno)
-                    print('not')
-                    print(errno.ENOTDIR)
-                    raise
-
     site_packages = None
     for dirpath, dirnames, filenames in os.walk(str(tmpdir)):
         if os.path.basename(dirpath) == 'site-packages':
             site_packages = dirpath
             break
+    paths = ""
     if site_packages:
         try:
             from cffi import _pycparser
@@ -49,15 +32,22 @@
                 pass
             else:
                 modules += ('ply',)   # needed for older versions of pycparser
+        paths = []
         for module in modules:
-            target = imp.find_module(module)[1]
-            deepcopy(target, os.path.join(site_packages,
-                                            os.path.basename(target)))
-    return tmpdir
+            target = __import__(module, None, None, [])
+            src = os.path.abspath(target.__file__)
+            for end in ['__init__.pyc', '__init__.pyo', '__init__.py']:
+                if src.lower().endswith(end):
+                    src = src[:-len(end)-1]
+                    break
+            paths.append(os.path.dirname(src))
+        paths = os.pathsep.join(paths)
+    return tmpdir, paths
 
 SNIPPET_DIR = py.path.local(__file__).join('..', 'snippets')
 
-def really_run_setup_and_program(dirname, venv_dir, python_snippet):
+def really_run_setup_and_program(dirname, venv_dir_and_paths, python_snippet):
+    venv_dir, paths = venv_dir_and_paths
     def remove(dir):
         dir = str(SNIPPET_DIR.join(dirname, dir))
         shutil.rmtree(dir, ignore_errors=True)
@@ -75,9 +65,11 @@
         else:
             bindir = 'bin'
         vp = str(venv_dir.join(bindir).join('python'))
-        subprocess.check_call((vp, 'setup.py', 'clean'))
-        subprocess.check_call((vp, 'setup.py', 'install'))
-        subprocess.check_call((vp, str(python_f)))
+        env = os.environ.copy()
+        env['PYTHONPATH'] = paths
+        subprocess.check_call((vp, 'setup.py', 'clean'), env=env)
+        subprocess.check_call((vp, 'setup.py', 'install'), env=env)
+        subprocess.check_call((vp, str(python_f)), env=env)
     finally:
         os.chdir(olddir)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi1/test_ffi_obj.py 
new/cffi-1.1.2/testing/cffi1/test_ffi_obj.py
--- old/cffi-1.1.0/testing/cffi1/test_ffi_obj.py        2015-05-30 
21:45:20.000000000 +0200
+++ new/cffi-1.1.2/testing/cffi1/test_ffi_obj.py        2015-06-09 
12:04:07.000000000 +0200
@@ -1,4 +1,4 @@
-import py
+import py, sys
 import _cffi_backend as _cffi1_backend
 
 
@@ -65,6 +65,7 @@
     ffi = _cffi1_backend.FFI()
     p = ffi.new("char[]", init=b"foobar\x00baz")
     assert ffi.string(p) == b"foobar"
+    assert ffi.string(cdata=p, maxlen=3) == b"foo"
 
 def test_ffi_errno():
     # xxx not really checking errno, just checking that we can read/write it
@@ -157,11 +158,19 @@
     assert str(e.value) == ("undefined struct/union name\n"
                             "struct never_heard_of_s\n"
                             "       ^")
+    e = py.test.raises(ffi.error, ffi.cast, "\t\n\x01\x1f~\x7f\x80\xff", 0)
+    marks = "?" if sys.version_info < (3,) else "??"
+    assert str(e.value) == ("identifier expected\n"
+                            "  ??~?%s%s\n"
+                            "  ^" % (marks, marks))
+    e = py.test.raises(ffi.error, ffi.cast, "X" * 600, 0)
+    assert str(e.value) == ("undefined type name")
 
 def test_ffi_buffer():
     ffi = _cffi1_backend.FFI()
     a = ffi.new("signed char[]", [5, 6, 7])
     assert ffi.buffer(a)[:] == b'\x05\x06\x07'
+    assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06'
 
 def test_ffi_from_buffer():
     import array
@@ -178,3 +187,11 @@
     ffi = _cffi1_backend.FFI()
     assert isinstance(ffi.cast("int", 42), CData)
     assert isinstance(ffi.typeof("int"), CType)
+
+def test_ffi_getwinerror():
+    if sys.platform != "win32":
+        py.test.skip("for windows")
+    ffi = _cffi1_backend.FFI()
+    n = (1 << 29) + 42
+    code, message = ffi.getwinerror(code=n)
+    assert code == n
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi1/test_new_ffi_1.py 
new/cffi-1.1.2/testing/cffi1/test_new_ffi_1.py
--- old/cffi-1.1.0/testing/cffi1/test_new_ffi_1.py      2015-05-30 
21:45:20.000000000 +0200
+++ new/cffi-1.1.2/testing/cffi1/test_new_ffi_1.py      2015-06-09 
12:04:07.000000000 +0200
@@ -32,7 +32,9 @@
         struct ab { int a, b; };
         struct abc { int a, b, c; };
 
-        enum foq { A0, B0, CC0, D0 };
+        /* don't use A0, B0, CC0, D0 because termios.h might be included
+           and it has its own #defines for these names */
+        enum foq { cffiA0, cffiB0, cffiCC0, cffiD0 };
         enum bar { A1, B1=-2, CC1, D1, E1 };
         enum baz { A2=0x1000, B2=0x2000 };
         enum foo2 { A3, B3, C3, D3 };
@@ -878,9 +880,9 @@
 
     def test_enum(self):
         # enum foq { A0, B0, CC0, D0 };
-        assert ffi.string(ffi.cast("enum foq", 0)) == "A0"
-        assert ffi.string(ffi.cast("enum foq", 2)) == "CC0"
-        assert ffi.string(ffi.cast("enum foq", 3)) == "D0"
+        assert ffi.string(ffi.cast("enum foq", 0)) == "cffiA0"
+        assert ffi.string(ffi.cast("enum foq", 2)) == "cffiCC0"
+        assert ffi.string(ffi.cast("enum foq", 3)) == "cffiD0"
         assert ffi.string(ffi.cast("enum foq", 4)) == "4"
         # enum bar { A1, B1=-2, CC1, D1, E1 };
         assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
@@ -1407,6 +1409,47 @@
         import gc; gc.collect(); gc.collect(); gc.collect()
         assert seen == [1]
 
+    def test_gc_2(self):
+        p = ffi.new("int *", 123)
+        seen = []
+        q1 = ffi.gc(p, lambda p: seen.append(1))
+        q2 = ffi.gc(q1, lambda p: seen.append(2))
+        import gc; gc.collect()
+        assert seen == []
+        del q1, q2
+        import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
+        assert seen == [2, 1]
+
+    def test_gc_3(self):
+        p = ffi.new("int *", 123)
+        r = ffi.new("int *", 123)
+        seen = []
+        seen_r = []
+        q1 = ffi.gc(p, lambda p: seen.append(1))
+        s1 = ffi.gc(r, lambda r: seen_r.append(4))
+        q2 = ffi.gc(q1, lambda p: seen.append(2))
+        s2 = ffi.gc(s1, lambda r: seen_r.append(5))
+        q3 = ffi.gc(q2, lambda p: seen.append(3))
+        import gc; gc.collect()
+        assert seen == []
+        assert seen_r == []
+        del q1, q2, q3, s2, s1
+        import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
+        assert seen == [3, 2, 1]
+        assert seen_r == [5, 4]
+
+    def test_gc_4(self):
+        p = ffi.new("int *", 123)
+        seen = []
+        q1 = ffi.gc(p, lambda p: seen.append(1))
+        q2 = ffi.gc(q1, lambda p: seen.append(2))
+        q3 = ffi.gc(q2, lambda p: seen.append(3))
+        import gc; gc.collect()
+        assert seen == []
+        del q1, q3     # q2 remains, and has a hard ref to q1
+        import gc; gc.collect(); gc.collect(); gc.collect()
+        assert seen == [3]
+
     def test_CData_CType(self):
         assert isinstance(ffi.cast("int", 0), ffi.CData)
         assert isinstance(ffi.new("int *"), ffi.CData)
@@ -1533,8 +1576,8 @@
         assert p.a == -52525
         #
         p = ffi.cast("enum foq", 2)
-        assert ffi.string(p) == "CC0"
-        assert ffi2.sizeof("char[CC0]") == 2
+        assert ffi.string(p) == "cffiCC0"
+        assert ffi2.sizeof("char[cffiCC0]") == 2
         #
         p = ffi.new("anon_foo_t *", [-52526])
         assert p.a == -52526
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi1/test_re_python.py 
new/cffi-1.1.2/testing/cffi1/test_re_python.py
--- old/cffi-1.1.0/testing/cffi1/test_re_python.py      2015-05-30 
21:45:50.000000000 +0200
+++ new/cffi-1.1.2/testing/cffi1/test_re_python.py      2015-06-09 
12:04:07.000000000 +0200
@@ -7,6 +7,7 @@
 
 def setup_module(mod):
     SRC = """
+    #include <string.h>
     #define FOOBAR (-42)
     static const int FOOBAZ = -43;
     #define BIGPOS 420000000000L
@@ -53,6 +54,7 @@
     struct foo_s;
     typedef struct bar_s { int x; signed char a[]; } bar_t;
     enum foo_e { AA, BB, CC };
+    int strlen(const char *);
     """)
     ffi.set_source('re_python_pysrc', None)
     ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
@@ -81,10 +83,20 @@
 def test_function_with_varargs():
     import _cffi_backend
     from re_python_pysrc import ffi
-    lib = ffi.dlopen(extmod)
+    lib = ffi.dlopen(extmod, 0)
     assert lib.add43(45, ffi.cast("int", -5)) == 45
     assert type(lib.add43) is _cffi_backend.FFI.CData
 
+def test_dlopen_none():
+    import _cffi_backend
+    from re_python_pysrc import ffi
+    name = None
+    if sys.platform == 'win32':
+        import ctypes.util
+        name = ctypes.util.find_msvcrt()
+    lib = ffi.dlopen(name)
+    assert lib.strlen(b"hello") == 5
+
 def test_dlclose():
     import _cffi_backend
     from re_python_pysrc import ffi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi1/test_recompiler.py 
new/cffi-1.1.2/testing/cffi1/test_recompiler.py
--- old/cffi-1.1.0/testing/cffi1/test_recompiler.py     2015-05-30 
21:45:50.000000000 +0200
+++ new/cffi-1.1.2/testing/cffi1/test_recompiler.py     2015-06-09 
12:04:10.000000000 +0200
@@ -992,3 +992,13 @@
     ffi.typeof('function_t*')
     lib.function(ffi.NULL)
     # assert did not crash
+
+def test_alignment_of_longlong():
+    ffi = FFI()
+    x1 = ffi.alignof('unsigned long long')
+    assert x1 in [4, 8]
+    ffi.cdef("struct foo_s { unsigned long long x; };")
+    lib = verify(ffi, 'test_alignment_of_longlong',
+                 "struct foo_s { unsigned long long x; };")
+    assert ffi.alignof('unsigned long long') == x1
+    assert ffi.alignof('struct foo_s') == x1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi1/test_verify1.py 
new/cffi-1.1.2/testing/cffi1/test_verify1.py
--- old/cffi-1.1.0/testing/cffi1/test_verify1.py        2015-05-30 
21:45:50.000000000 +0200
+++ new/cffi-1.1.2/testing/cffi1/test_verify1.py        2015-06-09 
12:04:07.000000000 +0200
@@ -2117,25 +2117,19 @@
     try:
         ffi1 = FFI()
         ffi1.cdef("int foo_verify_dlopen_flags;")
-
-        sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY)
+        sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_NOW)
         lib1 = ffi1.verify("int foo_verify_dlopen_flags;")
-        lib2 = get_second_lib()
-
-        lib1.foo_verify_dlopen_flags = 42
-        assert lib2.foo_verify_dlopen_flags == 42
-        lib2.foo_verify_dlopen_flags += 1
-        assert lib1.foo_verify_dlopen_flags == 43
     finally:
         sys.setdlopenflags(old)
 
-def get_second_lib():
-    # Hack, using modulename makes the test fail
     ffi2 = FFI()
-    ffi2.cdef("int foo_verify_dlopen_flags;")
-    lib2 = ffi2.verify("int foo_verify_dlopen_flags;",
-                       flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY)
-    return lib2
+    ffi2.cdef("int *getptr(void);")
+    lib2 = ffi2.verify("""
+        extern int foo_verify_dlopen_flags;
+        static int *getptr(void) { return &foo_verify_dlopen_flags; }
+    """)
+    p = lib2.getptr()
+    assert ffi1.addressof(lib1, 'foo_verify_dlopen_flags') == p
 
 def test_consider_not_implemented_function_type():
     ffi = FFI()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.1.0/testing/cffi1/test_zdist.py 
new/cffi-1.1.2/testing/cffi1/test_zdist.py
--- old/cffi-1.1.0/testing/cffi1/test_zdist.py  2015-05-30 21:45:50.000000000 
+0200
+++ new/cffi-1.1.2/testing/cffi1/test_zdist.py  2015-06-09 12:04:07.000000000 
+0200
@@ -29,13 +29,17 @@
         if hasattr(self, 'saved_cwd'):
             os.chdir(self.saved_cwd)
 
-    def run(self, args):
+    def run(self, args, cwd=None):
         env = os.environ.copy()
-        newpath = self.rootdir
-        if 'PYTHONPATH' in env:
-            newpath += os.pathsep + env['PYTHONPATH']
-        env['PYTHONPATH'] = newpath
-        subprocess.check_call([self.executable] + args, env=env)
+        # a horrible hack to prevent distutils from finding ~/.pydistutils.cfg
+        # (there is the --no-user-cfg option, but not in Python 2.6...)
+        env['HOME'] = '/this/path/does/not/exist'
+        if cwd is None:
+            newpath = self.rootdir
+            if 'PYTHONPATH' in env:
+                newpath += os.pathsep + env['PYTHONPATH']
+            env['PYTHONPATH'] = newpath
+        subprocess.check_call([self.executable] + args, cwd=cwd, env=env)
 
     def _prepare_setuptools(self):
         if hasattr(TestDist, '_setuptools_ready'):
@@ -44,8 +48,7 @@
             import setuptools
         except ImportError:
             py.test.skip("setuptools not found")
-        subprocess.check_call([self.executable, 'setup.py', 'egg_info'],
-                              cwd=self.rootdir)
+        self.run(['setup.py', 'egg_info'], cwd=self.rootdir)
         TestDist._setuptools_ready = True
 
     def check_produced_files(self, content, curdir=None):


Reply via email to