Author: andrewjlawrence
Branch: winmultiprocessing
Changeset: r96596:ff7e3469b931
Date: 2019-05-11 19:14 +0100
http://bitbucket.org/pypy/pypy/changeset/ff7e3469b931/

Log:    Merged in latest changes from py3.6

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -10,10 +10,6 @@
 32f35069a16d819b58c1b6efb17c44e3e53397b2 release-2.3.1
 10f1b29a2bd21f837090286174a9ca030b8680b2 release-2.5.0
 9c4588d731b7fe0b08669bd732c2b676cb0a8233 release-2.5.1
-fcdb941565156385cbac04cfb891f8f4c7a92ef6 release-2.6.0
-fcdb941565156385cbac04cfb891f8f4c7a92ef6 release-2.6.0
-e03971291f3a0729ecd3ee7fae7ddb0bb82d476c release-2.6.0
-e03971291f3a0729ecd3ee7fae7ddb0bb82d476c release-2.6.0
 295ee98b69288471b0fcf2e0ede82ce5209eb90b release-2.6.0
 f3ad1e1e1d6215e20d34bb65ab85ff9188c9f559 release-2.6.1
 850edf14b2c75573720f59e95767335fb1affe55 release-4.0.0
@@ -24,17 +20,10 @@
 b0a649e90b6642251fb4a765fe5b27a97b1319a9 release-5.1.1
 80ef432a32d9baa4b3c5a54c215e8ebe499f6374 release-5.1.2
 40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
-40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
 c09c19272c990a0611b17569a0085ad1ab00c8ff release-pypy2.7-v5.3
 7e8df3df96417c16c2d55b41352ec82c9c69c978 release-pypy2.7-v5.3.1
-68bb3510d8212ae9efb687e12e58c09d29e74f87 release-pypy2.7-v5.4.0
-68bb3510d8212ae9efb687e12e58c09d29e74f87 release-pypy2.7-v5.4.0
 77392ad263504df011ccfcabf6a62e21d04086d0 release-pypy2.7-v5.4.0
-050d84dd78997f021acf0e133934275d63547cc0 release-pypy2.7-v5.4.1
-050d84dd78997f021acf0e133934275d63547cc0 release-pypy2.7-v5.4.1
 0e2d9a73f5a1818d0245d75daccdbe21b2d5c3ef release-pypy2.7-v5.4.1
-4909c06daf41ce88f87dc01c57959cadad4df4a8 RevDB-pypy2.7-v5.4.1
-4909c06daf41ce88f87dc01c57959cadad4df4a8 RevDB-pypy2.7-v5.4.1
 d7724c0a5700b895a47de44074cdf5fd659a988f RevDB-pypy2.7-v5.4.1
 aff251e543859ce4508159dd9f1a82a2f553de00 release-pypy2.7-v5.6.0
 e90317857d27917bf840caf675832292ee070510 RevDB-pypy2.7-v5.6.1
@@ -45,33 +34,20 @@
 2875f328eae2216a87f3d6f335092832eb031f56 release-pypy3.5-v5.7.1
 c925e73810367cd960a32592dd7f728f436c125c release-pypy2.7-v5.8.0
 a37ecfe5f142bc971a86d17305cc5d1d70abec64 release-pypy3.5-v5.8.0
-03d614975835870da65ff0481e1edad68ebbcb8d release-pypy2.7-v5.9.0
 d72f9800a42b46a8056951b1da2426d2c2d8d502 release-pypy3.5-v5.9.0
-03d614975835870da65ff0481e1edad68ebbcb8d release-pypy2.7-v5.9.0
 84a2f3e6a7f88f2fe698e473998755b3bd1a12e2 release-pypy2.7-v5.9.0
 0e7ea4fe15e82d5124e805e2e4a37cae1a402d4b release-pypy2.7-v5.10.0
-a91df6163fb76df245091f741dbf6a23ddc72374 release-pypy3.5-v5.10.0
-a91df6163fb76df245091f741dbf6a23ddc72374 release-pypy3.5-v5.10.0
-0000000000000000000000000000000000000000 release-pypy3.5-v5.10.0
-0000000000000000000000000000000000000000 release-pypy3.5-v5.10.0
 09f9160b643e3f02ccb8c843b2fbb4e5cbf54082 release-pypy3.5-v5.10.0
 3f6eaa010fce78cc7973bdc1dfdb95970f08fed2 release-pypy3.5-v5.10.1
 ab0b9caf307db6592905a80b8faffd69b39005b8 release-pypy2.7-v6.0.0
 fdd60ed87e941677e8ea11acf9f1819466521bf2 release-pypy3.5-v6.0.0
 9112c8071614108b1042bfef0713915107004d62 release-pypy2.7-v7.0.0
 1f86f25937b6ae6c8b25236c35228fac587678bf release-pypy3.5-v7.0.0
-dab365a465140aa79a5f3ba4db784c4af4d5c195 release-pypy3.6-v7.0.0
-9112c8071614108b1042bfef0713915107004d62 release-pypy2.7-v7.0.0
 c8805ee6d7846ca2722b106eeaa2f128c699aba3 release-pypy2.7-v7.0.0
-1f86f25937b6ae6c8b25236c35228fac587678bf release-pypy3.5-v7.0.0
 928a4f70d3de7d17449456946154c5da6e600162 release-pypy3.5-v7.0.0
-dab365a465140aa79a5f3ba4db784c4af4d5c195 release-pypy3.6-v7.0.0
 fb40f7a5524c77b80e6c468e087d621610137261 release-pypy3.6-v7.0.0
 990cef41fe11e5d46b019a46aa956ff46ea1a234 release-pypy2.7-v7.1.0
-bb0d05b190b9c579f0c889a368636e14f6205bab release-pypy3.6-v7.1.0
-bb0d05b190b9c579f0c889a368636e14f6205bab release-pypy3.6-v7.1.0
-6fd188f8f903b7555920adf7d5e7fe21db1bd593 release-pypy3.6-v7.1.0
-6fd188f8f903b7555920adf7d5e7fe21db1bd593 release-pypy3.6-v7.1.0
-7a2e437acfceafe2665b23b1394dc6c66add3b89 release-pypy3.6-v7.1.0
-7a2e437acfceafe2665b23b1394dc6c66add3b89 release-pypy3.6-v7.1.0
 de061d87e39c7df4e436974096d7982c676a859d release-pypy3.6-v7.1.0
+784b254d669919c872a505b807db8462b6140973 release-pypy3.6-v7.1.1
+8cdda8b8cdb8ff29d9e620cccd6c5edd2f2a23ec release-pypy2.7-v7.1.1
+
diff --git a/lib-python/3/pdb.py b/lib-python/3/pdb.py
--- a/lib-python/3/pdb.py
+++ b/lib-python/3/pdb.py
@@ -341,8 +341,14 @@
     def interaction(self, frame, traceback):
         # Restore the previous signal handler at the Pdb prompt.
         if Pdb._previous_sigint_handler:
-            signal.signal(signal.SIGINT, Pdb._previous_sigint_handler)
-            Pdb._previous_sigint_handler = None
+            try:
+                signal.signal(signal.SIGINT, Pdb._previous_sigint_handler)
+                Pdb._previous_sigint_handler = None
+            except ValueError:
+                # ValueError happens when we're in a non-main thread,
+                # if we already invoked pdb in the same program from the
+                # main thread.  (PyPy fix)
+                pass
         if self.setup(frame, traceback):
             # no interaction desired at this time (happens if .pdbrc contains
             # a command like "continue")
diff --git a/lib_pypy/_blake2/impl/blake2b.o b/lib_pypy/_blake2/impl/blake2b.o
deleted file mode 100644
index 
0957bfc2e8b188b193b9eee3808641a638e0a2f7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch

[cut]

diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -95,7 +95,9 @@
 There are a few extra implications from the difference in the GC.  Most
 notably, if an object has a ``__del__``, the ``__del__`` is never called more
 than once in PyPy; but CPython will call the same ``__del__`` several times
-if the object is resurrected and dies again.  The ``__del__`` methods are
+if the object is resurrected and dies again (at least it is reliably so in
+older CPythons; newer CPythons try to call destructors not more than once,
+but there are counter-examples).  The ``__del__`` methods are
 called in "the right" order if they are on objects pointing to each
 other, as in CPython, but unlike CPython, if there is a dead cycle of
 objects referencing each other, their ``__del__`` methods are called anyway;
diff --git a/pypy/doc/index-of-release-notes.rst 
b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
 
 .. toctree::
 
+   release-v7.1.1.rst
    release-v7.1.0.rst
    release-v7.0.0.rst
    release-v6.0.0.rst
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
 .. toctree::
 
    whatsnew-head.rst
+   whatsnew-pypy2-7.1.0.rst
    whatsnew-pypy2-7.0.0.rst
    whatsnew-pypy2-6.0.0.rst
    whatsnew-pypy2-5.10.0.rst
diff --git a/pypy/doc/release-v7.1.1.rst b/pypy/doc/release-v7.1.1.rst
--- a/pypy/doc/release-v7.1.1.rst
+++ b/pypy/doc/release-v7.1.1.rst
@@ -68,10 +68,14 @@
 Changelog
 =========
 
-Changes shared across versions
-* improve performance of ``u''.append``
+Changes shared across versions:
+
+* Improve performance of ``u''.append``
+
 * Prevent a crash in ``zlib`` when flushing a closed stream
-* Fix a few corener cases when encountering unicode values above 0x110000
+
+* Fix a few corner cases when encountering unicode values above 0x110000
+
 * Teach the JIT how to handle very large constant lists, sets, or dicts
 * Fix building on ARM32 (issue 2984_)
 * Fix a bug in register assignment in ARM32
@@ -81,9 +85,9 @@
 * Fix memoryviews of ctype structures with padding, (cpython issue 32780_)
 * CFFI updated to as-yet-unreleased 1.12.3
 
-Python 3.6 only
+Python 3.6 only:
 
-* On win32, override some ``errno.E*`` values that were added to MSVC in v2010
+* Override some ``errno.E*`` values that were added to MSVC in v2010
   so that ``errno.E* == errno.WSAE*`` as in CPython
 * Do the same optimization that CPython does for ``(1, 2, 3, *a)`` (but at the
   AST level)
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
@@ -16,3 +16,12 @@
 .. branch: datetime_api_27
 
 Add ``DateTime_FromTimestamp`` and ``Date_FromTimestamp``
+
+.. branch: issue2968
+
+Fix segfault in cpyext_tp_new_tupl
+
+.. branch: semlock-deadlock
+
+Test and reduce the probability of a deadlock when acquiring a semaphore by
+moving global state changes closer to the actual aquire.
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -180,14 +180,17 @@
         too_many_args = False
 
         # put the special w_firstarg into the scope, if it exists
+        upfront = 0
+        args_w = self.arguments_w
         if w_firstarg is not None:
-            upfront = 1
             if co_argcount > 0:
                 scope_w[0] = w_firstarg
-        else:
-            upfront = 0
+                upfront = 1
+            else:
+                # ugh, this is a call to a method 'def meth(*args)', maybe
+                # (see test_issue2996_*).  Fall-back solution...
+                args_w = [w_firstarg] + args_w
 
-        args_w = self.arguments_w
         num_args = len(args_w)
         avail = num_args + upfront
 
@@ -210,11 +213,8 @@
         # collect extra positional arguments into the *vararg
         if signature.has_vararg():
             args_left = co_argcount - upfront
-            if args_left < 0:  # check required by rpython
-                starargs_w = [w_firstarg]
-                if num_args:
-                    starargs_w = starargs_w + args_w
-            elif num_args > args_left:
+            assert args_left >= 0  # check required by rpython
+            if num_args > args_left:
                 starargs_w = args_w[args_left:]
             else:
                 starargs_w = []
diff --git a/pypy/interpreter/astcompiler/codegen.py 
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -509,8 +509,7 @@
             return
         self.update_position(asrt.lineno)
         end = self.new_block()
-        if self.compile_info.optimize != 0:
-            self.emit_jump(ops.JUMP_IF_NOT_DEBUG, end)
+        self.emit_jump(ops.JUMP_IF_NOT_DEBUG, end)
         asrt.test.accept_jump_if(self, True, end)
         self.emit_op_name(ops.LOAD_GLOBAL, self.names, "AssertionError")
         if asrt.msg:
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -58,8 +58,9 @@
     assert argcount >= 0     # annotator hint
     assert kwonlyargcount >= 0
     argnames = list(varnames[:argcount])
-    if argcount < len(varnames):
+    if kwonlyargcount > 0:
         kwonlyargs = list(varnames[argcount:argcount + kwonlyargcount])
+        argcount += kwonlyargcount
     else:
         kwonlyargs = None
     if code.co_flags & CO_VARARGS:
@@ -68,7 +69,7 @@
     else:
         varargname = None
     if code.co_flags & CO_VARKEYWORDS:
-        kwargname = code.co_varnames[argcount + kwonlyargcount]
+        kwargname = code.co_varnames[argcount]
     else:
         kwargname = None
     return Signature(argnames, varargname, kwargname, kwonlyargs)
diff --git a/pypy/interpreter/test/test_argument.py 
b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -923,3 +923,18 @@
             def test(**kwargs):
                 return kwargs
             assert test(**q) == {"foo": "bar"}
+
+    def test_issue2996_1(self): """
+        class Class:
+            def method(*args, a_parameter=None, **kwargs):
+                pass
+        Class().method(**{'a_parameter': 4})
+        """
+
+    def test_issue2996_2(self): """
+        class Foo:
+            def methhh(*args, offset=42):
+                return args, offset
+        foo = Foo()
+        assert foo.methhh(**{}) == ((foo,), 42)
+        """
diff --git a/pypy/interpreter/test/test_compiler.py 
b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -824,6 +824,13 @@
         sig = cpython_code_signature(co)
         assert sig == Signature(['a', 'b'], None, 'kwargs', ['m', 'n'])
 
+        # a variant with varargname, which was buggy before issue2996
+        snippet = 'def f(*args, offset=42): pass'
+        containing_co = self.compiler.compile(snippet, '<string>', 'single', 0)
+        co = find_func(containing_co)
+        sig = cpython_code_signature(co)
+        assert sig == Signature([], 'args', None, ['offset'])
+
 
 class AppTestCompiler(object):
 
diff --git a/pypy/interpreter/test/test_zpy.py 
b/pypy/interpreter/test/test_zpy.py
--- a/pypy/interpreter/test/test_zpy.py
+++ b/pypy/interpreter/test/test_zpy.py
@@ -84,7 +84,28 @@
     # test 3 : additionnal pypy parameters
     output = run(sys.executable, pypypath, '-S', "-O", tmpfilepath, "hello")
     assert output.splitlines()[-1] == str([tmpfilepath,'hello'])
-    
+
+def test_optimize_removes_assert():
+    tmpfilepath = str(udir.join("test_assert.py"))
+    tmpfile = file(tmpfilepath, "w")
+    tmpfile.write("""
+try:
+    assert 0
+except AssertionError:
+    print("AssertionError")
+else:
+    print("nothing")
+""")
+    tmpfile.close()
+
+    # no optimization: crashes
+    output = run(sys.executable, pypypath, '-S', tmpfilepath)
+    assert "AssertionError" in output
+
+    # optimization: just works
+    output = run(sys.executable, pypypath, '-SO', tmpfilepath)
+    assert "nothing" in output
+
 
 TB_NORMALIZATION_CHK= """
 class K(object):
diff --git a/pypy/interpreter/unicodehelper.py 
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -1400,7 +1400,7 @@
                                   s, pos, pos + 4)
             result.append(r)
             continue
-        elif ch >= 0x110000:
+        elif r_uint(ch) >= 0x110000:
             r, pos, rettype = errorhandler(errors, public_encoding_name,
                                   "codepoint not in range(0x110000)",
                                   s, pos, len(s))
diff --git a/pypy/module/_codecs/interp_codecs.py 
b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -575,14 +575,7 @@
     if encoding is None:
         encoding = space.sys.defaultencoding
     w_encoder = space.getitem(lookup_codec(space, encoding), space.newint(0))
-    w_retval =  _call_codec(space, w_encoder, w_obj, "encoding", encoding, 
errors)
-    if not space.isinstance_w(w_retval, space.w_bytes):
-        raise oefmt(space.w_TypeError,
-                    "'%s' encoder returned '%T' instead of 'bytes'; "
-                    "use codecs.encode() to encode to arbitrary types",
-                    encoding,
-                    w_retval)
-    return w_retval
+    return _call_codec(space, w_encoder, w_obj, "encoding", encoding, errors)
 
 @unwrap_spec(errors='text_or_none')
 def readbuffer_encode(space, w_data, errors='strict'):
@@ -604,14 +597,7 @@
     if encoding is None:
         encoding = space.sys.defaultencoding
     w_decoder = space.getitem(lookup_codec(space, encoding), space.newint(1))
-    w_retval = _call_codec(space, w_decoder, w_obj, "decoding", encoding, 
errors)
-    if not isinstance(w_retval, W_UnicodeObject):
-        raise oefmt(space.w_TypeError,
-                    "'%s' decoder returned '%T' instead of 'str'; "
-                    "use codecs.decode() to decode to arbitrary types",
-                    encoding,
-                    w_retval)
-    return w_retval
+    return _call_codec(space, w_decoder, w_obj, "decoding", encoding, errors)
 
 @unwrap_spec(errors='text')
 def register_error(space, errors, w_handler):
@@ -842,7 +828,7 @@
             if not 0 <= x <= 0x10FFFF:
                 raise oefmt(space.w_TypeError,
                     "character mapping must be in range(0x110000)")
-            return rutf8.unichr_as_utf8(x)
+            return rutf8.unichr_as_utf8(x, allow_surrogates=True)
         elif space.is_w(w_ch, space.w_None):
             # Charmap may return None
             return errorchar
@@ -972,9 +958,17 @@
         unicode_name_handler)
 
     if first_escape_error_char is not None:
+        # Here, 'first_escape_error_char' is a single string character.
+        # Careful, it might be >= '\x80'.  If it is, it would made an
+        # invalid utf-8 string when pasted directory in it.
+        if ' ' <= first_escape_error_char < '\x7f':
+            msg = "invalid escape sequence '\\%s'" % (first_escape_error_char,)
+        else:
+            msg = "invalid escape sequence: '\\' followed by %s" % (
+                space.text_w(space.repr(
+                    space.newbytes(first_escape_error_char))),)
         space.warn(
-            space.newtext("invalid escape sequence '\\%s'"
-                          % str(first_escape_error_char)),
+            space.newtext(msg),
             space.w_DeprecationWarning
         )
     return space.newtuple([space.newutf8(result, lgt), space.newint(u_len)])
diff --git a/pypy/module/_codecs/test/test_codecs.py 
b/pypy/module/_codecs/test/test_codecs.py
--- a/pypy/module/_codecs/test/test_codecs.py
+++ b/pypy/module/_codecs/test/test_codecs.py
@@ -125,6 +125,7 @@
         assert (charmap_decode(b"\x00\x01\x02", "strict",
                                {0: u'\U0010FFFF', 1: u'b', 2: u'c'}) ==
                 (u"\U0010FFFFbc", 3))
+        assert charmap_decode(b'\xff', "strict", {0xff: 0xd800}) == 
(u'\ud800', 1)
 
     def test_escape_decode(self):
         from _codecs import unicode_escape_decode as decode
@@ -1386,7 +1387,7 @@
                      "foo\udca5bar")
         assert ("foo\udca5bar".encode("iso-8859-3", "surrogateescape") == 
                          b"foo\xa5bar")
-    
+
     def test_warn_escape_decode(self):
         import warnings
         import codecs
@@ -1394,10 +1395,37 @@
         with warnings.catch_warnings(record=True) as l:
             warnings.simplefilter("always")
             codecs.unicode_escape_decode(b'\\A')
-            codecs.unicode_escape_decode(b"\\A")
+            codecs.unicode_escape_decode(b"\\" + b"\xff")
 
         assert len(l) == 2
         assert isinstance(l[0].message, DeprecationWarning)
+        assert isinstance(l[1].message, DeprecationWarning)
 
+    def test_invalid_type_errors(self):
+        # hex is not a text encoding. it works via the codecs functions, but
+        # not the methods
+        import codecs
+        res = codecs.decode(b"aabb", "hex")
+        assert res == b"\xaa\xbb"
+        res = codecs.decode(u"aabb", "hex")
+        assert res == b"\xaa\xbb"
+        res = codecs.encode(b"\xaa\xbb", "hex")
+        assert res == b"aabb"
 
+        raises(LookupError, u"abc".encode, "hex")
 
+    def test_non_text_codec(self):
+        import _codecs
+        def search_function(encoding):
+            def f(input, errors="strict"):
+                return 52, len(input)
+            if encoding == 'test.mynontextenc':
+                return (f, f, None, None)
+            return None
+        _codecs.register(search_function)
+        res = _codecs.encode(u"abc", "test.mynontextenc")
+        assert res == 52
+        res = _codecs.decode(b"abc", "test.mynontextenc")
+        assert res == 52
+        raises(TypeError, u"abc".encode, "test.mynontextenc")
+        raises(TypeError, b"abc".decode, "test.mynontextenc")
diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -105,16 +105,10 @@
         # desired, all in one pass.
         seennl = self.seennl
 
-        # If, up to now, newlines are consistently \n, do a quick check
-        # for the \r
-        only_lf = False
-        if seennl == SEEN_LF or seennl == 0:
-            only_lf = (output.find('\r') < 0)
-
-        if only_lf:
-            # If not already seen, quick scan for a possible "\n" character.
+        if output.find('\r') < 0:
+            # If no \r, quick scan for a possible "\n" character.
             # (there's nothing else to be done, even when in translation mode)
-            if seennl == 0 and output.find('\n') >= 0:
+            if output.find('\n') >= 0:
                 seennl |= SEEN_LF
                 # Finished: we have scanned for newlines, and none of them
                 # need translating.
diff --git a/pypy/module/_io/test/test_textio.py 
b/pypy/module/_io/test/test_textio.py
--- a/pypy/module/_io/test/test_textio.py
+++ b/pypy/module/_io/test/test_textio.py
@@ -566,3 +566,13 @@
         _check(dec)
         dec = _io.IncrementalNewlineDecoder(None, translate=True)
         _check(dec)
+
+    def test_newlines2(self):
+        import _io, codecs
+        inner_decoder = codecs.getincrementaldecoder("utf-8")()
+        decoder = _io.IncrementalNewlineDecoder(inner_decoder, translate=True)
+        msg = b"abc\r\n\n\r\r\n\n"
+        decoded = ''
+        for ch in msg:
+            decoded += decoder.decode(bytes([ch]))
+        assert set(decoder.newlines) == {"\r", "\n", "\r\n"}
diff --git a/pypy/module/_multiprocessing/interp_semaphore.py 
b/pypy/module/_multiprocessing/interp_semaphore.py
--- a/pypy/module/_multiprocessing/interp_semaphore.py
+++ b/pypy/module/_multiprocessing/interp_semaphore.py
@@ -48,7 +48,8 @@
     eci = ExternalCompilationInfo(
         includes = ['sys/time.h',
                     'limits.h',
-                    'semaphore.h'],
+                    'semaphore.h',
+                    ],
         libraries = libraries,
         )
 
@@ -269,6 +270,8 @@
         res = rwin32.WaitForSingleObject(self.handle, 0)
 
         if res != rwin32.WAIT_TIMEOUT:
+            self.last_tid = rthread.get_ident()
+            self.count += 1
             return True
 
         msecs = full_msecs
@@ -301,6 +304,8 @@
 
         # handle result
         if res != rwin32.WAIT_TIMEOUT:
+            self.last_tid = rthread.get_ident()
+            self.count += 1
             return True
         return False
 
@@ -379,8 +384,9 @@
                     elif e.errno in (errno.EAGAIN, errno.ETIMEDOUT):
                         return False
                     raise
-                _check_signals(space)
-
+                _check_signals(space)    
+                self.last_tid = rthread.get_ident()
+                self.count += 1
                 return True
         finally:
             if deadline:
@@ -449,6 +455,7 @@
         self.count = 0
         self.maxvalue = maxvalue
         self.register_finalizer(space)
+        self.last_tid = -1
         self.name = name
 
     def name_get(self, space):
@@ -495,15 +502,15 @@
         if self.kind == RECURSIVE_MUTEX and self._ismine():
             self.count += 1
             return space.w_True
-
         try:
+            # sets self.last_tid and increments self.count
+            # those steps need to be as close as possible to
+            # acquiring the semlock for self._ismine() to support
+            # multiple threads 
             got = semlock_acquire(self, space, block, w_timeout)
         except OSError as e:
             raise wrap_oserror(space, e)
-
         if got:
-            self.last_tid = rthread.get_ident()
-            self.count += 1
             return space.w_True
         else:
             return space.w_False
@@ -520,10 +527,10 @@
 
         try:
             semlock_release(self, space)
+            self.count -= 1
         except OSError as e:
             raise wrap_oserror(space, e)
 
-        self.count -= 1
 
     def after_fork(self):
         self.count = 0
diff --git a/pypy/module/_multiprocessing/test/test_semaphore.py 
b/pypy/module/_multiprocessing/test/test_semaphore.py
--- a/pypy/module/_multiprocessing/test/test_semaphore.py
+++ b/pypy/module/_multiprocessing/test/test_semaphore.py
@@ -18,6 +18,7 @@
     def setup_class(cls):
         cls.w_SEMAPHORE = cls.space.wrap(SEMAPHORE)
         cls.w_RECURSIVE = cls.space.wrap(RECURSIVE_MUTEX)
+        cls.w_runappdirect = cls.space.wrap(cls.runappdirect)
 
     @py.test.mark.skipif("sys.platform == 'win32'")
     def test_sem_unlink(self):
@@ -138,3 +139,25 @@
         from _multiprocessing import SemLock
         sem = SemLock(self.SEMAPHORE, 1, 1, '/mp-123', unlink=True)
         assert sem._count() == 0
+
+    def test_in_threads(self):
+        from _multiprocessing import SemLock
+        from threading import Thread
+        from time import sleep
+        l = SemLock(0, 1, 1, "6", unlink=True)
+        if self.runappdirect:
+            def f(id):
+                for i in range(10000):
+                    pass
+        else:
+            def f(id):
+                for i in range(1000):
+                    # reduce the probability of thread switching
+                    # at exactly the wrong time in semlock_acquire
+                    for j in range(10):
+                        pass
+        threads = [Thread(None, f, args=(i,)) for i in range(2)]
+        [t.start() for t in threads]
+        # if the RLock calls to sem_wait and sem_post do not match,
+        # one of the threads will block and the call to join will fail
+        [t.join() for t in threads]
diff --git a/pypy/module/_pypyjson/interp_decoder.py 
b/pypy/module/_pypyjson/interp_decoder.py
--- a/pypy/module/_pypyjson/interp_decoder.py
+++ b/pypy/module/_pypyjson/interp_decoder.py
@@ -366,10 +366,14 @@
         hexdigits = self.getslice(start, i)
         try:
             val = int(hexdigits, 16)
-            if sys.maxunicode > 65535 and 0xd800 <= val <= 0xdfff:
-                # surrogate pair
-                if self.ll_chars[i] == '\\' and self.ll_chars[i+1] == 'u':
-                    val = self.decode_surrogate_pair(i, val)
+            if (0xd800 <= val <= 0xdbff and
+                    self.ll_chars[i] == '\\' and self.ll_chars[i+1] == 'u'):
+                hexdigits = self.getslice(i+2, i+6)
+                lowsurr = int(hexdigits, 16)
+                if 0xdc00 <= lowsurr <= 0xdfff:
+                    # decode surrogate pair
+                    val = 0x10000 + (((val - 0xd800) << 10) |
+                                     (lowsurr - 0xdc00))
                     i += 6
         except ValueError:
             raise DecoderError("Invalid \uXXXX escape (char %d)", i-1)
@@ -380,15 +384,6 @@
         builder.append(utf8_ch)
         return i
 
-    def decode_surrogate_pair(self, i, highsurr):
-        """ uppon enter the following must hold:
-              chars[i] == "\\" and chars[i+1] == "u"
-        """
-        i += 2
-        hexdigits = self.getslice(i, i+4)
-        lowsurr = int(hexdigits, 16) # the possible ValueError is caugth by 
the caller
-        return 0x10000 + (((highsurr - 0xd800) << 10) | (lowsurr - 0xdc00))
-
     def decode_key(self, i):
         """ returns a wrapped unicode """
         from rpython.rlib.rarithmetic import intmask
diff --git a/pypy/module/_pypyjson/test/test__pypyjson.py 
b/pypy/module/_pypyjson/test/test__pypyjson.py
--- a/pypy/module/_pypyjson/test/test__pypyjson.py
+++ b/pypy/module/_pypyjson/test/test__pypyjson.py
@@ -198,6 +198,17 @@
         res = _pypyjson.loads('"z\\ud834\\udd20x"')
         assert res == expected
 
+    def test_unicode_not_a_surrogate_pair(self):
+        import _pypyjson
+        res = _pypyjson.loads('"z\\ud800\\ud800x"')
+        assert list(res) == [u'z', u'\ud800', u'\ud800', u'x']
+        res = _pypyjson.loads('"z\\udbff\\uffffx"')
+        assert list(res) == [u'z', u'\udbff', u'\uffff', u'x']
+        res = _pypyjson.loads('"z\\ud800\\ud834\\udd20x"')
+        assert res == u'z\ud800\U0001d120x'
+        res = _pypyjson.loads('"z\\udc00\\udc00x"')
+        assert list(res) == [u'z', u'\udc00', u'\udc00', u'x']
+
     def test_lone_surrogate(self):
         import _pypyjson
         json = '{"a":"\\uD83D"}'
diff --git a/pypy/module/_rawffi/interp_rawffi.py 
b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -452,8 +452,13 @@
             elif c == 'c':
                 return space.newbytes(func(add_arg, argdesc, ll_type))
             elif c == 'u':
-                return space.newutf8(rutf8.unichr_as_utf8(
-                    r_uint(ord(func(add_arg, argdesc, ll_type)))), 1)
+                code = ord(func(add_arg, argdesc, ll_type))
+                try:
+                    return space.newutf8(rutf8.unichr_as_utf8(
+                        r_uint(code), allow_surrogates=True), 1)
+                except rutf8.OutOfRange:
+                    raise oefmt(space.w_ValueError,
+                        "unicode character %d out of range", code)
             elif c == 'f' or c == 'd' or c == 'g':
                 return space.newfloat(float(func(add_arg, argdesc, ll_type)))
             else:
diff --git a/pypy/module/_rawffi/test/test__rawffi.py 
b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -348,6 +348,21 @@
         arg2.free()
         a.free()
 
+    def test_unicode_array(self):
+        import _rawffi
+        A = _rawffi.Array('u')
+        a = A(6, u'\u1234')
+        assert a[0] == u'\u1234'
+        a[0] = u'\U00012345'
+        assert a[0] == u'\U00012345'
+        a[0] = u'\ud800'
+        assert a[0] == u'\ud800'
+        B = _rawffi.Array('i')
+        b = B.fromaddress(a.itemaddress(0), 1)
+        b[0] = 0xffffffff
+        raises(ValueError, "a[0]")
+        a.free()
+
     def test_returning_unicode(self):
         import _rawffi
         A = _rawffi.Array('u')
diff --git a/pypy/module/array/interp_array.py 
b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -94,8 +94,8 @@
     lgt = min(arr1.len, arr2.len)
     for i in range(lgt):
         arr_eq_driver.jit_merge_point(comp_func=comp_op)
-        w_elem1 = arr1.w_getitem(space, i)
-        w_elem2 = arr2.w_getitem(space, i)
+        w_elem1 = arr1.w_getitem(space, i, integer_instead_of_char=True)
+        w_elem2 = arr2.w_getitem(space, i, integer_instead_of_char=True)
         if comp_op == EQ:
             res = space.eq_w(w_elem1, w_elem2)
             if not res:
@@ -1142,10 +1142,11 @@
             else:
                 self.fromsequence(w_iterable)
 
-        def w_getitem(self, space, idx):
+        def w_getitem(self, space, idx, integer_instead_of_char=False):
             item = self.get_buffer()[idx]
             keepalive_until_here(self)
-            if mytype.typecode in 'bBhHil':
+            if mytype.typecode in 'bBhHil' or (
+                    integer_instead_of_char and mytype.typecode in 'cu'):
                 item = rffi.cast(lltype.Signed, item)
                 return space.newint(item)
             if mytype.typecode in 'ILqQ':
@@ -1158,7 +1159,7 @@
             elif mytype.typecode == 'u':
                 code = r_uint(ord(item))
                 try:
-                    item = rutf8.unichr_as_utf8(code)
+                    item = rutf8.unichr_as_utf8(code, allow_surrogates=True)
                 except rutf8.OutOfRange:
                     raise oefmt(space.w_ValueError,
                         "cannot operate on this array('u') because it contains"
diff --git a/pypy/module/array/test/test_array.py 
b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -892,14 +892,21 @@
         assert repr(mya('i', [1, 2, 3])) == "array('i', [1, 2, 3])"
         assert repr(mya('i', (1, 2, 3))) == "array('i', [1, 2, 3])"
 
+    def test_array_of_chars_equality(self):
+        input_bytes = '\x01\x63a\x00!'
+        a = self.array('c', input_bytes)
+        b = self.array('c', input_bytes)
+        b.byteswap()
+        assert a == b
+
     def test_unicode_outofrange(self):
         input_unicode = u'\x01\u263a\x00\ufeff'
         a = self.array('u', input_unicode)
         b = self.array('u', input_unicode)
         b.byteswap()
         assert b[2] == u'\u0000'
-        raises(ValueError, "b[1]")        # doesn't work
-        e = raises(ValueError, "a != b")  # doesn't work
+        assert a != b
+        e = raises(ValueError, "b[0]")        # doesn't work
         assert str(e.value) == (
             "cannot operate on this array('u') because it contains"
             " character U+1000000 not in range [U+0000; U+10ffff]"
@@ -910,6 +917,10 @@
         assert a.tounicode() == input_unicode
         raises(ValueError, b.tounicode)   # doesn't work
 
+    def test_unicode_surrogate(self):
+        a = self.array('u', u'\ud800')
+        assert a[0] == u'\ud800'
+
     def test_weakref(self):
         import weakref
         a = self.array('u', 'Hi!')
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -639,16 +639,18 @@
     'PyThread_ReInitTLS', 'PyThread_init_thread',
     'PyThread_start_new_thread',
 
-    'PyStructSequence_InitType', 'PyStructSequence_New',
-    'PyStructSequence_UnnamedField',
+    'PyStructSequence_InitType', 'PyStructSequence_InitType2',
+    'PyStructSequence_New', 'PyStructSequence_UnnamedField',
 
     'PyFunction_Type', 'PyMethod_Type', 'PyRange_Type', 'PyTraceBack_Type',
 
-    'Py_DebugFlag', 'Py_VerboseFlag', 'Py_InteractiveFlag', 'Py_InspectFlag',
+    'Py_DebugFlag', 'Py_VerboseFlag', 'Py_QuietFlag',
+    'Py_InteractiveFlag', 'Py_InspectFlag',
     'Py_OptimizeFlag', 'Py_NoSiteFlag', 'Py_BytesWarningFlag', 
'Py_UseClassExceptionsFlag',
-    'Py_FrozenFlag', 'Py_TabcheckFlag', 'Py_UnicodeFlag', 
'Py_IgnoreEnvironmentFlag',
-    'Py_DivisionWarningFlag', 'Py_DontWriteBytecodeFlag', 
'Py_NoUserSiteDirectory',
-    '_Py_QnewFlag', 'Py_Py3kWarningFlag', 'Py_HashRandomizationFlag', 
'_Py_PackageContext',
+    'Py_FrozenFlag', 'Py_IgnoreEnvironmentFlag',
+    'Py_DontWriteBytecodeFlag', 'Py_NoUserSiteDirectory',
+    'Py_UnbufferedStdioFlag', 'Py_HashRandomizationFlag', 'Py_IsolatedFlag',
+    '_Py_PackageContext',
     'PyOS_InputHook',
 
     'PyMem_RawMalloc', 'PyMem_RawCalloc', 'PyMem_RawRealloc', 'PyMem_RawFree',
@@ -664,6 +666,8 @@
     'PyObject_Init', 'PyObject_InitVar',
     'PyTuple_New', '_Py_Dealloc',
 ]
+if sys.platform == "win32":
+    SYMBOLS_C.append('Py_LegacyWindowsStdioFlag')
 TYPES = {}
 FORWARD_DECLS = []
 INIT_FUNCTIONS = []
diff --git a/pypy/module/cpyext/include/pythonrun.h 
b/pypy/module/cpyext/include/pythonrun.h
--- a/pypy/module/cpyext/include/pythonrun.h
+++ b/pypy/module/cpyext/include/pythonrun.h
@@ -9,6 +9,7 @@
 PyAPI_FUNC(void) Py_FatalError(const char *msg);
 
 /* taken from Python-3.2.3/Include/pydebug.h */
+/* Note: they are always 0 for now, expect Py_DebugFlag which is always 1 */
 PyAPI_DATA(int) Py_DebugFlag;
 PyAPI_DATA(int) Py_VerboseFlag;
 PyAPI_DATA(int) Py_QuietFlag;
@@ -20,11 +21,17 @@
 PyAPI_DATA(int) Py_UseClassExceptionsFlag;
 PyAPI_DATA(int) Py_FrozenFlag;
 PyAPI_DATA(int) Py_IgnoreEnvironmentFlag;
-PyAPI_DATA(int) Py_DivisionWarningFlag;
 PyAPI_DATA(int) Py_DontWriteBytecodeFlag;
 PyAPI_DATA(int) Py_NoUserSiteDirectory;
 PyAPI_DATA(int) Py_UnbufferedStdioFlag;
 PyAPI_DATA(int) Py_HashRandomizationFlag;
+PyAPI_DATA(int) Py_IsolatedFlag;
+
+#ifdef MS_WINDOWS
+PyAPI_DATA(int) Py_LegacyWindowsStdioFlag;
+#endif
+
+#define Py_GETENV(s) (Py_IgnoreEnvironmentFlag ? NULL : getenv(s))
 
 
 typedef struct {
diff --git a/pypy/module/cpyext/include/structseq.h 
b/pypy/module/cpyext/include/structseq.h
--- a/pypy/module/cpyext/include/structseq.h
+++ b/pypy/module/cpyext/include/structseq.h
@@ -24,6 +24,9 @@
 PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type,
                                            PyStructSequence_Desc *desc);
 
+PyAPI_FUNC(int) PyStructSequence_InitType2(PyTypeObject *type,
+                                           PyStructSequence_Desc *desc);
+
 PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type);
 
 typedef struct {
diff --git a/pypy/module/cpyext/src/missing.c b/pypy/module/cpyext/src/missing.c
--- a/pypy/module/cpyext/src/missing.c
+++ b/pypy/module/cpyext/src/missing.c
@@ -10,6 +10,7 @@
 
 int Py_DebugFlag = 1;
 int Py_VerboseFlag = 0;
+int Py_QuietFlag = 0;
 int Py_InteractiveFlag = 0;
 int Py_InspectFlag = 0;
 int Py_OptimizeFlag = 0;
@@ -17,15 +18,17 @@
 int Py_BytesWarningFlag = 0;
 int Py_UseClassExceptionsFlag = 0;
 int Py_FrozenFlag = 0;
-int Py_TabcheckFlag = 0;
-int Py_UnicodeFlag = 0;
 int Py_IgnoreEnvironmentFlag = 0;
-int Py_DivisionWarningFlag = 0;
 int Py_DontWriteBytecodeFlag = 0;
 int Py_NoUserSiteDirectory = 0;
-int _Py_QnewFlag = 0;
-int Py_Py3kWarningFlag = 0;
+int Py_UnbufferedStdioFlag = 0;
 int Py_HashRandomizationFlag = 0;
+int Py_IsolatedFlag = 0;
+
+#ifdef MS_WINDOWS
+int Py_LegacyWindowsStdioFlag = 0;
+#endif
+
 
 const char *Py_FileSystemDefaultEncoding;  /* filled when cpyext is imported */
 void _Py_setfilesystemdefaultencoding(const char *enc) {
diff --git a/pypy/module/cpyext/src/structseq.c 
b/pypy/module/cpyext/src/structseq.c
--- a/pypy/module/cpyext/src/structseq.c
+++ b/pypy/module/cpyext/src/structseq.c
@@ -315,8 +315,8 @@
     structseq_new,                              /* tp_new */
 };
 
-void
-PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
+int
+PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
 {
     PyObject *dict;
     PyMemberDef* members;
@@ -342,8 +342,10 @@
     type->tp_doc = desc->doc;
 
     members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
-    if (members == NULL)
-        return;
+    if (members == NULL) {
+        PyErr_NoMemory();
+        return -1;
+    }
 
     for (i = k = 0; i < n_members; ++i) {
         if (desc->fields[i].name == PyStructSequence_UnnamedField)
@@ -361,22 +363,33 @@
     type->tp_members = members;
 
     if (PyType_Ready(type) < 0)
-        return;
+        return -1;
     Py_INCREF(type);
 
     dict = type->tp_dict;
-#define SET_DICT_FROM_INT(key, value)                           \
+#define SET_DICT_FROM_SIZE(key, value)                          \
     do {                                                        \
-        PyObject *v = PyLong_FromLong((long) value);            \
-        if (v != NULL) {                                        \
-            PyDict_SetItemString(dict, key, v);                 \
+        PyObject *v = PyLong_FromSsize_t(value);                \
+        if (v == NULL)                                          \
+            return -1;                                          \
+        if (PyDict_SetItemString(dict, key, v) < 0) {           \
             Py_DECREF(v);                                       \
+            return -1;                                          \
         }                                                       \
+        Py_DECREF(v);                                           \
     } while (0)
 
-    SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);
-    SET_DICT_FROM_INT(real_length_key, n_members);
-    SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);
+    SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence);
+    SET_DICT_FROM_SIZE(real_length_key, n_members);
+    SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members);
+
+    return 0;
+}
+
+void
+PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
+{
+    (void)PyStructSequence_InitType2(type, desc);
 }
 
 PyTypeObject*
diff --git a/pypy/module/zlib/interp_zlib.py b/pypy/module/zlib/interp_zlib.py
--- a/pypy/module/zlib/interp_zlib.py
+++ b/pypy/module/zlib/interp_zlib.py
@@ -344,8 +344,7 @@
                 raise oefmt(space.w_ValueError,
                             "length must be greater than zero")
         if not self.stream:
-            raise zlib_error(space,
-                             "compressor object already flushed")
+            return space.newbytes('')
         data = self.unconsumed_tail
         try:
             self.lock()
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
@@ -421,4 +421,5 @@
         dco = zlib.decompressobj()
         dco.decompress(x)
         dco.flush()
-        raises(self.zlib.error, dco.flush)
+        # multiple flush calls should not raise
+        dco.flush()
diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py
--- a/pypy/objspace/std/formatting.py
+++ b/pypy/objspace/std/formatting.py
@@ -326,7 +326,8 @@
             space = self.space
             if do_unicode:
                 cp = rutf8.codepoint_at_pos(self.fmt, self.fmtpos - 1)
-                w_s = space.newutf8(rutf8.unichr_as_utf8(r_uint(cp)), 1)
+                w_s = space.newutf8(rutf8.unichr_as_utf8(r_uint(cp),
+                                                  allow_surrogates=True), 1)
             else:
                 cp = ord(self.fmt[self.fmtpos - 1])
                 w_s = space.newbytes(chr(cp))
@@ -478,7 +479,8 @@
                 n = space.int_w(w_value)
                 if do_unicode:
                     try:
-                        c = rutf8.unichr_as_utf8(r_uint(n))
+                        c = rutf8.unichr_as_utf8(r_uint(n),
+                                                 allow_surrogates=True)
                     except rutf8.OutOfRange:
                         raise oefmt(space.w_OverflowError,
                                     "unicode character code out of range")
diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py
--- a/pypy/objspace/std/newformat.py
+++ b/pypy/objspace/std/newformat.py
@@ -357,9 +357,11 @@
             if recursive:
                 spec = self._build_string(spec_start, end, level)
             w_rendered = self.space.format(w_obj, self.wrap(spec))
-            unwrapper = "utf8_w" if self.is_unicode else "bytes_w"
-            to_interp = getattr(self.space, unwrapper)
-            return to_interp(w_rendered)
+            if self.is_unicode:
+                w_rendered = self.space.unicode_from_object(w_rendered)
+                return self.space.utf8_w(w_rendered)
+            else:
+                return self.space.bytes_w(w_rendered)
 
         def formatter_parser(self):
             self.parser_list_w = []
diff --git a/pypy/objspace/std/test/test_newformat.py 
b/pypy/objspace/std/test/test_newformat.py
--- a/pypy/objspace/std/test/test_newformat.py
+++ b/pypy/objspace/std/test/test_newformat.py
@@ -245,6 +245,7 @@
     def test_simple(self):
         assert format(self.i(2)) == "2"
         assert isinstance(format(self.i(2), ""), str)
+        assert isinstance(self.i(2).__format__(""), str)
 
     def test_invalid(self):
         raises(ValueError, format, self.i(8), "s")
@@ -491,3 +492,9 @@
         excinfo = raises(ValueError, "{:j}".format, x(1))
         print(excinfo.value)
         assert str(excinfo.value) == "Unknown format code j for object of type 
'x'"
+
+    def test_format_char(self):
+        import sys
+        assert '{0:c}'.format(42) == '*'
+        assert '{0:c}'.format(1234) == '\u04d2'
+        raises(OverflowError, '{0:c}'.format, -1)
diff --git a/pypy/objspace/std/test/test_stringformat.py 
b/pypy/objspace/std/test/test_stringformat.py
--- a/pypy/objspace/std/test/test_stringformat.py
+++ b/pypy/objspace/std/test/test_stringformat.py
@@ -215,6 +215,7 @@
 
     def test_format_wrong_char(self):
         raises(ValueError, 'a%Zb'.__mod__, ((23,),))
+        raises(ValueError, u'a%\ud800b'.__mod__, ((23,),))
 
     def test_incomplete_format(self):
         raises(ValueError, '%'.__mod__, ((23,),))
@@ -234,6 +235,8 @@
         raises(TypeError, '%c'.__mod__, ("",))
         raises(TypeError, '%c'.__mod__, (['c'],))
         raises(TypeError, '%c'.__mod__, b'A')
+        surrogate = 0xd800
+        assert '%c' % surrogate == '\ud800'
 
     def test___int__index__(self):
         class MyInt(object):
diff --git a/pypy/objspace/std/test/test_unicodeobject.py 
b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -728,6 +728,7 @@
 
         raises(TypeError, 'hello'.translate)
         raises(ValueError, "\xff".translate, {0xff: sys.maxunicode+1})
+        raises(TypeError, u'x'.translate, {ord('x'):0x110000})
 
     def test_maketrans(self):
         assert 'abababc' == 'abababc'.translate({'b': '<i>'})
@@ -1179,8 +1180,7 @@
     def test_format_repeat(self):
         assert format(u"abc", u"z<5") == u"abczz"
         assert format(u"abc", u"\u2007<5") == u"abc\u2007\u2007"
-        #CPython2 raises UnicodeEncodeError
-        assert format(123, u"\u2007<5") == u"123\u2007\u2007"
+        assert format(123, "\u2007<5") == "123\u2007\u2007"
 
     def test_formatting_unicode__repr__(self):
         # Printable character
diff --git a/pypy/objspace/std/unicodeobject.py 
b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -1235,7 +1235,14 @@
                     a.pos, a.pos + 1)
                 assert False, "always raises"
             return space.newbytes(utf8)
-    return encode(space, w_obj, encoding, errors)
+    w_retval = encode(space, w_obj, encoding, errors)
+    if not space.isinstance_w(w_retval, space.w_bytes):
+        raise oefmt(space.w_TypeError,
+                    "'%s' encoder returned '%T' instead of 'bytes'; "
+                    "use codecs.encode() to encode to arbitrary types",
+                    encoding,
+                    w_retval)
+    return w_retval
 
 
 def decode_object(space, w_obj, encoding, errors=None):
@@ -1250,7 +1257,14 @@
             lgt = unicodehelper.check_utf8_or_raise(space, s)
             return space.newutf8(s, lgt)
     from pypy.module._codecs.interp_codecs import decode
-    return decode(space, w_obj, encoding, errors)
+    w_retval = decode(space, w_obj, encoding, errors)
+    if not isinstance(w_retval, W_UnicodeObject):
+        raise oefmt(space.w_TypeError,
+                    "'%s' decoder returned '%T' instead of 'str'; "
+                    "use codecs.decode() to decode to arbitrary types",
+                    encoding,
+                    w_retval)
+    return w_retval
 
 def unicode_from_object(space, w_obj):
     if space.is_w(space.type(w_obj), space.w_unicode):
diff --git a/pypy/tool/build_cffi_imports.py b/pypy/tool/build_cffi_imports.py
--- a/pypy/tool/build_cffi_imports.py
+++ b/pypy/tool/build_cffi_imports.py
@@ -7,6 +7,8 @@
 
 
 cffi_build_scripts = {
+    "_blake2": "_blake2/_blake2_build.py",
+    "_ssl": "_ssl_build.py",
     "sqlite3": "_sqlite3_build.py",
     "audioop": "_audioop_build.py",
     "tk": "_tkinter/tklib_build.py",
@@ -17,8 +19,6 @@
     "resource": "_resource_build.py" if sys.platform != "win32" else None,
     "lzma": "_lzma_build.py",
     "_decimal": "_decimal_build.py",
-    "_ssl": "_ssl_build.py",
-    "_blake2": "_blake2/_blake2_build.py",
     "_sha3": "_sha3/_sha3_build.py",
     "xx": None,    # for testing: 'None' should be completely ignored
     }
@@ -154,7 +154,7 @@
         status, stdout, stderr = run_subprocess(str(pypy_c), ['-m', 
'ensurepip'])
     failures = []
 
-    for key, module in sorted(cffi_build_scripts.items()):
+    for key, module in cffi_build_scripts.items():
         if only and key not in only:
             print("* SKIPPING", key, '(not specified in --only)')
             continue
diff --git a/pypy/tool/release/force-builds.py 
b/pypy/tool/release/force-builds.py
--- a/pypy/tool/release/force-builds.py
+++ b/pypy/tool/release/force-builds.py
@@ -8,8 +8,13 @@
 
 modified by PyPy team
 """
+from __future__ import absolute_import, division, print_function
 
-import os, sys, urllib, subprocess
+import os, sys, subprocess
+try:
+    from urllib2 import quote
+except ImportError:
+    from urllib.request import quote
 
 from twisted.internet import reactor, defer
 from twisted.python import log
@@ -29,10 +34,10 @@
     'pypy-c-jit-macosx-x86-64',
     'pypy-c-jit-win-x86-32',
     'pypy-c-jit-linux-s390x',
-    'build-pypy-c-jit-linux-armhf-raspbian',
-    'build-pypy-c-jit-linux-armel',
+#    'build-pypy-c-jit-linux-armhf-raspbian',
+#    'build-pypy-c-jit-linux-armel',
     'rpython-linux-x86-32',
-    'rpython-linux-x86-64'
+    'rpython-linux-x86-64',
     'rpython-win-x86-32'
 ]
 
@@ -54,7 +59,7 @@
         log.err(err, "Build force failure")
 
     for builder in BUILDERS:
-        print 'Forcing', builder, '...'
+        print('Forcing', builder, '...')
         url = "http://"; + server + "/builders/" + builder + "/force"
         args = [
             ('username', user),
@@ -63,15 +68,15 @@
             ('submit', 'Force Build'),
             ('branch', branch),
             ('comments', "Forced by command line script")]
-        url = url + '?' + '&'.join([k + '=' + urllib.quote(v) for (k, v) in 
args])
+        url = url + '?' + '&'.join([k + '=' + quote(v) for (k, v) in args])
         requests.append(
-            lock.run(client.getPage, url, 
followRedirect=False).addErrback(ebList))
+            lock.run(client.getPage, url.encode('utf-8'), 
followRedirect=False).addErrback(ebList))
 
     d = defer.gatherResults(requests)
     d.addErrback(log.err)
     d.addCallback(lambda ign: reactor.stop())
     reactor.run()
-    print 'See http://buildbot.pypy.org/summary after a while'
+    print('See http://buildbot.pypy.org/summary after a while')
 
 if __name__ == '__main__':
     log.startLogging(sys.stdout)
@@ -86,6 +91,6 @@
     try:
         subprocess.check_call(['hg','id','-r', options.branch])
     except subprocess.CalledProcessError:
-        print 'branch',  options.branch, 'could not be found in local 
repository'
+        print('branch',  options.branch, 'could not be found in local 
repository')
         sys.exit(-1) 
     main(options.branch, options.server, user=options.user)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to