Author: Matti Picus <[email protected]>
Branch: release-pypy2.7-v7.x
Changeset: r98253:1c36a847ec09
Date: 2019-12-08 09:00 +0200
http://bitbucket.org/pypy/pypy/changeset/1c36a847ec09/

Log:    merge default into release branch

diff --git a/lib_pypy/_cffi_ssl/_stdssl/error.py 
b/lib_pypy/_cffi_ssl/_stdssl/error.py
--- a/lib_pypy/_cffi_ssl/_stdssl/error.py
+++ b/lib_pypy/_cffi_ssl/_stdssl/error.py
@@ -27,13 +27,14 @@
         if self.strerror and isinstance(self.strerror, str):
             return self.strerror
         return str(self.args)
-# these are expected on socket as well
-socket.sslerror = SSLError
-for v in [ 'SSL_ERROR_ZERO_RETURN', 'SSL_ERROR_WANT_READ',
-     'SSL_ERROR_WANT_WRITE', 'SSL_ERROR_WANT_X509_LOOKUP', 'SSL_ERROR_SYSCALL',
-     'SSL_ERROR_SSL', 'SSL_ERROR_WANT_CONNECT', 'SSL_ERROR_EOF',
-     'SSL_ERROR_INVALID_ERROR_CODE' ]:
-    setattr(socket, v, locals()[v]) 
+# these are expected on socket in python2 as well
+if sys.version_info[0] < 3:
+    socket.sslerror = SSLError
+    for v in [ 'SSL_ERROR_ZERO_RETURN', 'SSL_ERROR_WANT_READ',
+         'SSL_ERROR_WANT_WRITE', 'SSL_ERROR_WANT_X509_LOOKUP', 
'SSL_ERROR_SYSCALL',
+         'SSL_ERROR_SSL', 'SSL_ERROR_WANT_CONNECT', 'SSL_ERROR_EOF',
+         'SSL_ERROR_INVALID_ERROR_CODE' ]:
+        setattr(socket, v, locals()[v]) 
 
 class SSLZeroReturnError(SSLError):
     """ SSL/TLS session closed cleanly. """
diff --git a/lib_pypy/_curses_build.py b/lib_pypy/_curses_build.py
--- a/lib_pypy/_curses_build.py
+++ b/lib_pypy/_curses_build.py
@@ -28,13 +28,25 @@
     # error message
     raise e_last
 
-def find_curses_include_dirs():
-    if os.path.exists('/usr/include/ncurses'):
-        return ['/usr/include/ncurses']
-    if os.path.exists('/usr/include/ncursesw'):
-        return ['/usr/include/ncursesw']
-    return []
+def find_curses_dir_and_name():
+    for base in ('/usr', '/usr/local'):
+        if os.path.exists(os.path.join(base, 'include', 'ncursesw')):
+            return base, 'ncursesw'
+        if os.path.exists(os.path.join(base, 'include', 'ncurses')):
+            return base, 'ncurses'
+    return '', None
 
+base, name = find_curses_dir_and_name()
+if base:
+    include_dirs = [os.path.join(base, 'include', name)]
+    library_dirs = [os.path.join(base, 'lib')]
+    libs = [name, name.replace('ncurses', 'panel')]
+else:
+    include_dirs = []
+    library_dirs = []
+    libs = [find_library(['ncursesw', 'ncurses']),
+                find_library(['panelw', 'panel']),
+           ]
 
 ffi = FFI()
 ffi.set_source("_curses_cffi", """
@@ -83,9 +95,10 @@
 void _m_getsyx(int *yx) {
     getsyx(yx[0], yx[1]);
 }
-""", libraries=[find_library(['ncurses', 'ncursesw']),
-                find_library(['panel', 'panelw'])],
-     include_dirs=find_curses_include_dirs())
+""", libraries=libs,
+     library_dirs = library_dirs,
+     include_dirs=include_dirs,
+)
 
 
 ffi.cdef("""
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -60,12 +60,9 @@
 Install build-time dependencies
 -------------------------------
 (**Note**: for some hints on how to translate the Python interpreter under
-Windows, see the `windows document`_ . For hints on how to cross-compile in
-a chroot using scratchbox2, see the `arm document`_ in the
-`RPython documentation`_)
+Windows, see the `windows document`_ . 
 
 .. _`windows document`: windows.html
-.. _`arm document`: http://rpython.readthedocs.org/en/latest/arm.html
 .. _`RPython documentation`: http://rpython.readthedocs.org
 
 The host Python needs to have CFFI installed. If translating on PyPy, CFFI is
@@ -88,9 +85,6 @@
 pyexpat
     libexpat1
 
-_ssl
-    libssl
-
 _vmprof
     libunwind (optional, loaded dynamically at runtime)
 
@@ -104,6 +98,9 @@
 sqlite3
     libsqlite3
 
+_ssl, _hashlib
+    libssl
+
 curses
     libncurses-dev   (for PyPy2)
     libncursesw-dev  (for PyPy3)
@@ -115,11 +112,12 @@
     tk-dev
 
 lzma (PyPy3 only)
-    liblzma
+    liblzma or libxz, version 5 and up
 
-To run untranslated tests, you need the Boehm garbage collector libgc.
+To run untranslated tests, you need the Boehm garbage collector libgc, version
+7.4 and up
 
-On recent Debian and Ubuntu (16.04 onwards), this is the command to install
+On Debian and Ubuntu (16.04 onwards), this is the command to install
 all build-time dependencies::
 
     apt-get install gcc make libffi-dev pkg-config zlib1g-dev libbz2-dev \
@@ -127,18 +125,11 @@
     tk-dev libgc-dev python-cffi \
     liblzma-dev libncursesw5-dev     # these two only needed on PyPy3
 
-On older Debian and Ubuntu (12.04-14.04)::
-
-    apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \
-    libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \
-    tk-dev libgc-dev python-cffi \
-    liblzma-dev libncursesw-dev      # these two only needed on PyPy3
-
 On Fedora::
 
     dnf install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \
     sqlite-devel ncurses-devel expat-devel openssl-devel tk-devel \
-    gdbm-devel python-cffi\
+    gdbm-devel python-cffi gc-devel\
     xz-devel  # For lzma on PyPy3.
 
 On SLES11::
diff --git a/pypy/doc/release-v7.3.0.rst b/pypy/doc/release-v7.3.0.rst
--- a/pypy/doc/release-v7.3.0.rst
+++ b/pypy/doc/release-v7.3.0.rst
@@ -18,6 +18,12 @@
 building third party packages for python, so this release changes the ABI tag
 for PyPy.
 
+Based on the great work done in `portable-pypy`_, the linux downloads we
+provide are now built on top of the `manylinux2010`_ CentOS6 docker image. 
+The tarballs include the needed shared objects to run on any platform that
+supports manylinux2010 wheels, which should include all supported versions of
+debian- and RedHat-based distributions (including Ubuntu, CentOS, and Fedora).
+
 The `CFFI`_ backend has been updated to version 1.13.1. We recommend using CFFI
 rather than c-extensions to interact with C.
 
@@ -57,6 +63,8 @@
 .. _`CFFI`: http://cffi.readthedocs.io
 .. _`cppyy`: https://cppyy.readthedocs.io
 .. _`available as wheels`: https://github.com/antocuni/pypy-wheels
+.. _`portable-pypy`: https://github.com/squeaky-pl/portable-pypy
+.. _`manylinux2010`: https://github.com/pypa/manylinux
 
 What is PyPy?
 =============
@@ -124,6 +132,7 @@
 * Check for overflow in ctypes array creation
 * Better support and report MSVC versions used to compile on windows
 * Allow any kind of buffer in socket.setsockopt(), like CPython (`issue 3114`_)
+* Fix importing a module with unicode in ``sys.path`` (`issue 3112`_)
 
 C-API (cpyext) and c-extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -166,6 +175,8 @@
   it.  (`issue 3096`_)
 * Remove incorrect clobbering of the ``locals`` after running ``exec()``
 * Adds encoding, decoding codepages on win32
