[pypy-commit] pypy py3.5: fix test_mixedmodule.py

2017-06-19 Thread rlamy
Author: Ronan Lamy 
Branch: py3.5
Changeset: r91627:675b2f4d2399
Date: 2017-06-19 17:41 +0100
http://bitbucket.org/pypy/pypy/changeset/675b2f4d2399/

Log:fix test_mixedmodule.py

diff --git a/pypy/interpreter/test/test_mixedmodule.py 
b/pypy/interpreter/test/test_mixedmodule.py
--- a/pypy/interpreter/test/test_mixedmodule.py
+++ b/pypy/interpreter/test/test_mixedmodule.py
@@ -1,38 +1,43 @@
+import pytest
+
+from pypy.tool.pytest.objspace import maketestobjspace
 from pypy.interpreter.mixedmodule import MixedModule
-import py.test
 
+@pytest.fixture()
+def space():
+# We need a fresh space for each test here
+return maketestobjspace()
 
-class TestMixedModule(object):
-def test_install(self):
-class Module(MixedModule):
-interpleveldefs = {}
-appleveldefs = {}
+def test_install(space):
+class Module(MixedModule):
+interpleveldefs = {}
+appleveldefs = {}
 
-m = Module(self.space, self.space.wrap("test_module"))
-m.install()
+m = Module(space, space.wrap("test_module"))
+m.install()
 
-assert self.space.builtin_modules["test_module"] is m
+assert space.builtin_modules["test_module"] is m
 
-def test_submodule(self):
-class SubModule(MixedModule):
-interpleveldefs = {}
-appleveldefs = {}
+def test_submodule(space):
+class SubModule(MixedModule):
+interpleveldefs = {}
+appleveldefs = {}
 
-class Module(MixedModule):
-interpleveldefs = {}
-appleveldefs = {}
-submodules = {
-"sub": SubModule
-}
+class Module(MixedModule):
+interpleveldefs = {}
+appleveldefs = {}
+submodules = {
+"sub": SubModule
+}
 
-m = Module(self.space, self.space.wrap("test_module"))
-m.install()
+m = Module(space, space.wrap("test_module"))
+m.install()
 
-assert self.space.builtin_modules["test_module"] is m
-assert isinstance(self.space.builtin_modules["test_module.sub"], 
SubModule)
+assert space.builtin_modules["test_module"] is m
+assert isinstance(space.builtin_modules["test_module.sub"], SubModule)
 
 class AppTestMixedModule(object):
-pytestmark = py.test.mark.skipif("config.option.runappdirect")
+pytestmark = pytest.mark.skipif("config.option.runappdirect")
 
 def setup_class(cls):
 space = cls.space
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.5: fix test

2017-06-19 Thread rlamy
Author: Ronan Lamy 
Branch: py3.5
Changeset: r91628:44469c25a324
Date: 2017-06-19 19:21 +0100
http://bitbucket.org/pypy/pypy/changeset/44469c25a324/

Log:fix test

diff --git a/pypy/module/imp/test/test_app.py b/pypy/module/imp/test/test_app.py
--- a/pypy/module/imp/test/test_app.py
+++ b/pypy/module/imp/test/test_app.py
@@ -115,6 +115,7 @@
 mod = imp.init_builtin(name)
 assert mod
 assert mod.__spec__
+test_is_builtin.dont_track_allocations = True
 
 def test_load_module_py(self):
 import imp
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy default: make FrozenDict fail PySequence_Check() - fixes obscure numpy test failure

2017-06-19 Thread mattip
Author: Matti Picus 
Branch: 
Changeset: r91626:6d81023ea3fe
Date: 2017-06-19 20:01 +0300
http://bitbucket.org/pypy/pypy/changeset/6d81023ea3fe/

Log:make FrozenDict fail PySequence_Check() - fixes obscure numpy test
failure

diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -290,6 +290,7 @@
 def make_frozendict(space):
 if space not in _frozendict_cache:
 _frozendict_cache[space] = _make_frozendict(space)
