Author: Carl Friedrich Bolz-Tereick <[email protected]>
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ł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áš Pruž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
+ [email protected]
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
+
[email protected]('__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ł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áš Pruž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
+ [email protected]
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": ['[email protected]'],
+ "Dodan Mihai": ['[email protected]'],
}
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 � depending
+the preferred way, because it will take a lot longer to run – 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]
+
[email protected]('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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit