Author: Carl Friedrich Bolz-Tereick <cfb...@gmx.de>
Branch: py3.6
Changeset: r93789:9c18391110eb
Date: 2018-02-09 11:06 +0100
http://bitbucket.org/pypy/pypy/changeset/9c18391110eb/

Log:    merge py3.5

diff too long, truncating to 2000 out of 17345 lines

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -44,3 +44,10 @@
 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
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -30,7 +30,7 @@
     DEALINGS IN THE SOFTWARE.
 
 
-PyPy Copyright holders 2003-2017
+PyPy Copyright holders 2003-2018
 ----------------------------------- 
 
 Except when otherwise stated (look for LICENSE files or information at
@@ -339,8 +339,10 @@
   Stanis&#322;aw Halik
   Julien Phalip
   Roman Podoliaka
+  Steve Papanik
   Eli Stevens
   Boglarka Vezer
+  gabrielg
   PavloKapyshin
   Tomer Chachamu
   Christopher Groskopf
@@ -363,11 +365,13 @@
   Konrad Delong
   Dinu Gherman
   pizi
+  Tom&#225;&#353; Pru&#382;ina
   James Robert
   Armin Ronacher
   Diana Popa
   Mads Kiilerich
   Brett Cannon
+  Caleb Hattingh
   aliceinwire
   Zooko Wilcox-O Hearn
   James Lan
@@ -388,6 +392,7 @@
   Jason Madden
   Yaroslav Fedevych
   Even Wiik Thomassen
+  m...@funkyhat.org
   Stefan Marr
 
   Heinrich-Heine University, Germany 
diff --git a/extra_tests/requirements.txt b/extra_tests/requirements.txt
--- a/extra_tests/requirements.txt
+++ b/extra_tests/requirements.txt
@@ -1,2 +1,3 @@
 pytest
 hypothesis
+vmprof
diff --git a/extra_tests/test_import.py b/extra_tests/test_import.py
new file mode 100644
--- /dev/null
+++ b/extra_tests/test_import.py
@@ -0,0 +1,41 @@
+import pytest
+import sys
+import time
+from _thread import start_new_thread
+
+@pytest.mark.xfail('__pypy__' not in sys.builtin_module_names,
+                   reason='Fails on CPython')
+def test_multithreaded_import(tmpdir):
+    tmpfile = tmpdir.join('multithreaded_import_test.py')
+    tmpfile.write('''if 1:
+        x = 666
+        import time
+        for i in range(1000): time.sleep(0.001)
+        x = 42
+    ''')
+
+    oldpath = sys.path[:]
+    try:
+        sys.path.insert(0, str(tmpdir))
+        got = []
+
+        def check():
+            import multithreaded_import_test
+            got.append(getattr(multithreaded_import_test, 'x', '?'))
+
+        for i in range(5):
+            start_new_thread(check, ())
+
+        for n in range(100):
+            for i in range(105):
+                time.sleep(0.001)
+            if len(got) == 5:
+                break
+        else:
+            raise AssertionError("got %r so far but still waiting" %
+                                    (got,))
+
+        assert got == [42] * 5
+
+    finally:
+        sys.path[:] = oldpath
diff --git a/extra_tests/test_json.py b/extra_tests/test_json.py
new file mode 100644
--- /dev/null
+++ b/extra_tests/test_json.py
@@ -0,0 +1,29 @@
+import pytest
+import json
+from hypothesis import given, strategies
+
+def is_(x, y):
+    return type(x) is type(y) and x == y
+
+def test_no_ensure_ascii():
+    assert is_(json.dumps(u"\u1234", ensure_ascii=False), u'"\u1234"')
+    assert is_(json.dumps(u"\xc0", ensure_ascii=False), u'"\xc0"')
+    with pytest.raises(TypeError):
+        json.dumps((u"\u1234", b"x"), ensure_ascii=False)
+    with pytest.raises(TypeError):
+        json.dumps((b"x", u"\u1234"), ensure_ascii=False)
+
+def test_issue2191():
+    assert is_(json.dumps(u"xxx", ensure_ascii=False), u'"xxx"')
+
+jsondata = strategies.recursive(
+    strategies.none() |
+    strategies.booleans() |
+    strategies.floats(allow_nan=False) |
+    strategies.text(),
+    lambda children: strategies.lists(children) |
+        strategies.dictionaries(strategies.text(), children))
+
+@given(jsondata)
+def test_roundtrip(d):
+    assert json.loads(json.dumps(d)) == d
diff --git a/extra_tests/test_vmprof_greenlet.py 
b/extra_tests/test_vmprof_greenlet.py
new file mode 100644
--- /dev/null
+++ b/extra_tests/test_vmprof_greenlet.py
@@ -0,0 +1,28 @@
+import time
+import pytest
+import greenlet
+vmprof = pytest.importorskip('vmprof')
+
+def count_samples(filename):
+    stats = vmprof.read_profile(filename)
+    return len(stats.profiles)
+
+def cpuburn(duration):
+    end = time.time() + duration
+    while time.time() < end:
+        pass
+
+def test_sampling_inside_callback(tmpdir):
+    # see also test_sampling_inside_callback inside
+    # pypy/module/_continuation/test/test_stacklet.py
+    #
+    G = greenlet.greenlet(cpuburn)
+    fname = tmpdir.join('log.vmprof')
+    with fname.open('w+b') as f:
+        vmprof.enable(f.fileno(), 1/250.0)
+        G.switch(0.1)
+        vmprof.disable()
+    
+    samples = count_samples(str(fname))
+    # 0.1 seconds at 250Hz should be 25 samples
+    assert 23 < samples < 27
diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py
--- a/lib-python/2.7/subprocess.py
+++ b/lib-python/2.7/subprocess.py
@@ -1296,7 +1296,7 @@
                   'copyfile' in caller.f_globals):
         dest_dir = sys.pypy_resolvedirof(target_executable)
         src_dir = sys.pypy_resolvedirof(sys.executable)
-        for libname in ['libpypy-c.so', 'libpypy-c.dylib']:
+        for libname in ['libpypy-c.so', 'libpypy-c.dylib', 'libpypy-c.dll']:
             dest_library = os.path.join(dest_dir, libname)
             src_library = os.path.join(src_dir, libname)
             if os.path.exists(src_library):
diff --git a/lib-python/3/json/encoder.py b/lib-python/3/json/encoder.py
--- a/lib-python/3/json/encoder.py
+++ b/lib-python/3/json/encoder.py
@@ -2,18 +2,8 @@
 """
 import re
 
-try:
-    from _json import encode_basestring_ascii as c_encode_basestring_ascii
-except ImportError:
-    c_encode_basestring_ascii = None
-try:
-    from _json import encode_basestring as c_encode_basestring
-except ImportError:
-    c_encode_basestring = None
-try:
-    from _json import make_encoder as c_make_encoder
-except ImportError:
-    c_make_encoder = None
+from __pypy__.builders import StringBuilder
+
 
 ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
 ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
@@ -33,19 +23,17 @@
 
 INFINITY = float('inf')
 
-def py_encode_basestring(s):
+def raw_encode_basestring(s):
     """Return a JSON representation of a Python string
 
     """
     def replace(match):
         return ESCAPE_DCT[match.group(0)]
-    return '"' + ESCAPE.sub(replace, s) + '"'
+    return ESCAPE.sub(replace, s)
+encode_basestring = lambda s: '"' + raw_encode_basestring(s) + '"'
 
 
-encode_basestring = (c_encode_basestring or py_encode_basestring)
-
-
-def py_encode_basestring_ascii(s):
+def raw_encode_basestring_ascii(s):
     """Return an ASCII-only JSON representation of a Python string
 
     """
@@ -64,12 +52,10 @@
                 s1 = 0xd800 | ((n >> 10) & 0x3ff)
                 s2 = 0xdc00 | (n & 0x3ff)
                 return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
-    return '"' + ESCAPE_ASCII.sub(replace, s) + '"'
+    return ESCAPE_ASCII.sub(replace, s)
+encode_basestring_ascii = lambda s: '"' + raw_encode_basestring_ascii(s) + '"'
 
 
-encode_basestring_ascii = (
-    c_encode_basestring_ascii or py_encode_basestring_ascii)
-
 class JSONEncoder(object):
     """Extensible JSON <http://json.org> encoder for Python data structures.
 
@@ -146,6 +132,10 @@
 
         self.skipkeys = skipkeys
         self.ensure_ascii = ensure_ascii
+        if ensure_ascii:
+            self.__encoder = raw_encode_basestring_ascii
+        else:
+            self.__encoder = raw_encode_basestring
         self.check_circular = check_circular
         self.allow_nan = allow_nan
         self.sort_keys = sort_keys
@@ -157,6 +147,11 @@
         if default is not None:
             self.default = default
 
+        if indent is not None and not isinstance(indent, str):
+            self.indent_str = ' ' * indent
+        else:
+            self.indent_str = indent
+
     def default(self, o):
         """Implement this method in a subclass such that it returns
         a serializable object for ``o``, or calls the base implementation
@@ -187,19 +182,126 @@
         '{"foo": ["bar", "baz"]}'
 
         """
-        # This is for extremely simple cases and benchmarks.
+        if self.check_circular:
+            markers = {}
+        else:
+            markers = None
+        builder = StringBuilder()
+        self.__encode(o, markers, builder, 0)
+        return builder.build()
+
+    def __emit_indent(self, builder, _current_indent_level):
+        if self.indent is not None:
+            _current_indent_level += 1
+            newline_indent = '\n' + self.indent_str * _current_indent_level
+            separator = self.item_separator + newline_indent
+            builder.append(newline_indent)
+        else:
+            separator = self.item_separator
+        return separator, _current_indent_level
+
+    def __emit_unindent(self, builder, _current_indent_level):
+        if self.indent is not None:
+            builder.append('\n')
+            builder.append(self.indent_str * (_current_indent_level - 1))
+
+    def __encode(self, o, markers, builder, _current_indent_level):
         if isinstance(o, str):
-            if self.ensure_ascii:
-                return encode_basestring_ascii(o)
+            builder.append('"')
+            builder.append(self.__encoder(o))
+            builder.append('"')
+        elif o is None:
+            builder.append('null')
+        elif o is True:
+            builder.append('true')
+        elif o is False:
+            builder.append('false')
+        elif isinstance(o, int):
+            # Subclasses of int/float may override __str__, but we still
+            # want to encode them as integers/floats in JSON. One example
+            # within the standard library is IntEnum.
+            builder.append(int.__str__(o))
+        elif isinstance(o, float):
+            builder.append(self.__floatstr(o))
+        elif isinstance(o, (list, tuple)):
+            if not o:
+                builder.append('[]')
+                return
+            self.__encode_list(o, markers, builder, _current_indent_level)
+        elif isinstance(o, dict):
+            if not o:
+                builder.append('{}')
+                return
+            self.__encode_dict(o, markers, builder, _current_indent_level)
+        else:
+            self.__mark_markers(markers, o)
+            res = self.default(o)
+            self.__encode(res, markers, builder, _current_indent_level)
+            self.__remove_markers(markers, o)
+            return res
+
+    def __encode_list(self, l, markers, builder, _current_indent_level):
+        self.__mark_markers(markers, l)
+        builder.append('[')
+        first = True
+        separator, _current_indent_level = self.__emit_indent(builder,
+                                                      _current_indent_level)
+        for elem in l:
+            if first:
+                first = False
             else:
-                return encode_basestring(o)
-        # This doesn't pass the iterator directly to ''.join() because the
-        # exceptions aren't as detailed.  The list call should be roughly
-        # equivalent to the PySequence_Fast that ''.join() would do.
-        chunks = self.iterencode(o, _one_shot=True)
-        if not isinstance(chunks, (list, tuple)):
-            chunks = list(chunks)
-        return ''.join(chunks)
+                builder.append(separator)
+            self.__encode(elem, markers, builder, _current_indent_level)
+            del elem # XXX grumble
+        self.__emit_unindent(builder, _current_indent_level)
+        builder.append(']')
+        self.__remove_markers(markers, l)
+
+    def __encode_dict(self, d, markers, builder, _current_indent_level):
+        self.__mark_markers(markers, d)
+        first = True
+        builder.append('{')
+        separator, _current_indent_level = self.__emit_indent(builder,
+                                                         _current_indent_level)
+        if self.sort_keys:
+            items = sorted(d.items(), key=lambda kv: kv[0])
+        else:
+            items = d.items()
+
+        for key, v in items:
+            if first:
+                first = False
+            else:
+                builder.append(separator)
+            if isinstance(key, str):
+                pass
+            # JavaScript is weakly typed for these, so it makes sense to
+            # also allow them.  Many encoders seem to do something like this.
+            elif isinstance(key, float):
+                key = self.__floatstr(key)
+            elif key is True:
+                key = 'true'
+            elif key is False:
+                key = 'false'
+            elif key is None:
+                key = 'null'
+            elif isinstance(key, int):
+                # see comment for int in __encode
+                key = int.__str__(key)
+            elif self.skipkeys:
+                continue
+            else:
+                raise TypeError("key " + repr(key) + " is not a string")
+            builder.append('"')
+            builder.append(self.__encoder(key))
+            builder.append('"')
+            builder.append(self.key_separator)
+            self.__encode(v, markers, builder, _current_indent_level)
+            del key
+            del v # XXX grumble
+        self.__emit_unindent(builder, _current_indent_level)
+        builder.append('}')
+        self.__remove_markers(markers, d)
 
     def iterencode(self, o, _one_shot=False):
         """Encode the given object and yield each string
@@ -215,83 +317,53 @@
             markers = {}
         else:
             markers = None
-        if self.ensure_ascii:
-            _encoder = encode_basestring_ascii
+        return self.__iterencode(o, markers, 0)
+
+    def __floatstr(self, o):
+        # Check for specials.  Note that this type of test is processor
+        # and/or platform-specific, so do tests which don't depend on the
+        # internals.
+
+        if o != o:
+            text = 'NaN'
+        elif o == INFINITY:
+            text = 'Infinity'
+        elif o == -INFINITY:
+            text = '-Infinity'
         else:
-            _encoder = encode_basestring
+            return float.__repr__(o)
 
-        def floatstr(o, allow_nan=self.allow_nan,
-                _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY):
-            # Check for specials.  Note that this type of test is processor
-            # and/or platform-specific, so do tests which don't depend on the
-            # internals.
+        if not self.allow_nan:
+            raise ValueError(
+                "Out of range float values are not JSON compliant: " +
+                repr(o))
 
-            if o != o:
-                text = 'NaN'
-            elif o == _inf:
-                text = 'Infinity'
-            elif o == _neginf:
-                text = '-Infinity'
-            else:
-                return _repr(o)
+        return text
 
-            if not allow_nan:
-                raise ValueError(
-                    "Out of range float values are not JSON compliant: " +
-                    repr(o))
+    def __mark_markers(self, markers, o):
+        if markers is not None:
+            if id(o) in markers:
+                raise ValueError("Circular reference detected")
+            markers[id(o)] = None
 
-            return text
+    def __remove_markers(self, markers, o):
+        if markers is not None:
+            del markers[id(o)]
 
-
-        if (_one_shot and c_make_encoder is not None
-                and self.indent is None):
-            _iterencode = c_make_encoder(
-                markers, self.default, _encoder, self.indent,
-                self.key_separator, self.item_separator, self.sort_keys,
-                self.skipkeys, self.allow_nan)
-        else:
-            _iterencode = _make_iterencode(
-                markers, self.default, _encoder, self.indent, floatstr,
-                self.key_separator, self.item_separator, self.sort_keys,
-                self.skipkeys, _one_shot)
-        return _iterencode(o, 0)
-
-def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
-        _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
-        ## HACK: hand-optimized bytecode; turn globals into locals
-        ValueError=ValueError,
-        dict=dict,
-        float=float,
-        id=id,
-        int=int,
-        isinstance=isinstance,
-        list=list,
-        str=str,
-        tuple=tuple,
-        _intstr=int.__str__,
-    ):
-
-    if _indent is not None and not isinstance(_indent, str):
-        _indent = ' ' * _indent
-
-    def _iterencode_list(lst, _current_indent_level):
+    def __iterencode_list(self, lst, markers, _current_indent_level):
         if not lst:
             yield '[]'
             return
-        if markers is not None:
-            markerid = id(lst)
-            if markerid in markers:
-                raise ValueError("Circular reference detected")
-            markers[markerid] = lst
+        self.__mark_markers(markers, lst)
         buf = '['
-        if _indent is not None:
+        if self.indent is not None:
             _current_indent_level += 1
-            newline_indent = '\n' + _indent * _current_indent_level
-            separator = _item_separator + newline_indent
+            newline_indent = '\n' + self.indent_str * _current_indent_level
+            separator = self.item_separator + newline_indent
             buf += newline_indent
         else:
             newline_indent = None
-            separator = _item_separator
+            separator = self.item_separator
         first = True
         for value in lst:
             if first:
@@ -299,7 +371,7 @@
             else:
                 buf = separator
             if isinstance(value, str):
-                yield buf + _encoder(value)
+                yield buf + '"' + self.__encoder(value) + '"'
             elif value is None:
                 yield buf + 'null'
             elif value is True:
@@ -307,49 +379,44 @@
             elif value is False:
                 yield buf + 'false'
             elif isinstance(value, int):
-                # Subclasses of int/float may override __str__, but we still
-                # want to encode them as integers/floats in JSON. One example
-                # within the standard library is IntEnum.
-                yield buf + _intstr(value)
+                # see comment for int in __encode
+                yield buf + int.__str__(value)
             elif isinstance(value, float):
-                # see comment above for int
-                yield buf + _floatstr(value)
+                yield buf + self.__floatstr(value)
             else:
                 yield buf
                 if isinstance(value, (list, tuple)):
-                    chunks = _iterencode_list(value, _current_indent_level)
+                    chunks = self.__iterencode_list(value, markers,
+                                                   _current_indent_level)
                 elif isinstance(value, dict):
-                    chunks = _iterencode_dict(value, _current_indent_level)
+                    chunks = self.__iterencode_dict(value, markers,
+                                                   _current_indent_level)
                 else:
-                    chunks = _iterencode(value, _current_indent_level)
+                    chunks = self.__iterencode(value, markers,
+                                              _current_indent_level)
                 yield from chunks
         if newline_indent is not None:
             _current_indent_level -= 1
-            yield '\n' + _indent * _current_indent_level
+            yield '\n' + self.indent_str * _current_indent_level
         yield ']'
-        if markers is not None:
-            del markers[markerid]
+        self.__remove_markers(markers, lst)
 
-    def _iterencode_dict(dct, _current_indent_level):
+    def __iterencode_dict(self, dct, markers, _current_indent_level):
         if not dct:
             yield '{}'
             return
-        if markers is not None:
-            markerid = id(dct)
-            if markerid in markers:
-                raise ValueError("Circular reference detected")
-            markers[markerid] = dct
+        self.__mark_markers(markers, dct)
         yield '{'
-        if _indent is not None:
+        if self.indent is not None:
             _current_indent_level += 1
-            newline_indent = '\n' + _indent * _current_indent_level
-            item_separator = _item_separator + newline_indent
+            newline_indent = '\n' + self.indent_str * _current_indent_level
+            item_separator = self.item_separator + newline_indent
             yield newline_indent
         else:
             newline_indent = None
-            item_separator = _item_separator
+            item_separator = self.item_separator
         first = True
-        if _sort_keys:
+        if self.sort_keys:
             items = sorted(dct.items(), key=lambda kv: kv[0])
         else:
             items = dct.items()
@@ -359,8 +426,7 @@
             # JavaScript is weakly typed for these, so it makes sense to
             # also allow them.  Many encoders seem to do something like this.
             elif isinstance(key, float):
-                # see comment for int/float in _make_iterencode
-                key = _floatstr(key)
+                key = self.__floatstr(key)
             elif key is True:
                 key = 'true'
             elif key is False:
@@ -368,9 +434,9 @@
             elif key is None:
                 key = 'null'
             elif isinstance(key, int):
-                # see comment for int/float in _make_iterencode
-                key = _intstr(key)
-            elif _skipkeys:
+                # see comment for int in __encode
+                key = int.__str__(key)
+            elif self.skipkeys:
                 continue
             else:
                 raise TypeError("key " + repr(key) + " is not a string")
@@ -378,10 +444,10 @@
                 first = False
             else:
                 yield item_separator
-            yield _encoder(key)
-            yield _key_separator
+            yield '"' + self.__encoder(key) + '"'
+            yield self.key_separator
             if isinstance(value, str):
-                yield _encoder(value)
+                yield '"' + self.__encoder(value) + '"'
             elif value is None:
                 yield 'null'
             elif value is True:
@@ -389,29 +455,29 @@
             elif value is False:
                 yield 'false'
             elif isinstance(value, int):
-                # see comment for int/float in _make_iterencode
-                yield _intstr(value)
+                yield int.__str__(value)
             elif isinstance(value, float):
-                # see comment for int/float in _make_iterencode
-                yield _floatstr(value)
+                yield self.__floatstr(value)
             else:
                 if isinstance(value, (list, tuple)):
-                    chunks = _iterencode_list(value, _current_indent_level)
+                    chunks = self.__iterencode_list(value, markers,
+                                                   _current_indent_level)
                 elif isinstance(value, dict):
-                    chunks = _iterencode_dict(value, _current_indent_level)
+                    chunks = self.__iterencode_dict(value, markers,
+                                                   _current_indent_level)
                 else:
-                    chunks = _iterencode(value, _current_indent_level)
+                    chunks = self.__iterencode(value, markers,
+                                              _current_indent_level)
                 yield from chunks
         if newline_indent is not None:
             _current_indent_level -= 1
-            yield '\n' + _indent * _current_indent_level
+            yield '\n' + self.indent_str * _current_indent_level
         yield '}'
-        if markers is not None:
-            del markers[markerid]
+        self.__remove_markers(markers, dct)
 
-    def _iterencode(o, _current_indent_level):
+    def __iterencode(self, o, markers, _current_indent_level):
         if isinstance(o, str):
-            yield _encoder(o)
+            yield '"' + self.__encoder(o) + '"'
         elif o is None:
             yield 'null'
         elif o is True:
@@ -419,23 +485,22 @@
         elif o is False:
             yield 'false'
         elif isinstance(o, int):
-            # see comment for int/float in _make_iterencode
-            yield _intstr(o)
+            yield int.__str__(o)
         elif isinstance(o, float):
-            # see comment for int/float in _make_iterencode
-            yield _floatstr(o)
+            yield self.__floatstr(o)
         elif isinstance(o, (list, tuple)):
-            yield from _iterencode_list(o, _current_indent_level)
+            yield from self.__iterencode_list(o, markers, 
_current_indent_level)
         elif isinstance(o, dict):
-            yield from _iterencode_dict(o, _current_indent_level)
+            yield from self.__iterencode_dict(o, markers, 
_current_indent_level)
         else:
-            if markers is not None:
-                markerid = id(o)
-                if markerid in markers:
-                    raise ValueError("Circular reference detected")
-                markers[markerid] = o
-            o = _default(o)
-            yield from _iterencode(o, _current_indent_level)
-            if markers is not None:
-                del markers[markerid]
-    return _iterencode
+            self.__mark_markers(markers, o)
+            obj = self.default(o)
+            yield from self.__iterencode(obj, markers, _current_indent_level)
+            self.__remove_markers(markers, o)
+
+
+# overwrite some helpers here with more efficient versions
+try:
+    from _pypyjson import raw_encode_basestring_ascii
+except ImportError:
+    pass
diff --git a/lib-python/3/subprocess.py b/lib-python/3/subprocess.py
--- a/lib-python/3/subprocess.py
+++ b/lib-python/3/subprocess.py
@@ -1614,7 +1614,7 @@
                   'copyfile' in caller.f_globals):
         dest_dir = sys.pypy_resolvedirof(target_executable)
         src_dir = sys.pypy_resolvedirof(sys.executable)
-        for libname in ['libpypy3-c.so', 'libpypy3-c.dylib']:
+        for libname in ['libpypy3-c.so', 'libpypy3-c.dylib', 'libpypy3-c.dll']:
             dest_library = os.path.join(dest_dir, libname)
             src_library = os.path.join(src_dir, libname)
             if os.path.exists(src_library):
diff --git a/lib-python/3/test/test_compile.py 
b/lib-python/3/test/test_compile.py
--- a/lib-python/3/test/test_compile.py
+++ b/lib-python/3/test/test_compile.py
@@ -527,7 +527,8 @@
             with open(fn, "wb") as fp:
                 fp.write(src)
             res = script_helper.run_python_until_end(fn)[0]
-        self.assertIn(b"Non-UTF-8", res.err)
+        # PyPy change: we have a different error here
+        self.assertIn(b"SyntaxError", res.err)
 
     def test_yet_more_evil_still_undecodable(self):
         # Issue #25388
diff --git a/lib-python/3/test/test_venv.py b/lib-python/3/test/test_venv.py
--- a/lib-python/3/test/test_venv.py
+++ b/lib-python/3/test/test_venv.py
@@ -45,6 +45,8 @@
                                       os.readlink(executable))
     except OSError:
         pass
+    except AttributeError:
+        pass
     return executable
 
 
diff --git a/lib-python/3/venv/__init__.py b/lib-python/3/venv/__init__.py
--- a/lib-python/3/venv/__init__.py
+++ b/lib-python/3/venv/__init__.py
@@ -111,13 +111,17 @@
             executable = sys.executable
         #
         # PyPy extension: resolve 'executable' if it is a symlink
-        try:
-            for i in range(10):
-                executable = os.path.abspath(executable)
-                executable = os.path.join(os.path.dirname(executable),
-                                          os.readlink(executable))
-        except OSError:
-            pass
+        # XXX as of PyPy 5.10, win32 does not have readlink
+        #     note it is highly unlikely that symlinks were used on win32
+        #     since it requires admin priveleges
+        if hasattr(os, 'readlink'):
+            try:
+                for i in range(10):
+                    executable = os.path.abspath(executable)
+                    executable = os.path.join(os.path.dirname(executable),
+                                              os.readlink(executable))
+            except OSError:
+                pass
         #
         dirname, exename = os.path.split(os.path.abspath(executable))
         context.executable = executable
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -62,7 +62,7 @@
         self.basename = basename
         self._usemodules = usemodules.split() + [
             '_socket', 'binascii', 'time',
-            'select', 'signal', 'faulthandler']
+            'select', 'signal', ]
         if not sys.platform == 'win32':
             self._usemodules.extend(['_posixsubprocess', 'fcntl'])
         self._compiler = compiler
diff --git a/lib_pypy/_cffi_ssl/_stdssl/__init__.py 
b/lib_pypy/_cffi_ssl/_stdssl/__init__.py
--- a/lib_pypy/_cffi_ssl/_stdssl/__init__.py
+++ b/lib_pypy/_cffi_ssl/_stdssl/__init__.py
@@ -20,9 +20,15 @@
         SSL_ERROR_EOF, SSL_ERROR_NO_SOCKET, SSL_ERROR_INVALID_ERROR_CODE,
         pyerr_write_unraisable)
 from _cffi_ssl._stdssl import error
-from select import poll, POLLIN, POLLOUT, select
+from select import select
 from enum import IntEnum as _IntEnum
 
+if sys.platform == 'win32':
+    HAVE_POLL = False
+else:
+    from select import poll, POLLIN, POLLOUT
+    HAVE_POLL = True
+
 OPENSSL_VERSION = ffi.string(lib.OPENSSL_VERSION_TEXT).decode('utf-8')
 OPENSSL_VERSION_NUMBER = lib.OPENSSL_VERSION_NUMBER
 ver = OPENSSL_VERSION_NUMBER
@@ -158,8 +164,6 @@
     def _monotonic_clock():
         return time.clock_gettime(time.CLOCK_MONOTONIC)
 
-HAVE_POLL = True
-
 def _ssl_select(sock, writing, timeout):
     if HAVE_POLL:
         p = poll()
diff --git a/lib_pypy/_ssl/__init__.py b/lib_pypy/_ssl/__init__.py
--- a/lib_pypy/_ssl/__init__.py
+++ b/lib_pypy/_ssl/__init__.py
@@ -14,3 +14,14 @@
 # RAND_egd is optional and might not be available on e.g. libressl
 if hasattr(_stdssl, 'RAND_egd'):
     RAND_egd          = builtinify(RAND_egd)
+
+import sys
+if sys.platform == "win32" and 'enum_certificates' not in globals():
+    def enum_certificates(*args, **kwds):
+        import warnings
+        warnings.warn("ssl.enum_certificates() is not implemented")
+        return []
+    def enum_crls(*args, **kwds):
+        import warnings
+        warnings.warn("ssl.enum_crls() is not implemented")
+        return []
diff --git a/lib_pypy/_winapi.py b/lib_pypy/_winapi.py
--- a/lib_pypy/_winapi.py
+++ b/lib_pypy/_winapi.py
@@ -164,6 +164,7 @@
 SW_HIDE = 0
 INFINITE = 0xffffffff
 WAIT_OBJECT_0 = 0
+WAIT_ABANDONED_0 = 0x80
 WAIT_TIMEOUT = 0x102
 CREATE_NEW_CONSOLE = 0x010
 CREATE_NEW_PROCESS_GROUP = 0x200
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.11.2
+Version: 1.11.3
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI
 from .error import CDefError, FFIError, VerificationError, VerificationMissing
 
-__version__ = "1.11.2"
-__version_info__ = (1, 11, 2)
+__version__ = "1.11.3"
+__version_info__ = (1, 11, 3)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -7,11 +7,38 @@
    we can learn about Py_DEBUG from pyconfig.h, but it is unclear if
    the same works for the other two macros.  Py_DEBUG implies them,
    but not the other way around.
+
+   Issue #350: more mess: on Windows, with _MSC_VER, we have to define
+   Py_LIMITED_API even before including pyconfig.h.  In that case, we
+   guess what pyconfig.h will do to the macros above, and check our
+   guess after the #include.
 */
 #if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API)
-#  include <pyconfig.h>
-#  if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
-#    define Py_LIMITED_API
+#  ifdef _MSC_VER
+#    if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && 
!defined(Py_REF_DEBUG)
+#      define Py_LIMITED_API
+#    endif
+#    include <pyconfig.h>
+     /* sanity-check: Py_LIMITED_API will cause crashes if any of these
+        are also defined.  Normally, the Python file PC/pyconfig.h does not
+        cause any of these to be defined, with the exception that _DEBUG
+        causes Py_DEBUG.  Double-check that. */
+#    ifdef Py_LIMITED_API
+#      if defined(Py_DEBUG)
+#        error "pyconfig.h unexpectedly defines Py_DEBUG but _DEBUG is not set"
+#      endif
+#      if defined(Py_TRACE_REFS)
+#        error "pyconfig.h unexpectedly defines Py_TRACE_REFS"
+#      endif
+#      if defined(Py_REF_DEBUG)
+#        error "pyconfig.h unexpectedly defines Py_REF_DEBUG"
+#      endif
+#    endif
+#  else
+#    include <pyconfig.h>
+#    if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
+#      define Py_LIMITED_API
+#    endif
 #  endif
 #endif
 
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -247,7 +247,7 @@
 
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.11.2"
+                               "\ncompiled with cffi version: 1.11.3"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -295,8 +295,9 @@
         base_module_name = self.module_name.split('.')[-1]
         if self.ffi._embedding is not None:
             prnt('#define _CFFI_MODULE_NAME  "%s"' % (self.module_name,))
-            prnt('#define _CFFI_PYTHON_STARTUP_CODE  %s' %
-                 (self._string_literal(self.ffi._embedding),))
+            prnt('static const char _CFFI_PYTHON_STARTUP_CODE[] = {')
+            self._print_string_literal_in_array(self.ffi._embedding)
+            prnt('0 };')
             prnt('#ifdef PYPY_VERSION')
             prnt('# define _CFFI_PYTHON_STARTUP_FUNC  _cffi_pypyinit_%s' % (
                 base_module_name,))
@@ -1271,17 +1272,18 @@
       _generate_cpy_extern_python_plus_c_ctx = \
       _generate_cpy_extern_python_ctx
 
-    def _string_literal(self, s):
-        def _char_repr(c):
-            # escape with a '\' the characters '\', '"' or (for trigraphs) '?'
-            if c in '\\"?': return '\\' + c
-            if ' ' <= c < '\x7F': return c
-            if c == '\n': return '\\n'
-            return '\\%03o' % ord(c)
-        lines = []
-        for line in s.splitlines(True) or ['']:
-            lines.append('"%s"' % ''.join([_char_repr(c) for c in line]))
-        return ' \\\n'.join(lines)
+    def _print_string_literal_in_array(self, s):
+        prnt = self._prnt
+        prnt('// # NB. this is not a string because of a size limit in MSVC')
+        for line in s.splitlines(True):
+            prnt(('// ' + line).rstrip())
+            printed_line = ''
+            for c in line:
+                if len(printed_line) >= 76:
+                    prnt(printed_line)
+                    printed_line = ''
+                printed_line += '%d,' % (ord(c),)
+            prnt(printed_line)
 
     # ----------
     # emitting the opcodes for individual types
diff --git a/lib_pypy/cffi/verifier.py b/lib_pypy/cffi/verifier.py
--- a/lib_pypy/cffi/verifier.py
+++ b/lib_pypy/cffi/verifier.py
@@ -301,7 +301,6 @@
     return suffixes
 
 def _ensure_dir(filename):
-    try:
-        os.makedirs(os.path.dirname(filename))
-    except OSError:
-        pass
+    dirname = os.path.dirname(filename)
+    if dirname and not os.path.isdir(dirname):
+        os.makedirs(dirname)
diff --git a/lib_pypy/faulthandler.py b/lib_pypy/faulthandler.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/faulthandler.py
@@ -0,0 +1,9 @@
+# This is only imported for platforms where the built-in faulthandler module 
is not 
+# available.  It provides no function at all so far, but it is enough to start 
the
+# CPython test suite.
+
+def enable(*args, **kwargs):
+    pass
+
+def register(*args, **kwargs):
+    pass
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -127,7 +127,7 @@
             return None
         if self.__main:
             self = getcurrent()
-        f = _continulet.__reduce__(self)[2][0]
+        f = self._get_frame()
         if not f:
             return None
         return f.f_back.f_back.f_back   # go past start(), __switch(), switch()
diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
--- a/lib_pypy/pyrepl/reader.py
+++ b/lib_pypy/pyrepl/reader.py
@@ -50,11 +50,12 @@
 
 
 def _my_unctrl(c, u=_make_unctrl_map()):
+    # takes an integer, returns a unicode
     if c in u:
         return u[c]
     else:
         if unicodedata.category(c).startswith('C'):
-            return br'\u%04x' % ord(c)
+            return r'\u%04x' % ord(c)
         else:
             return c
 
diff --git a/lib_pypy/pyrepl/unix_console.py b/lib_pypy/pyrepl/unix_console.py
--- a/lib_pypy/pyrepl/unix_console.py
+++ b/lib_pypy/pyrepl/unix_console.py
@@ -500,7 +500,7 @@
             os.write(self.output_fd, fmt[:x])
             fmt = fmt[y:]
             delay = int(m.group(1))
-            if '*' in m.group(2):
+            if b'*' in m.group(2):
                 delay *= self.height
             if self._pad:
                 nchars = (bps*delay)/1000
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -149,7 +149,7 @@
     xz-devel # For lzma on PyPy3.
     (XXX plus the SLES11 version of libgdbm-dev and tk-dev)
 
-On Mac OS X::
+On Mac OS X:
 
 Most of these build-time dependencies are installed alongside
 the Developer Tools. However, note that in order for the installation to
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -59,7 +59,7 @@
 
 # General information about the project.
 project = u'PyPy'
-copyright = u'2017, The PyPy Project'
+copyright = u'2018, The PyPy Project'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -217,6 +217,7 @@
   Alejandro J. Cura
   Vladimir Kryachko
   Gabriel
+  Thomas Hisch
   Mark Williams
   Kunal Grover
   Nathan Taylor
@@ -306,8 +307,10 @@
   Stanis&#322;aw Halik
   Julien Phalip
   Roman Podoliaka
+  Steve Papanik
   Eli Stevens
   Boglarka Vezer
+  gabrielg
   PavloKapyshin
   Tomer Chachamu
   Christopher Groskopf
@@ -330,11 +333,13 @@
   Konrad Delong
   Dinu Gherman
   pizi
+  Tom&#225;&#353; Pru&#382;ina
   James Robert
   Armin Ronacher
   Diana Popa
   Mads Kiilerich
   Brett Cannon
+  Caleb Hattingh
   aliceinwire
   Zooko Wilcox-O Hearn
   James Lan
@@ -355,4 +360,5 @@
   Jason Madden
   Yaroslav Fedevych
   Even Wiik Thomassen
+  m...@funkyhat.org
   Stefan Marr
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
@@ -362,7 +362,11 @@
 containers (as list items or in sets for example), the exact rule of
 equality used is "``if x is y or x == y``" (on both CPython and PyPy);
 as a consequence, because all ``nans`` are identical in PyPy, you
-cannot have several of them in a set, unlike in CPython.  (Issue `#1974`__)
+cannot have several of them in a set, unlike in CPython.  (Issue `#1974`__).
+Another consequence is that ``cmp(float('nan'), float('nan')) == 0``, because
+``cmp`` checks with ``is`` first whether the arguments are identical (there is
+no good value to return from this call to ``cmp``, because ``cmp`` pretends
+that there is a total order on floats, but that is wrong for NaNs).
 
 .. __: 
https://bitbucket.org/pypy/pypy/issue/1974/different-behaviour-for-collections-of
 
@@ -554,6 +558,15 @@
   ``del foo.bar`` where ``foo`` is a module (or class) that contains the
   function ``bar``, is significantly slower than CPython.
 
+* Various built-in functions in CPython accept only positional arguments
+  and not keyword arguments.  That can be considered a long-running
+  historical detail: newer functions tend to accept keyword arguments
+  and older function are occasionally fixed to do so as well.  In PyPy,
+  most built-in functions accept keyword arguments (``help()`` shows the
+  argument names).  But don't rely on it too much because future
+  versions of PyPy may have to rename the arguments if CPython starts
+  accepting them too.
+
 .. _`is ignored in PyPy`: http://bugs.python.org/issue14621
 .. _`little point`: 
http://events.ccc.de/congress/2012/Fahrplan/events/5152.en.html
 .. _`#2072`: https://bitbucket.org/pypy/pypy/issue/2072/
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -62,7 +62,7 @@
   * go to pypy/tool/release and run
     ``force-builds.py <release branch>``
     The following JIT binaries should be built, however, we need more buildbots
-    windows, linux-32, linux-64, osx64, armhf-raring, armhf-raspberrian, armel,
+    windows, linux-32, linux-64, osx64, armhf-raspberrian, armel,
     freebsd64 
 
   * wait for builds to complete, make sure there are no failures
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,8 @@
 
 .. toctree::
 
+   release-v5.10.1.rst
+   release-v5.10.0.rst
    release-v5.9.0.rst
    release-v5.8.0.rst
    release-v5.7.1.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-5.10.0.rst
    whatsnew-pypy2-5.9.0.rst
    whatsnew-pypy2-5.8.0.rst
    whatsnew-pypy2-5.7.0.rst
diff --git a/pypy/doc/release-v5.10.0.rst b/pypy/doc/release-v5.10.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-v5.10.0.rst
@@ -0,0 +1,100 @@
+======================================
+PyPy2.7 and PyPy3.5 v5.10 dual release
+======================================
+
+The PyPy team is proud to release both PyPy2.7 v5.10 (an interpreter supporting
+Python 2.7 syntax), and a final PyPy3.5 v5.10 (an interpreter for Python
+3.5 syntax). The two releases are both based on much the same codebase, thus
+the dual release.
+
+This release is an incremental release with very few new features, the main
+feature being the final PyPy3.5 release that works on linux and OS X with beta
+windows support. It also includes fixes for `vmprof`_ cooperation with 
greenlets.
+
+Compared to 5.9, the 5.10 release contains mostly bugfixes and small 
improvements.
+We have in the pipeline big new features coming for PyPy 6.0 that did not make
+the release cut and should be available within the next couple months.
+
+As always, this release is 100% compatible with the previous one and fixed
+several issues and bugs raised by the growing community of PyPy users.
+As always, we strongly recommend updating.
+
+There are quite a few important changes that are in the pipeline that did not
+make it into the 5.10 release. Most important are speed improvements to cpyext
+(which will make numpy and pandas a bit faster) and utf8 branch that changes
+internal representation of unicode to utf8, which should help especially the
+Python 3.5 version of PyPy.
+
+This release concludes the Mozilla Open Source `grant`_ for having a compatible
+PyPy 3.5 release and we're very grateful for that.  Of course, we will continue
+to improve PyPy 3.5 and probably move to 3.6 during the course of 2018.
+
+You can download the v5.10 releases here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project.
+
+We would also like to thank our contributors and
+encourage new people to join the project. PyPy has many
+layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
+improvements, tweaking popular `modules`_ to run on pypy, or general `help`_
+with making RPython's JIT even better.
+
+.. _vmprof: http://vmprof.readthedocs.io
+.. _grant: 
https://morepypy.blogspot.com/2016/08/pypy-gets-funding-from-mozilla-for.html
+.. _`PyPy`: index.html
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`modules`: project-ideas.html#make-more-python-modules-pypy-friendly
+.. _`help`: project-ideas.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7 and CPython 3.5. It's fast (`PyPy and CPython 2.7.x`_ performance 
comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+The PyPy release supports: 
+
+  * **x86** machines on most common operating systems
+    (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
+  
+  * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+  
+  * big- and little-endian variants of **PPC64** running Linux,
+
+  * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html
+
+Changelog
+=========
+
+* improve ssl handling on windows for pypy3 (makes pip work)
+* improve unicode handling in various error reporters
+* fix vmprof cooperation with greenlets
+* fix some things in cpyext
+* test and document the cmp(nan, nan) == 0 behaviour
+* don't crash when calling sleep with inf or nan
+* fix bugs in _io module
+* inspect.isbuiltin() now returns True for functions implemented in C
+* allow the sequences future-import, docstring, future-import for CPython bug 
compatibility
+* Issue #2699: non-ascii messages in warnings
+* posix.lockf
+* fixes for FreeBSD platform
+* add .debug files, so builds contain debugging info, instead of being stripped
+* improvements to cppyy
+* issue #2677 copy pure c PyBuffer_{From,To}Contiguous from cpython
+* issue #2682, split firstword on any whitespace in sqlite3
+* ctypes: allow ptr[0] = foo when ptr is a pointer to struct
+* matplotlib will work with tkagg backend once `matplotlib pr #9356`_ is merged
+* improvements to utf32 surrogate handling
+* cffi version bump to 1.11.2
+
+.. _`matplotlib pr #9356`: https://github.com/matplotlib/matplotlib/pull/9356
diff --git a/pypy/doc/release-v5.10.1.rst b/pypy/doc/release-v5.10.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-v5.10.1.rst
@@ -0,0 +1,63 @@
+===========
+PyPy 5.10.1
+===========
+
+We have released a bugfix PyPy3.5-v5.10.1
+due to the following issues:
+
+  * Fix ``time.sleep(float('nan')`` which would hang on windows
+
+  * Fix missing ``errno`` constants on windows
+
+  * Fix issue 2718_ for the REPL on linux
+
+  * Fix an overflow in converting 3 secs to nanosecs (issue 2717_ )
+
+  * Flag kwarg to ``os.setxattr`` had no effect
+
+  * Fix the winreg module for unicode entries in the registry on windows
+
+Note that many of these fixes are for our new beta verison of PyPy3.5 on
+windows. There may be more unicode problems in the windows beta version
+especially around the subject of directory- and file-names with non-ascii
+characters.
+
+Our downloads are available now. On macos, we recommend you wait for the
+Homebrew_ package.
+
+Thanks to those who reported the issues.
+
+.. _2718: https://bitbucket.org/pypy/pypy/issues/2718
+.. _2717: https://bitbucket.org/pypy/pypy/issues/2717
+.. _Homebrew: http://brewformulas.org/Pypy
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7 and CPython 3.5. It's fast (`PyPy and CPython 2.7.x`_ performance 
comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+This PyPy 3.5 release supports: 
+
+  * **x86** machines on most common operating systems
+    (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
+  
+  * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+  
+  * big- and little-endian variants of **PPC64** running Linux,
+
+  * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
+
+The PyPy Team
+
diff --git a/pypy/doc/tool/makecontributor.py b/pypy/doc/tool/makecontributor.py
--- a/pypy/doc/tool/makecontributor.py
+++ b/pypy/doc/tool/makecontributor.py
@@ -81,6 +81,7 @@
     'Yasir Suhail':['yasirs'],
     'Squeaky': ['squeaky'],
     "Amaury Forgeot d'Arc": ['amaur...@gmail.com'],
+    "Dodan Mihai": ['mihai.do...@gmail.com'],
     }
 
 alias_map = {}
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
@@ -1,31 +1,16 @@
-===========================
-What's new in PyPy2.7 5.10+
-===========================
-
-.. this is a revision shortly after release-pypy2.7-v5.9.0
-.. startrev:d56dadcef996
-
-.. branch: cppyy-packaging
-Cleanup and improve cppyy packaging
-
-.. branch: docs-osx-brew-openssl
-
-.. branch: keep-debug-symbols
-Add a smartstrip tool, which can optionally keep the debug symbols in a
-separate file, instead of just stripping them away. Use it in packaging
-
-.. branch: bsd-patches
-Fix failures on FreeBSD, contributed by David Naylor as patches on the issue
-tracker (issues 2694, 2695, 2696, 2697)
-
-.. branch: run-extra-tests
-Run extra_tests/ in buildbot
-
-.. branch: vmprof-0.4.10
-Upgrade the _vmprof backend to vmprof 0.4.10
-
-.. branch: fix-vmprof-stacklet-switch
-Fix a vmprof+continulets (i.e. greenelts, eventlet, gevent, ...)
-
-.. branch: win32-vcvars
-
+===========================
+What's new in PyPy2.7 5.10+
+===========================
+
+.. this is a revision shortly after release-pypy2.7-v5.10.0
+.. startrev: 6b024edd9d12
+
+.. branch: cpyext-avoid-roundtrip
+
+Big refactoring of some cpyext code, which avoids a lot of nonsense when
+calling C from Python and vice-versa: the result is a big speedup in
+function/method calls, up to 6 times faster.
+
+.. branch: cpyext-datetime2
+
+Support ``tzinfo`` field on C-API datetime objects, fixes latest pandas HEAD
diff --git a/pypy/doc/whatsnew-pypy2-5.10.0.rst 
b/pypy/doc/whatsnew-pypy2-5.10.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy2-5.10.0.rst
@@ -0,0 +1,42 @@
+==========================
+What's new in PyPy2.7 5.10
+==========================
+
+.. this is a revision shortly after release-pypy2.7-v5.9.0
+.. startrev:d56dadcef996
+
+
+.. branch: cppyy-packaging
+
+Cleanup and improve cppyy packaging
+
+.. branch: docs-osx-brew-openssl
+
+.. branch: keep-debug-symbols
+
+Add a smartstrip tool, which can optionally keep the debug symbols in a
+separate file, instead of just stripping them away. Use it in packaging
+
+.. branch: bsd-patches
+
+Fix failures on FreeBSD, contributed by David Naylor as patches on the issue
+tracker (issues 2694, 2695, 2696, 2697)
+
+.. branch: run-extra-tests
+
+Run extra_tests/ in buildbot
+
+.. branch: vmprof-0.4.10
+
+Upgrade the _vmprof backend to vmprof 0.4.10
+
+.. branch: fix-vmprof-stacklet-switch
+.. branch: fix-vmprof-stacklet-switch-2
+Fix a vmprof+continulets (i.e. greenelts, eventlet, gevent, ...)
+
+.. branch: win32-vcvars
+
+.. branch: rdict-fast-hash
+
+Make it possible to declare that the hash function of an r_dict is fast in 
RPython.
+
diff --git a/pypy/doc/whatsnew-pypy2-5.6.0.rst 
b/pypy/doc/whatsnew-pypy2-5.6.0.rst
--- a/pypy/doc/whatsnew-pypy2-5.6.0.rst
+++ b/pypy/doc/whatsnew-pypy2-5.6.0.rst
@@ -107,7 +107,7 @@
 
 .. branch: newinitwarn
 
-Match CPython's stricter handling of __new/init__ arguments
+Match CPython's stricter handling of ``__new__``/``__init__`` arguments
 
 .. branch: openssl-1.1
 
diff --git a/pypy/doc/whatsnew-pypy3-5.10.0.rst 
b/pypy/doc/whatsnew-pypy3-5.10.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy3-5.10.0.rst
@@ -0,0 +1,21 @@
+=========================
+What's new in PyPy3 5.9+
+=========================
+
+.. this is the revision after release-pypy3.5-5.9
+.. startrev: be41e3ac0a29
+
+.. branch: sched_yield
+Add sched_yield posix attribute
+
+.. branch: py3.5-appexec
+Raise if space.is_true(space.appexec()) used in app level tests, fix tests
+that did this
+
+.. branch: py3.5-mac-embedding
+Download and patch dependencies when building cffi-based stdlib modules
+
+.. branch: os_lockf
+
+.. branch: py3.5-xattr
+Add posix.*attr() functions
diff --git a/pypy/doc/whatsnew-pypy3-head.rst b/pypy/doc/whatsnew-pypy3-head.rst
--- a/pypy/doc/whatsnew-pypy3-head.rst
+++ b/pypy/doc/whatsnew-pypy3-head.rst
@@ -1,18 +1,16 @@
 =========================
-What's new in PyPy3 5.9+
+What's new in PyPy3 5.10+
 =========================
 
-.. this is the revision after release-pypy3.5-5.9
-.. startrev: be41e3ac0a29
+.. this is the revision after release-pypy3.5-v5.10
+.. startrev: 34c63fba0bba
 
-.. branch: sched_yield
-Add sched_yield posix attribute
+.. branch: hroncok/fix-typeerror-str-does-not-support-the-b-1514414905375
 
-.. branch: py3.5-appexec
-Raise if space.is_true(space.appexec()) used in app level tests, fix tests
-that did this
+Fix for bytestrings in console repl
 
-.. branch: py3.5-mac-embedding
-Download and patch dependencies when building cffi-based stdlib modules
+.. branch: py3-winreg
 
-.. branch: os_lockf
+Update winreg module to use unicode, wide-strings
+
+
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -11,7 +11,7 @@
 
 To build pypy-c you need a working python environment, and a C compiler.
 It is possible to translate with a CPython 2.6 or later, but this is not
-the preferred way, because it will take a lot longer to run &#65533; depending
+the preferred way, because it will take a lot longer to run &#8211; depending
 on your architecture, between two and three times as long. So head to
 `our downloads`_ and get the latest stable version.
 
@@ -103,6 +103,7 @@
 must also copy the ``vcvarsall.bat`` file fron the ``...\9.0`` directory to the
 ``...\9.0\VC`` directory, and edit it, changing the lines that set
 ``VCINSTALLDIR`` and ``WindowsSdkDir``::
+
     set VCINSTALLDIR=%~dp0\
     set WindowsSdkDir=%~dp0\..\WinSDK\
 
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -574,10 +574,6 @@
             except ValueError:
                 pass      # ignore "2 is not a valid file descriptor"
 
-    if we_are_translated():
-        import __pypy__
-        __pypy__.save_module_content_for_future_reload(sys)
-
     mainmodule = type(sys)('__main__')
     mainmodule.__loader__ = sys.__loader__
     mainmodule.__builtins__ = os.__builtins__
diff --git a/pypy/interpreter/astcompiler/assemble.py 
b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -1,7 +1,7 @@
 """Python control flow graph generation and bytecode assembly."""
 
+import math
 import os
-from rpython.rlib import rfloat
 from rpython.rlib.objectmodel import specialize, we_are_translated
 
 from pypy.interpreter.astcompiler import ast, consts, misc, symtable
@@ -269,7 +269,7 @@
         w_type = space.type(obj)
         if space.is_w(w_type, space.w_float):
             val = space.float_w(obj)
-            if val == 0.0 and rfloat.copysign(1., val) < 0:
+            if val == 0.0 and math.copysign(1., val) < 0:
                 w_key = space.newtuple([obj, space.w_float, space.w_None])
             else:
                 w_key = space.newtuple([obj, space.w_float])
@@ -279,9 +279,9 @@
             real = space.float_w(w_real)
             imag = space.float_w(w_imag)
             real_negzero = (real == 0.0 and
-                            rfloat.copysign(1., real) < 0)
+                            math.copysign(1., real) < 0)
             imag_negzero = (imag == 0.0 and
-                            rfloat.copysign(1., imag) < 0)
+                            math.copysign(1., imag) < 0)
             if real_negzero and imag_negzero:
                 tup = [obj, space.w_complex, space.w_None, space.w_None,
                        space.w_None]
diff --git a/pypy/interpreter/astcompiler/fstring.py 
b/pypy/interpreter/astcompiler/fstring.py
--- a/pypy/interpreter/astcompiler/fstring.py
+++ b/pypy/interpreter/astcompiler/fstring.py
@@ -342,10 +342,11 @@
     encoding = astbuilder.compile_info.encoding
     joined_pieces = []
     fmode = False
-    try:
-        for i in range(atom_node.num_children()):
+    for i in range(atom_node.num_children()):
+        child = atom_node.get_child(i)
+        try:
             w_next = parsestring.parsestr(
-                    space, encoding, atom_node.get_child(i).get_value())
+                    space, encoding, child.get_value())
             if not isinstance(w_next, parsestring.W_FString):
                 add_constant_string(astbuilder, joined_pieces, w_next,
                                     atom_node)
@@ -353,17 +354,20 @@
                 parse_f_string(astbuilder, joined_pieces, w_next, atom_node)
                 fmode = True
 
-    except error.OperationError as e:
-        if e.match(space, space.w_UnicodeError):
-            kind = 'unicode error'
-        elif e.match(space, space.w_ValueError):
-            kind = 'value error'
-        else:
-            raise
-        # Unicode/ValueError in literal: turn into SyntaxError
-        e.normalize_exception(space)
-        errmsg = space.text_w(space.str(e.get_w_value(space)))
-        raise astbuilder.error('(%s) %s' % (kind, errmsg), atom_node)
+        except error.OperationError as e:
+            if e.match(space, space.w_UnicodeError):
+                kind = '(unicode error) '
+            elif e.match(space, space.w_ValueError):
+                kind = '(value error) '
+            elif e.match(space, space.w_SyntaxError):
+                kind = ''
+            else:
+                raise
+            # Unicode/ValueError/SyntaxError (without position information) in
+            # literal: turn into SyntaxError with position information
+            e.normalize_exception(space)
+            errmsg = space.text_w(space.str(e.get_w_value(space)))
+            raise astbuilder.error('%s%s' % (kind, errmsg), child)
 
     if not fmode and len(joined_pieces) == 1:   # <= the common path
         return joined_pieces[0]   # ast.Str, Bytes or FormattedValue
diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py 
b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -1418,3 +1418,7 @@
         exc = py.test.raises(SyntaxError, self.get_ast, input).value
         assert exc.msg == ("(unicode error) 'unicodeescape' codec can't decode"
                            " bytes in position 0-1: truncated \\xXX escape")
+        input = "u'\\x1'"
+        exc = py.test.raises(SyntaxError, self.get_ast, input).value
+        assert exc.msg == ("(unicode error) 'unicodeescape' codec can't decode"
+                           " bytes in position 0-2: truncated \\xXX escape")
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -627,12 +627,12 @@
     if rwin32.WIN32 and isinstance(e, WindowsError):
         winerror = e.winerror
         try:
-            msg = rwin32.FormatError(winerror)
+            msg = rwin32.FormatErrorW(winerror)
         except ValueError:
-            msg = 'Windows Error %d' % winerror
+            msg = u'Windows Error %d' % winerror
         w_errno = space.w_None
         w_winerror = space.newint(winerror)
-        w_msg = space.newtext(msg)
+        w_msg = space.newunicode(msg)
     else:
         errno = e.errno
         if errno == EINTR:
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -171,6 +171,9 @@
     def visit_text0(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
+    def visit_unicode(self, el, app_sig):
+        self.checked_space_method(el, app_sig)
+
     def visit_fsencode(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
@@ -320,6 +323,9 @@
     def visit_text0(self, typ):
         self.run_args.append("space.text0_w(%s)" % (self.scopenext(),))
 
+    def visit_unicode(self, typ):
+        self.run_args.append("space.unicode_w(%s)" % (self.scopenext(),))
+
     def visit_fsencode(self, typ):
         self.run_args.append("space.fsencode_w(%s)" % (self.scopenext(),))
 
@@ -485,6 +491,9 @@
     def visit_text(self, typ):
         self.unwrap.append("space.text_w(%s)" % (self.nextarg(),))
 
+    def visit_unicode(self, typ):
+        self.unwrap.append("space.unicode_w(%s)" % (self.nextarg(),))
+
     def visit_text0(self, typ):
         self.unwrap.append("space.text0_w(%s)" % (self.nextarg(),))
 
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -4,7 +4,7 @@
 The bytecode interpreter itself is implemented by the PyFrame class.
 """
 
-import imp, struct, types, new, sys, os
+import imp, struct, types, sys, os
 
 from pypy.interpreter import eval
 from pypy.interpreter.signature import Signature
@@ -80,7 +80,7 @@
 class PyCode(eval.Code):
     "CPython-style code objects."
     _immutable_fields_ = ["_signature", "co_argcount", "co_kwonlyargcount", 
"co_cellvars[*]",
-                          "co_code", "co_consts_w[*]", "co_filename",
+                          "co_code", "co_consts_w[*]", "co_filename", 
"w_filename",
                           "co_firstlineno", "co_flags", "co_freevars[*]",
                           "co_lnotab", "co_names_w[*]", "co_nlocals",
                           "co_stacksize", "co_varnames[*]",
@@ -111,6 +111,7 @@
         assert isinstance(filename, str)
         rstring.check_str0(filename)
         self.co_filename = filename
+        self.w_filename = space.newfilename(filename)
         self.co_name = name
         self.co_firstlineno = firstlineno
         self.co_lnotab = lnotab
@@ -203,6 +204,7 @@
         if lastdirname:
             basename = '%s/%s' % (lastdirname, basename)
         self.co_filename = '<builtin>/%s' % (basename,)
+        self.w_filename = self.space.newfilename(self.co_filename)
 
     co_names = property(lambda self: [self.space.str_w(w_name) for w_name in 
self.co_names_w]) # for trace
 
@@ -427,7 +429,7 @@
             space.newtuple(self.co_consts_w),
             space.newtuple(self.co_names_w),
             space.newtuple([space.newtext(v) for v in self.co_varnames]),
-            space.newtext(self.co_filename),
+            self.w_filename,
             space.newtext(self.co_name),
             space.newint(self.co_firstlineno),
             space.newbytes(self.co_lnotab),
@@ -451,7 +453,7 @@
         space = self.space
         # co_name should be an identifier
         name = self.co_name.decode('utf-8')
-        fn = space.fsdecode_w(space.newbytes(self.co_filename))
+        fn = space.unicode_w(self.w_filename)
         return space.newunicode(u'<code object %s at 0x%s, file "%s", line 
%d>' % (
             name, unicode(self.getaddrstring(space)), fn,
             -1 if self.co_firstlineno == 0 else self.co_firstlineno))
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
@@ -1007,8 +1007,9 @@
         compile(b"# coding: latin1\n#\xfd\n", "dummy", "exec")
         raises(SyntaxError, compile, b"# coding: utf-8\n'\xfd'\n",
                "dummy", "exec") #1
-        raises(SyntaxError, compile, b'# coding: utf-8\nx=5\nb"\xfd"\n',
+        excinfo = raises(SyntaxError, compile, b'# coding: 
utf-8\nx=5\nb"\xfd"\n',
                "dummy", "exec") #2
+        assert excinfo.value.lineno == 3
         # the following example still fails on CPython 3.5.2, skip if -A
         if '__pypy__' in sys.builtin_module_names:
             raises(SyntaxError, compile, b"# coding: utf-8\n#\xfd\n",
@@ -1023,6 +1024,12 @@
         raises(SyntaxError, compile, b"#\x00\nx=5#\xfd\n", "dummy", "exec",
                PyCF_ACCEPT_NULL_BYTES)
 
+    def test_correct_offset_in_many_bytes(self):
+        excinfo = raises(SyntaxError, compile, b'# coding: utf-8\nx = b"a" 
b"c" b"\xfd"\n',
+               "dummy", "exec")
+        assert excinfo.value.lineno == 2
+        assert excinfo.value.offset == 14
+
     def test_dict_and_set_literal_order(self):
         x = 1
         l1 = list({1:'a', 3:'b', 2:'c', 4:'d'})
diff --git a/pypy/interpreter/test/test_timeutils.py 
b/pypy/interpreter/test/test_timeutils.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/test_timeutils.py
@@ -0,0 +1,13 @@
+import pytest
+from rpython.rlib.rarithmetic import r_longlong
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.timeutils import timestamp_w
+
+def test_timestamp_w(space):
+    w_1_year = space.newint(365 * 24 * 3600)
+    result = timestamp_w(space, w_1_year)
+    assert isinstance(result, r_longlong)
+    assert result // 10 ** 9 == space.int_w(w_1_year)
+    w_millenium = space.mul(w_1_year, space.newint(1000))
+    with pytest.raises(OperationError):  # timestamps overflow after ~300 years
+        timestamp_w(space, w_millenium)
diff --git a/pypy/interpreter/test/test_unicodehelper.py 
b/pypy/interpreter/test/test_unicodehelper.py
--- a/pypy/interpreter/test/test_unicodehelper.py
+++ b/pypy/interpreter/test/test_unicodehelper.py
@@ -1,5 +1,8 @@
 import py
-from pypy.interpreter.unicodehelper import encode_utf8, decode_utf8
+import pytest
+import struct
+from pypy.interpreter.unicodehelper import (
+    encode_utf8, decode_utf8, unicode_encode_utf_32_be, str_decode_utf_32_be)
 from pypy.interpreter.unicodehelper import encode_utf8sp, decode_utf8sp
 
 
@@ -67,3 +70,26 @@
     assert map(ord, got) == [0xd800, 0xdc00]
     got = decode_utf8sp(space, "\xf0\x90\x80\x80")
     assert map(ord, got) == [0x10000]
+
+@pytest.mark.parametrize('unich', [u"\ud800", u"\udc80"])
+def test_utf32_surrogates(unich):
+    assert (unicode_encode_utf_32_be(unich, 1, None) ==
+            struct.pack('>i', ord(unich)))
+    with pytest.raises(UnicodeEncodeError):
+        unicode_encode_utf_32_be(unich, 1, None, allow_surrogates=False)
+
+    def replace_with(ru, rs):
+        def errorhandler(errors, enc, msg, u, startingpos, endingpos):
+            if errors == 'strict':
+                raise UnicodeEncodeError(enc, u, startingpos, endingpos, msg)
+            return ru, rs, endingpos
+        return unicode_encode_utf_32_be(
+            u"<%s>" % unich, 3, None,
+            errorhandler, allow_surrogates=False)
+
+    assert replace_with(u'rep', None) == u'<rep>'.encode('utf-32-be')
+    assert (replace_with(None, '\xca\xfe\xca\xfe') ==
+            '\x00\x00\x00<\xca\xfe\xca\xfe\x00\x00\x00>')
+
+    with pytest.raises(UnicodeDecodeError):
+        str_decode_utf_32_be(b"\x00\x00\xdc\x80", 4, None)
diff --git a/pypy/interpreter/timeutils.py b/pypy/interpreter/timeutils.py
--- a/pypy/interpreter/timeutils.py
+++ b/pypy/interpreter/timeutils.py
@@ -1,6 +1,15 @@
 """
 Access to the time module's high-resolution monotonic clock
 """
+import math
+from rpython.rlib.rarithmetic import (
+    r_longlong, ovfcheck_float_to_longlong)
+from rpython.rlib import rfloat
+from pypy.interpreter.error import oefmt
+
+SECS_TO_NS = 10 ** 9
+MS_TO_NS = 10 ** 6
+US_TO_NS = 10 ** 3
 
 def monotonic(space):
     from pypy.module.time import interp_time
@@ -9,3 +18,23 @@
     else:
         w_res = interp_time.gettimeofday(space)
     return space.float_w(w_res)   # xxx back and forth
+
+def timestamp_w(space, w_secs):
+    if space.isinstance_w(w_secs, space.w_float):
+        secs = space.float_w(w_secs)
+        if math.isnan(secs):
+            raise oefmt(space.w_ValueError, "timestamp is nan")
+        result_float = math.ceil(secs * SECS_TO_NS)
+        try:
+            return ovfcheck_float_to_longlong(result_float)
+        except OverflowError:
+            raise oefmt(space.w_OverflowError,
+                "timestamp %R too large to convert to C _PyTime_t", w_secs)
+    else:
+        try:
+            sec = space.bigint_w(w_secs).tolonglong()
+            result = sec * r_longlong(SECS_TO_NS)
+        except OverflowError:
+            raise oefmt(space.w_OverflowError,
+                "timestamp %R too large to convert to C _PyTime_t", w_secs)
+        return result
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -627,7 +627,7 @@
     co_varnames = GetSetProperty(PyCode.fget_co_varnames),
     co_freevars = GetSetProperty(PyCode.fget_co_freevars),
     co_cellvars = GetSetProperty(PyCode.fget_co_cellvars),
-    co_filename = interp_attrproperty('co_filename', cls=PyCode, 
wrapfn="newfilename"),
+    co_filename = interp_attrproperty_w('w_filename', cls=PyCode),
     co_name = interp_attrproperty('co_name', cls=PyCode, wrapfn="newtext"),
     co_firstlineno = interp_attrproperty('co_firstlineno', cls=PyCode, 
wrapfn="newint"),
     co_lnotab = interp_attrproperty('co_lnotab', cls=PyCode, 
wrapfn="newbytes"),
diff --git a/pypy/interpreter/unicodehelper.py 
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -1,8 +1,13 @@
 import sys
 from pypy.interpreter.error import OperationError, oefmt
 from rpython.rlib.objectmodel import specialize
+from rpython.rlib.rarithmetic import intmask
+from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
 from rpython.rlib import runicode
-from pypy.module._codecs import interp_codecs
+from rpython.rlib.runicode import (
+    default_unicode_error_encode, default_unicode_error_decode,
+    MAXUNICODE, BYTEORDER, BYTEORDER2, UNICHR)
+
 _WIN32 = sys.platform == 'win32'
 _MACOSX = sys.platform == 'darwin'
 if _WIN32:
@@ -40,6 +45,7 @@
 # ____________________________________________________________
 
 def fsdecode(space, w_string):
+    from pypy.module._codecs import interp_codecs
     state = space.fromcache(interp_codecs.CodecState)
     if _WIN32:
         bytes = space.bytes_w(w_string)
@@ -70,6 +76,7 @@
     return space.newunicode(uni)
 
 def fsencode(space, w_uni):
+    from pypy.module._codecs import interp_codecs
     state = space.fromcache(interp_codecs.CodecState)
     if _WIN32:
         uni = space.unicode_w(w_uni)
@@ -107,6 +114,7 @@
 
 # These functions take and return unwrapped rpython strings and unicodes
 def decode_unicode_escape(space, string):
+    from pypy.module._codecs import interp_codecs
     state = space.fromcache(interp_codecs.CodecState)
     unicodedata_handler = state.get_unicodedata_handler(space)
     result, consumed = runicode.str_decode_unicode_escape(
@@ -157,3 +165,207 @@
     # encoding error, it should always be reversible, and the reverse is
     # encode_utf8sp().
     return decode_utf8(space, string, allow_surrogates=True)
+
+# ____________________________________________________________
+# utf-32
+
+def str_decode_utf_32(s, size, errors, final=True,
+                           errorhandler=None):
+    result, length, byteorder = str_decode_utf_32_helper(
+        s, size, errors, final, errorhandler, "native", 'utf-32-' + BYTEORDER2,
+        allow_surrogates=False)
+    return result, length
+
+def str_decode_utf_32_be(s, size, errors, final=True,
+                              errorhandler=None):
+    result, length, byteorder = str_decode_utf_32_helper(
+        s, size, errors, final, errorhandler, "big", 'utf-32-be',
+        allow_surrogates=False)
+    return result, length
+
+def str_decode_utf_32_le(s, size, errors, final=True,
+                              errorhandler=None):
+    result, length, byteorder = str_decode_utf_32_helper(
+        s, size, errors, final, errorhandler, "little", 'utf-32-le',
+        allow_surrogates=False)
+    return result, length
+
+BOM32_DIRECT = intmask(0x0000FEFF)
+BOM32_REVERSE = intmask(0xFFFE0000)
+
+def str_decode_utf_32_helper(s, size, errors, final=True,
+                             errorhandler=None,
+                             byteorder="native",
+                             public_encoding_name='utf32',
+                             allow_surrogates=True):
+    if errorhandler is None:
+        errorhandler = default_unicode_error_decode
+    bo = 0
+
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to