+* Remove socket error attributes from ``_ssl`` (`issue 3119`_)
+* Add missing ``os.getgrouplist`` (part of `issue 2375`_)
 
 Python 3.6 C-API
 ~~~~~~~~~~~~~~~~
@@ -182,6 +193,7 @@
 .. _`manylinux2010`: fix broken link
 .. _`macports pypy`: 
https://github.com/macports/macports-ports/blob/master/lang/pypy/files/darwin.py.diff
 
+.. _`issue 2375`: https://bitbucket.com/pypy/pypy/issues/2375
 .. _`issue 2389`: https://bitbucket.com/pypy/pypy/issues/2389
 .. _`issue 2687`: https://bitbucket.com/pypy/pypy/issues/2687
 .. _`issue 2970`: https://bitbucket.com/pypy/pypy/issues/2970
@@ -198,8 +210,10 @@
 .. _`issue 3100`: https://bitbucket.com/pypy/pypy/issues/3100
 .. _`issue 3108`: https://bitbucket.com/pypy/pypy/issues/3108
 .. _`issue 3109`: https://bitbucket.com/pypy/pypy/issues/3109
+.. _`issue 3112`: https://bitbucket.com/pypy/pypy/issues/3112
 .. _`issue 3114`: https://bitbucket.com/pypy/pypy/issues/3114
 .. _`issue 3117`: https://bitbucket.com/pypy/pypy/issues/3117
+.. _`issue 3119`: https://bitbucket.com/pypy/pypy/issues/3119
 .. _`issue 3120`: https://bitbucket.com/pypy/pypy/issues/3120
 
 .. _13312: https://bugs.python.org/issue13312
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -5,4 +5,6 @@
 .. this is a revision shortly after release-pypy-7.3.0
 .. startrev: dbbbae99135f 
 
+.. branch: backport-decode_timeval_ns-py3.7
 
+Backport ``rtime.decode_timeval_ns`` from py3.7 to rpython
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -155,7 +155,7 @@
 the `get_externals.py` utility to checkout the proper branch for your platform
 and PyPy version.
 
-.. _subrepository:  https://bitbucket.org/pypy/external
+.. _subrepository:  https://bitbucket.org/pypy/externals
 
 Using the mingw compiler
 ------------------------
diff --git a/pypy/interpreter/test/test_generator.py 
b/pypy/interpreter/test/apptest_generator.py
copy from pypy/interpreter/test/test_generator.py
copy to pypy/interpreter/test/apptest_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/apptest_generator.py
@@ -1,322 +1,311 @@
-class AppTestGenerator:
+from pytest import raises, skip
 
-    def test_generator(self):
-        def f():
+def test_generator():
+    def f():
+        yield 1
+    assert f().next() == 1
+
+def test_generator2():
+    def f():
+        yield 1
+    g = f()
+    assert g.next() == 1
+    with raises(StopIteration):
+        g.next()
+
+def test_attributes():
+    def f():
+        yield 1
+        assert g.gi_running
+    g = f()
+    assert g.gi_code is f.__code__
+    assert g.__name__ == 'f'
+    assert g.gi_frame is not None
+    assert not g.gi_running
+    g.next()
+    assert not g.gi_running
+    with raises(StopIteration):
+        g.next()
+    assert not g.gi_running
+    assert g.gi_frame is None
+    assert g.gi_code is f.__code__
+    assert g.__name__ == 'f'
+
+def test_generator3():
+    def f():
+        yield 1
+    g = f()
+    assert list(g) == [1]
+
+def test_generator4():
+    def f():
+        yield 1
+    g = f()
+    assert [x for x in g] == [1]
+
+def test_generator5():
+    def f():
+        v = (yield)
+        yield v
+    g = f()
+    g.next()
+    assert g.send(42) == 42
+
+def test_throw1():
+    def f():
+        yield 2
+    g = f()
+    # two arguments version
+    with raises(NameError):
+        g.throw(NameError, "Error")
+
+def test_throw2():
+    def f():
+        yield 2
+    g = f()
+    # single argument version
+    with raises(NameError):
+        g.throw(NameError("Error"))
+
+def test_throw3():
+    def f():
+        try:
             yield 1
-        assert f().next() == 1
+            yield 2
+        except NameError:
+            yield 3
+    g = f()
+    assert g.next() == 1
+    assert g.throw(NameError("Error")) == 3
+    with raises(StopIteration):
+        g.next()
 
-    def test_generator2(self):
-        def f():
+def test_throw4():
+    def f():
+        try:
             yield 1
-        g = f()
-        assert g.next() == 1
-        raises(StopIteration, g.next)
+            v = (yield 2)
+        except NameError:
+            yield 3
+    g = f()
+    assert g.next() == 1
+    assert g.next() == 2
+    assert g.throw(NameError("Error")) == 3
+    with raises(StopIteration):
+        g.next()
 
-    def test_attributes(self):
-        def f():
+def test_throw5():
+    def f():
+        try:
             yield 1
-            assert g.gi_running
-        g = f()
-        assert g.gi_code is f.__code__
-        assert g.__name__ == 'f'
-        assert g.gi_frame is not None
-        assert not g.gi_running
+        except Exception:
+            x = 3
+        try:
+            yield x
+        except Exception:
+            pass
+    g = f()
+    g.next()
+    # String exceptions are not allowed anymore
+    with raises(TypeError):
+        g.throw("Error")
+    assert g.throw(Exception) == 3
+    with raises(StopIteration):
+        g.throw(Exception)
+
+def test_throw6():
+    def f():
+        yield 2
+    g = f()
+    with raises(NameError):
+        g.throw(NameError, "Error", None)
+
+
+def test_throw_fail():
+    def f():
+        yield 1
+    g = f()
+    with raises(TypeError):
+        g.throw(NameError("Error"), "error")
+
+def test_throw_fail2():
+    def f():
+        yield 1
+    g = f()
+    with raises(TypeError):
+        g.throw(list())
+
+def test_throw_fail3():
+    def f():
+        yield 1
+    g = f()
+    with raises(TypeError):
+        g.throw(NameError("Error"), None, "not tb object")
+
+def test_throw_finishes_generator():
+    def f():
+        yield 1
+    g = f()
+    assert g.gi_frame is not None
+    with raises(ValueError):
+        g.throw(ValueError)
+    assert g.gi_frame is None
+
+def test_throw_bug():
+    def f():
+        try:
+            x.throw(IndexError)     # => "generator already executing"
+        except ValueError:
+            yield 1
+    x = f()
+    res = list(x)
+    assert res == [1]
+
+def test_throw_on_finished_generator():
+    def f():
+        yield 1
+    g = f()
+    res = g.next()
+    assert res == 1
+    with raises(StopIteration):
         g.next()
-        assert not g.gi_running
-        raises(StopIteration, g.next)
-        assert not g.gi_running
-        assert g.gi_frame is None
-        assert g.gi_code is f.__code__
-        assert g.__name__ == 'f'
+    with raises(NameError):
+        g.throw(NameError)
 
-    def test_generator3(self):
-        def f():
+def test_close():
+    def f():
+        yield 1
+    g = f()
+    assert g.close() is None
+
+def test_close2():
+    def f():
+        try:
             yield 1
-        g = f()
-        assert list(g) == [1]
+        except GeneratorExit:
+            raise StopIteration
+    g = f()
+    g.next()
+    assert g.close() is None
 
-    def test_generator4(self):
-        def f():
+def test_close3():
+    def f():
+        try:
             yield 1
-        g = f()
-        assert [x for x in g] == [1]
+        except GeneratorExit:
+            raise NameError
+    g = f()
+    g.next()
+    with raises(NameError):
+        g.close()
 
-    def test_generator5(self):
-        d = {}
-        exec """if 1:
-        def f():
-            v = (yield )
-            yield v
-        g = f()
-        g.next()
-        """ in d
-        g = d['g']
-        assert g.send(42) == 42
+def test_close_fail():
+    def f():
+        try:
+            yield 1
+        except GeneratorExit:
+            yield 2
+    g = f()
+    g.next()
+    with raises(RuntimeError):
+        g.close()
 