+_frozendict_cache[space].flag_map_or_seq = 'M'
 return _frozendict_cache[space]
 
 _frozendict_cache = {}
diff --git a/pypy/module/cpyext/test/test_iterator.py 
b/pypy/module/cpyext/test/test_iterator.py
--- a/pypy/module/cpyext/test/test_iterator.py
+++ b/pypy/module/cpyext/test/test_iterator.py
@@ -33,6 +33,11 @@
 return obj;
 '''
 ),
+   ("get_dictproxy", "METH_O",
+'''
+return PyDictProxy_New(args);
+'''
+),
("check", "METH_O",
 '''
 return PyInt_FromLong(
@@ -74,6 +79,10 @@
 assert operator.isMappingType(obj)
 #
 assert module.check(obj) == 2
+# make sure dictionaries return false for PySequence_Check
+assert module.check({'a': 1}) == 2
+obj = module.get_dictproxy({'a': 10})
+assert module.check(obj) == 2
 
 def test_iterable_nonmapping_object(self):
 module = self.import_extension('foo', [
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] cffi default: bah, I won't attempt to find the correct #ifdef magic to use on MSVC in C++ mode to know if 'char16_t' exists. The official one doesn't work, so meh.

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: 
Changeset: r2988:40a258cefe22
Date: 2017-06-19 12:35 +0200
http://bitbucket.org/cffi/cffi/changeset/40a258cefe22/

Log:bah, I won't attempt to find the correct #ifdef magic to use on MSVC
in C++ mode to know if 'char16_t' exists. The official one doesn't
work, so meh.

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
@@ -2259,6 +2259,9 @@
 assert ffi.typeof("int16_t") is ffi.typeof("char16_t") is 
ffi.typeof("long")
 
 def test_char16_char32_type(no_cpp=False):
+if no_cpp is False and sys.platform == "win32":
+py.test.skip("aaa why do modern MSVC compilers still define "
+ "a very old __cplusplus value")
 ffi = FFI()
 ffi.cdef("""
 char16_t foo_2bytes(char16_t);
@@ -2269,7 +2272,7 @@
 typedef uint_least16_t char16_t;
 typedef uint_least32_t char32_t;
 #endif
-
+
 char16_t foo_2bytes(char16_t a) { return (char16_t)(a + 42); }
 char32_t foo_4bytes(char32_t a) { return (char32_t)(a + 42); }
 """, no_cpp=no_cpp)
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] cffi default: More test fixes on Windows on Python 3

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: 
Changeset: r2987:b4e78ef300b0
Date: 2017-06-19 12:27 +0200
http://bitbucket.org/cffi/cffi/changeset/b4e78ef300b0/

Log:More test fixes on Windows on Python 3

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
@@ -418,7 +418,6 @@
 #
 p = ffi.new("wchar_t[]", u+'\U00023456')
 if SIZE_OF_WCHAR == 2:
-assert sys.maxunicode == 0x
 assert len(p) == 3
 assert p[0] == u+'\ud84d'
 assert p[1] == u+'\udc56'
diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py
--- a/testing/cffi1/test_re_python.py
+++ b/testing/cffi1/test_re_python.py
@@ -94,6 +94,8 @@
 if sys.platform == 'win32':
 import ctypes.util
 name = ctypes.util.find_msvcrt()
+if name is None:
+py.test.skip("dlopen(None) cannot work on Windows with Python 3")
 lib = ffi.dlopen(name)
 assert lib.strlen(b"hello") == 5
 
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] cffi default: Probable improvement

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: 
Changeset: r2986:54a7350ed586
Date: 2017-06-19 12:26 +0200
http://bitbucket.org/cffi/cffi/changeset/54a7350ed586/

Log:Probable improvement

