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ł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 + 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ł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 + 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 � 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] + +@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