-    def test_throw1(self):
-        def f():
-            yield 2
-        g = f()
-        # two arguments version
-        raises(NameError, g.throw, NameError, "Error")
+def test_close_on_collect():
+    import gc
+    def f():
+        try:
+            yield
+        finally:
+            f.x = 42
+    g = f()
+    g.next()
+    del g
+    gc.collect()
+    assert f.x == 42
 
-    def test_throw2(self):
-        def f():
-            yield 2
-        g = f()
-        # single argument version
-        raises(NameError, g.throw, NameError("Error"))
+def test_generator_raises_typeerror():
+    def f():
+        yield 1
+    g = f()
+    with raises(TypeError):
+        g.send()     # one argument required
+    with raises(TypeError):
+        g.send(1)  # not started, must send None
 
-    def test_throw3(self):
-        def f():
-            try:
-                yield 1
-                yield 2
-            except:
-                yield 3
-        g = f()
-        assert g.next() == 1
-        assert g.throw(NameError("Error")) == 3
-        raises(StopIteration, g.next)
+def test_generator_explicit_stopiteration():
+    def f():
+        yield 1
+        raise StopIteration
+    g = f()
+    assert [x for x in g] == [1]
 
-    def test_throw4(self):
-        d = {}
-        exec """if 1:
-        def f():
-            try:
-                yield 1
-                v = (yield 2)
-            except:
-                yield 3
-        g = f()
-        """ in d
-        g = d['g']
-        assert g.next() == 1
-        assert g.next() == 2
-        assert g.throw(NameError("Error")) == 3
-        raises(StopIteration, g.next)
+def test_generator_propagate_stopiteration():
+    def f():
+        it = iter([1])
+        while 1:
+            yield it.next()
+    g = f()
+    assert [x for x in g] == [1]
 
-    def test_throw5(self):
-        def f():
-            try:
-                yield 1
-            except:
-                x = 3
-            try:
-                yield x
-            except:
-                pass
-        g = f()
-        g.next()
-        # String exceptions are not allowed anymore
-        raises(TypeError, g.throw, "Error")
-        assert g.throw(Exception) == 3
-        raises(StopIteration, g.throw, Exception)
+def test_generator_restart():
+    def g():
+        i = me.next()
+        yield i
+    me = g()
+    with raises(ValueError):
+        me.next()
 
-    def test_throw6(self):
-        def f():
-            yield 2
-        g = f()
-        raises(NameError, g.throw, NameError, "Error", None)
+def test_generator_expression():
+    exec "res = sum(i*i for i in range(5))"
+    assert res == 30
 
+def test_generator_expression_2():
+    def f():
+        total = sum(i for i in [x for x in z])
+        return total, x
+    z = [1, 2, 7]
+    assert f() == (10, 7)
 
-    def test_throw_fail(self):
-        def f():
-            yield 1
-        g = f()
-        raises(TypeError, g.throw, NameError("Error"), "error")
+def test_repr():
+    def myFunc():
+        yield 1
+    g = myFunc()
+    r = repr(g)
+    assert r.startswith("<generator object myFunc at 0x")
+    assert list(g) == [1]
+    assert repr(g) == r
 
-    def test_throw_fail2(self):
-        def f():
-            yield 1
-        g = f()
-        raises(TypeError, g.throw, list())
+def test_unpackiterable_gen():
+    g = (i * i for i in range(-5, 3))
+    assert set(g) == set([0, 1, 4, 9, 16, 25])
+    assert set(g) == set()
+    assert set(i for i in range(0)) == set()
 
-    def test_throw_fail3(self):
-        def f():
-            yield 1
-        g = f()
-        raises(TypeError, g.throw, NameError("Error"), None, "not tb object")
+def test_explicit_stop_iteration_unpackiterable():
+    def f():
+        yield 1
+        raise StopIteration
+    assert tuple(f()) == (1,)
 
-    def test_throw_finishes_generator(self):
-        def f():
-            yield 1
-        g = f()
-        assert g.gi_frame is not None
-        raises(ValueError, g.throw, ValueError)
-        assert g.gi_frame is None
+def test_exception_is_cleared_by_yield():
+    def f():
+        try:
+            foobar
+        except NameError:
+            yield 5
+            raise    # should raise "no active exception to re-raise"
+    gen = f()
+    next(gen)  # --> 5
+    try:
+        next(gen)
+    except TypeError:
+        pass
 
-    def test_throw_bug(self):
-        def f():
-            try:
-                x.throw(IndexError)     # => "generator already executing"
-            except ValueError:
-                yield 1
-        x = f()
-        res = list(x)
-        assert res == [1]
-
-    def test_throw_on_finished_generator(self):
-        def f():
-            yield 1
-        g = f()
-        res = g.next()
-        assert res == 1
-        raises(StopIteration, g.next)
-        raises(NameError, g.throw, NameError)
-
-    def test_close(self):
-        def f():
-            yield 1
-        g = f()
-        assert g.close() is None
-
-    def test_close2(self):
-        def f():
-            try:
-                yield 1
-            except GeneratorExit:
-                raise StopIteration
-        g = f()
-        g.next()
-        assert g.close() is None
-
-    def test_close3(self):
-        def f():
-            try:
-                yield 1
-            except GeneratorExit:
-                raise NameError
-        g = f()
-        g.next()
-        raises(NameError, g.close)
-
-    def test_close_fail(self):
-        def f():
-            try:
-                yield 1
-            except GeneratorExit:
-                yield 2
-        g = f()
-        g.next()
-        raises(RuntimeError, g.close)
-
-    def test_close_on_collect(self):
-        ## we need to exec it, else it won't run on python2.4
-        d = {}
-        exec """
-        def f():
-            try:
-                yield
-            finally:
-                f.x = 42
-        """.strip() in d
-
-        g = d['f']()
-        g.next()
-        del g
-        import gc
-        gc.collect()
-        assert d['f'].x == 42
-
-    def test_generator_raises_typeerror(self):
-        def f():
-            yield 1
-        g = f()
-        raises(TypeError, g.send)     # one argument required
-        raises(TypeError, g.send, 1)  # not started, must send None
-
-    def test_generator_explicit_stopiteration(self):
-        def f():
-            yield 1
-            raise StopIteration
-        g = f()
-        assert [x for x in g] == [1]
-
-    def test_generator_propagate_stopiteration(self):
-        def f():
-            it = iter([1])
-            while 1: yield it.next()
-        g = f()
-        assert [x for x in g] == [1]
-
-    def test_generator_restart(self):
-        def g():
-            i = me.next()
-            yield i
-        me = g()
-        raises(ValueError, me.next)
-
-    def test_generator_expression(self):
-        exec "res = sum(i*i for i in range(5))"
-        assert res == 30
-
-    def test_generator_expression_2(self):
-        d = {}
-        exec """
-def f():
-    total = sum(i for i in [x for x in z])
-    return total, x
-z = [1, 2, 7]
-res = f()
-""" in d
-        assert d['res'] == (10, 7)
-
-    def test_repr(self):
-        def myFunc():
-            yield 1
-        g = myFunc()
-        r = repr(g)
-        assert r.startswith("<generator object myFunc at 0x")
-        assert list(g) == [1]
-        assert repr(g) == r
-
-    def test_unpackiterable_gen(self):
-        g = (i*i for i in range(-5, 3))
-        assert set(g) == set([0, 1, 4, 9, 16, 25])
-        assert set(g) == set()
-        assert set(i for i in range(0)) == set()
-
-    def test_explicit_stop_iteration_unpackiterable(self):
-        def f():
-            yield 1
-            raise StopIteration
-        assert tuple(f()) == (1,)
-
-    def test_exception_is_cleared_by_yield(self):
-        def f():
-            try:
-                foobar
-            except NameError:
-                yield 5
-                raise    # should raise "no active exception to re-raise"
-        gen = f()
-        next(gen)  # --> 5
-        try:
-            next(gen)
-        except TypeError:
-            pass
-
-    def test_multiple_invalid_sends(self):
-        def mygen():
-            yield 42
-        g = mygen()
-        raises(TypeError, g.send, 2)
-        raises(TypeError, g.send, 2)
-
-
-def test_should_not_inline(space):
-    from pypy.interpreter.generator import should_not_inline
-    w_co = space.appexec([], '''():
-        def g(x):
-            yield x + 5
-        return g.__code__
-    ''')
-    assert should_not_inline(w_co) == False
-    w_co = space.appexec([], '''():
-        def g(x):
-            yield x + 5
-            yield x + 6
-        return g.__code__
-    ''')
-    assert should_not_inline(w_co) == True
+def test_multiple_invalid_sends():
+    def mygen():
+        yield 42
+    g = mygen()
+    with raises(TypeError):
+        g.send(2)
+    with raises(TypeError):
+        g.send(2)
diff --git a/pypy/interpreter/test/test_generator.py 
b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -1,310 +1,3 @@
-class AppTestGenerator:
-
-    def test_generator(self):
-        def f():
-            yield 1
-        assert f().next() == 1
-
-    def test_generator2(self):
-        def f():
-            yield 1
-        g = f()
-        assert g.next() == 1
-        raises(StopIteration, g.next)
-
-    def test_attributes(self):
-        def f():
-            yield 1
-            assert g.gi_running
-        g = f()
-        assert g.gi_code is f.__code__
-        assert g.__name__ == 'f'
-        assert g.gi_frame is not None
-        assert not g.gi_running
-        g.next()
-        assert not g.gi_running
-        raises(StopIteration, g.next)
-        assert not g.gi_running
-        assert g.gi_frame is None
-        assert g.gi_code is f.__code__
-        assert g.__name__ == 'f'
-
-    def test_generator3(self):
-        def f():
-            yield 1
-        g = f()
-        assert list(g) == [1]
-
-    def test_generator4(self):
-        def f():
-            yield 1
-        g = f()
-        assert [x for x in g] == [1]
-
-    def test_generator5(self):
-        d = {}
-        exec """if 1:
-        def f():
-            v = (yield )
-            yield v
-        g = f()
-        g.next()
-        """ in d
-        g = d['g']
-        assert g.send(42) == 42
-
-    def test_throw1(self):
-        def f():
-            yield 2
-        g = f()
-        # two arguments version
-        raises(NameError, g.throw, NameError, "Error")
-
-    def test_throw2(self):
-        def f():
-            yield 2
-        g = f()
-        # single argument version
-        raises(NameError, g.throw, NameError("Error"))
-
-    def test_throw3(self):
-        def f():
-            try:
-                yield 1
-                yield 2
-            except:
-                yield 3
-        g = f()
-        assert g.next() == 1
-        assert g.throw(NameError("Error")) == 3
-        raises(StopIteration, g.next)
-
-    def test_throw4(self):
-        d = {}
-        exec """if 1:
-        def f():
-            try:
-                yield 1
-                v = (yield 2)
-            except:
-                yield 3
-        g = f()
-        """ in d
-        g = d['g']
-        assert g.next() == 1
-        assert g.next() == 2
-        assert g.throw(NameError("Error")) == 3
-        raises(StopIteration, g.next)
-
-    def test_throw5(self):
-        def f():
-            try:
-                yield 1
-            except:
-                x = 3
-            try:
-                yield x
-            except:
-                pass
-        g = f()
-        g.next()
-        # String exceptions are not allowed anymore
-        raises(TypeError, g.throw, "Error")
-        assert g.throw(Exception) == 3
-        raises(StopIteration, g.throw, Exception)
-
-    def test_throw6(self):
-        def f():
-            yield 2
-        g = f()
-        raises(NameError, g.throw, NameError, "Error", None)
-
-
-    def test_throw_fail(self):
-        def f():
-            yield 1
-        g = f()
-        raises(TypeError, g.throw, NameError("Error"), "error")
-
-    def test_throw_fail2(self):
-        def f():
-            yield 1
-        g = f()
-        raises(TypeError, g.throw, list())
-
-    def test_throw_fail3(self):
-        def f():
-            yield 1
-        g = f()
-        raises(TypeError, g.throw, NameError("Error"), None, "not tb object")
-
-    def test_throw_finishes_generator(self):
-        def f():
-            yield 1
-        g = f()
-        assert g.gi_frame is not None
-        raises(ValueError, g.throw, ValueError)
-        assert g.gi_frame is None
-
-    def test_throw_bug(self):
-        def f():
-            try:
-                x.throw(IndexError)     # => "generator already executing"
-            except ValueError:
-                yield 1
-        x = f()
-        res = list(x)
-        assert res == [1]
-
-    def test_throw_on_finished_generator(self):
-        def f():
-            yield 1
-        g = f()
-        res = g.next()
-        assert res == 1
-        raises(StopIteration, g.next)
-        raises(NameError, g.throw, NameError)
-
-    def test_close(self):
-        def f():
-            yield 1
-        g = f()
-        assert g.close() is None
-
-    def test_close2(self):
-        def f():
-            try:
-                yield 1
-            except GeneratorExit:
-                raise StopIteration
-        g = f()
-        g.next()
-        assert g.close() is None
-
-    def test_close3(self):
-        def f():
-            try:
-                yield 1
-            except GeneratorExit:
-                raise NameError
-        g = f()
-        g.next()
-        raises(NameError, g.close)
-
-    def test_close_fail(self):
-        def f():
-            try:
-                yield 1
-            except GeneratorExit:
-                yield 2
-        g = f()
-        g.next()
-        raises(RuntimeError, g.close)
-
-    def test_close_on_collect(self):
-        ## we need to exec it, else it won't run on python2.4
-        d = {}
-        exec """
-        def f():
-            try:
-                yield
-            finally:
-                f.x = 42
-        """.strip() in d
-
-        g = d['f']()
-        g.next()
-        del g
-        import gc
-        gc.collect()
-        assert d['f'].x == 42
-
-    def test_generator_raises_typeerror(self):
-        def f():
-            yield 1
-        g = f()
-        raises(TypeError, g.send)     # one argument required
-        raises(TypeError, g.send, 1)  # not started, must send None
-
-    def test_generator_explicit_stopiteration(self):
-        def f():
-            yield 1
-            raise StopIteration
-        g = f()
-        assert [x for x in g] == [1]
-
-    def test_generator_propagate_stopiteration(self):
-        def f():
-            it = iter([1])
-            while 1: yield it.next()
-        g = f()
-        assert [x for x in g] == [1]
-
-    def test_generator_restart(self):
-        def g():
-            i = me.next()
-            yield i
-        me = g()
-        raises(ValueError, me.next)
-
-    def test_generator_expression(self):
-        exec "res = sum(i*i for i in range(5))"
-        assert res == 30
-
-    def test_generator_expression_2(self):
-        d = {}
-        exec """
-def f():
-    total = sum(i for i in [x for x in z])
-    return total, x
-z = [1, 2, 7]
-res = f()
-""" in d
-        assert d['res'] == (10, 7)
-
-    def test_repr(self):
-        def myFunc():
-            yield 1
-        g = myFunc()
-        r = repr(g)
-        assert r.startswith("<generator object myFunc at 0x")
-        assert list(g) == [1]
-        assert repr(g) == r
-
-    def test_unpackiterable_gen(self):
-        g = (i*i for i in range(-5, 3))
-        assert set(g) == set([0, 1, 4, 9, 16, 25])
-        assert set(g) == set()
-        assert set(i for i in range(0)) == set()
-
-    def test_explicit_stop_iteration_unpackiterable(self):
-        def f():
-            yield 1
-            raise StopIteration
-        assert tuple(f()) == (1,)
-
-    def test_exception_is_cleared_by_yield(self):
-        def f():
-            try:
-                foobar
-            except NameError:
-                yield 5
-                raise    # should raise "no active exception to re-raise"
-        gen = f()
-        next(gen)  # --> 5
-        try:
-            next(gen)
-        except TypeError:
-            pass
-
-    def test_multiple_invalid_sends(self):
-        def mygen():
-            yield 42
-        g = mygen()
-        raises(TypeError, g.send, 2)
-        raises(TypeError, g.send, 2)
-
-
 def test_should_not_inline(space):
     from pypy.interpreter.generator import should_not_inline
     w_co = space.appexec([], '''():
diff --git a/pypy/module/_hashlib/__init__.py b/pypy/module/_hashlib/__init__.py
deleted file mode 100644
diff --git a/pypy/module/_hashlib/interp_hashlib.py 
b/pypy/module/_hashlib/interp_hashlib.py
deleted file mode 100644
--- a/pypy/module/_hashlib/interp_hashlib.py
+++ /dev/null
@@ -1,204 +0,0 @@
-from __future__ import with_statement
-
-from rpython.rlib import rgc, ropenssl
-from rpython.rlib.objectmodel import we_are_translated
-from rpython.rlib.rstring import StringBuilder
-from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.tool.sourcetools import func_renamer
-
-from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.gateway import unwrap_spec, interp2app, WrappedDefault
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.module.thread.os_lock import Lock
-
-
-algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
-
-def hash_name_mapper_callback(obj_name, userdata):
-    if not obj_name:
-        return
-    # Ignore aliased names, they pollute the list and OpenSSL appears
-    # to have a its own definition of alias as the resulting list
-    # still contains duplicate and alternate names for several
-    # algorithms.
-    if rffi.cast(lltype.Signed, obj_name[0].c_alias):
-        return
-    name = rffi.charp2str(obj_name[0].c_name)
-    global_name_fetcher.meth_names.append(name)
-
-class NameFetcher:
-    def setup(self):
-        self.meth_names = []
-    def _cleanup_(self):
-        self.__dict__.clear()
-global_name_fetcher = NameFetcher()
-
-def fetch_names(space):
-    global_name_fetcher.setup()
-    ropenssl.init_digests()
-    ropenssl.OBJ_NAME_do_all(ropenssl.OBJ_NAME_TYPE_MD_METH,
-                             hash_name_mapper_callback, None)
-    meth_names = global_name_fetcher.meth_names
-    global_name_fetcher.meth_names = None
-    return space.call_function(space.w_frozenset, space.newlist(
-        [space.newtext(name) for name in meth_names]))
-
-class W_Hash(W_Root):
-    NULL_CTX = lltype.nullptr(ropenssl.EVP_MD_CTX.TO)
-    ctx = NULL_CTX
-
-    def __init__(self, space, name, copy_from=NULL_CTX):
-        self.name = name
-        digest_type = self.digest_type_by_name(space)
-        self.digest_size = ropenssl.EVP_MD_size(digest_type)
-
-        # Allocate a lock for each HASH object.
-        # An optimization would be to not release the GIL on small requests,
-        # and use a custom lock only when needed.
-        self.lock = Lock(space)
-
-        ctx = ropenssl.EVP_MD_CTX_new()
-        if ctx is None:
-            raise MemoryError
-        rgc.add_memory_pressure(ropenssl.HASH_MALLOC_SIZE + self.digest_size,
-                                self)
-        try:
-            if copy_from:
-                if not ropenssl.EVP_MD_CTX_copy(ctx, copy_from):
-                    raise ValueError
-            else:
-                ropenssl.EVP_DigestInit(ctx, digest_type)
-            self.ctx = ctx
-        except:
-            ropenssl.EVP_MD_CTX_free(ctx)
-            raise
-        self.register_finalizer(space)
-
-    def _finalize_(self):
-        ctx = self.ctx
-        if ctx:
-            self.ctx = lltype.nullptr(ropenssl.EVP_MD_CTX.TO)
-            ropenssl.EVP_MD_CTX_free(ctx)
-
-    def digest_type_by_name(self, space):
-        digest_type = ropenssl.EVP_get_digestbyname(self.name)
-        if not digest_type:
-            raise oefmt(space.w_ValueError, "unknown hash function")
-        return digest_type
-
-    def descr_repr(self, space):
-        addrstring = self.getaddrstring(space)
-        return space.newtext("<%s HASH object at 0x%s>" % (
-            self.name, addrstring))
-
-    @unwrap_spec(string='bufferstr')
-    def update(self, space, string):
-        with rffi.scoped_nonmovingbuffer(string) as buf:
-            with self.lock:
-                # XXX try to not release the GIL for small requests
-                ropenssl.EVP_DigestUpdate(self.ctx, buf, len(string))
-
-    def copy(self, space):
-        "Return a copy of the hash object."
-        with self.lock:
-            return W_Hash(space, self.name, copy_from=self.ctx)
-
-    def digest(self, space):
-        "Return the digest value as a string of binary data."
-        digest = self._digest(space)
-        return space.newbytes(digest)
-
-    def hexdigest(self, space):
-        "Return the digest value as a string of hexadecimal digits."
-        digest = self._digest(space)
-        hexdigits = '0123456789abcdef'
-        result = StringBuilder(self.digest_size * 2)
-        for c in digest:
-            result.append(hexdigits[(ord(c) >> 4) & 0xf])
-            result.append(hexdigits[ ord(c)       & 0xf])
-        return space.newtext(result.build())
-
-    def get_digest_size(self, space):
-        return space.newint(self.digest_size)
-
-    def get_block_size(self, space):
-        digest_type = self.digest_type_by_name(space)
-        block_size = ropenssl.EVP_MD_block_size(digest_type)
-        return space.newint(block_size)
-
-    def get_name(self, space):
-        return space.newtext(self.name)
-
-    def _digest(self, space):
-        ctx = ropenssl.EVP_MD_CTX_new()
-        if ctx is None:
-            raise MemoryError
-        try:
-            with self.lock:
-                if not ropenssl.EVP_MD_CTX_copy(ctx, self.ctx):
-                    raise ValueError
-            digest_size = self.digest_size
-            with rffi.scoped_alloc_buffer(digest_size) as buf:
-                ropenssl.EVP_DigestFinal(ctx, buf.raw, None)
-                return buf.str(digest_size)
-        finally:
-            ropenssl.EVP_MD_CTX_free(ctx)
-
-
-W_Hash.typedef = TypeDef(
-    'HASH',
-    __repr__=interp2app(W_Hash.descr_repr),
-    update=interp2app(W_Hash.update),
-    copy=interp2app(W_Hash.copy),
-    digest=interp2app(W_Hash.digest),
-    hexdigest=interp2app(W_Hash.hexdigest),
-    #
-    digest_size=GetSetProperty(W_Hash.get_digest_size),
-    digestsize=GetSetProperty(W_Hash.get_digest_size),
-    block_size=GetSetProperty(W_Hash.get_block_size),
-    name=GetSetProperty(W_Hash.get_name),
-)
-W_Hash.typedef.acceptable_as_base_class = False
-
-@unwrap_spec(name='text', string='bufferstr')
-def new(space, name, string=''):
-    w_hash = W_Hash(space, name)
-    w_hash.update(space, string)
-    return w_hash
-
-# shortcut functions
-def make_new_hash(name, funcname):
-    @func_renamer(funcname)
-    @unwrap_spec(string='bufferstr')
-    def new_hash(space, string=''):
-        return new(space, name, string)
-    return new_hash
-
-for _name in algorithms:
-    _newname = 'new_%s' % (_name,)
-    globals()[_newname] = make_new_hash(_name, _newname)
-
-
-HAS_FAST_PKCS5_PBKDF2_HMAC = ropenssl.PKCS5_PBKDF2_HMAC is not None
-if HAS_FAST_PKCS5_PBKDF2_HMAC:
-    @unwrap_spec(name='text', password='bytes', salt='bytes', rounds=int,
-                 w_dklen=WrappedDefault(None))
-    def pbkdf2_hmac(space, name, password, salt, rounds, w_dklen):
-        digest = ropenssl.EVP_get_digestbyname(name)
-        if not digest:
-            raise oefmt(space.w_ValueError, "unknown hash function")
-        if space.is_w(w_dklen, space.w_None):
-            dklen = ropenssl.EVP_MD_size(digest)
-        else:
-            dklen = space.int_w(w_dklen)
-        if dklen < 1:
-            raise oefmt(space.w_ValueError,
-                        "key length must be greater than 0.")
-        with rffi.scoped_alloc_buffer(dklen) as buf:
-            r = ropenssl.PKCS5_PBKDF2_HMAC(
-                password, len(password), salt, len(salt), rounds, digest,
-                dklen, buf.raw)
-            if not r:
-                raise ValueError
-            return space.newbytes(buf.str(dklen))
diff --git a/pypy/module/_hashlib/moduledef.py 
b/pypy/module/_hashlib/moduledef.py
deleted file mode 100644
--- a/pypy/module/_hashlib/moduledef.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from pypy.interpreter.mixedmodule import MixedModule
-from pypy.module._hashlib.interp_hashlib import (
-    algorithms, fetch_names, HAS_FAST_PKCS5_PBKDF2_HMAC)
-
-
-class Module(MixedModule):
-    interpleveldefs = {
-        'new' : 'interp_hashlib.new',
-        }
-
-    appleveldefs = {
-        }
-
-    for name in algorithms:
-        interpleveldefs['openssl_' + name] = 'interp_hashlib.new_' + name
-
-    if HAS_FAST_PKCS5_PBKDF2_HMAC:
-        interpleveldefs['pbkdf2_hmac'] = 'interp_hashlib.pbkdf2_hmac'
-
-    def startup(self, space):
-        w_meth_names = fetch_names(space)
-        space.setattr(self, space.newtext('openssl_md_meth_names'), 
w_meth_names)
diff --git a/pypy/module/_hashlib/test/test_hashlib.py 
b/pypy/module/_hashlib/test/test_hashlib.py
deleted file mode 100644
--- a/pypy/module/_hashlib/test/test_hashlib.py
+++ /dev/null
@@ -1,123 +0,0 @@
-class AppTestHashlib:
-    spaceconfig = {
-        "usemodules": ['_hashlib', 'array', 'struct', 'binascii'],
-    }
-
-    def test_method_names(self):
-        import _hashlib
-        assert isinstance(_hashlib.openssl_md_meth_names, frozenset)
-        assert "md5" in _hashlib.openssl_md_meth_names
-
-    def test_simple(self):
-        import _hashlib
-        assert _hashlib.new('md5').__class__.__name__ == 'HASH'
-        assert len(_hashlib.new('md5').hexdigest()) == 32
-
-    def test_attributes(self):
-        import hashlib
-        for name, (expected_size, expected_block_size) in {
-                'md5': (16, 64),
-                'sha1': (20, 64),
-                'sha224': (28, 64),
-                'sha256': (32, 64),
-                'sha384': (48, 128),
-                'sha512': (64, 128),
-                }.items():
-            h = hashlib.new(name)
-            assert h.name == name
-            assert h.digest_size == expected_size
-            assert h.digestsize == expected_size
-            assert h.block_size == expected_block_size
-            #
-            h.update('abc')
-            h2 = h.copy()
-            h.update('def')
-            digest = h.digest()
-            hexdigest = h.hexdigest()
-            h2.update('d')
-            h2.update('ef')
-            assert digest    == h2.digest()
-            assert hexdigest == h2.hexdigest()
-            assert len(digest)    == h.digest_size
-            assert len(hexdigest) == h.digest_size * 2
-            c_digest    = digest
-            c_hexdigest = hexdigest
-
-            # also test the pure Python implementation
-            py_new = getattr(hashlib, '__get_builtin_constructor')
-            h = py_new(name)('')
-            assert h.digest_size == expected_size
-            assert h.digestsize == expected_size
-            assert h.block_size == expected_block_size
-            #
-            h.update('abc')
-            h2 = h.copy()
-            h.update('def')
-            digest = h.digest()
-            hexdigest = h.hexdigest()
-            h2.update('d')
-            h2.update('ef')
-            assert digest    == h2.digest()
-            assert hexdigest == h2.hexdigest()
-
-            # compare both implementations
-            assert c_digest    == digest
-            assert c_hexdigest == hexdigest
-
-    def test_shortcut(self):
-        import hashlib
-        assert repr(hashlib.md5()).startswith("<md5 HASH object")
-
-    def test_unicode(self):
-        import _hashlib
-        assert _hashlib.new('sha1', u'xxx').__class__.__name__ == 'HASH'
-
-    def test_uppercase(self):
-        import _hashlib
-        h = _hashlib.new('MD5')
-        assert h.digest_size == 16
-        assert len(h.hexdigest()) == 32
-
-    def test_buffer(self):
-        import _hashlib, array
-        b = array.array('b', 'x' * 10)
-        h = _hashlib.new('md5', b)
-        h.update(b)
-        assert h.digest() == _hashlib.openssl_md5('x' * 20).digest()
-        _hashlib.openssl_sha1(b).digest()
-
-    def test_extra_algorithms(self):
-        expected_results = {
-            "md5": "bb649c83dd1ea5c9d9dec9a18df0ffe9",
-            "md4": "c275b8454684ea416b93d7a418b43176",
-            "mdc2": None,   # XXX find the correct expected value
-            "sha": "e2b0a8609b47c58e5d984c9ccfe69f9b654b032b",
-            "ripemd160": "cc4a5ce1b3df48aec5d22d1f16b894a0b894eccc",
-            "whirlpool": ("1a22b79fe5afda02c63a25927193ed01dc718b74"
-                          "026e597608ce431f9c3d2c9e74a7350b7fbb7c5d"
-                          "4effe5d7a31879b8b7a10fd2f544c4ca268ecc6793923583"),
-            }
-        import _hashlib
-        test_string = "Nobody inspects the spammish repetition"
-        for hash_name, expected in sorted(expected_results.items()):
-            try:
-                m = _hashlib.new(hash_name)
-            except ValueError as e:
-                print 'skipped %s: %s' % (hash_name, e)
-                continue
-            m.update(test_string)
-            got = m.hexdigest()
-            assert got and type(got) is str and len(got) % 2 == 0
-            got.decode('hex')
-            if expected is not None:
-                assert got == expected
-
-    def test_pbkdf2(self):
-        try:
-            from _hashlib import pbkdf2_hmac
-        except ImportError:
-            skip("Requires OpenSSL >= 1.1")
-        out = pbkdf2_hmac('sha1', 'password', 'salt', 1)
-        assert out == '0c60c80f961f0e71f3a9b524af6012062fe037a6'.decode('hex')
-        out = pbkdf2_hmac('sha1', 'password', 'salt', 2, None)
-        assert out == 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957'.decode('hex')
diff --git a/pypy/module/_hashlib/test/test_ztranslation.py 
b/pypy/module/_hashlib/test/test_ztranslation.py
deleted file mode 100644
--- a/pypy/module/_hashlib/test/test_ztranslation.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from pypy.objspace.fake.checkmodule import checkmodule
-
-def test_checkmodule():
-    checkmodule('_hashlib')
diff --git a/pypy/module/_minimal_curses/fficurses.py 
b/pypy/module/_minimal_curses/fficurses.py
--- a/pypy/module/_minimal_curses/fficurses.py
+++ b/pypy/module/_minimal_curses/fficurses.py
@@ -5,11 +5,6 @@
 from rpython.rtyper.tool import rffi_platform
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
-# We cannot trust ncurses5-config, it's broken in various ways in
-# various versions.  For example it might not list -ltinfo even though
-# it's needed, or --cflags might be completely empty.  On Ubuntu 10.04
-# it gives -I/usr/include/ncurses, which doesn't exist at all.  Crap.
-
 def try_cflags():
     yield ExternalCompilationInfo(includes=['curses.h', 'term.h'])
     yield ExternalCompilationInfo(includes=['curses.h', 'term.h'],
@@ -20,8 +15,9 @@
                                             'ncurses/term.h'])
 
 def try_ldflags():
+    yield ExternalCompilationInfo(libraries=['curses', 'tinfo'])
     yield ExternalCompilationInfo(libraries=['curses'])
-    yield ExternalCompilationInfo(libraries=['curses', 'tinfo'])
+    yield ExternalCompilationInfo(libraries=['ncurses', 'tinfo'])
     yield ExternalCompilationInfo(libraries=['ncurses'])
     yield ExternalCompilationInfo(libraries=['ncurses'],
                                   library_dirs=['/usr/lib64'])
@@ -30,7 +26,11 @@
 
 def try_tools():
     try:
-        yield ExternalCompilationInfo.from_pkg_config("ncurses")
+        yield ExternalCompilationInfo.from_config_tool("ncursesw6-config")
+    except Exception:
+        pass
+    try:
+        yield ExternalCompilationInfo.from_config_tool("ncurses5-config")
     except Exception:
         pass
     try:
@@ -38,7 +38,7 @@
     except Exception:
         pass
     try:
-        yield ExternalCompilationInfo.from_config_tool("ncurses5-config")
+        yield ExternalCompilationInfo.from_pkg_config("ncursesw")
     except Exception:
         pass
 
diff --git a/pypy/module/cpyext/cparser.py b/pypy/module/cpyext/cparser.py
--- a/pypy/module/cpyext/cparser.py
+++ b/pypy/module/cpyext/cparser.py
@@ -705,6 +705,7 @@
         self.struct_typedefs = {}
         self._handled = set()
         self._frozen = False
+        self._cdecl_type_cache = {} # {cdecl: TYPE} cache
         if includes is not None:
             for header in includes:
                 self.include(header)
@@ -840,6 +841,14 @@
             raise NotImplementedError
 
     def gettype(self, cdecl):
+        try:
+            return self._cdecl_type_cache[cdecl]
+        except KeyError:
+            result = self._real_gettype(cdecl)
+            self._cdecl_type_cache[cdecl] = result
+            return result
+
+    def _real_gettype(self, cdecl):
         obj = self.ctx.parse_type(cdecl)
         result = self.convert_type(obj)
         if isinstance(result, DelayedStruct):
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -448,14 +448,19 @@
             return w_loader
 
 def _getimporter(space, w_pathitem):
-    # the function 'imp._getimporter' is a pypy-only extension
+    # 'imp._getimporter' is somewhat like CPython's get_path_importer
     w_path_importer_cache = space.sys.get("path_importer_cache")
     w_importer = space.finditem(w_path_importer_cache, w_pathitem)
     if w_importer is None:
         space.setitem(w_path_importer_cache, w_pathitem, space.w_None)
         for w_hook in space.unpackiterable(space.sys.get("path_hooks")):
+            w_pathbytes = w_pathitem
+            if space.isinstance_w(w_pathitem, space.w_unicode):
+                from pypy.module.sys.interp_encoding import 
getfilesystemencoding
+                w_pathbytes = space.call_method(space.w_unicode, 'encode',
+                                     w_pathitem, getfilesystemencoding(space))
             try:
-                w_importer = space.call_function(w_hook, w_pathitem)
+                w_importer = space.call_function(w_hook, w_pathbytes)
             except OperationError as e:
                 if not e.match(space, space.w_ImportError):
                     raise
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
@@ -4,7 +4,8 @@
 
 class AppTestImpModule:
     spaceconfig = {
-        'usemodules': ['binascii', 'imp', 'itertools', 'time', 'struct'],
+        'usemodules': ['binascii', 'imp', 'itertools', 'time', 'struct',
+                       'zipimport'],
     }
 
     def setup_class(cls):
@@ -246,3 +247,14 @@
         assert marshal.loads == 42
 
         marshal.loads = old
+
+    def test_unicode_in_sys_path(self):
+        # issue 3112: when _getimporter calls
+        # for x in sys.path: for h in sys.path_hooks: h(x)
+        # make sure x is properly encoded
+        import sys
+        import zipimport #  installs a sys.path_hook
+        if sys.getfilesystemencoding().lower() == 'utf-8':
+            sys.path.insert(0, u'\xef')
+        with raises(ImportError):
+            import impossible_module
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py 
b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -4,8 +4,10 @@
 from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
 from rpython.rlib.rawstorage import misaligned_is_fine
 
+IS_X86 = platform.machine().startswith('x86') or platform.machine() == 'i686'
+
 def no_vector_backend():
-    if platform.machine().startswith('x86'):
+    if IS_X86:
         from rpython.jit.backend.x86.detect_feature import detect_sse4_2
         if sys.maxsize < 2**31:
             return True    
@@ -19,7 +21,7 @@
     return True
 
 def align_check(input):
-    if platform.machine().startswith('x86'):
+    if IS_X86:
         return ""
     if sys.maxsize > 2**32:
         mask = 7
diff --git a/pypy/module/thread/test/test_thread.py 
b/pypy/module/thread/test/test_thread.py
--- a/pypy/module/thread/test/test_thread.py
+++ b/pypy/module/thread/test/test_thread.py
@@ -1,38 +1,9 @@
 import thread, time
 from pypy.module.thread.test.support import GenericTestThread
+import pytest
 
 class AppTestThread(GenericTestThread):
 
-    def setup_class(cls):
-        GenericTestThread.setup_class.im_func(cls)
-        # if we cannot start more than, say, 1000 threads on this OS, then
-        # we can check that we get the proper error at app-level
-        space = cls.space
-        lock = thread.allocate_lock()
-        lock.acquire()
-        def f():
-            lock.acquire()
-            lock.release()
-        start = thread._count()
-        try:
-            try:
-                for i in range(1000):
-                    thread.start_new_thread(f, ())
-            finally:
-                lock.release()
-        except (thread.error, MemoryError):
-            cls.w_can_start_many_threads = space.wrap(False)
-        else:
-            cls.w_can_start_many_threads = space.wrap(True)
-        # wait a bit to allow all threads to finish now
-        remaining = thread._count()
-        retries = 0
-        while remaining > start:
-            retries += 1
-            if retries == 200:
-                raise Exception("the test's threads don't stop!")
-            time.sleep(0.2)
-            remaining = thread._count()
 
     def test_start_new_thread(self):
         import thread
@@ -189,35 +160,6 @@
             assert done    # see stderr for failures in threads
         assert sorted(lst) == range(120)
 
-    def test_many_threads(self):
-        import thread, time
-        if self.can_start_many_threads:
-            skip("this OS supports too many threads to check (> 1000)")
-        lock = thread.allocate_lock()
-        lock.acquire()
-        count = [0]
-        def f():
-            count[0] += 1
-            lock.acquire()
-            lock.release()
-            count[0] -= 1
-        try:
-            try:
-                for i in range(1000):
-                    thread.start_new_thread(f, ())
-            finally:
-                lock.release()
-                # wait a bit to allow most threads to finish now
-                while count[0] > 10:
-                    print count[0]     # <- releases the GIL
-                print "ok."
-        except (thread.error, MemoryError):
-            pass
-        else:
-            raise Exception("could unexpectedly start 1000 threads")
-        # safety: check that we can start a new thread here
-        thread.start_new_thread(lambda: None, ())
-
     def test_stack_size(self):
         import thread
         thread.stack_size(0)
@@ -256,3 +198,74 @@
             waiting = []
             thread.start_new_thread(f, ())
             raises(KeyboardInterrupt, busy_wait)
+
[email protected]("too slow")
+class _AppTestThread(GenericTestThread):
+    '''
+    This test is very slow, do not run it by default.
+    '''
+    def setup_class(cls):
+        GenericTestThread.setup_class.im_func(cls)
+        # if we cannot start more than, say, 1000 threads on this OS, then
+        # we can check that we get the proper error at app-level
+        space = cls.space
+        lock = thread.allocate_lock()
+        lock.acquire()
+        def f():
+            lock.acquire()
+            lock.release()
+        start = thread._count()
+        try:
+            try:
+                for i in range(1000):
+                    thread.start_new_thread(f, ())
+            finally:
+                lock.release()
+        except (thread.error, MemoryError):
+            cls.w_can_start_many_threads = space.wrap(False)
+        else:
+            cls.w_can_start_many_threads = space.wrap(True)
+        # wait a bit to allow all threads to finish now
+        remaining = thread._count()
+        retries = 0
+        while remaining > start:
+            retries += 1
+            if retries == 200:
+                raise Exception("the test's threads don't stop!")
+            time.sleep(0.2)
+            remaining = thread._count()
+
+    def test_many_threads(self):
+        import time, sys
+        if sys.version_info[0] < 3:
+            import thread as _thread
+        else:
+            import _thread
+        if self.can_start_many_threads or sys.platform == 'win32':
+            skip("this OS supports too many threads to check (> 1000)")
+        lock = _thread.allocate_lock()
+        lock.acquire()
+        count = [0]
+        def f():
+            count[0] += 1
+            lock.acquire()
+            lock.release()
+            count[0] -= 1
+        try:
+            try:
+                for i in range(1000):
+                    _thread.start_new_thread(f, ())
+            finally:
+                lock.release()
+                # wait a bit to allow most threads to finish now
+                while count[0] > 10:
+                    print(count[0])     # <- releases the GIL
+                print("ok.")
+        except (_thread.error, MemoryError):
+            pass
+        else:
+            raise Exception("could unexpectedly start 1000 threads")
+        # safety: check that we can start a new thread here
+        _thread.start_new_thread(lambda: None, ())
+
+
diff --git a/pypy/module/zlib/test/test_zlib.py 
b/pypy/module/zlib/test/test_zlib.py
--- a/pypy/module/zlib/test/test_zlib.py
+++ b/pypy/module/zlib/test/test_zlib.py
@@ -345,7 +345,7 @@
 
         assert (d1 + from_copy) == (d1 + from_compressor)
 
-    @py.test.mark.skipif(rzlib.ZLIB_VERSION == '1.2.8', reason='does not error 
check')
+    @py.test.mark.skipif(rzlib.ZLIB_VERSION in ('1.2.8', '1.2.3'), 
reason='does not error check')
     def test_cannot_copy_compressor_with_stream_in_inconsistent_state(self):
         if self.runappdirect: skip("can't run with -A")
         compressor = self.zlib.compressobj()
diff --git a/pypy/test_all.py b/pypy/test_all.py
--- a/pypy/test_all.py
+++ b/pypy/test_all.py
@@ -17,14 +17,20 @@
 For more information, use test_all.py -h.
 """
 import sys, os
+import shutil
 
 
 if __name__ == '__main__':
     if len(sys.argv) == 1 and os.path.dirname(sys.argv[0]) in '.':
         print >> sys.stderr, __doc__
         sys.exit(2)
-    #Add toplevel repository dir to sys.path
-    
sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
+    toplevel = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+    # Always remove the cached files
+    # Before translation this is done via "py.path.local(CACHE_DIR).remove()"
+    print 'removing %s/rpython/_cache' % toplevel
+    shutil.rmtree('%s/rpython/_cache' % toplevel, ignore_errors=True)
+    # Add toplevel repository dir to sys.path
+    sys.path.insert(0, toplevel)
     import pytest
     if sys.platform == 'win32':
         #Try to avoid opening a dialog box if one of the tests causes a system 
error
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -67,6 +67,8 @@
     name = options.name
     if not name:
         name = 'pypy-nightly'
+    if options.make_portable and 'portable' not in name:
+        name += '-portable'
     assert '/' not in name
     rename_pypy_c = options.pypy_c
     override_pypy_c = options.override_pypy_c
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -800,7 +800,7 @@
         DIRENT = rffi_platform.Struct('struct dirent',
             [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1)),
              ('d_ino', lltype.Signed)]
-            + [('d_type', rffi.INT)] if HAVE_D_TYPE else [])
+            + ([('d_type', rffi.INT)] if HAVE_D_TYPE else []))
         if HAVE_D_TYPE:
             DT_UNKNOWN = rffi_platform.ConstantInteger('DT_UNKNOWN')
             DT_REG     = rffi_platform.ConstantInteger('DT_REG')
@@ -1931,8 +1931,7 @@
                               rffi.INT, save_err=rffi.RFFI_FULL_ERRNO_ZERO)
     c_sched_get_priority_min = external('sched_get_priority_min', [rffi.INT],
                              rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
-    if not _WIN32:
-        c_sched_yield = external('sched_yield', [], rffi.INT)
+    c_sched_yield = external('sched_yield', [], rffi.INT)
 
     @enforceargs(int)
     def sched_get_priority_max(policy):
@@ -1945,6 +1944,36 @@
     def sched_yield():
         return handle_posix_error('sched_yield', c_sched_yield())
 
+    c_getgroupslist = external('getgrouplist', [rffi.CCHARP, GID_T,
+                            GID_GROUPS_T, rffi.INTP], rffi.INT,
+                            save_err=rffi.RFFI_SAVE_ERRNO)
+
+    def getgrouplist(user, group):
+        groups_p = lltype.malloc(GID_GROUPS_T.TO, 64, flavor='raw')
+        ngroups_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        ngroups_p[0] = rffi.cast(rffi.INT, 64)
+        try:
+            n = handle_posix_error('getgrouplist', c_getgroupslist(user, group,
+                             groups_p, ngroups_p))
+            if n == -1:
+               if widen(ngroups_p[0]) > 64:
+                    # reallocate. Should never happen
+                    lltype.free(groups_p, flavor='raw')
+                    groups_p = lltype.nullptr(GID_GROUPS_T.TO)
+                    groups_p = lltype.malloc(GID_GROUPS_T.TO, 
widen(ngroups_p[0]),
+                                             flavor='raw')
+                     
+                    n = handle_posix_error('getgrouplist', 
c_getgroupslist(user,
+                                                     group, groups_p, 
ngroups_p))
+            ngroups = widen(ngroups_p[0])
+            groups = [0] * ngroups
+            for i in range(ngroups):
+                groups[i] = groups_p[i]
+            return groups
+        finally:
+            lltype.free(ngroups_p, flavor='raw')
+            if groups_p:
+                lltype.free(groups_p, flavor='raw')
 #___________________________________________________________________
 
 c_chroot = external('chroot', [rffi.CCHARP], rffi.INT,
diff --git a/rpython/rlib/rtime.py b/rpython/rlib/rtime.py
--- a/rpython/rlib/rtime.py
+++ b/rpython/rlib/rtime.py
@@ -9,7 +9,7 @@
 from rpython.rtyper.tool import rffi_platform
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rlib.objectmodel import register_replacement_for
-from rpython.rlib.rarithmetic import intmask, UINT_MAX
+from rpython.rlib.rarithmetic import intmask, r_int64, UINT_MAX
 from rpython.rlib import rposix
 
 _WIN32 = sys.platform.startswith('win')
@@ -94,6 +94,10 @@
     return (float(rffi.getintfield(t, 'c_tv_sec')) +
             float(rffi.getintfield(t, 'c_tv_usec')) * 0.000001)
 
+def decode_timeval_ns(t):
+    return (r_int64(rffi.getintfield(t, 'c_tv_sec')) * 10**9 +
+            r_int64(rffi.getintfield(t, 'c_tv_usec')) * 10**3)
+
 
 def external(name, args, result, compilation_info=eci, **kwds):
     return rffi.llexternal(name, args, result,
diff --git a/rpython/rlib/test/test_rzlib.py b/rpython/rlib/test/test_rzlib.py
--- a/rpython/rlib/test/test_rzlib.py
+++ b/rpython/rlib/test/test_rzlib.py
@@ -274,7 +274,7 @@
     rzlib.deflateEnd(copied)
     assert bytes1 + bytes_copy == compressed
 
[email protected](rzlib.ZLIB_VERSION == '1.2.8', reason='does not error 
check')
[email protected](rzlib.ZLIB_VERSION in ('1.2.3', '1.2.8'), reason='does 
not error check')
 def test_unsuccessful_compress_copy():
     """
     Errors during unsuccesful deflateCopy operations raise RZlibErrors.
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to