diff --git a/c/wchar_helper_3.h b/c/wchar_helper_3.h
--- a/c/wchar_helper_3.h
+++ b/c/wchar_helper_3.h
@@ -143,13 +143,7 @@
   cffi_char32_t *result,
   Py_ssize_t resultlen)
 {
-Py_ssize_t len = PyUnicode_GET_LENGTH(unicode);
-unsigned int kind = PyUnicode_KIND(unicode);
-void *data = PyUnicode_DATA(unicode);
-Py_ssize_t i;
-
-for (i = 0; i < len; i++)
-result[i] = PyUnicode_READ(kind, data, i);
-
+if (PyUnicode_AsUCS4(unicode, (Py_UCS4 *)result, resultlen, 0) == NULL)
+return -1;
 return 0;
 }
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] cffi default: Don't use error capture around ffi.gc() finalizer errors

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: 
Changeset: r2984:1d3da4b31373
Date: 2017-06-19 11:58 +0200
http://bitbucket.org/cffi/cffi/changeset/1d3da4b31373/

Log:Don't use error capture around ffi.gc() finalizer errors

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -1852,12 +1852,15 @@
 Py_DECREF(result);
 }
 else {
-PyObject *ecap, *t, *v, *tb;
+PyObject *t, *v, *tb;
 PyErr_Fetch(, , );
-ecap = _cffi_start_error_capture();
+/* Don't use error capture here, because it is very much
+ * like errors at __del__(), and these ones are not captured
+ * either */
+/* ecap = _cffi_start_error_capture(); */
 _my_PyErr_WriteUnraisable(t, v, tb, "From callback for ffi.gc ",
   origobj, NULL);
-_cffi_stop_error_capture(ecap);
+/* _cffi_stop_error_capture(ecap); */
 }
 Py_DECREF(destructor);
 
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] cffi default: Write a copy of wchar_helper.h that uses CPython 3.3's new

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: 
Changeset: r2985:5e554e5c0dfc
Date: 2017-06-19 12:06 +0200
http://bitbucket.org/cffi/cffi/changeset/5e554e5c0dfc/

Log:Write a copy of wchar_helper.h that uses CPython 3.3's new unicode
string API. It makes sense anyway for speed reasons, but it also
avoids even more special cases for platforms with 16-bit wchar_t on
CPython >= 3.3.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -286,7 +286,11 @@
 # include "file_emulator.h"
 #endif
 
-#include "wchar_helper.h"
+#ifdef PyUnicode_KIND /* Python >= 3.3 */
+# include "wchar_helper_3.h"
+#else
+# include "wchar_helper.h"
+#endif
 
 #include "../cffi/_cffi_errors.h"
 
diff --git a/c/wchar_helper_3.h b/c/wchar_helper_3.h
new file mode 100644
--- /dev/null
+++ b/c/wchar_helper_3.h
@@ -0,0 +1,155 @@
+/*
+ * wchar_t helpers, version CPython >= 3.3.
+ *
+ * CPython 3.3 added support for sys.maxunicode == 0x10 on all
+ * platforms, even ones with wchar_t limited to 2 bytes.  As such,
+ * this code here works from the outside like wchar_helper.h in the
+ * case Py_UNICODE_SIZE == 4, but the implementation is very different.
+ */
+
+typedef uint16_t cffi_char16_t;
+typedef uint32_t cffi_char32_t;
+
+
+static PyObject *
+_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size)
+{
+return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, w, size);
+}
+
+static PyObject *
+_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size)
+{
+/* are there any surrogate pairs, and if so, how many? */
+Py_ssize_t i, count_surrogates = 0;
+for (i = 0; i < size - 1; i++) {
+if (0xD800 <= w[i] && w[i] <= 0xDBFF &&
+0xDC00 <= w[i+1] && w[i+1] <= 0xDFFF)
+count_surrogates++;
+}
+if (count_surrogates == 0) {
+/* no, fast path */
+return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, w, size);
+}
+else
+{
+PyObject *result = PyUnicode_New(size - count_surrogates, 0x10);
+Py_UCS4 *data;
+assert(PyUnicode_KIND(result) == PyUnicode_4BYTE_KIND);
+data = PyUnicode_4BYTE_DATA(result);
+
+for (i = 0; i < size; i++)
+{
+cffi_char32_t ch = w[i];
+if (0xD800 <= ch && ch <= 0xDBFF && i < size - 1) {
+cffi_char32_t ch2 = w[i + 1];
+if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
+ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x1;
+i++;
+}
+}
+*data++ = ch;
+}
+return result;
+}
+}
+
+static int
+_my_PyUnicode_AsSingleChar16(PyObject *unicode, cffi_char16_t *result,
+ char *err_got)
+{
+cffi_char32_t ch;
+if (PyUnicode_GET_LENGTH(unicode) != 1) {
+sprintf(err_got, "unicode string of length %zd",
+PyUnicode_GET_LENGTH(unicode));
+return -1;
+}
+ch = PyUnicode_READ_CHAR(unicode, 0);
+
+if (ch > 0x)
+{
+sprintf(err_got, "larger-than-0x character");
+return -1;
+}
+*result = (cffi_char16_t)ch;
+return 0;
+}
+
+static int
+_my_PyUnicode_AsSingleChar32(PyObject *unicode, cffi_char32_t *result,
+ char *err_got)
+{
+if (PyUnicode_GET_LENGTH(unicode) != 1) {
+sprintf(err_got, "unicode string of length %zd",
+PyUnicode_GET_LENGTH(unicode));
+return -1;
+}
+*result = PyUnicode_READ_CHAR(unicode, 0);
+return 0;
+}
+
+static Py_ssize_t _my_PyUnicode_SizeAsChar16(PyObject *unicode)
+{
+Py_ssize_t length = PyUnicode_GET_LENGTH(unicode);
+Py_ssize_t result = length;
+unsigned int kind = PyUnicode_KIND(unicode);
+
+if (kind == PyUnicode_4BYTE_KIND)
+{
+Py_UCS4 *data = PyUnicode_4BYTE_DATA(unicode);
+Py_ssize_t i;
+for (i = 0; i < length; i++) {
+if (data[i] > 0x)
+result++;
+}
+}
+return result;
+}
+
+static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode)
+{
+return PyUnicode_GET_LENGTH(unicode);
+}
+
+static int _my_PyUnicode_AsChar16(PyObject *unicode,
+  cffi_char16_t *result,
+  Py_ssize_t resultlen)
+{
+Py_ssize_t len = PyUnicode_GET_LENGTH(unicode);
+unsigned int kind = PyUnicode_KIND(unicode);
+void *data = PyUnicode_DATA(unicode);
+Py_ssize_t i;
+
+for (i = 0; i < len; i++) {
+cffi_char32_t ordinal = PyUnicode_READ(kind, data, i);
+if (ordinal > 0x) {
+if (ordinal > 0x10) {
+PyErr_Format(PyExc_ValueError,
+ "unicode character out of range for "
+ "conversion to char16_t: 0x%x", (int)ordinal);
+return -1;
+}
+ordinal -= 0x1;
+*result++ = 

[pypy-commit] cffi default: Some test fixes for Python 3 on Windows

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: 
Changeset: r2983:09cc68d4b9cf
Date: 2017-06-19 10:55 +0200
http://bitbucket.org/cffi/cffi/changeset/09cc68d4b9cf/

Log:Some test fixes for Python 3 on Windows

diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -61,6 +61,10 @@
 path = None
 else:
 path = ctypes.util.find_library(name)
+if path is None and name == 'c':
+assert sys.platform == 'win32'
+assert sys.version_info >= (3,)
+py.test.skip("dlopen(None) cannot work on Windows with Python 3")
 return load_library(path, flags)
 
 def test_load_library():
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -765,7 +765,7 @@
 if sys.platform != "win32":
 return backend.load_library(None, flags)
 name = "c"# Windows: load_library(None) fails, but this works
-  # (backward compatibility hack only)
+  # on Python 2 (backward compatibility hack only)
 first_error = None
 if '.' in name or '/' in name or os.sep in name:
 try:
@@ -775,6 +775,9 @@
 import ctypes.util
 path = ctypes.util.find_library(name)
 if path is None:
+if name == "c" and sys.platform == "win32" and sys.version_info >= 
(3,):
+raise OSError("dlopen(None) cannot work on Windows for Python 3 "
+  "(see http://bugs.python.org/issue23606)")
 msg = ("ctypes.util.find_library() did not manage "
"to locate a library called %r" % (name,))
 if first_error is not None:
diff --git a/doc/source/cdef.rst b/doc/source/cdef.rst
--- a/doc/source/cdef.rst
+++ b/doc/source/cdef.rst
@@ -306,7 +306,10 @@
 contain a full path or not (in which case it is searched in standard
 locations, as described in ``man dlopen``), with extensions or not.
 Alternatively, if ``libpath`` is None, it returns the standard C library
-(which can be used to access the functions of glibc, on Linux).
+(which can be used to access the functions of glibc, on Linux).  Note
+that ``libpath`` `cannot be None`__ on Windows with Python 3.
+
+.. __: http://bugs.python.org/issue23606
 
 Let me state it again: this gives ABI-level access to the library, so
 you need to have all types declared manually exactly as they were
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
@@ -10,6 +10,10 @@
 SIZE_OF_PTR   = ctypes.sizeof(ctypes.c_void_p)
 SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
 
+def needs_dlopen_none():
+if sys.platform == 'win32' and sys.version_info >= (3,):
+py.test.skip("dlopen(None) cannot work on Windows for Python 3")
+
 
 class BackendTests:
 
@@ -354,7 +358,6 @@
 #
 p = ffi.new("wchar_t[]", u+'\U00023456')
 if SIZE_OF_WCHAR == 2:
-assert sys.maxunicode == 0x
 assert len(p) == 3
 assert p[0] == u+'\ud84d'
 assert p[1] == u+'\udc56'
@@ -937,6 +940,7 @@
 def test_enum_partial(self):
 ffi = FFI(backend=self.Backend())
 ffi.cdef(r"enum foo {A, ...}; enum bar { B, C };")
+needs_dlopen_none()
 lib = ffi.dlopen(None)
 assert lib.B == 0
 py.test.raises(VerificationMissing, getattr, lib, "A")
@@ -1844,6 +1848,7 @@
 #define DOT_UL 1000UL
 enum foo {AA, BB=DOT, CC};
 """)
+needs_dlopen_none()
 lib = ffi.dlopen(None)
 assert ffi.string(ffi.cast("enum foo", 100)) == "BB"
 assert lib.DOT_0 == 0
@@ -1873,6 +1878,7 @@
 ffi = FFI()
 ffi.include(ffi1)
 ffi.cdef("enum { EE2, EE3 };")
+needs_dlopen_none()
 lib = ffi.dlopen(None)
 assert lib.EE1 == 0
 assert lib.EE2 == 0
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
@@ -5,6 +5,7 @@
 from cffi.backend_ctypes import CTypesBackend
 from testing.udir import udir
 from testing.support import FdWriteCapture
+from .backend_tests import needs_dlopen_none
 
 try:
 from StringIO import StringIO
@@ -111,6 +112,7 @@
 int fputs(const char *, void *);
 void *stderr;
 """)
+needs_dlopen_none()
 ffi.C = ffi.dlopen(None)
 ffi.C.fputs   # fetch before capturing, for easier debugging
 with FdWriteCapture() as fd:
@@ -127,6 +129,7 @@
 int fputs(char *, void *);
 void *stderr;
 """)
+needs_dlopen_none()
 ffi.C = ffi.dlopen(None)
 ffi.C.fputs   # fetch before capturing, for easier debugging
 with FdWriteCapture() as fd:
@@ -143,6 +146,7 @@
int fprintf(void *, const char *format, ...);
void *stderr;
 """)
+needs_dlopen_none()
 ffi.C = 

[pypy-commit] cffi default: Py3 compat

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: 
Changeset: r2982:7495a3729d42
Date: 2017-06-19 10:12 +0200
http://bitbucket.org/cffi/cffi/changeset/7495a3729d42/

Log:Py3 compat

diff --git a/cffi/_cffi_errors.h b/cffi/_cffi_errors.h
--- a/cffi/_cffi_errors.h
+++ b/cffi/_cffi_errors.h
@@ -36,7 +36,11 @@
 if (result == NULL)
 goto error;
 
+#if PY_MAJOR_VERSION >= 3
+bi = PyImport_ImportModule("builtins");
+#else
 bi = PyImport_ImportModule("__builtin__");
+#endif
 if (bi == NULL)
 goto error;
 PyDict_SetItemString(result, "__builtins__", bi);
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.5: hg merge default

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: py3.5
Changeset: r91625:be1dadf96ba4
Date: 2017-06-19 09:59 +0200
http://bitbucket.org/pypy/pypy/changeset/be1dadf96ba4/

Log:hg merge default

also attempt to write the Python3 version of cffi's errorbox.py on
Windows, but not tested so far

diff --git a/lib_pypy/cffi/_cffi_errors.h b/lib_pypy/cffi/_cffi_errors.h
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi/_cffi_errors.h
@@ -0,0 +1,141 @@
+#ifndef CFFI_MESSAGEBOX
+# ifdef _MSC_VER
+#  define CFFI_MESSAGEBOX  1
+# else
+#  define CFFI_MESSAGEBOX  0
+# endif
+#endif
+
+
+#if CFFI_MESSAGEBOX
+/* Windows only: logic to take the Python-CFFI embedding logic
+   initialization errors and display them in a background thread
+   with MessageBox.  The idea is that if the whole program closes
+   as a result of this problem, then likely it is already a console
+   program and you can read the stderr output in the console too.
+   If it is not a console program, then it will likely show its own
+   dialog to complain, or generally not abruptly close, and for this
+   case the background thread should stay alive.
+*/
+static void *volatile _cffi_bootstrap_text;
+
+static PyObject *_cffi_start_error_capture(void)
+{
+PyObject *result = NULL;
+PyObject *x, *m, *bi;
+
+if (InterlockedCompareExchangePointer(&_cffi_bootstrap_text,
+(void *)1, NULL) != NULL)
+return (PyObject *)1;
+
+m = PyImport_AddModule("_cffi_error_capture");
+if (m == NULL)
+goto error;
+
+result = PyModule_GetDict(m);
+if (result == NULL)
+goto error;
+
+bi = PyImport_ImportModule("__builtin__");
+if (bi == NULL)
+goto error;
+PyDict_SetItemString(result, "__builtins__", bi);
+Py_DECREF(bi);
+
+x = PyRun_String(
+"import sys\n"
+"class FileLike:\n"
+"  def write(self, x):\n"
+"of.write(x)\n"
+"self.buf += x\n"
+"fl = FileLike()\n"
+"fl.buf = ''\n"
+"of = sys.stderr\n"
+"sys.stderr = fl\n"
+"def done():\n"
+"  sys.stderr = of\n"
+"  return fl.buf\n",   /* make sure the returned value stays alive */
+Py_file_input,
+result, result);
+Py_XDECREF(x);
+
+ error:
+if (PyErr_Occurred())
+{
+PyErr_WriteUnraisable(Py_None);
+PyErr_Clear();
+}
+return result;
+}
+
+#pragma comment(lib, "user32.lib")
+
+static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored)
+{
+Sleep(666);/* may be interrupted if the whole process is closing */
+#if PY_MAJOR_VERSION >= 3
+MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text,
+L"Python-CFFI error",
+MB_OK | MB_ICONERROR);
+#else
+MessageBoxA(NULL, (char *)_cffi_bootstrap_text,
+"Python-CFFI error",
+MB_OK | MB_ICONERROR);
+#endif
+_cffi_bootstrap_text = NULL;
+return 0;
+}
+
+static void _cffi_stop_error_capture(PyObject *ecap)
+{
+PyObject *s;
+void *text;
+
+if (ecap == (PyObject *)1)
+return;
+
+if (ecap == NULL)
+goto error;
+
+s = PyRun_String("done()", Py_eval_input, ecap, ecap);
+if (s == NULL)
+goto error;
+
+/* Show a dialog box, but in a background thread, and
+   never show multiple dialog boxes at once. */
+#if PY_MAJOR_VERSION >= 3
+text = PyUnicode_AsWideCharString(s, NULL);
+#else
+text = PyString_AsString(s);
+#endif
+
+_cffi_bootstrap_text = text;
+
+if (text != NULL)
+{
+HANDLE h;
+h = CreateThread(NULL, 0, _cffi_bootstrap_dialog,
+ NULL, 0, NULL);
+if (h != NULL)
+CloseHandle(h);
+}
+/* decref the string, but it should stay alive as 'fl.buf'
+   in the small module above.  It will really be freed only if
+   we later get another similar error.  So it's a leak of at
+   most one copy of the small module.  That's fine for this
+   situation which is usually a "fatal error" anyway. */
+Py_DECREF(s);
+PyErr_Clear();
+return;
+
+  error:
+_cffi_bootstrap_text = NULL;
+PyErr_Clear();
+}
+
+#else
+
+static PyObject *_cffi_start_error_capture(void) { return NULL; }
+static void _cffi_stop_error_capture(PyObject *ecap) { }
+
+#endif
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -109,6 +109,8 @@
 /**  CPython-specific section  **/
 #ifndef PYPY_VERSION
 
+#include "_cffi_errors.h"
+
 
 #define _cffi_call_python_org  _cffi_exports[_CFFI_CPIDX]
 
@@ -220,8 +222,16 @@
 /* Print as much information as potentially useful.
Debugging load-time failures with embedding is not fun
 */
+PyObject *ecap;
 PyObject *exception, *v, *tb, *f, *modules, *mod;
 PyErr_Fetch(, , );
+ecap = _cffi_start_error_capture();
+f = 

[pypy-commit] pypy default: update to cffi/cace5cac5ccb

2017-06-19 Thread arigo
Author: Armin Rigo 
Branch: 
Changeset: r91624:211e6e8190f1
Date: 2017-06-19 09:34 +0200
http://bitbucket.org/pypy/pypy/changeset/211e6e8190f1/

Log:update to cffi/cace5cac5ccb

diff --git a/lib_pypy/cffi/_cffi_errors.h b/lib_pypy/cffi/_cffi_errors.h
new file mode 100644
--- /dev/null
+++ b/lib_pypy/cffi/_cffi_errors.h
@@ -0,0 +1,141 @@
+#ifndef CFFI_MESSAGEBOX
+# ifdef _MSC_VER
+#  define CFFI_MESSAGEBOX  1
+# else
+#  define CFFI_MESSAGEBOX  0
+# endif
+#endif
+
+
+#if CFFI_MESSAGEBOX
+/* Windows only: logic to take the Python-CFFI embedding logic
+   initialization errors and display them in a background thread
+   with MessageBox.  The idea is that if the whole program closes
+   as a result of this problem, then likely it is already a console
+   program and you can read the stderr output in the console too.
+   If it is not a console program, then it will likely show its own
+   dialog to complain, or generally not abruptly close, and for this
+   case the background thread should stay alive.
+*/
+static void *volatile _cffi_bootstrap_text;
+
+static PyObject *_cffi_start_error_capture(void)
+{
+PyObject *result = NULL;
+PyObject *x, *m, *bi;
+
+if (InterlockedCompareExchangePointer(&_cffi_bootstrap_text,
+(void *)1, NULL) != NULL)
+return (PyObject *)1;
+
+m = PyImport_AddModule("_cffi_error_capture");
+if (m == NULL)
+goto error;
+
+result = PyModule_GetDict(m);
+if (result == NULL)
+goto error;
+
+bi = PyImport_ImportModule("__builtin__");
+if (bi == NULL)
+goto error;
+PyDict_SetItemString(result, "__builtins__", bi);
+Py_DECREF(bi);
+
+x = PyRun_String(
+"import sys\n"
+"class FileLike:\n"
+"  def write(self, x):\n"
+"of.write(x)\n"
+"self.buf += x\n"
+"fl = FileLike()\n"
+"fl.buf = ''\n"
+"of = sys.stderr\n"
+"sys.stderr = fl\n"
+"def done():\n"
+"  sys.stderr = of\n"
+"  return fl.buf\n",   /* make sure the returned value stays alive */
+Py_file_input,
+result, result);
+Py_XDECREF(x);
+
+ error:
+if (PyErr_Occurred())
+{
+PyErr_WriteUnraisable(Py_None);
+PyErr_Clear();
+}
+return result;
+}
+
+#pragma comment(lib, "user32.lib")
+
+static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored)
+{
+Sleep(666);/* may be interrupted if the whole process is closing */
+#if PY_MAJOR_VERSION >= 3
+MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text,
+L"Python-CFFI error",
+MB_OK | MB_ICONERROR);
+#else
+MessageBoxA(NULL, (char *)_cffi_bootstrap_text,
+"Python-CFFI error",
+MB_OK | MB_ICONERROR);
+#endif
+_cffi_bootstrap_text = NULL;
+return 0;
+}
+
+static void _cffi_stop_error_capture(PyObject *ecap)
+{
+PyObject *s;
+void *text;
+
+if (ecap == (PyObject *)1)
+return;
+
+if (ecap == NULL)
+goto error;
+
+s = PyRun_String("done()", Py_eval_input, ecap, ecap);
+if (s == NULL)
+goto error;
+
+/* Show a dialog box, but in a background thread, and
+   never show multiple dialog boxes at once. */
+#if PY_MAJOR_VERSION >= 3
+text = PyUnicode_AsWideCharString(s, NULL);
+#else
+text = PyString_AsString(s);
+#endif
+
+_cffi_bootstrap_text = text;
+
+if (text != NULL)
+{
+HANDLE h;
+h = CreateThread(NULL, 0, _cffi_bootstrap_dialog,
+ NULL, 0, NULL);
+if (h != NULL)
+CloseHandle(h);
+}
+/* decref the string, but it should stay alive as 'fl.buf'
+   in the small module above.  It will really be freed only if
+   we later get another similar error.  So it's a leak of at
+   most one copy of the small module.  That's fine for this
+   situation which is usually a "fatal error" anyway. */
+Py_DECREF(s);
+PyErr_Clear();
+return;
+
+  error:
+_cffi_bootstrap_text = NULL;
+PyErr_Clear();
+}
+
+#else
+
+static PyObject *_cffi_start_error_capture(void) { return NULL; }
+static void _cffi_stop_error_capture(PyObject *ecap) { }
+
+#endif
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -109,6 +109,8 @@
 /**  CPython-specific section  **/
 #ifndef PYPY_VERSION
 
+#include "_cffi_errors.h"
+
 
 #define _cffi_call_python_org  _cffi_exports[_CFFI_CPIDX]
 
@@ -220,8 +222,16 @@
 /* Print as much information as potentially useful.
Debugging load-time failures with embedding is not fun
 */
+PyObject *ecap;
 PyObject *exception, *v, *tb, *f, *modules, *mod;
 PyErr_Fetch(, , );
+ecap = _cffi_start_error_capture();
+f = PySys_GetObject((char *)"stderr");
+if (f != NULL && f != Py_None) {
+PyFile_WriteString(
+