[pypy-commit] pypy py3.6: Add support for FsPath to os.unlink()
Author: Amaury Forgeot d'Arc Branch: py3.6 Changeset: r95558:77d2a71504df Date: 2019-01-01 18:44 +0100 http://bitbucket.org/pypy/pypy/changeset/77d2a71504df/ Log:Add support for FsPath to os.unlink() diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -727,8 +727,9 @@ else: return space.newint(rc) -@unwrap_spec(dir_fd=DirFD(rposix.HAVE_UNLINKAT)) -def unlink(space, w_path, __kwonly__, dir_fd=DEFAULT_DIR_FD): +@unwrap_spec(path=path_or_fd(allow_fd=False), + dir_fd=DirFD(rposix.HAVE_UNLINKAT)) +def unlink(space, path, __kwonly__, dir_fd=DEFAULT_DIR_FD): """unlink(path, *, dir_fd=None) Remove a file (same as remove()). @@ -739,15 +740,16 @@ If it is unavailable, using it will raise a NotImplementedError.""" try: if rposix.HAVE_UNLINKAT and dir_fd != DEFAULT_DIR_FD: -path = space.fsencode_w(w_path) -rposix.unlinkat(path, dir_fd, removedir=False) +rposix.unlinkat(space.fsencode_w(path.w_path), +dir_fd, removedir=False) else: -dispatch_filename(rposix.unlink)(space, w_path) +call_rposix(rposix.unlink, path) except OSError as e: -raise wrap_oserror2(space, e, w_path, eintr_retry=False) +raise wrap_oserror2(space, e, path.w_path, eintr_retry=False) -@unwrap_spec(dir_fd=DirFD(rposix.HAVE_UNLINKAT)) -def remove(space, w_path, __kwonly__, dir_fd=DEFAULT_DIR_FD): +@unwrap_spec(path=path_or_fd(allow_fd=False), + dir_fd=DirFD(rposix.HAVE_UNLINKAT)) +def remove(space, path, __kwonly__, dir_fd=DEFAULT_DIR_FD): """remove(path, *, dir_fd=None) Remove a file (same as unlink()). @@ -758,12 +760,12 @@ If it is unavailable, using it will raise a NotImplementedError.""" try: if rposix.HAVE_UNLINKAT and dir_fd != DEFAULT_DIR_FD: -path = space.fsencode_w(w_path) -rposix.unlinkat(path, dir_fd, removedir=False) +rposix.unlinkat(space.fsencode_w(path.w_path), +dir_fd, removedir=False) else: -dispatch_filename(rposix.unlink)(space, w_path) +call_rposix(rposix.unlink, path) except OSError as e: -raise wrap_oserror2(space, e, w_path, eintr_retry=False) +raise wrap_oserror2(space, e, path.w_path, eintr_retry=False) def _getfullpathname(space, w_path): """helper for ntpath.abspath """ @@ -1109,9 +,9 @@ wrap_oserror(space, e, eintr_retry=True) @unwrap_spec(src_dir_fd=DirFD(rposix.HAVE_RENAMEAT), -dst_dir_fd=DirFD(rposix.HAVE_RENAMEAT)) + dst_dir_fd=DirFD(rposix.HAVE_RENAMEAT)) def rename(space, w_src, w_dst, __kwonly__, -src_dir_fd=DEFAULT_DIR_FD, dst_dir_fd=DEFAULT_DIR_FD): + src_dir_fd=DEFAULT_DIR_FD, dst_dir_fd=DEFAULT_DIR_FD): """rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None) Rename a file or directory. diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -390,6 +390,16 @@ if sys.platform != "win32": assert posix.access(pdir, posix.X_OK) is False +def test_unlink(self): +os = self.posix +path = self.path +with open(path, 'wb'): +pass +class Path: +def __fspath__(self): +return path +os.unlink(Path()) + def test_times(self): """ posix.times() should return a posix.times_result object giving ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: hg merge py3.5
Author: Amaury Forgeot d'Arc Branch: py3.6 Changeset: r95559:df0beeb7b5ec Date: 2019-01-01 18:50 +0100 http://bitbucket.org/pypy/pypy/changeset/df0beeb7b5ec/ Log:hg merge py3.5 diff --git a/LICENSE b/LICENSE --- a/LICENSE +++ b/LICENSE @@ -30,7 +30,7 @@ DEALINGS IN THE SOFTWARE. -PyPy Copyright holders 2003-2018 +PyPy Copyright holders 2003-2019 Except when otherwise stated (look for LICENSE files or information at diff --git a/extra_tests/cffi_tests/cffi0/test_ffi_backend.py b/extra_tests/cffi_tests/cffi0/test_ffi_backend.py --- a/extra_tests/cffi_tests/cffi0/test_ffi_backend.py +++ b/extra_tests/cffi_tests/cffi0/test_ffi_backend.py @@ -327,6 +327,16 @@ assert ffi.typeof(c) is ffi.typeof("char[]") ffi.cast("unsigned short *", c)[1] += 500 assert list(a) == [1, 20500, 3] +assert c == ffi.from_buffer(a, True) +assert c == ffi.from_buffer(a, require_writable=True) +# +p = ffi.from_buffer(b"abcd") +assert p[2] == b"c" +# +assert p == ffi.from_buffer(b"abcd", False) +py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", True) +py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", + require_writable=True) def test_memmove(self): ffi = FFI() diff --git a/extra_tests/cffi_tests/cffi1/test_ffi_obj.py b/extra_tests/cffi_tests/cffi1/test_ffi_obj.py --- a/extra_tests/cffi_tests/cffi1/test_ffi_obj.py +++ b/extra_tests/cffi_tests/cffi1/test_ffi_obj.py @@ -244,6 +244,16 @@ assert ffi.typeof(c) is ffi.typeof("char[]") ffi.cast("unsigned short *", c)[1] += 500 assert list(a) == [1, 20500, 3] +assert c == ffi.from_buffer(a, True) +assert c == ffi.from_buffer(a, require_writable=True) +# +p = ffi.from_buffer(b"abcd") +assert p[2] == b"c" +# +assert p == ffi.from_buffer(b"abcd", False) +py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", True) +py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", + require_writable=True) def test_memmove(): ffi = _cffi1_backend.FFI() diff --git a/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py b/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py --- a/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py +++ b/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py @@ -1654,6 +1654,16 @@ assert ffi.typeof(c) is ffi.typeof("char[]") ffi.cast("unsigned short *", c)[1] += 500 assert list(a) == [1, 20500, 3] +assert c == ffi.from_buffer(a, True) +assert c == ffi.from_buffer(a, require_writable=True) +# +p = ffi.from_buffer(b"abcd") +assert p[2] == b"c" +# +assert p == ffi.from_buffer(b"abcd", False) +py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", True) +py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", + require_writable=True) def test_all_primitives(self): assert set(PRIMITIVE_TO_INDEX) == set([ diff --git a/extra_tests/test_pyrepl/conftest.py b/extra_tests/test_pyrepl/conftest.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_pyrepl/conftest.py @@ -0,0 +1,8 @@ +import sys + +def pytest_ignore_collect(path): +if '__pypy__' not in sys.builtin_module_names: +try: +import pyrepl +except ImportError: +return True diff --git a/lib-python/3/datetime.py b/lib-python/3/datetime.py --- a/lib-python/3/datetime.py +++ b/lib-python/3/datetime.py @@ -537,7 +537,11 @@ -self._microseconds) def __pos__(self): -return self +# for CPython compatibility, we cannot use +# our __class__ here, but need a real timedelta +return timedelta(self._days, + self._seconds, + self._microseconds) def __abs__(self): if self._days < 0: @@ -829,8 +833,7 @@ month = self._month if day is None: day = self._day -# PyPy fix: returns type(self)() instead of date() -return type(self)(year, month, day) +return date.__new__(type(self), year, month, day) # Comparisons of date objects with other. @@ -1323,8 +1326,8 @@ tzinfo = self.tzinfo if fold is None: fold = self._fold -# PyPy fix: returns type(self)() instead of time() -return type(self)(hour, minute, second, microsecond, tzinfo, fold=fold) +return time.__new__(type(self), +hour, minute, second, microsecond, tzinfo) # Pickle support. @@ -1387,13 +1390,13 @@ hour, minute, second, microsecond, fold) _check_tzinfo_arg(tzinfo) self =
[pypy-commit] pypy py3.6: The variable annotation: '(var): int' should consider (var) as an expression,
Author: Amaury Forgeot d'Arc Branch: py3.6 Changeset: r95539:26c82f5c208f Date: 2018-12-30 13:17 +0100 http://bitbucket.org/pypy/pypy/changeset/26c82f5c208f/ Log:The variable annotation: '(var): int' should consider (var) as an expression, and not cause var to become a local variable. diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py --- a/pypy/interpreter/astcompiler/symtable.py +++ b/pypy/interpreter/astcompiler/symtable.py @@ -429,11 +429,15 @@ self.scope.contains_annotated = True target = assign.target if isinstance(target, ast.Name): -scope = SYM_ANNOTATED +# XXX Should check (and fail) for previous 'global' annotation. name = target.id +scope = SYM_BLANK +if assign.simple: +scope |= SYM_ANNOTATED if assign.value: scope |= SYM_USED -self.note_symbol(name, scope) +if scope: +self.note_symbol(name, scope) else: target.walkabout(self) if assign.value is not None: diff --git a/pypy/interpreter/astcompiler/test/test_symtable.py b/pypy/interpreter/astcompiler/test/test_symtable.py --- a/pypy/interpreter/astcompiler/test/test_symtable.py +++ b/pypy/interpreter/astcompiler/test/test_symtable.py @@ -517,6 +517,9 @@ fscp = self.func_scope("def f(): implicit_global[0]: int") assert fscp.lookup("implicit_global") == symtable.SCOPE_GLOBAL_IMPLICIT +fscp = self.func_scope("def f(): (implicit_global): int") +assert fscp.lookup("implicit_global") == symtable.SCOPE_UNKNOWN + def test_issue13343(self): scp = self.mod_scope("lambda *, k1=x, k2: None") assert scp.lookup("x") == symtable.SCOPE_GLOBAL_IMPLICIT diff --git a/pypy/interpreter/test/test_annotations.py b/pypy/interpreter/test/test_annotations.py --- a/pypy/interpreter/test/test_annotations.py +++ b/pypy/interpreter/test/test_annotations.py @@ -73,6 +73,15 @@ ... ''' +def test_non_simple_func_annotation(self): +''' +a = 5 +def f(): +(a): int +return a +assert f() == 5 +''' + def test_repeated_setup(self): # each exec will run another SETUP_ANNOTATIONS # we want to confirm that this doesn't blow away @@ -147,4 +156,3 @@ """ c = compile(s, "f", "exec") assert c.co_firstlineno == 3 - ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Check conflict between 'global' and variable annotation.
Author: Amaury Forgeot d'Arc Branch: py3.6 Changeset: r95540:3f85fe07a914 Date: 2018-12-30 14:57 +0100 http://bitbucket.org/pypy/pypy/changeset/3f85fe07a914/ Log:Check conflict between 'global' and variable annotation. This fixes the last failure in test_grammar. diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py --- a/pypy/interpreter/astcompiler/symtable.py +++ b/pypy/interpreter/astcompiler/symtable.py @@ -429,8 +429,17 @@ self.scope.contains_annotated = True target = assign.target if isinstance(target, ast.Name): -# XXX Should check (and fail) for previous 'global' annotation. name = target.id +old_role = self.scope.lookup_role(name) +if assign.simple: +if old_role & SYM_GLOBAL: +raise SyntaxError( +"annotated name '%s' can't be global" % name, +assign.lineno, assign.col_offset) +if old_role & SYM_NONLOCAL: +raise SyntaxError( +"annotated name '%s' can't be nonlocal" % name, +assign.lineno, assign.col_offset) scope = SYM_BLANK if assign.simple: scope |= SYM_ANNOTATED diff --git a/pypy/interpreter/astcompiler/test/test_symtable.py b/pypy/interpreter/astcompiler/test/test_symtable.py --- a/pypy/interpreter/astcompiler/test/test_symtable.py +++ b/pypy/interpreter/astcompiler/test/test_symtable.py @@ -494,6 +494,14 @@ assert exc_global.msg == "annotated name 'x' can't be global" assert exc_global.lineno == 3 +def test_annotation_global2(self): +src_global = ("def f():\n" + "global x\n" + "x: int\n") +exc_global = py.test.raises(SyntaxError, self.func_scope, src_global).value +assert exc_global.msg == "annotated name 'x' can't be global" +assert exc_global.lineno == 3 + def test_annotation_nonlocal(self): src_nonlocal = ("def f():\n" "x: int\n" ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Fix some doctests: PyPy does not add the function name to the error message,
Author: Amaury Forgeot d'Arc Branch: py3.6 Changeset: r95538:d510a67badcd Date: 2018-12-30 03:41 +0100 http://bitbucket.org/pypy/pypy/changeset/d510a67badcd/ Log:Fix some doctests: PyPy does not add the function name to the error message, and one exception was wrong. diff --git a/lib-python/3/test/test_unpack_ex.py b/lib-python/3/test/test_unpack_ex.py --- a/lib-python/3/test/test_unpack_ex.py +++ b/lib-python/3/test/test_unpack_ex.py @@ -244,16 +244,16 @@ ... TypeError: ...got multiple values for keyword argument 'x' ->>> f(x=5, **{'x': 3}, **{'x': 2}) -Traceback (most recent call last): - ... -TypeError: f() got multiple values for keyword argument 'x' - ->>> f(**{1: 3}, **{1: 5}) +>>> f(x=5, **{'x': 3}, **{'x': 2}) # doctest:+ELLIPSIS Traceback (most recent call last): ... TypeError: ...got multiple values for keyword argument 'x' +>>> f(**{1: 3}, **{1: 5}) # doctest:+ELLIPSIS +Traceback (most recent call last): + ... +TypeError: ...keywords must be strings... + >>> f(x=5, **{'x': 3}, **{'x': 2}) # doctest:+ELLIPSIS Traceback (most recent call last): ... ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Port CPython commit 91108f0: Issue #25210: Change error message of do_richcompare()
Author: Amaury Forgeot d'Arc Branch: py3.6 Changeset: r95537:0f59af55378c Date: 2018-08-05 17:33 +0200 http://bitbucket.org/pypy/pypy/changeset/0f59af55378c/ Log:Port CPython commit 91108f0: Issue #25210: Change error message of do_richcompare() diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py --- a/pypy/objspace/descroperation.py +++ b/pypy/objspace/descroperation.py @@ -619,7 +619,8 @@ # # if we arrived here, they are unorderable raise oefmt(space.w_TypeError, -"unorderable types: %T %s %T", w_obj1, symbol, w_obj2) +"'%s' not supported between instances of '%T' and '%T'", +symbol, w_obj1, w_obj2) return func_with_new_name(comparison_impl, 'comparison_%s_impl'%left.strip('_')) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: CPython Issue 18550: Check error values in socket.setblocking()
Author: Amaury Forgeot d'Arc Branch: py3.6 Changeset: r95536:cafe126a986a Date: 2018-08-06 15:49 +0200 http://bitbucket.org/pypy/pypy/changeset/cafe126a986a/ Log:CPython Issue 18550: Check error values in socket.setblocking() diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py --- a/pypy/module/_socket/interp_socket.py +++ b/pypy/module/_socket/interp_socket.py @@ -608,14 +608,17 @@ return space.newint(count) @unwrap_spec(flag=int) -def setblocking_w(self, flag): +def setblocking_w(self, space, flag): """setblocking(flag) Set the socket to blocking (flag is true) or non-blocking (false). setblocking(True) is equivalent to settimeout(None); setblocking(False) is equivalent to settimeout(0.0). """ -self.sock.setblocking(bool(flag)) +try: +self.sock.setblocking(bool(flag)) +except SocketError as e: +raise converted_error(space, e) @unwrap_spec(level=int, optname=int) def setsockopt_w(self, space, level, optname, w_optval): @@ -654,7 +657,10 @@ timeout = space.float_w(w_timeout) if timeout < 0.0: raise oefmt(space.w_ValueError, "Timeout value out of range") -self.sock.settimeout(timeout) +try: +self.sock.settimeout(timeout) +except SocketError as e: +raise converted_error(space, e) @unwrap_spec(nbytes=int, flags=int) def recv_into_w(self, space, w_buffer, nbytes=0, flags=0): diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py --- a/pypy/module/_socket/test/test_sock_app.py +++ b/pypy/module/_socket/test/test_sock_app.py @@ -402,6 +402,12 @@ e = raises(OSError, s.close) assert e.value.errno in (errno.EBADF, errno.ENOTSOCK) +def test_setblocking_invalidfd(self): +import errno, _socket +s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0) +_socket.socket(fileno=s.fileno()).close() +raises(OSError, s.setblocking, False) + def test_socket_connect(self): import _socket, os s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0) diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py --- a/rpython/rlib/_rsocket_rffi.py +++ b/rpython/rlib/_rsocket_rffi.py @@ -1270,7 +1270,8 @@ getprotobyname = external('getprotobyname', [rffi.CCHARP], lltype.Ptr(cConfig.protoent)) if _POSIX: -fcntl = external('fcntl', [socketfd_type, rffi.INT, rffi.INT], rffi.INT) +fcntl = external('fcntl', [socketfd_type, rffi.INT, rffi.INT], rffi.INT, + save_err=SAVE_ERR) socketpair_t = rffi.CArray(socketfd_type) socketpair = external('socketpair', [rffi.INT, rffi.INT, rffi.INT, lltype.Ptr(socketpair_t)], rffi.INT, @@ -1282,7 +1283,7 @@ if _WIN32: ioctlsocket = external('ioctlsocket', [socketfd_type, rffi.LONG, rffi.ULONGP], - rffi.INT) + rffi.INT, save_err=SAVE_ERR) select = external('select', [rffi.INT, fd_set, fd_set, diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -567,17 +567,21 @@ if hasattr(_c, 'fcntl'): def _setblocking(self, block): orig_delay_flag = intmask(_c.fcntl(self.fd, _c.F_GETFL, 0)) +if orig_delay_flag == -1: +raise self.error_handler() if block: delay_flag = orig_delay_flag & ~_c.O_NONBLOCK else: delay_flag = orig_delay_flag | _c.O_NONBLOCK if orig_delay_flag != delay_flag: -_c.fcntl(self.fd, _c.F_SETFL, delay_flag) +if _c.fcntl(self.fd, _c.F_SETFL, delay_flag) == -1: +raise self.error_handler() elif hasattr(_c, 'ioctlsocket'): def _setblocking(self, block): flag = lltype.malloc(rffi.ULONGP.TO, 1, flavor='raw') flag[0] = rffi.cast(rffi.ULONG, not block) -_c.ioctlsocket(self.fd, _c.FIONBIO, flag) +if _c.ioctlsocket(self.fd, _c.FIONBIO, flag) != 0: +raise self.error_handler() lltype.free(flag, flavor='raw') if hasattr(_c, 'poll') and not _c.poll_may_be_broken: ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: hg merge default
Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r95535:f81df27a6bf7 Date: 2018-12-30 03:20 +0100 http://bitbucket.org/pypy/pypy/changeset/f81df27a6bf7/ Log:hg merge default diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -1105,9 +1105,8 @@ assert type(str(z)) is str assert str(z) == u'foobaz' # -# two completely corner cases where we differ from CPython: -#assert unicode(encoding='supposedly_the_encoding') == u'' -#assert unicode(errors='supposedly_the_error') == u'' +assert str(encoding='supposedly_the_encoding') == u'' +assert str(errors='supposedly_the_error') == u'' e = raises(TypeError, str, u'', 'supposedly_the_encoding') assert str(e.value) == 'decoding str is not supported' e = raises(TypeError, str, u'', errors='supposedly_the_error') diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -223,20 +223,18 @@ @staticmethod def descr_new(space, w_unicodetype, w_object=None, w_encoding=None, w_errors=None): -if w_object is None: -w_object = W_UnicodeObject.EMPTY -w_obj = w_object - encoding, errors = _get_encoding_and_errors(space, w_encoding, w_errors) -if encoding is None and errors is None: -# this is very quick if w_obj is already a w_unicode -w_value = unicode_from_object(space, w_obj) +if w_object is None: +w_value = W_UnicodeObject.EMPTY +elif encoding is None and errors is None: +# this is very quick if w_object is already a w_unicode +w_value = unicode_from_object(space, w_object) else: -if space.isinstance_w(w_obj, space.w_unicode): +if space.isinstance_w(w_object, space.w_unicode): raise oefmt(space.w_TypeError, "decoding str is not supported") -w_value = unicode_from_encoded_object(space, w_obj, +w_value = unicode_from_encoded_object(space, w_object, encoding, errors) if space.is_w(w_unicodetype, space.w_unicode): return w_value ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: unicode(encoding='x') returns the empty string u''.
Author: Amaury Forgeot d'Arc Branch: Changeset: r95534:24f6622d7e24 Date: 2018-12-29 23:06 +0100 http://bitbucket.org/pypy/pypy/changeset/24f6622d7e24/ Log:unicode(encoding='x') returns the empty string u''. This behavior is explicitly tested in py3.5. diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -1163,9 +1163,8 @@ assert type(unicode(z)) is unicode assert unicode(z) == u'foobaz' # -# two completely corner cases where we differ from CPython: -#assert unicode(encoding='supposedly_the_encoding') == u'' -#assert unicode(errors='supposedly_the_error') == u'' +assert unicode(encoding='supposedly_the_encoding') == u'' +assert unicode(errors='supposedly_the_error') == u'' e = raises(TypeError, unicode, u'', 'supposedly_the_encoding') assert str(e.value) == 'decoding Unicode is not supported' e = raises(TypeError, unicode, u'', errors='supposedly_the_error') diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -192,23 +192,20 @@ return space.newlist_unicode(lst) @staticmethod -@unwrap_spec(w_string=WrappedDefault("")) -def descr_new(space, w_unicodetype, w_string, w_encoding=None, +def descr_new(space, w_unicodetype, w_string=None, w_encoding=None, w_errors=None): -# NB. the default value of w_obj is really a *wrapped* empty string: -# there is gateway magic at work -w_obj = w_string - encoding, errors = _get_encoding_and_errors(space, w_encoding, w_errors) -if encoding is None and errors is None: -# this is very quick if w_obj is already a w_unicode -w_value = unicode_from_object(space, w_obj) +if w_string is None: +w_value = W_UnicodeObject.EMPTY +elif encoding is None and errors is None: +# this is very quick if w_string is already a w_unicode +w_value = unicode_from_object(space, w_string) else: -if space.isinstance_w(w_obj, space.w_unicode): +if space.isinstance_w(w_string, space.w_unicode): raise oefmt(space.w_TypeError, "decoding Unicode is not supported") -w_value = unicode_from_encoded_object(space, w_obj, +w_value = unicode_from_encoded_object(space, w_string, encoding, errors) if space.is_w(w_unicodetype, space.w_unicode): return w_value ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: We don't need SSL_is_init_finished after all
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94421:a29a0980fd16 Date: 2018-04-23 00:34 +0200 http://bitbucket.org/pypy/pypy/changeset/a29a0980fd16/ Log:We don't need SSL_is_init_finished after all diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py --- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py +++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py @@ -198,8 +198,6 @@ const char *SSL_get_cipher_list(const SSL *, int); Cryptography_STACK_OF_SSL_CIPHER *SSL_get_ciphers(const SSL *); -int SSL_is_init_finished(const SSL*); - /* context */ void SSL_CTX_free(SSL_CTX *); long SSL_CTX_set_timeout(SSL_CTX *, long); 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 @@ -705,7 +705,7 @@ raise ValueError("Session refers to a different SSLContext.") if self.socket_type != SSL_CLIENT: raise ValueError("Cannot set session for server-side SSLSocket.") -if lib.SSL_is_init_finished(self.ssl): +if self.handshake_done: raise ValueError("Cannot set session after handshake.") if not lib.SSL_set_session(self.ssl, value._session): raise pyssl_error(self, 0) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: The class is named ssl.SSLSession. Restore the import in ssl.py
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94422:85c682c5ec33 Date: 2018-04-23 00:38 +0200 http://bitbucket.org/pypy/pypy/changeset/85c682c5ec33/ Log:The class is named ssl.SSLSession. Restore the import in ssl.py diff --git a/lib-python/3/ssl.py b/lib-python/3/ssl.py --- a/lib-python/3/ssl.py +++ b/lib-python/3/ssl.py @@ -100,7 +100,7 @@ import _ssl # if we can't import it, let the error propagate from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION -from _ssl import _SSLContext, MemoryBIO#, SSLSession # XXX: PyPy hack +from _ssl import _SSLContext, MemoryBIO, SSLSession from _ssl import ( SSLError, SSLZeroReturnError, SSLWantReadError, SSLWantWriteError, SSLSyscallError, SSLEOFError, 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 @@ -695,11 +695,11 @@ @property def session(self): "Get / set SSLSession." -return Session(self) +return SSLSession(self) @session.setter def session(self, value): -if not isinstance(value, Session): +if not isinstance(value, SSLSession): raise TypeError("Value is not a SSLSession.") if self.ctx.ctx != value._ctx.ctx: raise ValueError("Session refers to a different SSLContext.") @@ -742,7 +742,7 @@ return (cipher_name, cipher_protocol, bits) -class Session(object): +class SSLSession(object): def __new__(cls, ssl): self = object.__new__(cls) session = lib.SSL_get1_session(ssl.ssl) @@ -753,7 +753,7 @@ return self def __eq__(self, other): -if not isinstance(other, Session): +if not isinstance(other, SSLSession): return NotImplemented; return self.id == other.id ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: The session.id is a bytes string with NULs, use ffi.unpack() instead of ffi.string()
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94419:3f675393a946 Date: 2018-04-22 21:40 +0200 http://bitbucket.org/pypy/pypy/changeset/3f675393a946/ Log:The session.id is a bytes string with NULs, use ffi.unpack() instead of ffi.string() 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 @@ -761,7 +761,7 @@ def id(self): lenp = ffi.new("unsigned int*") id = lib.SSL_SESSION_get_id(self._session, lenp) -return ffi.string(id, lenp[0]) +return ffi.unpack(id, lenp[0]) @property def time(self): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Is it only on my machine? 10% of the time, the test fails because the error is:
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94418:2360f76c2d3c Date: 2018-04-22 21:39 +0200 http://bitbucket.org/pypy/pypy/changeset/2360f76c2d3c/ Log:Is it only on my machine? 10% of the time, the test fails because the error is: '[SSL: NO_SHARED_CIPHER] error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure' diff --git a/lib-python/3/test/test_ssl.py b/lib-python/3/test/test_ssl.py --- a/lib-python/3/test/test_ssl.py +++ b/lib-python/3/test/test_ssl.py @@ -3087,7 +3087,7 @@ with context.wrap_socket(socket.socket()) as s: with self.assertRaises(OSError): s.connect((HOST, server.port)) -self.assertIn("no shared cipher", str(server.conn_errors[0])) +self.assertEqual("NO_SHARED_CIPHER", server.conn_errors[0].reason) def test_version_basic(self): """ ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Complete the implementation of PROTOCOL_TLS_CLIENT: host names are checked.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94417:869382060075 Date: 2018-04-22 21:31 +0200 http://bitbucket.org/pypy/pypy/changeset/869382060075/ Log:Complete the implementation of PROTOCOL_TLS_CLIENT: host names are checked. 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 @@ -822,10 +822,16 @@ raise ssl_error("failed to allocate SSL context") self.ctx = ffi.gc(lib.SSL_CTX_new(method), lib.SSL_CTX_free) +# Don't check host name by default self._check_hostname = False +if protocol == PROTOCOL_TLS_CLIENT: +self._check_hostname = True +self.verify_mode = CERT_REQUIRED +else: +self._check_hostname = False +self.verify_mode = CERT_NONE # Defaults -lib.SSL_CTX_set_verify(self.ctx, lib.SSL_VERIFY_NONE, ffi.NULL) options = lib.SSL_OP_ALL & ~lib.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS if not lib.Cryptography_HAS_SSL2 or protocol != PROTOCOL_SSLv2: options |= lib.SSL_OP_NO_SSLv2 @@ -910,7 +916,9 @@ if mode == lib.SSL_VERIFY_NONE and self.check_hostname: raise ValueError("Cannot set verify_mode to CERT_NONE when " \ "check_hostname is enabled.") -lib.SSL_CTX_set_verify(self.ctx, mode, ffi.NULL); +# Keep current verify cb +verify_cb = lib.SSL_CTX_get_verify_callback(self.ctx) +lib.SSL_CTX_set_verify(self.ctx, mode, verify_cb) @property def verify_flags(self): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Fix default socket options, added by CPython Issue 28043.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94415:26bff7c256af Date: 2018-04-22 21:04 +0200 http://bitbucket.org/pypy/pypy/changeset/26bff7c256af/ Log:Fix default socket options, added by CPython Issue 28043. 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 @@ -64,7 +64,9 @@ for name in dir(lib): if name.startswith('SSL_OP'): -globals()[name[4:]] = getattr(lib, name) +value = getattr(lib, name) +if value != 0: +globals()[name[4:]] = getattr(lib, name) OP_ALL = lib.SSL_OP_ALL & ~lib.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS @@ -829,6 +831,12 @@ options |= lib.SSL_OP_NO_SSLv2 if protocol != PROTOCOL_SSLv3: options |= lib.SSL_OP_NO_SSLv3 +# Minimal security flags for server and client side context. +# Client sockets ignore server-side parameters. +options |= lib.SSL_OP_NO_COMPRESSION; +options |= lib.SSL_OP_CIPHER_SERVER_PREFERENCE; +options |= lib.SSL_OP_SINGLE_DH_USE; +options |= lib.SSL_OP_SINGLE_ECDH_USE; lib.SSL_CTX_set_options(self.ctx, options) lib.SSL_CTX_set_session_id_context(self.ctx, b"Python", len(b"Python")) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Implement SSLSession.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94414:6dc2dbf20397 Date: 2018-04-22 20:41 +0200 http://bitbucket.org/pypy/pypy/changeset/6dc2dbf20397/ Log:Implement SSLSession. diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py --- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py +++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py @@ -198,6 +198,8 @@ const char *SSL_get_cipher_list(const SSL *, int); Cryptography_STACK_OF_SSL_CIPHER *SSL_get_ciphers(const SSL *); +int SSL_is_init_finished(const SSL*); + /* context */ void SSL_CTX_free(SSL_CTX *); long SSL_CTX_set_timeout(SSL_CTX *, long); @@ -265,6 +267,10 @@ SSL_SESSION *SSL_get_session(const SSL *); const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *, unsigned int *); +long SSL_SESSION_get_time(const SSL_SESSION *); +long SSL_SESSION_get_timeout(const SSL_SESSION *); +int SSL_SESSION_has_ticket(const SSL_SESSION *); +long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *); /* not a macro, but older OpenSSLs don't pass the args as const */ char *SSL_CIPHER_description(const SSL_CIPHER *, char *, int); @@ -509,6 +515,14 @@ memcpy(out, session->master_key, outlen); return outlen; } + +int SSL_SESSION_has_ticket(const SSL_SESSION *s) { +return (s->tlsext_ticklen > 0) ? 1 : 0; +} +unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) +{ +return s->tlsext_tick_lifetime_hint; +} #endif static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1; 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 @@ -693,7 +693,20 @@ @property def session(self): "Get / set SSLSession." -return None +return Session(self) + +@session.setter +def session(self, value): +if not isinstance(value, Session): +raise TypeError("Value is not a SSLSession.") +if self.ctx.ctx != value._ctx.ctx: +raise ValueError("Session refers to a different SSLContext.") +if self.socket_type != SSL_CLIENT: +raise ValueError("Cannot set session for server-side SSLSocket.") +if lib.SSL_is_init_finished(self.ssl): +raise ValueError("Cannot set session after handshake.") +if not lib.SSL_set_session(self.ssl, value._session): +raise pyssl_error(self, 0) @property def session_reused(self): @@ -727,6 +740,43 @@ return (cipher_name, cipher_protocol, bits) +class Session(object): +def __new__(cls, ssl): +self = object.__new__(cls) +session = lib.SSL_get1_session(ssl.ssl) +if not session: +return None +self._session = ffi.gc(session, lib.SSL_SESSION_free) +self._ctx = ssl.ctx +return self + +def __eq__(self, other): +if not isinstance(other, Session): +return NotImplemented; +return self.id == other.id + +@property +def id(self): +lenp = ffi.new("unsigned int*") +id = lib.SSL_SESSION_get_id(self._session, lenp) +return ffi.string(id, lenp[0]) + +@property +def time(self): +return lib.SSL_SESSION_get_time(self._session) + +@property +def timeout(self): +return lib.SSL_SESSION_get_timeout(self._session) + +@property +def has_ticket(self): +return bool(lib.SSL_SESSION_has_ticket(self._session)) + +@property +def ticket_lifetime_hint(self): +return lib.SSL_SESSION_get_ticket_lifetime_hint(self._session) + SSL_CTX_STATS_NAMES = """ number connect connect_good connect_renegotiate accept accept_good ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Apply the rest of CPython Issue 28043. This part is not well tested...
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94416:fc92860d2c30 Date: 2018-04-22 21:11 +0200 http://bitbucket.org/pypy/pypy/changeset/fc92860d2c30/ Log:Apply the rest of CPython Issue 28043. This part is not well tested... 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 @@ -833,13 +833,24 @@ options |= lib.SSL_OP_NO_SSLv3 # Minimal security flags for server and client side context. # Client sockets ignore server-side parameters. -options |= lib.SSL_OP_NO_COMPRESSION; -options |= lib.SSL_OP_CIPHER_SERVER_PREFERENCE; -options |= lib.SSL_OP_SINGLE_DH_USE; -options |= lib.SSL_OP_SINGLE_ECDH_USE; +options |= lib.SSL_OP_NO_COMPRESSION +options |= lib.SSL_OP_CIPHER_SERVER_PREFERENCE +options |= lib.SSL_OP_SINGLE_DH_USE +options |= lib.SSL_OP_SINGLE_ECDH_USE lib.SSL_CTX_set_options(self.ctx, options) lib.SSL_CTX_set_session_id_context(self.ctx, b"Python", len(b"Python")) +# A bare minimum cipher list without completely broken cipher suites. +# It's far from perfect but gives users a better head start. +if lib.Cryptography_HAS_SSL2 and protocol == PROTOCOL_SSLv2: +# SSLv2 needs MD5 +default_ciphers = b"HIGH:!aNULL:!eNULL" +else: +default_ciphers = b"HIGH:!aNULL:!eNULL:!MD5" +if not lib.SSL_CTX_set_cipher_list(ctx, default_ciphers): +lib.ERR_clear_error() +raise SSLError("No cipher can be selected.") + if HAS_ECDH: # Allow automatic ECDH curve selection (on # OpenSSL 1.0.2+), or use prime256v1 by default. ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Add support for PROTOCOL_TLS_CLIENT and PROTOCOL_TLS_SERVER
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94412:e82fec399c34 Date: 2018-04-22 19:37 +0200 http://bitbucket.org/pypy/pypy/changeset/e82fec399c34/ Log:Add support for PROTOCOL_TLS_CLIENT and PROTOCOL_TLS_SERVER (CPython Issue #28085) 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 @@ -83,6 +83,8 @@ PROTOCOL_TLSv1 = 3 PROTOCOL_TLSv1_1 = 4 PROTOCOL_TLSv1_2 = 5 +PROTOCOL_TLS_CLIENT = 0x10 +PROTOCOL_TLS_SERVER = 0x11 _PROTOCOL_NAMES = (name for name in dir(lib) if name.startswith('PROTOCOL_')) @@ -746,6 +748,10 @@ method = lib.SSLv2_method() elif protocol == PROTOCOL_SSLv23: method = lib.SSLv23_method() +elif protocol == PROTOCOL_TLS_CLIENT: +method = lib.SSLv23_client_method() +elif protocol == PROTOCOL_TLS_SERVER: +method = lib.SSLv23_server_method() else: raise ValueError("invalid protocol version") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Return a dummy .session to let more SSL tests pass.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r94413:2271eaab22b2 Date: 2018-04-22 19:42 +0200 http://bitbucket.org/pypy/pypy/changeset/2271eaab22b2/ Log:Return a dummy .session to let more SSL tests pass. 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 @@ -690,6 +690,16 @@ return None return _str_with_len(out[0], outlen[0]) +@property +def session(self): +"Get / set SSLSession." +return None + +@property +def session_reused(self): +"Was the client session reused during handshake?" +return bool(lib.SSL_session_reused(self.ssl)) + def _fs_decode(name): return name.decode(sys.getfilesystemencoding()) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: More checks for forbidden 'await'
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93956:e8e5e733ff62 Date: 2018-03-05 00:19 +0100 http://bitbucket.org/pypy/pypy/changeset/e8e5e733ff62/ Log:More checks for forbidden 'await' diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py --- a/pypy/interpreter/astcompiler/codegen.py +++ b/pypy/interpreter/astcompiler/codegen.py @@ -283,6 +283,10 @@ def _get_code_flags(self): return 0 +def _check_async_function(self): +"""Returns true if 'await' is allowed.""" +return False + def _handle_body(self, body): """Compile a list of statements, handling doc strings if needed.""" if body: @@ -1087,6 +1091,8 @@ self.emit_op(ops.YIELD_FROM) def visit_Await(self, aw): +if not self._check_async_function(): +self.error("'await' outside async function", aw) self.update_position(aw.lineno) aw.value.walkabout(self) self.emit_op(ops.GET_AWAITABLE) @@ -1752,6 +1758,9 @@ for i in range(start, len(func.body)): func.body[i].walkabout(self) +def _check_async_function(self): +return True + class LambdaCodeGenerator(AbstractFunctionCodeGenerator): def _compile(self, lam): @@ -1780,6 +1789,9 @@ def _end_comp(self): self.emit_op(ops.RETURN_VALUE) +def _check_async_function(self): +return True + class GenExpCodeGenerator(ComprehensionCodeGenerator): diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py --- a/pypy/interpreter/astcompiler/test/test_compiler.py +++ b/pypy/interpreter/astcompiler/test/test_compiler.py @@ -1163,6 +1163,14 @@ """ self.simple_test(source, "None", None) +def test_await_in_nested(self): +source = """if 1: +async def foo(): +def bar(): +[i for i in await items] +""" +e = py.test.raises(SyntaxError, self.simple_test, source, "None", None) + def test_load_classderef(self): source = """if 1: def f(): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Remember the __cause__ when an exception is raised in __await__.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93958:ab182b33a9c1 Date: 2018-03-05 09:26 +0100 http://bitbucket.org/pypy/pypy/changeset/ab182b33a9c1/ Log:Remember the __cause__ when an exception is raised in __await__. diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -1596,14 +1596,15 @@ try: w_awaitable = get_awaitable_iter(space, w_iter) except OperationError as e: -# yay! get_awaitable_iter() carefully builds a useful -# error message, but here we're eating *all errors* -# to replace it with a generic one. if e.async(space): raise -raise oefmt(space.w_TypeError, +new_error = oefmt(space.w_TypeError, "'async for' received an invalid object " "from __aiter__: %T", w_iter) +e.normalize_exception(space) +new_error.normalize_exception(space) +new_error.set_cause(space, e.get_w_value(space)) +raise new_error space.warn(space.newtext( "'%s' implements legacy __aiter__ protocol; " "__aiter__ should return an asynchronous " @@ -1628,14 +1629,15 @@ try: w_awaitable = get_awaitable_iter(space, w_next_iter) except OperationError as e: -# yay! get_awaitable_iter() carefully builds a useful -# error message, but here we're eating *all errors* -# to replace it with a generic one. if e.async(space): raise -raise oefmt(space.w_TypeError, +new_error = oefmt(space.w_TypeError, "'async for' received an invalid object " "from __anext__: %T", w_next_iter) +e.normalize_exception(space) +new_error.normalize_exception(space) +new_error.set_cause(space, e.get_w_value(space)) +raise new_error self.pushvalue(w_awaitable) def FORMAT_VALUE(self, oparg, next_instr): diff --git a/pypy/interpreter/test/test_coroutine.py b/pypy/interpreter/test/test_coroutine.py --- a/pypy/interpreter/test/test_coroutine.py +++ b/pypy/interpreter/test/test_coroutine.py @@ -75,6 +75,24 @@ assert next(cr.__await__()) == 20 """ +def test_for_error_cause(self): """ +class F: +def __aiter__(self): +return self +def __anext__(self): +return self +def __await__(self): +1 / 0 + +async def main(): +async for _ in F(): +pass + +c = raises(TypeError, main().send, None) +assert 'an invalid object from __anext__' in c.value.args[0], c.value +assert isinstance(c.value.__cause__, ZeroDivisionError) +""" + def test_set_coroutine_wrapper(self): """ import sys async def f(): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Using 'await' in other contexts raises a DeprecationWarning
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93957:3da474cc3b78 Date: 2018-03-05 09:04 +0100 http://bitbucket.org/pypy/pypy/changeset/3da474cc3b78/ Log:Using 'await' in other contexts raises a DeprecationWarning diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py --- a/pypy/interpreter/astcompiler/astbuilder.py +++ b/pypy/interpreter/astcompiler/astbuilder.py @@ -125,7 +125,7 @@ def check_forbidden_name(self, name, node): try: -misc.check_forbidden_name(name) +misc.check_forbidden_name(self.space, name) except misc.ForbiddenNameAssignment as e: self.error("cannot assign to %s" % (e.name,), node) @@ -135,7 +135,7 @@ def set_context(self, expr, ctx): """Set the context of an expression to Store or Del if possible.""" try: -expr.set_context(ctx) +expr.set_context(self.space, ctx) except ast.UnacceptableExpressionContext as e: self.error_ast(e.msg, e.node) except misc.ForbiddenNameAssignment as e: diff --git a/pypy/interpreter/astcompiler/asthelpers.py b/pypy/interpreter/astcompiler/asthelpers.py --- a/pypy/interpreter/astcompiler/asthelpers.py +++ b/pypy/interpreter/astcompiler/asthelpers.py @@ -15,7 +15,7 @@ def as_node_list(self, space): raise AssertionError("only for expressions") -def set_context(self, ctx): +def set_context(self, space, ctx): raise AssertionError("should only be on expressions") @@ -27,7 +27,7 @@ def as_node_list(self, space): return None -def set_context(self, ctx): +def set_context(self, space, ctx): d = self._description if d is None: d = "%r" % (self,) @@ -43,32 +43,32 @@ def as_node_list(self, space): return self.elts -def set_context(self, ctx): +def set_context(self, space, ctx): if self.elts: for elt in self.elts: -elt.set_context(ctx) +elt.set_context(space, ctx) self.ctx = ctx class __extend__(ast.Attribute): -def set_context(self, ctx): +def set_context(self, space, ctx): if ctx == ast.Store: -misc.check_forbidden_name(self.attr, self) +misc.check_forbidden_name(space, self.attr, self) self.ctx = ctx class __extend__(ast.Subscript): -def set_context(self, ctx): +def set_context(self, space, ctx): self.ctx = ctx class __extend__(ast.Name): -def set_context(self, ctx): +def set_context(self, space, ctx): if ctx == ast.Store: -misc.check_forbidden_name(self.id, self) +misc.check_forbidden_name(space, self.id, self) self.ctx = ctx @@ -79,14 +79,14 @@ def as_node_list(self, space): return self.elts -def set_context(self, ctx): +def set_context(self, space, ctx): if self.elts: for elt in self.elts: -elt.set_context(ctx) +elt.set_context(space, ctx) self.ctx = ctx else: # Assignment to () raises an error. -ast.expr.set_context(self, ctx) +ast.expr.set_context(self, space, ctx) class __extend__(ast.Lambda): @@ -141,9 +141,9 @@ _description = "starred expression" -def set_context(self, ctx): +def set_context(self, space, ctx): self.ctx = ctx -self.value.set_context(ctx) +self.value.set_context(space, ctx) class __extend__(ast.IfExp): diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py --- a/pypy/interpreter/astcompiler/misc.py +++ b/pypy/interpreter/astcompiler/misc.py @@ -68,10 +68,14 @@ self.node = node -def check_forbidden_name(name, node=None): +def check_forbidden_name(space, name, node=None): """Raise an error if the name cannot be assigned to.""" if name in ("None", "__debug__"): raise ForbiddenNameAssignment(name, node) +if name in ("async", "await"): +space.warn(space.newtext( +"'async' and 'await' will become reserved keywords" +" in Python 3.7"), space.w_DeprecationWarning) # XXX Warn about using True and False diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py --- a/pypy/interpreter/astcompiler/test/test_compiler.py +++ b/pypy/interpreter/astcompiler/test/test_compiler.py @@ -1300,6 +1300,14 @@ # compiling the produced AST previously triggered a crash compile(ast, '', 'exec') +def test_await_warning(self): +import warnings +source = "def f(): await = 5" +with warnings.catch_warnings(record=True) as l: +warnings.simplefilter("always") +compile(source, '', 'exec') +assert
[pypy-commit] pypy py3.6: Move coroutine tests to test_coroutine.py
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93955:df41ee03b376 Date: 2018-03-04 14:52 +0100 http://bitbucket.org/pypy/pypy/changeset/df41ee03b376/ Log:Move coroutine tests to test_coroutine.py diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py --- a/pypy/interpreter/astcompiler/test/test_compiler.py +++ b/pypy/interpreter/astcompiler/test/test_compiler.py @@ -1466,55 +1466,3 @@ return f'ab{x}cd' """ code, blocks = generate_function_code(source, self.space) - -class AppTestCoroutine: -def w_run_async(self, coro): -buffer = [] -result = None -while True: -try: -buffer.append(coro.send(None)) -except StopIteration as ex: -result = ex.args[0] if ex.args else None -break -return buffer, result - -def test_async_generator(self): -""" -async def f(i): -return i - -async def run_list(): -return [await c for c in [f(1), f(41)]] - -assert self.run_async(run_list()) == ([], [1, 41]) -""" - -def test_async_genexpr(self): -""" -async def f(it): -for i in it: -yield i - -async def run_gen(): -gen = (i + 1 async for i in f([10, 20])) -return [g + 100 async for g in gen] - -assert self.run_async(run_gen()) == ([], [111, 121]) -""" - -def test_anext_tuple(self): -""" -async def foo(): -try: -yield (1,) -except ZeroDivisionError: -yield (2,) - -async def run(): -it = foo().__aiter__() -return await it.__anext__() - -assert self.run_async(run()) == ([], (1,)) -""" - diff --git a/pypy/interpreter/test/test_coroutine.py b/pypy/interpreter/test/test_coroutine.py --- a/pypy/interpreter/test/test_coroutine.py +++ b/pypy/interpreter/test/test_coroutine.py @@ -499,3 +499,53 @@ else: assert False, "didn't raise" """ + +def w_run_async(self, coro): +buffer = [] +result = None +while True: +try: +buffer.append(coro.send(None)) +except StopIteration as ex: +result = ex.args[0] if ex.args else None +break +return buffer, result + +def test_async_generator(self): +""" +async def f(i): +return i + +async def run_list(): +return [await c for c in [f(1), f(41)]] + +assert self.run_async(run_list()) == ([], [1, 41]) +""" + +def test_async_genexpr(self): +""" +async def f(it): +for i in it: +yield i + +async def run_gen(): +gen = (i + 1 async for i in f([10, 20])) +return [g + 100 async for g in gen] + +assert self.run_async(run_gen()) == ([], [111, 121]) +""" + +def test_anext_tuple(self): +""" +async def foo(): +try: +yield (1,) +except ZeroDivisionError: +yield (2,) + +async def run(): +it = foo().__aiter__() +return await it.__anext__() + +assert self.run_async(run()) == ([], (1,)) +""" ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Legacy __aiter__ protocol now emits a DeprecationWarning.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93954:256b3eca58cb Date: 2018-03-04 10:05 +0100 http://bitbucket.org/pypy/pypy/changeset/256b3eca58cb/ Log:Legacy __aiter__ protocol now emits a DeprecationWarning. diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -1609,7 +1609,7 @@ "__aiter__ should return an asynchronous " "iterator, not awaitable" % space.type(w_obj).name), -space.w_PendingDeprecationWarning) +space.w_DeprecationWarning) self.pushvalue(w_awaitable) def GET_ANEXT(self, oparg, next_instr): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Some ast validation errors are shown as TypeError
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93945:4f89f769905c Date: 2018-03-03 17:07 +0100 http://bitbucket.org/pypy/pypy/changeset/4f89f769905c/ Log:Some ast validation errors are shown as TypeError diff --git a/pypy/interpreter/astcompiler/test/test_validate.py b/pypy/interpreter/astcompiler/test/test_validate.py --- a/pypy/interpreter/astcompiler/test/test_validate.py +++ b/pypy/interpreter/astcompiler/test/test_validate.py @@ -397,7 +397,8 @@ def test_constant(self): node = ast.Constant(self.space.newlist([1]), 0, 0) -self.expr(node, "got an invalid type in Constant: list") +self.expr(node, "got an invalid type in Constant: list", + exc=validate.ValidationTypeError) def test_stdlib_validates(self): stdlib = os.path.join(os.path.dirname(ast.__file__), '../../../lib-python/3') diff --git a/pypy/interpreter/astcompiler/validate.py b/pypy/interpreter/astcompiler/validate.py --- a/pypy/interpreter/astcompiler/validate.py +++ b/pypy/interpreter/astcompiler/validate.py @@ -11,12 +11,17 @@ class ValidationError(Exception): +# Will be seen as a ValueError def __init__(self, message): self.message = message def __str__(self): return self.message +class ValidationTypeError(ValidationError): +# Will be seen as a TypeError +pass + def expr_context_name(ctx): if not 1 <= ctx <= len(ast.expr_context_to_class): @@ -111,8 +116,8 @@ for w_item in space.unpackiterable(w_obj): validate_constant(space, w_item) return -raise ValidationError("got an invalid type in Constant: %s" % - space.type(w_obj).name) +raise ValidationTypeError("got an invalid type in Constant: %s" % + space.type(w_obj).name) class AstValidator(ast.ASTVisitor): diff --git a/pypy/interpreter/pycompiler.py b/pypy/interpreter/pycompiler.py --- a/pypy/interpreter/pycompiler.py +++ b/pypy/interpreter/pycompiler.py @@ -138,6 +138,9 @@ def validate_ast(self, node): try: validate.validate_ast(self.space, node) +except validate.ValidationTypeError as e: +raise OperationError(self.space.w_TypeError, + self.space.newtext(e.message)) except validate.ValidationError as e: raise OperationError(self.space.w_ValueError, self.space.newtext(e.message)) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: CPython Issue #26129: grp.getgrgid() sends a DeprecationWarning when passing non-integers
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93932:0ebac2fc9fb1 Date: 2018-02-26 01:13 +0100 http://bitbucket.org/pypy/pypy/changeset/0ebac2fc9fb1/ Log:CPython Issue #26129: grp.getgrgid() sends a DeprecationWarning when passing non-integers diff --git a/lib_pypy/grp.py b/lib_pypy/grp.py --- a/lib_pypy/grp.py +++ b/lib_pypy/grp.py @@ -33,7 +33,13 @@ @builtinify def getgrgid(gid): -res = lib.getgrgid(gid) +try: +res = lib.getgrgid(gid) +except TypeError: +gid = int(gid) +res = lib.getgrgid(gid) +import warnings +warnings.warn("group id must be int", DeprecationWarning) if not res: # XXX maybe check error eventually raise KeyError(gid) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: hg merge py3.5
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93931:eb5abc38e4b2 Date: 2018-02-25 23:09 +0100 http://bitbucket.org/pypy/pypy/changeset/eb5abc38e4b2/ Log:hg merge py3.5 diff too long, truncating to 2000 out of 5407 lines diff --git a/extra_tests/test_pyrepl/__init__.py b/extra_tests/test_pyrepl/__init__.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_pyrepl/__init__.py @@ -0,0 +1,1 @@ + diff --git a/extra_tests/test_pyrepl/infrastructure.py b/extra_tests/test_pyrepl/infrastructure.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_pyrepl/infrastructure.py @@ -0,0 +1,87 @@ +# Copyright 2000-2004 Michael Hudson-Doyle +# +#All Rights Reserved +# +# +# Permission to use, copy, modify, and distribute this software and +# its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appear in all copies and +# that both that copyright notice and this permission notice appear in +# supporting documentation. +# +# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO +# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, +# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import print_function +from contextlib import contextmanager +import os + +from pyrepl.reader import Reader +from pyrepl.console import Console, Event + + +class EqualsAnything(object): +def __eq__(self, other): +return True + + +EA = EqualsAnything() + + +class TestConsole(Console): +height = 24 +width = 80 +encoding = 'utf-8' + +def __init__(self, events, verbose=False): +self.events = events +self.next_screen = None +self.verbose = verbose + +def refresh(self, screen, xy): +if self.next_screen is not None: +assert screen == self.next_screen, "[ %s != %s after %r ]" % ( +screen, self.next_screen, self.last_event_name) + +def get_event(self, block=1): +ev, sc = self.events.pop(0) +self.next_screen = sc +if not isinstance(ev, tuple): +ev = (ev, None) +self.last_event_name = ev[0] +if self.verbose: +print("event", ev) +return Event(*ev) + + +class BaseTestReader(Reader): + +def get_prompt(self, lineno, cursor_on_line): +return '' + +def refresh(self): +Reader.refresh(self) +self.dirty = True + + +def read_spec(test_spec, reader_class=BaseTestReader): +# remember to finish your test_spec with 'accept' or similar! +con = TestConsole(test_spec, verbose=True) +reader = reader_class(con) +reader.readline() + + +@contextmanager +def sane_term(): +"""Ensure a TERM that supports clear""" +old_term, os.environ['TERM'] = os.environ.get('TERM'), 'xterm' +yield +if old_term is not None: +os.environ['TERM'] = old_term +else: +del os.environ['TERM'] diff --git a/extra_tests/test_pyrepl/test_basic.py b/extra_tests/test_pyrepl/test_basic.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_pyrepl/test_basic.py @@ -0,0 +1,116 @@ +# Copyright 2000-2004 Michael Hudson-Doyle +# +#All Rights Reserved +# +# +# Permission to use, copy, modify, and distribute this software and +# its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appear in all copies and +# that both that copyright notice and this permission notice appear in +# supporting documentation. +# +# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO +# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, +# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +import pytest +from .infrastructure import read_spec + + +def test_basic(): +read_spec([(('self-insert', 'a'), ['a']), + ( 'accept',['a'])]) + + +def test_repeat(): +read_spec([(('digit-arg', '3'), ['']), + (('self-insert', 'a'), ['aaa']), + ( 'accept',['aaa'])]) + + +def test_kill_line(): +read_spec([(('self-insert', 'abc'), ['abc']), + ( 'left',None), + ( 'kill-line', ['ab']), + ( 'accept', ['ab'])]) + + +def test_unix_line_discard(): +
[pypy-commit] pypy py3.6: CPython Issue #14711: os.stat_float_times() has been deprecated.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93933:1297ffb4dd1a Date: 2018-02-26 01:57 +0100 http://bitbucket.org/pypy/pypy/changeset/1297ffb4dd1a/ Log:CPython Issue #14711: os.stat_float_times() has been deprecated. diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -586,6 +586,8 @@ future calls return ints. If newval is omitted, return the current setting. """ +space.warn(space.newtext("stat_float_times() is deprecated"), + space.w_DeprecationWarning) state = space.fromcache(StatState) if newval == -1: diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -162,8 +162,12 @@ def test_stat_float_times(self): path = self.path posix = self.posix -current = posix.stat_float_times() -assert current is True +import warnings +with warnings.catch_warnings(record=True) as l: +warnings.simplefilter('always') +current = posix.stat_float_times() +assert current is True +assert "stat_float_times" in repr(l[0].message) try: posix.stat_float_times(True) st = posix.stat(path) @@ -180,6 +184,7 @@ finally: posix.stat_float_times(current) + def test_stat_result(self): st = self.posix.stat_result((0, 0, 0, 0, 0, 0, 0, 41, 42.1, 43)) assert st.st_atime == 41 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Restore necessary import
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93890:cf1579e0d8fa Date: 2018-02-25 22:16 +0100 http://bitbucket.org/pypy/pypy/changeset/cf1579e0d8fa/ Log:Restore necessary import diff --git a/lib-python/3/ctypes/test/test_parameters.py b/lib-python/3/ctypes/test/test_parameters.py --- a/lib-python/3/ctypes/test/test_parameters.py +++ b/lib-python/3/ctypes/test/test_parameters.py @@ -1,4 +1,4 @@ -import unittest +import unittest, sys from ctypes.test import need_symbol from ctypes.test import xfail ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Trigger gc collection after "del", to unblock the test.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93889:6379ab551ae1 Date: 2018-02-25 22:01 +0100 http://bitbucket.org/pypy/pypy/changeset/6379ab551ae1/ Log:Trigger gc collection after "del", to unblock the test. diff --git a/lib-python/3/test/test_concurrent_futures.py b/lib-python/3/test/test_concurrent_futures.py --- a/lib-python/3/test/test_concurrent_futures.py +++ b/lib-python/3/test/test_concurrent_futures.py @@ -161,6 +161,7 @@ executor.map(abs, range(-5, 5)) threads = executor._threads del executor +test.support.gc_collect() for t in threads: self.assertRegex(t.name, r'^SpecialPool_[0-4]$') @@ -171,6 +172,7 @@ executor.map(abs, range(-5, 5)) threads = executor._threads del executor +test.support.gc_collect() for t in threads: # We don't particularly care what the default name is, just that ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Add _blake2 to the build_cffi_imports script.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93887:6f93003631b8 Date: 2018-02-25 19:52 +0100 http://bitbucket.org/pypy/pypy/changeset/6f93003631b8/ Log:Add _blake2 to the build_cffi_imports script. diff --git a/lib_pypy/_blake2/_blake2_build.py b/lib_pypy/_blake2/_blake2_build.py --- a/lib_pypy/_blake2/_blake2_build.py +++ b/lib_pypy/_blake2/_blake2_build.py @@ -41,8 +41,8 @@ """ blake2b_source = """ -#include "blake2.h" -#include "blake2-impl.h" +#include "impl/blake2.h" +#include "impl/blake2-impl.h" #define BLAKE_OUTBYTES BLAKE2B_OUTBYTES #define BLAKE_SALTBYTES BLAKE2B_SALTBYTES @@ -63,7 +63,7 @@ """ -_libdir = os.path.join(os.path.dirname(__file__), 'impl') +_libdir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'impl')) blake2b_ffi = FFI() blake2b_ffi.cdef(blake_cdef) diff --git a/pypy/tool/build_cffi_imports.py b/pypy/tool/build_cffi_imports.py --- a/pypy/tool/build_cffi_imports.py +++ b/pypy/tool/build_cffi_imports.py @@ -18,7 +18,8 @@ "lzma": "_lzma_build.py", "_decimal": "_decimal_build.py", "_ssl": "_ssl_build.py", -# hashlib does not need to be built! It uses API calls from _ssl +"_blake2": "_blake2/_blake2_build.py", +"_sha3": "_sha3/_sha3_build.py", "xx": None,# for testing: 'None' should be completely ignored } ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Add Unicode database 9.0.0
Author: Amaury Forgeot d'ArcBranch: Changeset: r93629:912f3925af42 Date: 2018-01-04 17:44 +0100 http://bitbucket.org/pypy/pypy/changeset/912f3925af42/ Log:Add Unicode database 9.0.0 diff too long, truncating to 2000 out of 75520 lines diff --git a/rpython/rlib/unicodedata/CaseFolding-9.0.0.txt b/rpython/rlib/unicodedata/CaseFolding-9.0.0.txt new file mode 100644 --- /dev/null +++ b/rpython/rlib/unicodedata/CaseFolding-9.0.0.txt @@ -0,0 +1,1495 @@ +# CaseFolding-9.0.0.txt +# Date: 2016-03-02, 18:54:54 GMT +# 2016 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Case Folding Properties +# +# This file is a supplement to the UnicodeData file. +# It provides a case folding mapping generated from the Unicode Character Database. +# If all characters are mapped according to the full mapping below, then +# case differences (according to UnicodeData.txt and SpecialCasing.txt) +# are eliminated. +# +# The data supports both implementations that require simple case foldings +# (where string lengths don't change), and implementations that allow full case folding +# (where string lengths may grow). Note that where they can be supported, the +# full case foldings are superior: for example, they allow "MASSE" and "Mae" to match. +# +# All code points not listed in this file map to themselves. +# +# NOTE: case folding does not preserve normalization formats! +# +# For information on case folding, including how to have case folding +# preserve normalization formats, see Section 3.13 Default Case Algorithms in +# The Unicode Standard. +# +# +# Format +# +# The entries in this file are in the following machine-readable format: +# +# ; ; ; # +# +# The status field is: +# C: common case folding, common mappings shared by both simple and full mappings. +# F: full case folding, mappings that cause strings to grow in length. Multiple characters are separated by spaces. +# S: simple case folding, mappings to single characters where different from F. +# T: special case for uppercase I and dotted uppercase I +#- For non-Turkic languages, this mapping is normally not used. +#- For Turkic languages (tr, az), this mapping can be used instead of the normal mapping for these characters. +# Note that the Turkic mappings do not maintain canonical equivalence without additional processing. +# See the discussions of case mapping in the Unicode Standard for more information. +# +# Usage: +# A. To do a simple case folding, use the mappings with status C + S. +# B. To do a full case folding, use the mappings with status C + F. +# +#The mappings with status T can be used or omitted depending on the desired case-folding +#behavior. (The default option is to exclude them.) +# +# = + +# Property: Case_Folding + +# All code points not explicitly listed for Case_Folding +# have the value C for the status field, and the code point itself for the mapping field. + +# = +0041; C; 0061; # LATIN CAPITAL LETTER A +0042; C; 0062; # LATIN CAPITAL LETTER B +0043; C; 0063; # LATIN CAPITAL LETTER C +0044; C; 0064; # LATIN CAPITAL LETTER D +0045; C; 0065; # LATIN CAPITAL LETTER E +0046; C; 0066; # LATIN CAPITAL LETTER F +0047; C; 0067; # LATIN CAPITAL LETTER G +0048; C; 0068; # LATIN CAPITAL LETTER H +0049; C; 0069; # LATIN CAPITAL LETTER I +0049; T; 0131; # LATIN CAPITAL LETTER I +004A; C; 006A; # LATIN CAPITAL LETTER J +004B; C; 006B; # LATIN CAPITAL LETTER K +004C; C; 006C; # LATIN CAPITAL LETTER L +004D; C; 006D; # LATIN CAPITAL LETTER M +004E; C; 006E; # LATIN CAPITAL LETTER N +004F; C; 006F; # LATIN CAPITAL LETTER O +0050; C; 0070; # LATIN CAPITAL LETTER P +0051; C; 0071; # LATIN CAPITAL LETTER Q +0052; C; 0072; # LATIN CAPITAL LETTER R +0053; C; 0073; # LATIN CAPITAL LETTER S +0054; C; 0074; # LATIN CAPITAL LETTER T +0055; C; 0075; # LATIN CAPITAL LETTER U +0056; C; 0076; # LATIN CAPITAL LETTER V +0057; C; 0077; # LATIN CAPITAL LETTER W +0058; C; 0078; # LATIN CAPITAL LETTER X +0059; C; 0079; # LATIN CAPITAL LETTER Y +005A; C; 007A; # LATIN CAPITAL LETTER Z +00B5; C; 03BC; # MICRO SIGN +00C0; C; 00E0; # LATIN CAPITAL LETTER A WITH GRAVE +00C1; C; 00E1; # LATIN CAPITAL LETTER A WITH ACUTE +00C2; C; 00E2; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX +00C3; C; 00E3; # LATIN CAPITAL LETTER A WITH TILDE +00C4; C; 00E4; # LATIN CAPITAL LETTER A WITH DIAERESIS +00C5; C; 00E5; # LATIN CAPITAL LETTER A WITH RING ABOVE +00C6; C; 00E6; # LATIN CAPITAL LETTER AE +00C7; C;
[pypy-commit] pypy py3.6: Add Unicode database 9.0.0
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93626:4d728845e198 Date: 2018-01-04 17:44 +0100 http://bitbucket.org/pypy/pypy/changeset/4d728845e198/ Log:Add Unicode database 9.0.0 diff too long, truncating to 2000 out of 75520 lines diff --git a/rpython/rlib/unicodedata/CaseFolding-9.0.0.txt b/rpython/rlib/unicodedata/CaseFolding-9.0.0.txt new file mode 100644 --- /dev/null +++ b/rpython/rlib/unicodedata/CaseFolding-9.0.0.txt @@ -0,0 +1,1495 @@ +# CaseFolding-9.0.0.txt +# Date: 2016-03-02, 18:54:54 GMT +# 2016 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Case Folding Properties +# +# This file is a supplement to the UnicodeData file. +# It provides a case folding mapping generated from the Unicode Character Database. +# If all characters are mapped according to the full mapping below, then +# case differences (according to UnicodeData.txt and SpecialCasing.txt) +# are eliminated. +# +# The data supports both implementations that require simple case foldings +# (where string lengths don't change), and implementations that allow full case folding +# (where string lengths may grow). Note that where they can be supported, the +# full case foldings are superior: for example, they allow "MASSE" and "Mae" to match. +# +# All code points not listed in this file map to themselves. +# +# NOTE: case folding does not preserve normalization formats! +# +# For information on case folding, including how to have case folding +# preserve normalization formats, see Section 3.13 Default Case Algorithms in +# The Unicode Standard. +# +# +# Format +# +# The entries in this file are in the following machine-readable format: +# +# ; ; ; # +# +# The status field is: +# C: common case folding, common mappings shared by both simple and full mappings. +# F: full case folding, mappings that cause strings to grow in length. Multiple characters are separated by spaces. +# S: simple case folding, mappings to single characters where different from F. +# T: special case for uppercase I and dotted uppercase I +#- For non-Turkic languages, this mapping is normally not used. +#- For Turkic languages (tr, az), this mapping can be used instead of the normal mapping for these characters. +# Note that the Turkic mappings do not maintain canonical equivalence without additional processing. +# See the discussions of case mapping in the Unicode Standard for more information. +# +# Usage: +# A. To do a simple case folding, use the mappings with status C + S. +# B. To do a full case folding, use the mappings with status C + F. +# +#The mappings with status T can be used or omitted depending on the desired case-folding +#behavior. (The default option is to exclude them.) +# +# = + +# Property: Case_Folding + +# All code points not explicitly listed for Case_Folding +# have the value C for the status field, and the code point itself for the mapping field. + +# = +0041; C; 0061; # LATIN CAPITAL LETTER A +0042; C; 0062; # LATIN CAPITAL LETTER B +0043; C; 0063; # LATIN CAPITAL LETTER C +0044; C; 0064; # LATIN CAPITAL LETTER D +0045; C; 0065; # LATIN CAPITAL LETTER E +0046; C; 0066; # LATIN CAPITAL LETTER F +0047; C; 0067; # LATIN CAPITAL LETTER G +0048; C; 0068; # LATIN CAPITAL LETTER H +0049; C; 0069; # LATIN CAPITAL LETTER I +0049; T; 0131; # LATIN CAPITAL LETTER I +004A; C; 006A; # LATIN CAPITAL LETTER J +004B; C; 006B; # LATIN CAPITAL LETTER K +004C; C; 006C; # LATIN CAPITAL LETTER L +004D; C; 006D; # LATIN CAPITAL LETTER M +004E; C; 006E; # LATIN CAPITAL LETTER N +004F; C; 006F; # LATIN CAPITAL LETTER O +0050; C; 0070; # LATIN CAPITAL LETTER P +0051; C; 0071; # LATIN CAPITAL LETTER Q +0052; C; 0072; # LATIN CAPITAL LETTER R +0053; C; 0073; # LATIN CAPITAL LETTER S +0054; C; 0074; # LATIN CAPITAL LETTER T +0055; C; 0075; # LATIN CAPITAL LETTER U +0056; C; 0076; # LATIN CAPITAL LETTER V +0057; C; 0077; # LATIN CAPITAL LETTER W +0058; C; 0078; # LATIN CAPITAL LETTER X +0059; C; 0079; # LATIN CAPITAL LETTER Y +005A; C; 007A; # LATIN CAPITAL LETTER Z +00B5; C; 03BC; # MICRO SIGN +00C0; C; 00E0; # LATIN CAPITAL LETTER A WITH GRAVE +00C1; C; 00E1; # LATIN CAPITAL LETTER A WITH ACUTE +00C2; C; 00E2; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX +00C3; C; 00E3; # LATIN CAPITAL LETTER A WITH TILDE +00C4; C; 00E4; # LATIN CAPITAL LETTER A WITH DIAERESIS +00C5; C; 00E5; # LATIN CAPITAL LETTER A WITH RING ABOVE +00C6; C; 00E6; # LATIN CAPITAL LETTER AE
[pypy-commit] pypy py3.6: Upgrade pypy3.6 to UnicodeData 9.0.0
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93627:c06ae9f3ddac Date: 2018-01-04 17:58 +0100 http://bitbucket.org/pypy/pypy/changeset/c06ae9f3ddac/ Log:Upgrade pypy3.6 to UnicodeData 9.0.0 diff --git a/pypy/module/unicodedata/__init__.py b/pypy/module/unicodedata/__init__.py --- a/pypy/module/unicodedata/__init__.py +++ b/pypy/module/unicodedata/__init__.py @@ -15,7 +15,7 @@ interpleveldefs = { 'unidata_version' : 'space.wrap(interp_ucd.ucd.version)', 'ucd_3_2_0' : 'space.wrap(interp_ucd.ucd_3_2_0)', -'ucd_8_0_0' : 'space.wrap(interp_ucd.ucd_8_0_0)', +'ucd_9_0_0' : 'space.wrap(interp_ucd.ucd_9_0_0)', 'ucd' : 'space.wrap(interp_ucd.ucd)', '__doc__' : "space.wrap('unicode character database')", } diff --git a/pypy/module/unicodedata/interp_ucd.py b/pypy/module/unicodedata/interp_ucd.py --- a/pypy/module/unicodedata/interp_ucd.py +++ b/pypy/module/unicodedata/interp_ucd.py @@ -9,7 +9,7 @@ from rpython.rlib.rarithmetic import r_longlong from rpython.rlib.objectmodel import we_are_translated from rpython.rlib.runicode import MAXUNICODE -from rpython.rlib.unicodedata import unicodedb_8_0_0, unicodedb_3_2_0 +from rpython.rlib.unicodedata import unicodedb_9_0_0, unicodedb_3_2_0 from rpython.rlib.runicode import code_to_unichr, ord_accepts_surrogate import sys @@ -337,5 +337,5 @@ **methods) ucd_3_2_0 = UCD(unicodedb_3_2_0) -ucd_8_0_0 = UCD(unicodedb_8_0_0) -ucd = ucd_8_0_0 +ucd_9_0_0 = UCD(unicodedb_9_0_0) +ucd = ucd_9_0_0 diff --git a/pypy/module/unicodedata/test/test_unicodedata.py b/pypy/module/unicodedata/test/test_unicodedata.py --- a/pypy/module/unicodedata/test/test_unicodedata.py +++ b/pypy/module/unicodedata/test/test_unicodedata.py @@ -153,3 +153,9 @@ for cp in range(0xf, 0xf0300, 7): exc = raises(ValueError, unicodedata.name, chr(cp)) assert str(exc.value) == 'no such name' + +def test_east_asian_width_9_0_changes(self): +import unicodedata +assert unicodedata.ucd_3_2_0.east_asian_width('\u231a') == 'N' +assert unicodedata.ucd.east_asian_width('\u231a') == 'W' + ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Match CPython error message
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93624:cd17bd421135 Date: 2018-01-04 00:06 +0100 http://bitbucket.org/pypy/pypy/changeset/cd17bd421135/ Log:Match CPython error message diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py --- a/pypy/module/_io/interp_io.py +++ b/pypy/module/_io/interp_io.py @@ -78,9 +78,9 @@ if text and binary: raise oefmt(space.w_ValueError, "can't have text and binary mode at once") -if reading + writing + creating + appending > 1: +if creating + reading + writing + appending > 1: raise oefmt(space.w_ValueError, -"must have exactly one of read/write/create/append mode") +"must have exactly one of create/read/write/append mode") if binary and encoding is not None: raise oefmt(space.w_ValueError, "binary mode doesn't take an encoding argument") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: warnings.warn() now has a "source" argument.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93625:dbcd63982736 Date: 2018-01-04 09:15 +0100 http://bitbucket.org/pypy/pypy/changeset/dbcd63982736/ Log:warnings.warn() now has a "source" argument. In the future, ResourceWarnings might log the traceback where this object was allocated (when tracemalloc works on PyPy) In the mean time, this fixes the last failures in test_io. diff --git a/pypy/module/_warnings/interp_warnings.py b/pypy/module/_warnings/interp_warnings.py --- a/pypy/module/_warnings/interp_warnings.py +++ b/pypy/module/_warnings/interp_warnings.py @@ -276,12 +276,12 @@ break space.call_method(w_stderr, "write", space.newunicode(message)) -def do_warn(space, w_message, w_category, stacklevel): +def do_warn(space, w_message, w_category, stacklevel, w_source=None): context_w = setup_context(space, stacklevel) -do_warn_explicit(space, w_category, w_message, context_w) +do_warn_explicit(space, w_category, w_message, context_w, w_source=w_source) def do_warn_explicit(space, w_category, w_message, context_w, - w_sourceline=None): + w_sourceline=None, w_source=None): w_filename, lineno, w_module, w_registry = context_w # normalize module @@ -342,19 +342,32 @@ if warned: # Already warned for this module return -w_show_fxn = get_warnings_attr(space, "showwarning") -if w_show_fxn is None: + +w_show_fn = get_warnings_attr(space, "_showwarnmsg") +if w_show_fn is None: show_warning(space, w_filename, lineno, w_text, w_category, w_sourceline) -else: -space.call_function( -w_show_fxn, w_message, w_category, w_filename, w_lineno) +return + +if not space.is_true(space.callable(w_show_fn)): +raise oefmt(space.w_TypeError, +"warnings._showwarnmsg() must be set to a callable") +w_message_cls = get_warnings_attr(space, "WarningMessage") +if w_message_cls is None: +raise oefmt(space.w_RuntimeError, +"unable to get warnings.WarningMessage") +w_source = w_source or space.w_None +w_msg = space.call_function( +w_message_cls, w_message, w_category, +w_filename, w_lineno, space.w_None, space.w_None, w_source) +space.call_function(w_show_fn, w_msg) + @unwrap_spec(stacklevel=int) -def warn(space, w_message, w_category=None, stacklevel=1): +def warn(space, w_message, w_category=None, stacklevel=1, w_source=None): "Issue a warning, or maybe ignore it or raise an exception." w_category = get_category(space, w_message, w_category); -do_warn(space, w_message, w_category, stacklevel) +do_warn(space, w_message, w_category, stacklevel, w_source) def get_source_line(space, w_globals, lineno): @@ -394,14 +407,15 @@ w_registry = WrappedDefault(None), w_module_globals = WrappedDefault(None)) def warn_explicit(space, w_message, w_category, w_filename, lineno, - w_module=None, w_registry=None, w_module_globals=None): + w_module=None, w_registry=None, w_module_globals=None, + w_source=None): "Low-level inferface to warnings functionality." w_source_line = get_source_line(space, w_module_globals, lineno) do_warn_explicit(space, w_category, w_message, (w_filename, lineno, w_module, w_registry), - w_source_line) + w_source_line, w_source) def filters_mutated(space): space.fromcache(State).filters_mutated(space) diff --git a/pypy/module/_warnings/test/test_warnings.py b/pypy/module/_warnings/test/test_warnings.py --- a/pypy/module/_warnings/test/test_warnings.py +++ b/pypy/module/_warnings/test/test_warnings.py @@ -42,6 +42,13 @@ _warnings.warn_explicit("some message", Warning, "", 1, module_globals=globals()) +def test_with_source(self): +import warnings, _warnings +source = [] +with warnings.catch_warnings(record=True) as w: +_warnings.warn("some message", Warning, source=source) +assert w[0].source is source + def test_default_action(self): import warnings, _warnings warnings.defaultaction = 'ignore' ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Add math.tau
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93619:6190ca28a930 Date: 2017-12-25 19:08 +0100 http://bitbucket.org/pypy/pypy/changeset/6190ca28a930/ Log:Add math.tau diff --git a/pypy/module/math/__init__.py b/pypy/module/math/__init__.py --- a/pypy/module/math/__init__.py +++ b/pypy/module/math/__init__.py @@ -11,6 +11,7 @@ interpleveldefs = { 'e' : 'interp_math.get(space).w_e', 'pi' : 'interp_math.get(space).w_pi', + 'tau': 'interp_math.get(space).w_tau', 'inf': 'interp_math.get(space).w_inf', 'nan': 'interp_math.get(space).w_nan', 'pow': 'interp_math.pow', diff --git a/pypy/module/math/interp_math.py b/pypy/module/math/interp_math.py --- a/pypy/module/math/interp_math.py +++ b/pypy/module/math/interp_math.py @@ -10,6 +10,7 @@ def __init__(self, space): self.w_e = space.newfloat(math.e) self.w_pi = space.newfloat(math.pi) +self.w_tau = space.newfloat(math.pi * 2.0) self.w_inf = space.newfloat(rfloat.INFINITY) self.w_nan = space.newfloat(rfloat.NAN) def get(space): diff --git a/pypy/module/math/test/test_math.py b/pypy/module/math/test/test_math.py --- a/pypy/module/math/test/test_math.py +++ b/pypy/module/math/test/test_math.py @@ -380,3 +380,7 @@ assert math.isinf(math.inf) assert math.inf > -math.inf assert math.isnan(math.nan) + +def test_pi_tau(self): +import math +assert math.tau == math.pi * 2.0 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Add an option to allow underscores in integer literals. RPython part.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93621:23240e4a895f Date: 2018-01-03 22:51 +0100 http://bitbucket.org/pypy/pypy/changeset/23240e4a895f/ Log:Add an option to allow underscores in integer literals. RPython part. diff --git a/rpython/rlib/rarithmetic.py b/rpython/rlib/rarithmetic.py --- a/rpython/rlib/rarithmetic.py +++ b/rpython/rlib/rarithmetic.py @@ -845,7 +845,7 @@ # String parsing support # --- -def string_to_int(s, base=10): +def string_to_int(s, base=10, allow_underscores=False): """Utility to converts a string to an integer. If base is 0, the proper base is guessed based on the leading characters of 's'. Raises ParseStringError in case of error. @@ -854,7 +854,8 @@ from rpython.rlib.rstring import ( NumberStringParser, ParseStringOverflowError, strip_spaces) s = literal = strip_spaces(s) -p = NumberStringParser(s, literal, base, 'int') +p = NumberStringParser(s, literal, base, 'int', + allow_underscores=allow_underscores) base = p.base result = 0 while True: diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py --- a/rpython/rlib/rbigint.py +++ b/rpython/rlib/rbigint.py @@ -272,7 +272,7 @@ @staticmethod @jit.elidable -def fromstr(s, base=0): +def fromstr(s, base=0, allow_underscores=False): """As string_to_int(), but ignores an optional 'l' or 'L' suffix and returns an rbigint.""" from rpython.rlib.rstring import NumberStringParser, \ @@ -281,7 +281,8 @@ if (s.endswith('l') or s.endswith('L')) and base < 22: # in base 22 and above, 'L' is a valid digit! try: long('L',22) s = s[:-1] -parser = NumberStringParser(s, literal, base, 'long') +parser = NumberStringParser(s, literal, base, 'long', +allow_underscores=allow_underscores) return rbigint._from_numberstring_parser(parser) @staticmethod diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py --- a/rpython/rlib/rstring.py +++ b/rpython/rlib/rstring.py @@ -417,6 +417,9 @@ def __init__(self, msg): self.msg = msg +def __str__(self): +return self.msg + class InvalidBaseError(ParseStringError): """Signals an invalid base argument""" @@ -431,7 +434,7 @@ raise ParseStringError("invalid literal for %s() with base %d" % (self.fname, self.original_base)) -def __init__(self, s, literal, base, fname): +def __init__(self, s, literal, base, fname, allow_underscores=False): self.fname = fname sign = 1 if s.startswith('-'): @@ -441,6 +444,8 @@ s = strip_spaces(s[1:]) self.sign = sign self.original_base = base +self.allow_underscores = allow_underscores +self.last_is_underscore = False if base == 0: if s.startswith('0x') or s.startswith('0X'): @@ -480,13 +485,22 @@ digit = (digit - ord('A')) + 10 elif 'a' <= c <= 'z': digit = (digit - ord('a')) + 10 +elif c == '_' and self.allow_underscores: +if self.last_is_underscore: +self.error() +self.last_is_underscore = True +self.i += 1 +return self.next_digit() else: self.error() if digit >= self.base: self.error() self.i += 1 +self.last_is_underscore = False return digit else: +if self.last_is_underscore: +self.error() return -1 def prev_digit(self): diff --git a/rpython/rlib/test/test_rarithmetic.py b/rpython/rlib/test/test_rarithmetic.py --- a/rpython/rlib/test/test_rarithmetic.py +++ b/rpython/rlib/test/test_rarithmetic.py @@ -553,6 +553,51 @@ py.test.raises(ParseStringError, string_to_int, '+'+s, base) py.test.raises(ParseStringError, string_to_int, '-'+s, base) +def test_number_underscores(self): +VALID_UNDERSCORE_LITERALS = [ +'0_0_0', +'4_2', +'1__', +'0b1001_0100', +'0x_', +'0o5_7_7', +'0b_0', +'0x_f', +'0o_5', +] +INVALID_UNDERSCORE_LITERALS = [ +# Trailing underscores: +'0_', +'42_', +'1.4j_', +'0x_', +'0b1_', +'0xf_', +'0o5_', +# Underscores in the base selector: +'0_b0', +'0_xf', +'0_o5', +# Old-style octal, still disallowed: +'09_99', +# Multiple consecutive underscores: +'4___2', +'0b1001__0100', +'0x__',
[pypy-commit] pypy default: Add an option to allow underscores in integer literals. RPython part.
Author: Amaury Forgeot d'ArcBranch: Changeset: r93623:0d3c3f5e2bdb Date: 2018-01-03 22:51 +0100 http://bitbucket.org/pypy/pypy/changeset/0d3c3f5e2bdb/ Log:Add an option to allow underscores in integer literals. RPython part. diff --git a/rpython/rlib/rarithmetic.py b/rpython/rlib/rarithmetic.py --- a/rpython/rlib/rarithmetic.py +++ b/rpython/rlib/rarithmetic.py @@ -845,7 +845,7 @@ # String parsing support # --- -def string_to_int(s, base=10): +def string_to_int(s, base=10, allow_underscores=False): """Utility to converts a string to an integer. If base is 0, the proper base is guessed based on the leading characters of 's'. Raises ParseStringError in case of error. @@ -854,7 +854,8 @@ from rpython.rlib.rstring import ( NumberStringParser, ParseStringOverflowError, strip_spaces) s = literal = strip_spaces(s) -p = NumberStringParser(s, literal, base, 'int') +p = NumberStringParser(s, literal, base, 'int', + allow_underscores=allow_underscores) base = p.base result = 0 while True: diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py --- a/rpython/rlib/rbigint.py +++ b/rpython/rlib/rbigint.py @@ -272,7 +272,7 @@ @staticmethod @jit.elidable -def fromstr(s, base=0): +def fromstr(s, base=0, allow_underscores=False): """As string_to_int(), but ignores an optional 'l' or 'L' suffix and returns an rbigint.""" from rpython.rlib.rstring import NumberStringParser, \ @@ -281,7 +281,8 @@ if (s.endswith('l') or s.endswith('L')) and base < 22: # in base 22 and above, 'L' is a valid digit! try: long('L',22) s = s[:-1] -parser = NumberStringParser(s, literal, base, 'long') +parser = NumberStringParser(s, literal, base, 'long', +allow_underscores=allow_underscores) return rbigint._from_numberstring_parser(parser) @staticmethod diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py --- a/rpython/rlib/rstring.py +++ b/rpython/rlib/rstring.py @@ -417,6 +417,9 @@ def __init__(self, msg): self.msg = msg +def __str__(self): +return self.msg + class InvalidBaseError(ParseStringError): """Signals an invalid base argument""" @@ -431,7 +434,7 @@ raise ParseStringError("invalid literal for %s() with base %d" % (self.fname, self.original_base)) -def __init__(self, s, literal, base, fname): +def __init__(self, s, literal, base, fname, allow_underscores=False): self.fname = fname sign = 1 if s.startswith('-'): @@ -441,6 +444,8 @@ s = strip_spaces(s[1:]) self.sign = sign self.original_base = base +self.allow_underscores = allow_underscores +self.last_is_underscore = False if base == 0: if s.startswith('0x') or s.startswith('0X'): @@ -480,13 +485,22 @@ digit = (digit - ord('A')) + 10 elif 'a' <= c <= 'z': digit = (digit - ord('a')) + 10 +elif c == '_' and self.allow_underscores: +if self.last_is_underscore: +self.error() +self.last_is_underscore = True +self.i += 1 +return self.next_digit() else: self.error() if digit >= self.base: self.error() self.i += 1 +self.last_is_underscore = False return digit else: +if self.last_is_underscore: +self.error() return -1 def prev_digit(self): diff --git a/rpython/rlib/test/test_rarithmetic.py b/rpython/rlib/test/test_rarithmetic.py --- a/rpython/rlib/test/test_rarithmetic.py +++ b/rpython/rlib/test/test_rarithmetic.py @@ -553,6 +553,51 @@ py.test.raises(ParseStringError, string_to_int, '+'+s, base) py.test.raises(ParseStringError, string_to_int, '-'+s, base) +def test_number_underscores(self): +VALID_UNDERSCORE_LITERALS = [ +'0_0_0', +'4_2', +'1__', +'0b1001_0100', +'0x_', +'0o5_7_7', +'0b_0', +'0x_f', +'0o_5', +] +INVALID_UNDERSCORE_LITERALS = [ +# Trailing underscores: +'0_', +'42_', +'1.4j_', +'0x_', +'0b1_', +'0xf_', +'0o5_', +# Underscores in the base selector: +'0_b0', +'0_xf', +'0_o5', +# Old-style octal, still disallowed: +'09_99', +# Multiple consecutive underscores: +'4___2', +'0b1001__0100', +'0x__', +
[pypy-commit] pypy py3.6: Add BLAKE2 (blake2b and blake2s) to hashlib.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93617:f6a0b040703c Date: 2017-12-22 21:03 +0100 http://bitbucket.org/pypy/pypy/changeset/f6a0b040703c/ Log:Add BLAKE2 (blake2b and blake2s) to hashlib. diff too long, truncating to 2000 out of 3659 lines diff --git a/lib-python/3/hashlib.py b/lib-python/3/hashlib.py --- a/lib-python/3/hashlib.py +++ b/lib-python/3/hashlib.py @@ -56,9 +56,9 @@ # This tuple and __get_builtin_constructor() must be modified if a new # always available algorithm is added. __always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', + 'blake2b', 'blake2s', # FIXME the following algorithms were added in # cpython3.6 but are missing in pypy - # 'blake2b', 'blake2s', # 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', # 'shake_128', 'shake_256' ) diff --git a/lib_pypy/_blake2/__init__.py b/lib_pypy/_blake2/__init__.py new file mode 100644 --- /dev/null +++ b/lib_pypy/_blake2/__init__.py @@ -0,0 +1,151 @@ +import codecs + +def make_blake_hash(class_name, cffi_mod): +_ffi = cffi_mod.ffi +_lib = cffi_mod.lib + +class _blake: +SALT_SIZE = _lib.BLAKE_SALTBYTES +PERSON_SIZE = _lib.BLAKE_PERSONALBYTES +MAX_KEY_SIZE = _lib.BLAKE_KEYBYTES +MAX_DIGEST_SIZE = _lib.BLAKE_OUTBYTES + +def __new__(cls, string=None, *, digest_size=MAX_DIGEST_SIZE, +key=None, salt=None, person=None, fanout=1, depth=1, +leaf_size=None, node_offset=None, node_depth=0, +inner_size=0, last_node=False): +self = super().__new__(cls) + +self._param = _ffi.new("blake_param*") +self._state = _ffi.new("blake_state*") + +# Set digest size. +if not 1 <= digest_size <= self.MAX_DIGEST_SIZE: +raise ValueError( +"digest_size must be between 1 and %s bytes" % +self.MAX_DIGEST_SIZE) +self._param.digest_length = digest_size + +# Set salt parameter. +if salt is not None: +if len(salt) > self.SALT_SIZE: +raise ValueError( +"maximum salt length is %d bytes" % +self.SALT_SIZE) +_ffi.memmove(self._param.salt, salt, len(salt)) + +# Set personalization parameter. +if person: +if len(person) > _lib.BLAKE_PERSONALBYTES: +raise ValueError("maximum person length is %d bytes" % + _lib.BLAKE_PERSONALBYTES) +_ffi.memmove(self._param.personal, person, len(person)) + +# Set tree parameters. +if not 0 <= fanout <= 255: +raise ValueError("fanout must be between 0 and 255") +self._param.fanout = fanout + +if not 1 <= depth <= 255: +raise ValueError("depth must be between 1 and 255") +self._param.depth = depth + +if leaf_size is not None: +if leaf_size > 0x: +raise OverflowError("leaf_size is too large") +# NB: Simple assignment here would be incorrect on big +# endian platforms. +_lib.store32(_ffi.addressof(self._param, 'leaf_length'), + leaf_size) + +if node_offset is not None: +if class_name == 'blake2s': +if node_offset > 0x: +# maximum 2**48 - 1 +raise OverflowError("node_offset is too large") +_lib.store48(_lib.addressof_node_offset(self._param), + node_offset) +else: +# NB: Simple assignment here would be incorrect on big +# endian platforms. +_lib.store64(_lib.addressof_node_offset(self._param), + node_offset) + +if not 0 <= node_depth <= 255: +raise ValueError("node_depth must be between 0 and 255") +self._param.node_depth = node_depth + +if not 0 <= inner_size <= _lib.BLAKE_OUTBYTES: +raise ValueError("inner_size must be between 0 and is %d" % + _lib.BLAKE_OUTBYTES) +self._param.inner_length = inner_size + +# Set key length. +if key: +if len(key) > _lib.BLAKE_KEYBYTES: +raise ValueError("maximum key length is %d bytes" % + _lib.BLAKE_KEYBYTES) +self._param.key_length = len(key) + +# Initialize hash state. +if _lib.blake_init_param(self._state, self._param) < 0: +
[pypy-commit] pypy py3.6: Add sha3 (aka. Keccak) hashes to hashlib.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93618:88331f108204 Date: 2017-12-25 18:11 +0100 http://bitbucket.org/pypy/pypy/changeset/88331f108204/ Log:Add sha3 (aka. Keccak) hashes to hashlib. diff too long, truncating to 2000 out of 5634 lines diff --git a/lib-python/3/hashlib.py b/lib-python/3/hashlib.py --- a/lib-python/3/hashlib.py +++ b/lib-python/3/hashlib.py @@ -57,10 +57,8 @@ # always available algorithm is added. __always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'blake2b', 'blake2s', - # FIXME the following algorithms were added in - # cpython3.6 but are missing in pypy - # 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', - # 'shake_128', 'shake_256' + 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', + 'shake_128', 'shake_256' ) diff --git a/lib_pypy/_sha3/__init__.py b/lib_pypy/_sha3/__init__.py new file mode 100644 --- /dev/null +++ b/lib_pypy/_sha3/__init__.py @@ -0,0 +1,107 @@ +from ._sha3_cffi import ffi as _ffi, lib as _lib +import codecs + +SHA3_MAX_DIGESTSIZE = 64 # 64 Bytes (512 Bits) for 224 to 512 +SHA3_LANESIZE = (20 * 8) # ExtractLane needs max uint64_t[20] extra. + +class _sha3: +_keccak_init = None # Overridden in subclasses + +def __new__(cls, string=None): +self = super().__new__(cls) +self._hash_state = _ffi.new("Keccak_HashInstance*") + +cls._keccak_init(self._hash_state) + +if string: +self.update(string) +return self + +def update(self, string): +buf = _ffi.from_buffer(string) +res = _lib.Keccak_HashUpdate(self._hash_state, buf, len(buf) * 8) + +def digest(self): +digest = _ffi.new("char[]", + SHA3_MAX_DIGESTSIZE + SHA3_LANESIZE) +state_copy = _ffi.new("Keccak_HashInstance*") +_ffi.memmove(state_copy, self._hash_state, + _ffi.sizeof("Keccak_HashInstance")) +if _lib.Keccak_HashFinal(state_copy, digest) != _lib.SUCCESS: +raise RuntimeError("internal error in SHA3 Final()") +return _ffi.unpack(digest, self._hash_state.fixedOutputLength // 8) + +def hexdigest(self): +return codecs.encode(self.digest(), 'hex').decode() + +def copy(self): +copy = super().__new__(type(self)) +copy._hash_state = _ffi.new("Keccak_HashInstance*") +_ffi.memmove(copy._hash_state, self._hash_state, + _ffi.sizeof("Keccak_HashInstance")) +return copy + +@property +def digest_size(self): +return self._hash_state.fixedOutputLength // 8 + +@property +def block_size(self): +return self._hash_state.sponge.rate // 8 + +@property +def _capacity_bits(self): +return 1600 - self._hash_state.sponge.rate + +@property +def _rate_bits(self): +return self._hash_state.sponge.rate + +@property +def _suffix(self): +return bytes([self._hash_state.delimitedSuffix]) + + +class _shake(_sha3): +def digest(self, length): +# ExtractLane needs at least SHA3_MAX_DIGESTSIZE + SHA3_LANESIZE and +# SHA_LANESIZE extra space. +digest = _ffi.new("char[]", length + SHA3_LANESIZE) +# Get the raw (binary) digest value +state_copy = _ffi.new("Keccak_HashInstance*") +_ffi.memmove(state_copy, self._hash_state, + _ffi.sizeof("Keccak_HashInstance")) +if _lib.Keccak_HashFinal(state_copy, digest) != _lib.SUCCESS: +raise RuntimeError("internal error in SHA3 Final()") +if _lib.Keccak_HashSqueeze(state_copy, digest, length * 8) != _lib.SUCCESS: +raise RuntimeError("internal error in SHA3 Squeeze()") +return _ffi.unpack(digest, length) + +def hexdigest(self, length): +return codecs.encode(self.digest(length), 'hex').decode() + + +class sha3_224(_sha3): +name = "sha3_224" +_keccak_init = _lib.Keccak_HashInitialize_SHA3_224 + +class sha3_256(_sha3): +name = "sha3_256" +_keccak_init = _lib.Keccak_HashInitialize_SHA3_256 + +class sha3_384(_sha3): +name = "sha3_384" +_keccak_init = _lib.Keccak_HashInitialize_SHA3_384 + +class sha3_512(_sha3): +name = "sha3_512" +_keccak_init = _lib.Keccak_HashInitialize_SHA3_512 + +class shake_128(_shake): +name = "shake_128" +_keccak_init = _lib.Keccak_HashInitialize_SHAKE128 + +class shake_256(_shake): +name = "shake_256" +_keccak_init = _lib.Keccak_HashInitialize_SHAKE256 + diff --git a/lib_pypy/_sha3/_sha3_build.py b/lib_pypy/_sha3/_sha3_build.py new file mode 100644 --- /dev/null +++ b/lib_pypy/_sha3/_sha3_build.py @@ -0,0 +1,78 @@ +import os +import sys + +from cffi import FFI + + +ffi = FFI() +ffi.cdef(""" +typedef struct { +unsigned int rate; +...; +} KeccakWidth1600_SpongeInstance; +
[pypy-commit] pypy py3.6: Allow undescores in int() literals.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93622:ff9805f6a687 Date: 2018-01-03 22:51 +0100 http://bitbucket.org/pypy/pypy/changeset/ff9805f6a687/ Log:Allow undescores in int() literals. diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py --- a/pypy/objspace/std/intobject.py +++ b/pypy/objspace/std/intobject.py @@ -810,7 +810,7 @@ def _string_to_int_or_long(space, w_inttype, w_source, string, base=10): try: -value = string_to_int(string, base) +value = string_to_int(string, base, allow_underscores=True) except ParseStringError as e: raise wrap_parsestringerror(space, e, w_source) except ParseStringOverflowError as e: ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Attempt to parse numbers with underscores
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93620:c123301c02cc Date: 2018-01-03 12:17 +0100 http://bitbucket.org/pypy/pypy/changeset/c123301c02cc/ Log:Attempt to parse numbers with underscores diff --git a/pypy/interpreter/pyparser/dfa_generated.py b/pypy/interpreter/pyparser/dfa_generated.py --- a/pypy/interpreter/pyparser/dfa_generated.py +++ b/pypy/interpreter/pyparser/dfa_generated.py @@ -7,10 +7,14 @@ accepts = [True, True, True, True, True, True, True, True, True, True, True, False, True, True, True, True, True, False, False, False, True, False, False, - False, True, False, True, False, True, False, False, True, False, False, True, False, False, - True, True, True, False, False, True, False, - False, False, True] + True, False, False, True, False, False, True, + False, False, True, False, True, False, True, + False, True, False, False, False, False, True, + True, False, False, False, False, True, False, + True, False, True, False, True, False, True, True, + False, True, False, True, False, False, True, + True, True, True, True] states = [ # 0 {'\t': 0, '\n': 15, '\x0c': 0, @@ -110,21 +114,21 @@ 'v': 1, 'w': 1, 'x': 1, 'y': 1, 'z': 1, '\x80': 1}, # 5 -{'.': 26, '0': 24, '1': 25, '2': 25, - '3': 25, '4': 25, '5': 25, '6': 25, - '7': 25, '8': 25, '9': 25, 'B': 23, - 'E': 27, 'J': 15, 'O': 22, 'X': 21, - 'b': 23, 'e': 27, 'j': 15, 'o': 22, - 'x': 21}, +{'.': 27, '0': 24, '1': 26, '2': 26, + '3': 26, '4': 26, '5': 26, '6': 26, + '7': 26, '8': 26, '9': 26, 'B': 23, + 'E': 28, 'J': 15, 'O': 22, 'X': 21, + '_': 25, 'b': 23, 'e': 28, 'j': 15, + 'o': 22, 'x': 21}, # 6 -{'.': 26, '0': 6, '1': 6, '2': 6, +{'.': 27, '0': 6, '1': 6, '2': 6, '3': 6, '4': 6, '5': 6, '6': 6, - '7': 6, '8': 6, '9': 6, 'E': 27, - 'J': 15, 'e': 27, 'j': 15}, + '7': 6, '8': 6, '9': 6, 'E': 28, + 'J': 15, '_': 29, 'e': 28, 'j': 15}, # 7 -{'.': 29, '0': 28, '1': 28, '2': 28, - '3': 28, '4': 28, '5': 28, '6': 28, - '7': 28, '8': 28, '9': 28}, +{'.': 31, '0': 30, '1': 30, '2': 30, + '3': 30, '4': 30, '5': 30, '6': 30, + '7': 30, '8': 30, '9': 30}, # 8 {'*': 14, '=': 15}, # 9 @@ -144,107 +148,240 @@ # 16 {'\n': 15}, # 17 -{automata.DEFAULT: 33, '\n': 30, - '\r': 30, "'": 31, '\\': 32}, +{automata.DEFAULT: 35, '\n': 32, + '\r': 32, "'": 33, '\\': 34}, # 18 -{automata.DEFAULT: 36, '\n': 30, - '\r': 30, '"': 34, '\\': 35}, +{automata.DEFAULT: 38, '\n': 32, + '\r': 32, '"': 36, '\\': 37}, # 19 {'\n': 15, '\r': 16}, # 20 -{automata.DEFAULT: 20, '\n': 30, '\r': 30}, +{automata.DEFAULT: 20, '\n': 32, '\r': 32}, # 21 -{'0': 37, '1': 37, '2': 37, '3': 37, - '4': 37, '5': 37, '6': 37, '7': 37, - '8': 37, '9': 37, 'A': 37, 'B': 37, - 'C': 37, 'D': 37, 'E': 37, 'F': 37, - 'a': 37, 'b': 37, 'c': 37, 'd': 37, - 'e': 37, 'f': 37}, +{'0': 39, '1': 39, '2': 39, '3': 39, + '4': 39, '5': 39, '6': 39, '7': 39, + '8': 39, '9': 39, 'A': 39, 'B': 39, + 'C': 39, 'D': 39, 'E': 39, 'F': 39, + '_': 40, 'a': 39, 'b': 39, 'c': 39, + 'd': 39, 'e': 39, 'f': 39}, # 22 -{'0': 38, '1': 38, '2': 38, '3': 38, - '4': 38, '5': 38, '6': 38, '7': 38}, +{'0': 41, '1': 41, '2': 41, '3': 41, + '4': 41, '5': 41, '6': 41, '7': 41, + '_': 42}, # 23 -{'0': 39, '1': 39}, +{'0': 43, '1': 43, '_': 44}, # 24 -{'.': 26, '0': 24, '1': 25, '2': 25, - '3': 25, '4': 25, '5': 25, '6': 25, - '7': 25, '8': 25, '9': 25, 'E': 27, - 'J': 15, 'e': 27, 'j': 15}, +{'.': 27, '0': 24, '1': 26, '2': 26, + '3': 26, '4': 26, '5': 26, '6': 26, + '7': 26, '8': 26, '9': 26, 'E': 28, + 'J': 15, '_': 25, 'e': 28, 'j': 15}, # 25 -{'.': 26, '0': 25, '1': 25, '2': 25, - '3': 25, '4': 25, '5': 25, '6': 25, - '7': 25, '8': 25, '9': 25, 'E': 27, - 'J': 15, 'e': 27, 'j': 15}, +{'0': 45, '1': 46, '2': 46, '3': 46, + '4': 46, '5': 46, '6': 46, '7': 46, + '8': 46, '9': 46}, # 26 -{'0': 26, '1': 26, '2': 26, '3': 26, - '4': 26, '5': 26, '6': 26, '7': 26, - '8': 26, '9': 26, 'E': 40, 'J': 15, - 'e': 40, 'j': 15}, +{'.': 27, '0': 26, '1': 26, '2': 26, + '3': 26, '4': 26, '5': 26, '6': 26, + '7': 26, '8': 26, '9': 26, 'E': 28, + 'J': 15, '_': 47, 'e': 28, 'j': 15}, # 27 -{'+': 41, '-': 41, '0': 42, '1': 42, - '2': 42, '3': 42, '4': 42, '5': 42, - '6': 42, '7': 42, '8': 42, '9': 42}, +{'0': 27, '1': 27, '2': 27, '3': 27, + '4': 27, '5': 27, '6': 27, '7': 27, + '8': 27, '9': 27, 'E': 48, 'J': 15, + 'e': 48, 'j': 15}, # 28 -{'0': 28, '1': 28, '2': 28, '3': 28, - '4': 28, '5': 28, '6': 28, '7':
[pypy-commit] pypy default: parser.sequence2st: add validation of the passed tuple.
Author: Amaury Forgeot d'ArcBranch: Changeset: r93616:749063799a58 Date: 2018-01-02 00:53 +0100 http://bitbucket.org/pypy/pypy/changeset/749063799a58/ Log:parser.sequence2st: add validation of the passed tuple. Do it the 2016 way, by walking the grammar DFA, instead of a ton of custom validation code. diff --git a/pypy/module/parser/pyparser.py b/pypy/module/parser/pyparser.py --- a/pypy/module/parser/pyparser.py +++ b/pypy/module/parser/pyparser.py @@ -124,9 +124,13 @@ return space.call_args(space.getattr(w_st, space.newtext("compile")), __args__) -def raise_parser_error(space, w_tuple, message): +def parser_error(space, w_tuple, message): raise OperationError(get_error(space), space.newtuple( -[w_tuple, space.newtext("Illegal component tuple.")])) +[w_tuple, space.newtext(message)])) + +def parse_error(space, message): +return OperationError(get_error(space), + space.newtext(message)) def get_node_type(space, w_tuple): @@ -134,7 +138,7 @@ w_type = space.getitem(w_tuple, space.newint(0)) return space.int_w(w_type) except OperationError: -raise_parser_error(space, w_tuple, "Illegal component tuple.") +raise parser_error(space, w_tuple, "Illegal component tuple.") class NodeState: def __init__(self): @@ -146,7 +150,7 @@ if 0 <= type < 256: # The tuple is simple, but it doesn't start with a start symbol. # Raise an exception now and be done with it. -raise_parser_error(space, w_tuple, +raise parser_error(space, w_tuple, "Illegal syntax-tree; cannot start with terminal symbol.") node = pyparse.parser.Nonterminal(type, []) build_node_children(space, w_tuple, node, node_state) @@ -162,7 +166,8 @@ elif length == 3: _, w_obj, w_lineno = space.unpackiterable(w_elem, 3) else: -raise_error(space, "terminal nodes must have 2 or 3 entries") +raise parse_error( +space, "terminal nodes must have 2 or 3 entries") strn = space.text_w(w_obj) child = pyparse.parser.Terminal(type, strn, node_state.lineno, 0) else: @@ -174,7 +179,36 @@ node_state.lineno += 1 +def validate_node(space, tree): +assert tree.type >= 256 +type = tree.type - 256 +parser = pyparse.PythonParser(space) +if type >= len(parser.grammar.dfas): +raise parse_error(space, "Unrecognized node type %d." % type) +dfa = parser.grammar.dfas[type] +# Run the DFA for this nonterminal +states, first = dfa +arcs, is_accepting = states[0] +for pos in range(tree.num_children()): +ch = tree.get_child(pos) +for i, next_state in arcs: +label = parser.grammar.labels[i] +if label == ch.type: +# The child is acceptable; validate it recursively +if ch.type >= 256: +validate_node(space, ch) +# Update the state, and move on to the next child. +arcs, is_accepting = states[next_state] +break +else: +raise parse_error(space, "Illegal node") +if not is_accepting: +raise parse_error(space, "Illegal number of children for %d node" % + tree.type) + + def tuple2st(space, w_sequence): # Convert the tree to the internal form before checking it tree = build_node_tree(space, w_sequence) +validate_node(space, tree) return W_STType(tree, 'eval') diff --git a/pypy/module/parser/test/test_parser.py b/pypy/module/parser/test/test_parser.py --- a/pypy/module/parser/test/test_parser.py +++ b/pypy/module/parser/test/test_parser.py @@ -71,3 +71,19 @@ check_expr("foo(1)") check_suite("def f(): yield 1") + +def test_bad_tree(self): +import parser +# from import a +tree = \ +(257, + (267, + (268, + (269, +(281, + (283, (1, 'from'), (1, 'import'), + (286, (284, (1, 'fred')), + (4, ''))), + (4, ''), (0, '')) +raises(parser.ParserError, + parser.sequence2st, tree) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: First stab at parser.tuple2st()
Author: Amaury Forgeot d'ArcBranch: Changeset: r93615:28aa6e61df25 Date: 2017-12-28 22:49 +0100 http://bitbucket.org/pypy/pypy/changeset/28aa6e61df25/ Log:First stab at parser.tuple2st() diff --git a/pypy/module/parser/__init__.py b/pypy/module/parser/__init__.py --- a/pypy/module/parser/__init__.py +++ b/pypy/module/parser/__init__.py @@ -24,5 +24,7 @@ 'ASTType' : 'pyparser.W_STType', 'compilest': 'pyparser.compilest', 'compileast' : 'pyparser.compilest', -'ParserError' : 'space.new_exception_class("parser.ParserError")', +'tuple2st' : 'pyparser.tuple2st', +'sequence2st' : 'pyparser.tuple2st', +'ParserError' : 'pyparser.get_error(space)', } diff --git a/pypy/module/parser/pyparser.py b/pypy/module/parser/pyparser.py --- a/pypy/module/parser/pyparser.py +++ b/pypy/module/parser/pyparser.py @@ -8,6 +8,14 @@ from rpython.rlib.objectmodel import specialize +class Cache: +def __init__(self, space): +self.error = space.new_exception_class("parser.ParserError") + +def get_error(space): +return space.fromcache(Cache).error + + class W_STType(W_Root): def __init__(self, tree, mode): self.tree = tree @@ -114,3 +122,59 @@ @unwrap_spec(w_st=W_STType) def compilest(space, w_st, __args__): return space.call_args(space.getattr(w_st, space.newtext("compile")), __args__) + + +def raise_parser_error(space, w_tuple, message): +raise OperationError(get_error(space), space.newtuple( +[w_tuple, space.newtext("Illegal component tuple.")])) + + +def get_node_type(space, w_tuple): +try: +w_type = space.getitem(w_tuple, space.newint(0)) +return space.int_w(w_type) +except OperationError: +raise_parser_error(space, w_tuple, "Illegal component tuple.") + +class NodeState: +def __init__(self): +self.lineno = 0 + +def build_node_tree(space, w_tuple): +type = get_node_type(space, w_tuple) +node_state = NodeState() +if 0 <= type < 256: +# The tuple is simple, but it doesn't start with a start symbol. +# Raise an exception now and be done with it. +raise_parser_error(space, w_tuple, + "Illegal syntax-tree; cannot start with terminal symbol.") +node = pyparse.parser.Nonterminal(type, []) +build_node_children(space, w_tuple, node, node_state) +return node + +def build_node_children(space, w_tuple, node, node_state): +for w_elem in space.unpackiterable(w_tuple)[1:]: +type = get_node_type(space, w_elem) +if type < 256: # Terminal node +length = space.len_w(w_elem) +if length == 2: +_, w_obj = space.unpackiterable(w_elem, 2) +elif length == 3: +_, w_obj, w_lineno = space.unpackiterable(w_elem, 3) +else: +raise_error(space, "terminal nodes must have 2 or 3 entries") +strn = space.text_w(w_obj) +child = pyparse.parser.Terminal(type, strn, node_state.lineno, 0) +else: +child = pyparse.parser.Nonterminal(type, []) +node.append_child(child) +if type >= 256: # Nonterminal node +build_node_children(space, w_elem, child, node_state) +elif type == pyparse.pygram.tokens.NEWLINE: +node_state.lineno += 1 + + +def tuple2st(space, w_sequence): +# Convert the tree to the internal form before checking it +tree = build_node_tree(space, w_sequence) +return W_STType(tree, 'eval') diff --git a/pypy/module/parser/test/test_parser.py b/pypy/module/parser/test/test_parser.py --- a/pypy/module/parser/test/test_parser.py +++ b/pypy/module/parser/test/test_parser.py @@ -56,3 +56,18 @@ def test_error(self): assert repr(self.m.ParserError) == "" + +def test_roundtrip(self): +def roundtrip(f, s): +st1 = f(s) +t = st1.totuple() +st2 = self.m.sequence2st(t) +assert t == st2.totuple() + +def check_expr(s): +roundtrip(self.m.expr, s) +def check_suite(s): +roundtrip(self.m.suite, s) + +check_expr("foo(1)") +check_suite("def f(): yield 1") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: re.Match.group() now accepts index-like objects.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93459:5e9a2c6daf17 Date: 2017-12-17 19:19 +0100 http://bitbucket.org/pypy/pypy/changeset/5e9a2c6daf17/ Log:re.Match.group() now accepts index-like objects. diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py --- a/pypy/module/_sre/interp_sre.py +++ b/pypy/module/_sre/interp_sre.py @@ -604,7 +604,7 @@ def do_span(self, w_arg): space = self.space try: -groupnum = space.int_w(w_arg) +groupnum = space.getindex_w(w_arg, space.w_OverflowError) except OperationError as e: if not e.match(space, space.w_TypeError) and \ not e.match(space, space.w_OverflowError): diff --git a/pypy/module/_sre/test/test_app_sre.py b/pypy/module/_sre/test/test_app_sre.py --- a/pypy/module/_sre/test/test_app_sre.py +++ b/pypy/module/_sre/test/test_app_sre.py @@ -227,6 +227,15 @@ exc = raises(IndexError, re.match("", "").group, sys.maxsize + 1) assert str(exc.value) == "no such group" +def test_group_takes_index(self): +import re +class Index: +def __init__(self, value): +self.value = value +def __index__(self): +return self.value +assert re.match("(foo)", "foo").group(Index(1)) == "foo" + def test_expand(self): import re m = re.search("a(..)(?P..)", "ab1bc") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: CPython Issue #16864: Cursor.lastrowid now supports REPLACE statement
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93457:b9413da29d91 Date: 2017-12-14 22:52 +0100 http://bitbucket.org/pypy/pypy/changeset/b9413da29d91/ Log:CPython Issue #16864: Cursor.lastrowid now supports REPLACE statement diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -930,7 +930,9 @@ self.__rowcount = 0 self.__rowcount += _lib.sqlite3_changes(self.__connection._db) -if not multiple and self.__statement._type == _STMT_TYPE_INSERT: +if not multiple and self.__statement._type in ( +# REPLACE is an alias for INSERT OR REPLACE +_STMT_TYPE_INSERT, _STMT_TYPE_REPLACE): self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db) else: self.__lastrowid = None ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: CPython Issue #28727: re.Pattern objects created by re.compile() become comparable
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93461:77d216c5b248 Date: 2017-12-17 22:03 +0100 http://bitbucket.org/pypy/pypy/changeset/77d216c5b248/ Log:CPython Issue #28727: re.Pattern objects created by re.compile() become comparable (only x==y and x!=y operators) diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py --- a/pypy/module/_sre/interp_sre.py +++ b/pypy/module/_sre/interp_sre.py @@ -5,6 +5,7 @@ from pypy.interpreter.typedef import make_weakref_descr from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault from pypy.interpreter.error import OperationError, oefmt +from rpython.rlib.objectmodel import compute_hash from rpython.rlib.rarithmetic import intmask from rpython.rlib import jit from rpython.rlib.rstring import StringBuilder, UnicodeBuilder @@ -133,6 +134,24 @@ uflags = u'|'.join([item.decode('latin-1') for item in flag_items]) return space.newunicode(u're.compile(%s%s%s)' % (u, usep, uflags)) +def descr_eq(self, space, w_other): +if not isinstance(w_other, W_SRE_Pattern): +return space.w_NotImplemented +other = w_other +# Compare the code and the pattern because the same pattern can +# produce different codes depending on the locale used to compile the +# pattern when the re.LOCALE flag is used. Don't compare groups, +# indexgroup nor groupindex: they are derivated from the pattern. +return space.newbool( +self.flags == other.flags and +self.code == other.code and +space.eq_w(self.w_pattern, other.w_pattern)) + +def descr_hash(self, space): +code = ''.join([chr(c) for c in self.code]) +return space.newint(compute_hash( +(self.flags, code, space.hash_w(self.w_pattern + def fget_groupindex(self, space): w_groupindex = self.w_groupindex if space.isinstance_w(w_groupindex, space.w_dict): @@ -488,6 +507,8 @@ __deepcopy__ = interp2app(W_SRE_Pattern.cannot_copy_w), __repr__ = interp2app(W_SRE_Pattern.repr_w), __weakref__ = make_weakref_descr(W_SRE_Pattern), +__eq__ = interp2app(W_SRE_Pattern.descr_eq), +__hash__ = interp2app(W_SRE_Pattern.descr_hash), findall = interp2app(W_SRE_Pattern.findall_w), finditer = interp2app(W_SRE_Pattern.finditer_w), match= interp2app(W_SRE_Pattern.match_w), diff --git a/pypy/module/_sre/test/test_app_sre.py b/pypy/module/_sre/test/test_app_sre.py --- a/pypy/module/_sre/test/test_app_sre.py +++ b/pypy/module/_sre/test/test_app_sre.py @@ -133,6 +133,33 @@ assert repr(r) == ( r"""re.compile('f(o"\\d)', re.IGNORECASE|re.DOTALL|re.VERBOSE)""") +def test_pattern_compare(self): +import re +pattern1 = re.compile('abc', re.IGNORECASE) + +# equal to itself +assert pattern1 == pattern1 +assert not(pattern1 != pattern1) +# equal +re.purge() +pattern2 = re.compile('abc', re.IGNORECASE) +assert hash(pattern2) == hash(pattern1) +assert pattern2 == pattern1 + +# not equal: different pattern +re.purge() +pattern3 = re.compile('XYZ', re.IGNORECASE) +# warranty that hash values are different +assert pattern3 != pattern1 + +# not equal: different flag (flags=0) +re.purge() +pattern4 = re.compile('abc') +assert pattern4 != pattern1 + +# only == and != comparison operators are supported +raises(TypeError, "pattern1 < pattern2") + class AppTestSreMatch: spaceconfig = dict(usemodules=('array', )) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: CPython Issue #29444: Add array bound check in group(), because the underlying
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93458:dda99c39353f Date: 2017-12-17 18:57 +0100 http://bitbucket.org/pypy/pypy/changeset/dda99c39353f/ Log:CPython Issue #29444: Add array bound check in group(), because the underlying buffer is mutable. Difficult to test in non-translated code... diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py --- a/pypy/module/_sre/interp_sre.py +++ b/pypy/module/_sre/interp_sre.py @@ -36,6 +36,9 @@ def slice_w(space, ctx, start, end, w_default): if 0 <= start <= end: if isinstance(ctx, rsre_core.BufMatchContext): +length = ctx._buffer.getlength() +start = min(start, length) +end = min(end, length) return space.newbytes(ctx._buffer.getslice(start, end, 1, end-start)) if isinstance(ctx, rsre_core.StrMatchContext): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: CPython Issue #24454: Regular expression match object groups are now
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93460:0e57c6df8538 Date: 2017-12-17 19:34 +0100 http://bitbucket.org/pypy/pypy/changeset/0e57c6df8538/ Log:CPython Issue #24454: Regular expression match object groups are now accessible using __getitem__. "mo[x]" is equivalent to "mo.group(x)". diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py --- a/pypy/module/_sre/interp_sre.py +++ b/pypy/module/_sre/interp_sre.py @@ -533,6 +533,10 @@ space = self.space raise oefmt(space.w_TypeError, "cannot copy this match object") +def descr_getitem(self, space, w_index): +start, end = self.do_span(w_index) +return slice_w(space, self.ctx, start, end, space.w_None) + @jit.look_inside_iff(lambda self, args_w: jit.isconstant(len(args_w))) def group_w(self, args_w): space = self.space @@ -684,6 +688,8 @@ __copy__ = interp2app(W_SRE_Match.cannot_copy_w), __deepcopy__ = interp2app(W_SRE_Match.cannot_copy_w), __repr__ = interp2app(W_SRE_Match.repr_w), +__getitem__ = interp2app(W_SRE_Match.descr_getitem), +# group= interp2app(W_SRE_Match.group_w), groups = interp2app(W_SRE_Match.groups_w), groupdict= interp2app(W_SRE_Match.groupdict_w), diff --git a/pypy/module/_sre/test/test_app_sre.py b/pypy/module/_sre/test/test_app_sre.py --- a/pypy/module/_sre/test/test_app_sre.py +++ b/pypy/module/_sre/test/test_app_sre.py @@ -236,6 +236,10 @@ return self.value assert re.match("(foo)", "foo").group(Index(1)) == "foo" +def test_getitem(self): +import re +assert re.match("(foo)bar", "foobar")[1] == "foo" + def test_expand(self): import re m = re.search("a(..)(?P..)", "ab1bc") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: CPython Issue #25971: Unify error messages in float.as_integer_ratio(), Decimal.as_integer_ratio(), and Fraction constructors.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93455:bea2e807c6dc Date: 2017-12-14 00:05 +0100 http://bitbucket.org/pypy/pypy/changeset/bea2e807c6dc/ Log:CPython Issue #25971: Unify error messages in float.as_integer_ratio(), Decimal.as_integer_ratio(), and Fraction constructors. diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -620,10 +620,10 @@ num, den = float_as_rbigint_ratio(value) except OverflowError: raise oefmt(space.w_OverflowError, -"cannot pass infinity to as_integer_ratio()") +"cannot convert Infinity to integer ratio") except ValueError: raise oefmt(space.w_ValueError, -"cannot pass nan to as_integer_ratio()") +"cannot convert NaN to integer ratio") w_num = space.newlong_from_rbigint(num) w_den = space.newlong_from_rbigint(den) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Correctly port pypy modifications to sqlite tests
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93456:f83d3719aebd Date: 2017-12-14 22:48 +0100 http://bitbucket.org/pypy/pypy/changeset/f83d3719aebd/ Log:Correctly port pypy modifications to sqlite tests diff --git a/lib-python/3/sqlite3/test/userfunctions.py b/lib-python/3/sqlite3/test/userfunctions.py --- a/lib-python/3/sqlite3/test/userfunctions.py +++ b/lib-python/3/sqlite3/test/userfunctions.py @@ -314,7 +314,7 @@ # XXX it's better to raise OperationalError in order to stop # the query earlier. cur = self.con.cursor() -with self.assertRaises(AttributeError) as cm: +with self.assertRaises(sqlite.OperationalError) as cm: cur.execute("select nostep(t) from test") self.assertEqual(str(cm.exception), "user-defined aggregate's 'step' method raised error") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Since Python3.6, the seed() call to urandom() has been moved to the _random module.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93462:3f28eff2fcfc Date: 2017-12-18 09:36 +0100 http://bitbucket.org/pypy/pypy/changeset/3f28eff2fcfc/ Log:Since Python3.6, the seed() call to urandom() has been moved to the _random module. diff --git a/pypy/module/_random/interp_random.py b/pypy/module/_random/interp_random.py --- a/pypy/module/_random/interp_random.py +++ b/pypy/module/_random/interp_random.py @@ -1,13 +1,13 @@ import time -from pypy.interpreter.error import oefmt +from pypy.interpreter.error import oefmt, OperationError from pypy.interpreter.typedef import TypeDef from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.baseobjspace import W_Root +from pypy.module.posix import interp_posix from rpython.rlib.rarithmetic import r_uint, intmask, widen from rpython.rlib import rbigint, rrandom, rstring - def descr_new__(space, w_subtype, __args__): w_anything = __args__.firstarg() x = space.allocate_instance(W_Random, w_subtype) @@ -25,14 +25,19 @@ return space.newfloat(self._rnd.random()) def seed(self, space, w_n=None): -if w_n is None: -w_n = space.newint(int(time.time())) +if space.is_none(w_n): +# TODO: Use a non-blocking version of urandom +try: +w_n = interp_posix.urandom(space, 8) +except OperationError as e: +if not e.match(space, space.w_OSError): +raise +w_n = space.newint(int(time.time() * 256)) +if space.isinstance_w(w_n, space.w_int): +w_n = space.abs(w_n) else: -if space.isinstance_w(w_n, space.w_int): -w_n = space.abs(w_n) -else: -n = space.hash_w(w_n) -w_n = space.newint(r_uint(n)) +n = space.hash_w(w_n) +w_n = space.newint(r_uint(n)) key = [] w_one = space.newint(1) w_two = space.newint(2) diff --git a/pypy/module/_random/test/test_random.py b/pypy/module/_random/test/test_random.py --- a/pypy/module/_random/test/test_random.py +++ b/pypy/module/_random/test/test_random.py @@ -86,9 +86,9 @@ rnd = _random.Random() rnd.seed() state1 = rnd.getstate() -import time; time.sleep(1.1) # must be at least 1 second here -rnd.seed() # (note that random.py overrides -state2 = rnd.getstate() # seed() to improve the resolution) +import time; time.sleep(0.01) +rnd.seed() +state2 = rnd.getstate() assert state1 != state2 def test_randbits(self): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: mmap.write() return the number of bytes written: RPython part
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93415:09b70b8c9aba Date: 2017-12-13 23:50 +0100 http://bitbucket.org/pypy/pypy/changeset/09b70b8c9aba/ Log:mmap.write() return the number of bytes written: RPython part diff --git a/rpython/rlib/rmmap.py b/rpython/rlib/rmmap.py --- a/rpython/rlib/rmmap.py +++ b/rpython/rlib/rmmap.py @@ -492,6 +492,7 @@ self.setslice(start, data) self.pos = start + data_len +return data_len def write_byte(self, byte): if len(byte) != 1: diff --git a/rpython/rlib/test/test_rmmap.py b/rpython/rlib/test/test_rmmap.py --- a/rpython/rlib/test/test_rmmap.py +++ b/rpython/rlib/test/test_rmmap.py @@ -258,7 +258,7 @@ f.flush() def func(no): m = mmap.mmap(no, 6, access=mmap.ACCESS_WRITE) -m.write("ciao\n") +assert m.write("ciao\n") == 5 m.seek(0) assert m.read(6) == "ciao\nr" m.close() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: mmap.write() return the number of bytes written: RPython part
Author: Amaury Forgeot d'ArcBranch: Changeset: r93417:5ef9bb870cd2 Date: 2017-12-13 23:50 +0100 http://bitbucket.org/pypy/pypy/changeset/5ef9bb870cd2/ Log:mmap.write() return the number of bytes written: RPython part diff --git a/rpython/rlib/rmmap.py b/rpython/rlib/rmmap.py --- a/rpython/rlib/rmmap.py +++ b/rpython/rlib/rmmap.py @@ -492,6 +492,7 @@ self.setslice(start, data) self.pos = start + data_len +return data_len def write_byte(self, byte): if len(byte) != 1: diff --git a/rpython/rlib/test/test_rmmap.py b/rpython/rlib/test/test_rmmap.py --- a/rpython/rlib/test/test_rmmap.py +++ b/rpython/rlib/test/test_rmmap.py @@ -258,7 +258,7 @@ f.flush() def func(no): m = mmap.mmap(no, 6, access=mmap.ACCESS_WRITE) -m.write("ciao\n") +assert m.write("ciao\n") == 5 m.seek(0) assert m.read(6) == "ciao\nr" m.close() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: mmap.write() return the number of bytes written: AppLevel part
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93416:98fb1b0c5570 Date: 2017-12-13 23:52 +0100 http://bitbucket.org/pypy/pypy/changeset/98fb1b0c5570/ Log:mmap.write() return the number of bytes written: AppLevel part diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py --- a/pypy/module/mmap/interp_mmap.py +++ b/pypy/module/mmap/interp_mmap.py @@ -103,7 +103,7 @@ data = self.space.charbuf_w(w_data) self.check_writeable() try: -self.mmap.write(data) +return self.space.newint(self.mmap.write(data)) except RValueError as v: raise mmap_error(self.space, v) diff --git a/pypy/module/mmap/test/test_mmap.py b/pypy/module/mmap/test/test_mmap.py --- a/pypy/module/mmap/test/test_mmap.py +++ b/pypy/module/mmap/test/test_mmap.py @@ -268,7 +268,7 @@ m = mmap.mmap(f.fileno(), 6, access=mmap.ACCESS_WRITE) raises(TypeError, m.write, 123) raises(ValueError, m.write, b"c"*10) -m.write(b"ciao\n") +assert m.write(b"ciao\n") == 5 m.seek(0) assert m.read(6) == b"ciao\nr" m.close() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: The py3k version of the utf32 decoder should not allow lone surrogates.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r93413:b0267eee69d8 Date: 2017-12-13 10:04 +0100 http://bitbucket.org/pypy/pypy/changeset/b0267eee69d8/ Log:The py3k version of the utf32 decoder should not allow lone surrogates. diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -489,21 +489,21 @@ return result, length def py3k_str_decode_utf_16(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "native", 'utf-16-' + BYTEORDER2) return result, length def py3k_str_decode_utf_16_be(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "big", 'utf-16-be') return result, length def py3k_str_decode_utf_16_le(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "little", 'utf-16-le') @@ -714,41 +714,41 @@ 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "native") 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "big") 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "little") return result, length def py3k_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) +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "native", +'utf-32-' + BYTEORDER2, allow_surrogates=False) return result, length def py3k_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') +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "big", +'utf-32-be', allow_surrogates=False) return result, length def py3k_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') +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(0xFEFF) @@ -757,7 +757,8 @@ def str_decode_utf_32_helper(s, size, errors, final=True, errorhandler=None, byteorder="native", - public_encoding_name='utf32'): + public_encoding_name='utf32', + allow_surrogates=True): if errorhandler is None:
[pypy-commit] pypy py3.5: Applevel test for the utf32 surrogates.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r93414:c9a148ecf262 Date: 2017-12-13 10:05 +0100 http://bitbucket.org/pypy/pypy/changeset/c9a148ecf262/ Log:Applevel test for the utf32 surrogates. diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -778,6 +778,18 @@ '[]'.encode(encoding)) assert (u'[\udc80]'.encode(encoding, "replace") == '[?]'.encode(encoding)) +for encoding, ill_surrogate in [('utf-8', b'\xed\xb2\x80'), +('utf-16-le', b'\x80\xdc'), +('utf-16-be', b'\xdc\x80'), +('utf-32-le', b'\x80\xdc\x00\x00'), +('utf-32-be', b'\x00\x00\xdc\x80')]: +print(encoding) +before, after = "[", "]" +before_sequence = before.encode(encoding) +after_sequence = after.encode(encoding) +test_string = before + "\uDC80" + after +test_sequence = before_sequence + ill_surrogate + after_sequence +raises(UnicodeDecodeError, test_sequence.decode, encoding) def test_charmap_encode(self): assert 'xxx'.encode('charmap') == b'xxx' ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Add support for half floats in the RPython rstruct module.
Author: Amaury Forgeot d'ArcBranch: Changeset: r93412:ca5586010ac3 Date: 2017-12-11 20:29 +0100 http://bitbucket.org/pypy/pypy/changeset/ca5586010ac3/ Log:Add support for half floats in the RPython rstruct module. diff --git a/rpython/rlib/rstruct/standardfmttable.py b/rpython/rlib/rstruct/standardfmttable.py --- a/rpython/rlib/rstruct/standardfmttable.py +++ b/rpython/rlib/rstruct/standardfmttable.py @@ -105,6 +105,18 @@ _pack_string(fmtiter, string, count-1) +def pack_halffloat(fmtiter): +size = 2 +fl = fmtiter.accept_float_arg() +try: +result = ieee.pack_float(fmtiter.wbuf, fmtiter.pos, + fl, size, fmtiter.bigendian) +except OverflowError: +raise StructOverflowError("float too large for format 'e'") +else: +fmtiter.advance(size) +return result + def make_float_packer(TYPE): size = rffi.sizeof(TYPE) def packer(fmtiter): @@ -247,6 +259,11 @@ end = count fmtiter.appendobj(data[1:end]) +@specialize.argtype(0) +def unpack_halffloat(fmtiter): +data = fmtiter.read(2) +fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian)) + def make_ieee_unpacker(TYPE): @specialize.argtype(0) def unpack_ieee(fmtiter): @@ -374,6 +391,8 @@ 'needcount' : True }, 'p':{ 'size' : 1, 'pack' : pack_pascal, 'unpack' : unpack_pascal, 'needcount' : True }, +'e':{ 'size' : 2, 'pack' : pack_halffloat, +'unpack' : unpack_halffloat}, 'f':{ 'size' : 4, 'pack' : make_float_packer(rffi.FLOAT), 'unpack' : unpack_float}, 'd':{ 'size' : 8, 'pack' : make_float_packer(rffi.DOUBLE), diff --git a/rpython/rlib/rstruct/test/test_pack.py b/rpython/rlib/rstruct/test/test_pack.py --- a/rpython/rlib/rstruct/test/test_pack.py +++ b/rpython/rlib/rstruct/test/test_pack.py @@ -138,6 +138,19 @@ self.check('f', 123.456) self.check('d', 123.456789) +def test_pack_halffloat(self): +if self.fmttable is nativefmttable.native_fmttable: +# Host Python cannot handle half floats. +return +size = 2 +wbuf = MutableStringBuffer(size) +self.mypack_into('e', wbuf, 6.5e+04) +got = wbuf.finish() +if self.bigendian: +assert got == b'\x7b\xef' +else: +assert got == b'\xef\x7b' + def test_float_overflow(self): if self.fmt_prefix == '@': # native packing, no overflow diff --git a/rpython/rlib/rstruct/test/test_runpack.py b/rpython/rlib/rstruct/test/test_runpack.py --- a/rpython/rlib/rstruct/test/test_runpack.py +++ b/rpython/rlib/rstruct/test/test_runpack.py @@ -78,6 +78,10 @@ assert f != 12.34 # precision lost assert abs(f - 12.34) < 1E-6 +def test_unpack_halffloat(self): +assert runpack(">e", b"\x7b\xef") == 64992.0 +assert runpack("
[pypy-commit] pypy default: The py3k version of the utf32 decoder should not allow lone surrogates.
Author: Amaury Forgeot d'ArcBranch: Changeset: r93411:33178f62171f Date: 2017-12-13 10:04 +0100 http://bitbucket.org/pypy/pypy/changeset/33178f62171f/ Log:The py3k version of the utf32 decoder should not allow lone surrogates. diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -489,21 +489,21 @@ return result, length def py3k_str_decode_utf_16(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "native", 'utf-16-' + BYTEORDER2) return result, length def py3k_str_decode_utf_16_be(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "big", 'utf-16-be') return result, length def py3k_str_decode_utf_16_le(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "little", 'utf-16-le') @@ -714,41 +714,41 @@ 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "native") 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "big") 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "little") return result, length def py3k_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) +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "native", +'utf-32-' + BYTEORDER2, allow_surrogates=False) return result, length def py3k_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') +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "big", +'utf-32-be', allow_surrogates=False) return result, length def py3k_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') +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(0xFEFF) @@ -757,7 +757,8 @@ def str_decode_utf_32_helper(s, size, errors, final=True, errorhandler=None, byteorder="native", - public_encoding_name='utf32'): + public_encoding_name='utf32', + allow_surrogates=True): if errorhandler is None: errorhandler =
[pypy-commit] pypy py3.6: Fix struct test.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93408:24d2c052c1dd Date: 2017-12-12 23:21 +0100 http://bitbucket.org/pypy/pypy/changeset/24d2c052c1dd/ Log:Fix struct test. diff --git a/pypy/module/struct/test/test_struct.py b/pypy/module/struct/test/test_struct.py --- a/pypy/module/struct/test/test_struct.py +++ b/pypy/module/struct/test/test_struct.py @@ -49,7 +49,7 @@ assert calcsize('=Q') == 8 assert calcsize(' d') == 8 -assert calcsize('
[pypy-commit] pypy py3.6: Applevel test for the utf32 surrogates.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93410:c99a2002f6fc Date: 2017-12-13 10:05 +0100 http://bitbucket.org/pypy/pypy/changeset/c99a2002f6fc/ Log:Applevel test for the utf32 surrogates. diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -772,6 +772,18 @@ '[]'.encode(encoding)) assert (u'[\udc80]'.encode(encoding, "replace") == '[?]'.encode(encoding)) +for encoding, ill_surrogate in [('utf-8', b'\xed\xb2\x80'), +('utf-16-le', b'\x80\xdc'), +('utf-16-be', b'\xdc\x80'), +('utf-32-le', b'\x80\xdc\x00\x00'), +('utf-32-be', b'\x00\x00\xdc\x80')]: +print(encoding) +before, after = "[", "]" +before_sequence = before.encode(encoding) +after_sequence = after.encode(encoding) +test_string = before + "\uDC80" + after +test_sequence = before_sequence + ill_surrogate + after_sequence +raises(UnicodeDecodeError, test_sequence.decode, encoding) def test_charmap_encode(self): assert 'xxx'.encode('charmap') == b'xxx' ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: The py3k version of the utf32 decoder should not allow lone surrogates.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93409:8f8a8d212853 Date: 2017-12-13 10:04 +0100 http://bitbucket.org/pypy/pypy/changeset/8f8a8d212853/ Log:The py3k version of the utf32 decoder should not allow lone surrogates. diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -489,21 +489,21 @@ return result, length def py3k_str_decode_utf_16(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "native", 'utf-16-' + BYTEORDER2) return result, length def py3k_str_decode_utf_16_be(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "big", 'utf-16-be') return result, length def py3k_str_decode_utf_16_le(s, size, errors, final=True, - errorhandler=None): + errorhandler=None): result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final, errorhandler, "little", 'utf-16-le') @@ -714,41 +714,41 @@ 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "native") 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "big") 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") +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "little") return result, length def py3k_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) +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "native", +'utf-32-' + BYTEORDER2, allow_surrogates=False) return result, length def py3k_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') +result, length, byteorder = str_decode_utf_32_helper( +s, size, errors, final, errorhandler, "big", +'utf-32-be', allow_surrogates=False) return result, length def py3k_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') +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(0xFEFF) @@ -757,7 +757,8 @@ def str_decode_utf_32_helper(s, size, errors, final=True, errorhandler=None, byteorder="native", - public_encoding_name='utf32'): + public_encoding_name='utf32', + allow_surrogates=True): if errorhandler is None:
[pypy-commit] pypy py3.6: Oops, fix tests and translation.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93391:ea22b4d272be Date: 2017-12-12 19:21 +0100 http://bitbucket.org/pypy/pypy/changeset/ea22b4d272be/ Log:Oops, fix tests and translation. diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -151,9 +151,14 @@ except OperationError as e: if not e.match(space, space.w_TypeError): raise -if allow_fd and space.index_CHECK(w_value): -fd = unwrap_fd(space, w_value, "string, bytes or integer") -return Path(fd, None, None, w_value) +if allow_fd: +try: +space.index(w_value) +except OperationError: +pass +else: +fd = unwrap_fd(space, w_value, "string, bytes or integer") +return Path(fd, None, None, w_value) # Inline fspath() for better error messages. w_fspath_method = space.lookup(w_value, '__fspath__') @@ -165,12 +170,12 @@ if allow_fd: raise oefmt(space.w_TypeError, -"illegal type for path parameter (expected " -"string, bytes, os.PathLike or integer, got %T)", w_value) +"illegal type for path parameter (should be " +"string, bytes, os.PathLike or integer, not %T)", w_value) else: raise oefmt(space.w_TypeError, -"illegal type for path parameter (expected " -"string, bytes or os.PathLike, got %T)", w_value) +"illegal type for path parameter (should be " +"string, bytes or os.PathLike, not %T)", w_value) class _PathOrFd(Unwrapper): def unwrap(self, space, w_value): diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -208,7 +208,7 @@ excinfo = raises(TypeError, self.posix.stat, None) assert "can't specify None" in str(excinfo.value) excinfo = raises(TypeError, self.posix.stat, 2.) -assert "should be string, bytes or integer, not float" in str(excinfo.value) +assert "should be string, bytes, os.PathLike or integer, not float" in str(excinfo.value) raises(ValueError, self.posix.stat, -1) raises(ValueError, self.posix.stat, b"abc\x00def") raises(ValueError, self.posix.stat, u"abc\x00def") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Most file operations now accept a PathLike object with a __fspath__ method.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93389:10f89fd70107 Date: 2017-12-12 18:51 +0100 http://bitbucket.org/pypy/pypy/changeset/10f89fd70107/ Log:Most file operations now accept a PathLike object with a __fspath__ method. diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py --- a/pypy/module/_io/interp_io.py +++ b/pypy/module/_io/interp_io.py @@ -6,6 +6,7 @@ TypeDef, interp_attrproperty, generic_new_descr) from pypy.module._io.interp_fileio import W_FileIO from pypy.module._io.interp_textio import W_TextIOWrapper +from pypy.module.posix import interp_posix class Cache: @@ -25,7 +26,7 @@ if not (space.isinstance_w(w_file, space.w_unicode) or space.isinstance_w(w_file, space.w_bytes) or space.isinstance_w(w_file, space.w_int)): -raise oefmt(space.w_TypeError, "invalid file: %R", w_file) +w_file = interp_posix.fspath(space, w_file) reading = writing = creating = appending = updating = text = binary = universal = False diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -151,12 +151,26 @@ except OperationError as e: if not e.match(space, space.w_TypeError): raise -if allow_fd: -fd = unwrap_fd(space, w_value, "string, bytes or integer") -return Path(fd, None, None, w_value) -raise oefmt(space.w_TypeError, -"illegal type for path parameter (expected " -"string or bytes, got %T)", w_value) +if allow_fd and space.index_CHECK(w_value): +fd = unwrap_fd(space, w_value, "string, bytes or integer") +return Path(fd, None, None, w_value) + +# Inline fspath() for better error messages. +w_fspath_method = space.lookup(w_value, '__fspath__') +if w_fspath_method: +w_result = space.get_and_call_function(w_fspath_method, w_value) +if (space.isinstance_w(w_result, space.w_text) or +space.isinstance_w(w_result, space.w_bytes)): +return _unwrap_path(space, w_result, allow_fd=False) + +if allow_fd: +raise oefmt(space.w_TypeError, +"illegal type for path parameter (expected " +"string, bytes, os.PathLike or integer, got %T)", w_value) +else: +raise oefmt(space.w_TypeError, +"illegal type for path parameter (expected " +"string, bytes or os.PathLike, got %T)", w_value) class _PathOrFd(Unwrapper): def unwrap(self, space, w_value): diff --git a/pypy/module/posix/test/test_scandir.py b/pypy/module/posix/test/test_scandir.py --- a/pypy/module/posix/test/test_scandir.py +++ b/pypy/module/posix/test/test_scandir.py @@ -207,3 +207,10 @@ del iterator gc.collect() assert not l + +def test_lstat(self): +posix = self.posix +d = next(posix.scandir()) +with open(d) as fp: +length = len(fp.read()) +assert posix.lstat(d).st_size == length ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: os.fspath() accepts a DirEntry
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93388:07c74faf3629 Date: 2017-12-12 01:01 +0100 http://bitbucket.org/pypy/pypy/changeset/07c74faf3629/ Log:os.fspath() accepts a DirEntry diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py --- a/pypy/module/posix/__init__.py +++ b/pypy/module/posix/__init__.py @@ -82,6 +82,7 @@ 'get_terminal_size': 'interp_posix.get_terminal_size', 'scandir': 'interp_scandir.scandir', +'DirEntry': 'interp_scandir.W_DirEntry', 'get_inheritable': 'interp_posix.get_inheritable', 'set_inheritable': 'interp_posix.set_inheritable', 'fspath': 'interp_posix.fspath', diff --git a/pypy/module/posix/interp_scandir.py b/pypy/module/posix/interp_scandir.py --- a/pypy/module/posix/interp_scandir.py +++ b/pypy/module/posix/interp_scandir.py @@ -335,6 +335,7 @@ path = GetSetProperty(W_DirEntry.fget_path, doc="the entry's full path name; equivalent to " "os.path.join(scandir_path, entry.name)"), +__fspath__ = interp2app(W_DirEntry.fget_path), is_dir = interp2app(W_DirEntry.descr_is_dir), is_file = interp2app(W_DirEntry.descr_is_file), is_symlink = interp2app(W_DirEntry.descr_is_symlink), diff --git a/pypy/module/posix/test/test_scandir.py b/pypy/module/posix/test/test_scandir.py --- a/pypy/module/posix/test/test_scandir.py +++ b/pypy/module/posix/test/test_scandir.py @@ -169,8 +169,14 @@ def test_repr(self): posix = self.posix d = next(posix.scandir(self.dir1)) +assert isinstance(d, posix.DirEntry) assert repr(d) == "" +def test_fspath(self): +posix = self.posix +d = next(posix.scandir(self.dir1)) +assert self.posix.fspath(d).endswith('dir1/file1') + def test_resource_warning(self): posix = self.posix import warnings, gc ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Add support for half floats in the RPython rstruct module.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93376:51f3350c4b8b Date: 2017-12-11 20:29 +0100 http://bitbucket.org/pypy/pypy/changeset/51f3350c4b8b/ Log:Add support for half floats in the RPython rstruct module. diff --git a/rpython/rlib/rstruct/standardfmttable.py b/rpython/rlib/rstruct/standardfmttable.py --- a/rpython/rlib/rstruct/standardfmttable.py +++ b/rpython/rlib/rstruct/standardfmttable.py @@ -105,6 +105,18 @@ _pack_string(fmtiter, string, count-1) +def pack_halffloat(fmtiter): +size = 2 +fl = fmtiter.accept_float_arg() +try: +result = ieee.pack_float(fmtiter.wbuf, fmtiter.pos, + fl, size, fmtiter.bigendian) +except OverflowError: +raise StructOverflowError("float too large for format 'e'") +else: +fmtiter.advance(size) +return result + def make_float_packer(TYPE): size = rffi.sizeof(TYPE) def packer(fmtiter): @@ -247,6 +259,11 @@ end = count fmtiter.appendobj(data[1:end]) +@specialize.argtype(0) +def unpack_halffloat(fmtiter): +data = fmtiter.read(2) +fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian)) + def make_ieee_unpacker(TYPE): @specialize.argtype(0) def unpack_ieee(fmtiter): @@ -374,6 +391,8 @@ 'needcount' : True }, 'p':{ 'size' : 1, 'pack' : pack_pascal, 'unpack' : unpack_pascal, 'needcount' : True }, +'e':{ 'size' : 2, 'pack' : pack_halffloat, +'unpack' : unpack_halffloat}, 'f':{ 'size' : 4, 'pack' : make_float_packer(rffi.FLOAT), 'unpack' : unpack_float}, 'd':{ 'size' : 8, 'pack' : make_float_packer(rffi.DOUBLE), diff --git a/rpython/rlib/rstruct/test/test_pack.py b/rpython/rlib/rstruct/test/test_pack.py --- a/rpython/rlib/rstruct/test/test_pack.py +++ b/rpython/rlib/rstruct/test/test_pack.py @@ -138,6 +138,19 @@ self.check('f', 123.456) self.check('d', 123.456789) +def test_pack_halffloat(self): +if self.fmttable is nativefmttable.native_fmttable: +# Host Python cannot handle half floats. +return +size = 2 +wbuf = MutableStringBuffer(size) +self.mypack_into('e', wbuf, 6.5e+04) +got = wbuf.finish() +if self.bigendian: +assert got == b'\x7b\xef' +else: +assert got == b'\xef\x7b' + def test_float_overflow(self): if self.fmt_prefix == '@': # native packing, no overflow diff --git a/rpython/rlib/rstruct/test/test_runpack.py b/rpython/rlib/rstruct/test/test_runpack.py --- a/rpython/rlib/rstruct/test/test_runpack.py +++ b/rpython/rlib/rstruct/test/test_runpack.py @@ -78,6 +78,10 @@ assert f != 12.34 # precision lost assert abs(f - 12.34) < 1E-6 +def test_unpack_halffloat(self): +assert runpack(">e", b"\x7b\xef") == 64992.0 +assert runpack("
[pypy-commit] pypy py3.6: Check that the 'e' format works in the struct module.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93377:abab5c6e2946 Date: 2017-12-11 20:29 +0100 http://bitbucket.org/pypy/pypy/changeset/abab5c6e2946/ Log:Check that the 'e' format works in the struct module. diff --git a/pypy/module/struct/test/test_struct.py b/pypy/module/struct/test/test_struct.py --- a/pypy/module/struct/test/test_struct.py +++ b/pypy/module/struct/test/test_struct.py @@ -49,6 +49,7 @@ assert calcsize('=Q') == 8 assert calcsize(' d') == 8 +assert calcsize(' e", 65504.0) == b'\x7b\xff' +assert unpack(">e", b'\x7b\xff') == (65504.0,) +raises(OverflowError, pack, "
[pypy-commit] pypy py3.6: Match CPython exception for bad lineno or col_offset: always ValueError.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93378:4fc91603abd7 Date: 2017-12-11 23:18 +0100 http://bitbucket.org/pypy/pypy/changeset/4fc91603abd7/ Log:Match CPython exception for bad lineno or col_offset: always ValueError. diff --git a/pypy/interpreter/astcompiler/ast.py b/pypy/interpreter/astcompiler/ast.py --- a/pypy/interpreter/astcompiler/ast.py +++ b/pypy/interpreter/astcompiler/ast.py @@ -28,6 +28,12 @@ w_obj = space.w_None return w_obj +def obj_to_int(space, w_value): +if not space.isinstance_w(w_value, space.w_long): +raise oefmt(space.w_ValueError, +"invalid integer value: %R", w_value) +return space.int_w(w_value) + class AST(object): __metaclass__ = extendabletype @@ -444,8 +450,8 @@ decorator_list_w = space.unpackiterable(w_decorator_list) _decorator_list = [expr.from_object(space, w_item) for w_item in decorator_list_w] _returns = expr.from_object(space, w_returns) -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) +_lineno = obj_to_int(space, w_lineno) +_col_offset = obj_to_int(space, w_col_offset) return FunctionDef(_name, _args, _body, _decorator_list, _returns, _lineno, _col_offset) State.ast_type('FunctionDef', 'stmt', ['name', 'args', 'body', 'decorator_list', 'returns']) @@ -524,8 +530,8 @@ decorator_list_w = space.unpackiterable(w_decorator_list) _decorator_list = [expr.from_object(space, w_item) for w_item in decorator_list_w] _returns = expr.from_object(space, w_returns) -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) +_lineno = obj_to_int(space, w_lineno) +_col_offset = obj_to_int(space, w_col_offset) return AsyncFunctionDef(_name, _args, _body, _decorator_list, _returns, _lineno, _col_offset) State.ast_type('AsyncFunctionDef', 'stmt', ['name', 'args', 'body', 'decorator_list', 'returns']) @@ -617,8 +623,8 @@ _body = [stmt.from_object(space, w_item) for w_item in body_w] decorator_list_w = space.unpackiterable(w_decorator_list) _decorator_list = [expr.from_object(space, w_item) for w_item in decorator_list_w] -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) +_lineno = obj_to_int(space, w_lineno) +_col_offset = obj_to_int(space, w_col_offset) return ClassDef(_name, _bases, _keywords, _body, _decorator_list, _lineno, _col_offset) State.ast_type('ClassDef', 'stmt', ['name', 'bases', 'keywords', 'body', 'decorator_list']) @@ -654,8 +660,8 @@ w_lineno = get_field(space, w_node, 'lineno', False) w_col_offset = get_field(space, w_node, 'col_offset', False) _value = expr.from_object(space, w_value) -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) +_lineno = obj_to_int(space, w_lineno) +_col_offset = obj_to_int(space, w_col_offset) return Return(_value, _lineno, _col_offset) State.ast_type('Return', 'stmt', ['value']) @@ -698,8 +704,8 @@ w_col_offset = get_field(space, w_node, 'col_offset', False) targets_w = space.unpackiterable(w_targets) _targets = [expr.from_object(space, w_item) for w_item in targets_w] -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) +_lineno = obj_to_int(space, w_lineno) +_col_offset = obj_to_int(space, w_col_offset) return Delete(_targets, _lineno, _col_offset) State.ast_type('Delete', 'stmt', ['targets']) @@ -750,8 +756,8 @@ _value = expr.from_object(space, w_value) if _value is None: raise_required_value(space, w_node, 'value') -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) +_lineno = obj_to_int(space, w_lineno) +_col_offset = obj_to_int(space, w_col_offset) return Assign(_targets, _value, _lineno, _col_offset) State.ast_type('Assign', 'stmt', ['targets', 'value']) @@ -803,8 +809,8 @@ _value = expr.from_object(space, w_value) if _value is None: raise_required_value(space, w_node, 'value') -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) +_lineno = obj_to_int(space, w_lineno) +_col_offset = obj_to_int(space, w_col_offset) return AugAssign(_target, _op, _value, _lineno, _col_offset) State.ast_type('AugAssign', 'stmt', ['target', 'op', 'value']) @@ -877,8 +883,8 @@ _body = [stmt.from_object(space, w_item) for w_item in body_w] orelse_w = space.unpackiterable(w_orelse) _orelse = [stmt.from_object(space, w_item) for w_item in orelse_w] -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) +_lineno = obj_to_int(space,
[pypy-commit] pypy py3.6: Add Decimal.as_integer_ratio()
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93375:5b8174a4dd1d Date: 2017-12-11 19:47 +0100 http://bitbucket.org/pypy/pypy/changeset/5b8174a4dd1d/ Log:Add Decimal.as_integer_ratio() diff --git a/lib_pypy/_decimal.py b/lib_pypy/_decimal.py --- a/lib_pypy/_decimal.py +++ b/lib_pypy/_decimal.py @@ -448,6 +448,36 @@ return DecimalTuple(sign, coeff, expt) +def as_integer_ratio(self): +"Convert a Decimal to its exact integer ratio representation" +if _mpdec.mpd_isspecial(self._mpd): +if _mpdec.mpd_isnan(self._mpd): +raise ValueError("cannot convert NaN to integer ratio") +else: +raise OverflowError("cannot convert Infinity to integer ratio") + +context = getcontext() +tmp = Decimal._new_empty() +with _CatchStatus(context) as (ctx, status_ptr): +_mpdec.mpd_qcopy(tmp._mpd, self._mpd, status_ptr) +exp = tmp._mpd.exp if tmp else 0 +tmp._mpd.exp = 0 + +# context and rounding are unused here: the conversion is exact +numerator = tmp._to_int(_mpdec.MPD_ROUND_FLOOR) + +exponent = 10 ** abs(exp) +if exp >= 0: +numerator *= exponent +denominator = 1 +else: +denominator = exponent +gcd = _math.gcd(numerator, denominator) +numerator //= gcd +denominator //= gcd + +return numerator, denominator + def _convert_for_comparison(self, other, op): if isinstance(other, Decimal): return self, other ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: CPython Issue26482: can pickle recursive deque objects.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93371:ce0523b30644 Date: 2017-12-11 19:14 +0100 http://bitbucket.org/pypy/pypy/changeset/ce0523b30644/ Log:CPython Issue26482: can pickle recursive deque objects. diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py --- a/lib_pypy/_collections.py +++ b/lib_pypy/_collections.py @@ -323,7 +323,7 @@ self.rotate(-index) def __reduce_ex__(self, proto): -return type(self), (list(self), self.maxlen) +return type(self), ((), self.maxlen), None, iter(self) __hash__ = None diff --git a/pypy/module/_collections/interp_deque.py b/pypy/module/_collections/interp_deque.py --- a/pypy/module/_collections/interp_deque.py +++ b/pypy/module/_collections/interp_deque.py @@ -491,23 +491,14 @@ "Return state information for pickling." space = self.space w_type = space.type(self) -w_dict = space.findattr(self, space.newtext('__dict__')) -w_list = space.call_function(space.w_list, self) -if w_dict is None: -if self.maxlen == sys.maxint: -result = [ -w_type, space.newtuple([w_list])] -else: -result = [ -w_type, space.newtuple([w_list, space.newint(self.maxlen)])] +w_dict = space.findattr(self, space.newtext('__dict__')) or space.w_None +w_it = space.iter(self) +if self.maxlen == sys.maxint: +w_lentuple = space.newtuple([]) else: -if self.maxlen == sys.maxint: -w_len = space.w_None -else: -w_len = space.newint(self.maxlen) -result = [ -w_type, space.newtuple([w_list, w_len]), w_dict] -return space.newtuple(result) +w_lentuple = space.newtuple([space.newtuple([]), + space.newint(self.maxlen)]) +return space.newtuple([w_type, w_lentuple, w_dict, w_it]) def get_maxlen(space, self): if self.maxlen == sys.maxint: diff --git a/pypy/module/_collections/test/test_deque.py b/pypy/module/_collections/test/test_deque.py --- a/pypy/module/_collections/test/test_deque.py +++ b/pypy/module/_collections/test/test_deque.py @@ -264,25 +264,25 @@ # d = deque('hello world') r = d.__reduce__() -assert r == (deque, (list('hello world'),)) +assert r[:3] == (deque, (), None) # d = deque('hello world', 42) r = d.__reduce__() -assert r == (deque, (list('hello world'), 42)) +assert r[:3] == (deque, ((), 42), None) # class D(deque): pass d = D('hello world') d.a = 5 r = d.__reduce__() -assert r == (D, (list('hello world'), None), {'a': 5}) +assert r[:3] == (D, (), {'a': 5}) # class D(deque): pass d = D('hello world', 42) d.a = 5 r = d.__reduce__() -assert r == (D, (list('hello world'), 42), {'a': 5}) +assert r[:3] == (D, ((), 42), {'a': 5}) def test_copy(self): from _collections import deque ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: Python 3.6 is more strict with deprecated files like 'U+'
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93370:e0f1b581e68d Date: 2017-12-11 12:01 +0100 http://bitbucket.org/pypy/pypy/changeset/e0f1b581e68d/ Log:Python 3.6 is more strict with deprecated files like 'U+' diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py --- a/pypy/module/_io/interp_io.py +++ b/pypy/module/_io/interp_io.py @@ -68,9 +68,9 @@ rawmode += "+" if universal: -if writing or appending: +if writing or appending or creating or updating: raise oefmt(space.w_ValueError, -"can't use U and writing mode at once") +"mode U cannot be combined with 'x', 'w', 'a', or '+'") space.warn(space.newtext("'U' mode is deprecated ('r' has the same " "effect in Python 3.x)"), space.w_DeprecationWarning) diff --git a/pypy/module/_io/test/test_io.py b/pypy/module/_io/test/test_io.py --- a/pypy/module/_io/test/test_io.py +++ b/pypy/module/_io/test/test_io.py @@ -210,6 +210,8 @@ raises(ValueError, io.open, self.tmpfile, "ww") raises(ValueError, io.open, self.tmpfile, "rwa") raises(ValueError, io.open, self.tmpfile, "b", newline="\n") +raises(ValueError, io.open, self.tmpfile, "U+") +raises(ValueError, io.open, self.tmpfile, "xU") def test_array_write(self): import _io, array ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.6: The ast module now has a "Constant" node that AST optimizers can use.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93353:cadf41717a3f Date: 2017-12-10 17:47 +0100 http://bitbucket.org/pypy/pypy/changeset/cadf41717a3f/ Log:The ast module now has a "Constant" node that AST optimizers can use. Use it in place of PyPy's specific "Const". diff --git a/pypy/interpreter/astcompiler/ast.py b/pypy/interpreter/astcompiler/ast.py --- a/pypy/interpreter/astcompiler/ast.py +++ b/pypy/interpreter/astcompiler/ast.py @@ -1743,6 +1743,8 @@ return NameConstant.from_object(space, w_node) if space.isinstance_w(w_node, get(space).w_Ellipsis): return Ellipsis.from_object(space, w_node) +if space.isinstance_w(w_node, get(space).w_Constant): +return Constant.from_object(space, w_node) if space.isinstance_w(w_node, get(space).w_Attribute): return Attribute.from_object(space, w_node) if space.isinstance_w(w_node, get(space).w_Subscript): @@ -1755,8 +1757,6 @@ return List.from_object(space, w_node) if space.isinstance_w(w_node, get(space).w_Tuple): return Tuple.from_object(space, w_node) -if space.isinstance_w(w_node, get(space).w_Const): -return Const.from_object(space, w_node) raise oefmt(space.w_TypeError, "Expected expr node, got %T", w_node) State.ast_type('expr', 'AST', None, ['lineno', 'col_offset']) @@ -2841,6 +2841,43 @@ State.ast_type('Ellipsis', 'expr', []) +class Constant(expr): + +def __init__(self, value, lineno, col_offset): +self.value = value +expr.__init__(self, lineno, col_offset) + +def walkabout(self, visitor): +visitor.visit_Constant(self) + +def mutate_over(self, visitor): +return visitor.visit_Constant(self) + +def to_object(self, space): +w_node = space.call_function(get(space).w_Constant) +w_value = self.value # constant +space.setattr(w_node, space.newtext('value'), w_value) +w_lineno = space.newint(self.lineno) # int +space.setattr(w_node, space.newtext('lineno'), w_lineno) +w_col_offset = space.newint(self.col_offset) # int +space.setattr(w_node, space.newtext('col_offset'), w_col_offset) +return w_node + +@staticmethod +def from_object(space, w_node): +w_value = get_field(space, w_node, 'value', False) +w_lineno = get_field(space, w_node, 'lineno', False) +w_col_offset = get_field(space, w_node, 'col_offset', False) +_value = w_value +if _value is None: +raise_required_value(space, w_node, 'value') +_lineno = space.int_w(w_lineno) +_col_offset = space.int_w(w_col_offset) +return Constant(_value, _lineno, _col_offset) + +State.ast_type('Constant', 'expr', ['value']) + + class Attribute(expr): def __init__(self, value, attr, ctx, lineno, col_offset): @@ -3137,43 +3174,6 @@ State.ast_type('Tuple', 'expr', ['elts', 'ctx']) -class Const(expr): - -def __init__(self, obj, lineno, col_offset): -self.obj = obj -expr.__init__(self, lineno, col_offset) - -def walkabout(self, visitor): -visitor.visit_Const(self) - -def mutate_over(self, visitor): -return visitor.visit_Const(self) - -def to_object(self, space): -w_node = space.call_function(get(space).w_Const) -w_obj = self.obj # object -space.setattr(w_node, space.newtext('obj'), w_obj) -w_lineno = space.newint(self.lineno) # int -space.setattr(w_node, space.newtext('lineno'), w_lineno) -w_col_offset = space.newint(self.col_offset) # int -space.setattr(w_node, space.newtext('col_offset'), w_col_offset) -return w_node - -@staticmethod -def from_object(space, w_node): -w_obj = get_field(space, w_node, 'obj', False) -w_lineno = get_field(space, w_node, 'lineno', False) -w_col_offset = get_field(space, w_node, 'col_offset', False) -_obj = w_obj -if _obj is None: -raise_required_value(space, w_node, 'obj') -_lineno = space.int_w(w_lineno) -_col_offset = space.int_w(w_col_offset) -return Const(_obj, _lineno, _col_offset) - -State.ast_type('Const', 'expr', ['obj']) - - class expr_context(AST): @staticmethod def from_object(space, w_node): @@ -4140,6 +4140,8 @@ return self.default_visitor(node) def visit_Ellipsis(self, node): return self.default_visitor(node) +def visit_Constant(self, node): +return self.default_visitor(node) def visit_Attribute(self, node): return self.default_visitor(node) def visit_Subscript(self, node): @@ -4152,8 +4154,6 @@ return self.default_visitor(node) def visit_Tuple(self, node): return self.default_visitor(node) -def visit_Const(self, node): -return self.default_visitor(node) def
[pypy-commit] pypy py3.6: Scandir: Add a context manager, and a ResourceWarning when it is not explictly closed.
Author: Amaury Forgeot d'ArcBranch: py3.6 Changeset: r93354:2d7ef69f48bd Date: 2017-12-10 21:33 +0100 http://bitbucket.org/pypy/pypy/changeset/2d7ef69f48bd/ Log:Scandir: Add a context manager, and a ResourceWarning when it is not explictly closed. diff --git a/pypy/module/posix/interp_scandir.py b/pypy/module/posix/interp_scandir.py --- a/pypy/module/posix/interp_scandir.py +++ b/pypy/module/posix/interp_scandir.py @@ -51,11 +51,25 @@ self.dirfd = dirfd self.w_path_prefix = w_path_prefix self.result_is_bytes = result_is_bytes +self.register_finalizer(space) -@rgc.must_be_light_finalizer -def __del__(self): -if self.dirp: -rposix_scandir.closedir(self.dirp) +def _finalize_(self): +if not self.dirp: +return +space = self.space +try: +msg = ("unclosed scandir iterator %s" % + space.text_w(space.repr(self))) +space.warn(space.newtext(msg), space.w_ResourceWarning) +except OperationError as e: +# Spurious errors can appear at shutdown +if e.match(space, space.w_Warning): +e.write_unraisable(space, '', self) +self._close() + +def _close(self): +rposix_scandir.closedir(self.dirp) +self.dirp = rposix_scandir.NULL_DIRP def iter_w(self): return self @@ -96,16 +110,31 @@ # known_type = rposix_scandir.get_known_type(entry) inode = rposix_scandir.get_inode(entry) +except: +self._close() +raise finally: self._in_next = False direntry = W_DirEntry(self, name, known_type, inode) return direntry +def close_w(self): +self._close() + +def enter_w(self): +return self + +def exit_w(self, space, __args__): +self._close() + W_ScandirIterator.typedef = TypeDef( 'posix.ScandirIterator', __iter__ = interp2app(W_ScandirIterator.iter_w), __next__ = interp2app(W_ScandirIterator.next_w), +__enter__ = interp2app(W_ScandirIterator.enter_w), +__exit__ = interp2app(W_ScandirIterator.exit_w), +close = interp2app(W_ScandirIterator.close_w), ) W_ScandirIterator.typedef.acceptable_as_base_class = False diff --git a/pypy/module/posix/test/test_scandir.py b/pypy/module/posix/test/test_scandir.py --- a/pypy/module/posix/test/test_scandir.py +++ b/pypy/module/posix/test/test_scandir.py @@ -170,3 +170,34 @@ posix = self.posix d = next(posix.scandir(self.dir1)) assert repr(d) == "" + +def test_resource_warning(self): +posix = self.posix +import warnings, gc +iterator = posix.scandir(self.dir1) +next(iterator) +with warnings.catch_warnings(record=True) as l: +warnings.simplefilter("always") +del iterator +gc.collect() +assert isinstance(l[0].message, ResourceWarning) +# +iterator = posix.scandir(self.dir1) +next(iterator) +with warnings.catch_warnings(record=True) as l: +warnings.simplefilter("always") +iterator.close() +del iterator +gc.collect() +assert len(l) == 0 + +def test_context_manager(self): +posix = self.posix +import warnings, gc +with warnings.catch_warnings(record=True) as l: +warnings.simplefilter("always") +with posix.scandir(self.dir1) as iterator: +next(iterator) +del iterator +gc.collect() +assert not l ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Issue2684: pyexpat.CreateParser() did not handle correctly namespace_separator=""
Author: Amaury Forgeot d'ArcBranch: Changeset: r92811:df15dab6a182 Date: 2017-10-20 21:36 +0200 http://bitbucket.org/pypy/pypy/changeset/df15dab6a182/ Log:Issue2684: pyexpat.CreateParser() did not handle correctly namespace_separator="" diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py --- a/pypy/module/pyexpat/interp_pyexpat.py +++ b/pypy/module/pyexpat/interp_pyexpat.py @@ -808,7 +808,7 @@ w_encoding) if space.is_none(w_namespace_separator): -namespace_separator = 0 +namespace_separator = -1 elif space.isinstance_w(w_namespace_separator, space.w_text): separator = space.text_w(w_namespace_separator) if len(separator) == 0: @@ -831,7 +831,7 @@ elif space.is_w(w_intern, space.w_None): w_intern = None -if namespace_separator: +if namespace_separator >= 0: xmlparser = XML_ParserCreateNS( encoding, rffi.cast(rffi.CHAR, namespace_separator)) diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py --- a/pypy/module/pyexpat/test/test_parser.py +++ b/pypy/module/pyexpat/test/test_parser.py @@ -59,7 +59,7 @@ p.CharacterDataHandler = lambda s: data.append(s) encoding = encoding_arg is None and 'utf-8' or encoding_arg -res = p.Parse(u"\u00f6".encode(encoding), isfinal=True) +res = p.Parse(u"\u00f6".encode(encoding), True) assert res == 1 assert data == [u"\u00f6"] @@ -188,6 +188,34 @@ p.ParseFile(fake_reader) assert fake_reader.read_count == 4 +def test_entities(self): +import pyexpat +parser = pyexpat.ParserCreate(None, "") + +def startElement(tag, attrs): +assert tag == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#RDF' +assert attrs == { +'http://www.w3.org/XML/1998/namespacebase': +'http://www.semanticweb.org/jiba/ontologies/2017/0/test'} +parser.StartElementHandler = startElement +parser.Parse(""" + +http://www.w3.org/2002/07/owl#; > +http://www.w3.org/2001/XMLSchema#; > +http://www.w3.org/2000/01/rdf-schema#; > +http://www.w3.org/1999/02/22-rdf-syntax-ns#; > +]> + +http://www.semanticweb.org/jiba/ontologies/2017/0/test#; + xml:base="http://www.semanticweb.org/jiba/ontologies/2017/0/test; + xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#; + xmlns:owl="http://www.w3.org/2002/07/owl#; + xmlns:xsd="http://www.w3.org/2001/XMLSchema#; + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#;> + +""", True) + class AppTestPyexpat2: spaceconfig = dict(usemodules=['pyexpat', 'itertools', '_socket', 'time', 'struct', 'binascii']) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Try to fix translation on Windows: skip socket.sendmsg and associated macros.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r92475:826d99189c3b Date: 2017-09-27 14:27 +0200 http://bitbucket.org/pypy/pypy/changeset/826d99189c3b/ Log:Try to fix translation on Windows: skip socket.sendmsg and associated macros. diff --git a/pypy/module/_socket/__init__.py b/pypy/module/_socket/__init__.py --- a/pypy/module/_socket/__init__.py +++ b/pypy/module/_socket/__init__.py @@ -37,7 +37,8 @@ CMSG_SPACE CMSG_LEN """.split(): -if (name in ('inet_pton', 'inet_ntop', 'socketpair') and +if (name in ('inet_pton', 'inet_ntop', 'socketpair', + 'CMSG_SPACE', 'CMSG_LEN') and not hasattr(rsocket, name)): continue diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py --- a/pypy/module/_socket/interp_socket.py +++ b/pypy/module/_socket/interp_socket.py @@ -879,11 +879,14 @@ socketmethodnames = """ _accept bind close connect connect_ex fileno detach getpeername getsockname getsockopt gettimeout listen -recv recvfrom recvmsg send sendall sendto sendmsg setblocking +recv recvfrom send sendall sendto setblocking setsockopt settimeout shutdown _reuse _drop recv_into recvfrom_into """.split() if hasattr(rsocket._c, 'WSAIoctl'): socketmethodnames.append('ioctl') +if rsocket._c.HAVE_SENDMSG: +socketmethodnames.append('sendmsg') +socketmethodnames.append('recvmsg') socketmethods = {} for methodname in socketmethodnames: diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py --- a/rpython/rlib/_rsocket_rffi.py +++ b/rpython/rlib/_rsocket_rffi.py @@ -348,7 +348,8 @@ ('ifr_name', rffi.CFixedArray(rffi.CHAR, 8))]) # insert handler for sendmsg / recvmsg here -if _POSIX: +HAVE_SENDMSG = bool(_POSIX) +if HAVE_SENDMSG: includes = ['stddef.h', 'sys/socket.h', 'unistd.h', diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -1393,7 +1393,7 @@ return (make_socket(fd0, family, type, proto, SocketClass), make_socket(fd1, family, type, proto, SocketClass)) -if _c._POSIX: +if _c.HAVE_SENDMSG: def CMSG_LEN( demanded_len): """ Socket method to determine the optimal byte size of the ancillary. ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Oops, fix win32 build
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91657:d0f683da0c05 Date: 2017-06-28 07:59 +0200 http://bitbucket.org/pypy/pypy/changeset/d0f683da0c05/ Log:Oops, fix win32 build diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -1301,7 +1301,7 @@ newpath = _as_bytes0(newpath) handle_posix_error('link', c_link(oldpath, newpath)) else: -traits = _preferred_traits(path1) +traits = _preferred_traits(oldpath) win32traits = make_win32_traits(traits) oldpath = traits.as_str0(oldpath) newpath = traits.as_str0(newpath) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Fix translation on Windows. space.text_w returns an RPython bytestring.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91656:f5d11f59787a Date: 2017-06-27 23:46 +0200 http://bitbucket.org/pypy/pypy/changeset/f5d11f59787a/ Log:Fix translation on Windows. space.text_w returns an RPython bytestring. diff --git a/pypy/module/_cffi_backend/errorbox.py b/pypy/module/_cffi_backend/errorbox.py --- a/pypy/module/_cffi_backend/errorbox.py +++ b/pypy/module/_cffi_backend/errorbox.py @@ -86,7 +86,7 @@ return w_text = self.space.call_function(w_done) -p = rffi.unicode2wcharp(self.space.text_w(w_text), +p = rffi.unicode2wcharp(self.space.unicode_w(w_text), track_allocation=False) if self.text_p: rffi.free_wcharp(self.text_p, track_allocation=False) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Issue #2594: Fix truncated errors messages in _lzma.py
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91655:38e0caea905c Date: 2017-06-27 23:36 +0200 http://bitbucket.org/pypy/pypy/changeset/38e0caea905c/ Log:Issue #2594: Fix truncated errors messages in _lzma.py Full messages were found in CPython _lzmamodule.c diff --git a/lib_pypy/_lzma.py b/lib_pypy/_lzma.py --- a/lib_pypy/_lzma.py +++ b/lib_pypy/_lzma.py @@ -153,39 +153,39 @@ def parse_filter_spec_lzma(id, preset=m.LZMA_PRESET_DEFAULT, **kwargs): ret = ffi.new('lzma_options_lzma*') if m.lzma_lzma_preset(ret, preset): -raise LZMAError("Invalid...") +raise LZMAError("Invalid compression preset: %s" % preset) for arg, val in kwargs.items(): if arg in ('dict_size', 'lc', 'lp', 'pb', 'nice_len', 'depth'): setattr(ret, arg, val) elif arg in ('mf', 'mode'): setattr(ret, arg, int(val)) else: -raise ValueError("Invalid...") +raise ValueError("Invalid filter specifier for LZMA filter") return ret def parse_filter_spec(spec): if not isinstance(spec, collections.Mapping): -raise TypeError("Filter...") +raise TypeError("Filter specifier must be a dict or dict-like object") ret = ffi.new('lzma_filter*') try: ret.id = spec['id'] except KeyError: -raise ValueError("Filter...") +raise ValueError("Filter specifier must have an \"id\" entry") if ret.id in (m.LZMA_FILTER_LZMA1, m.LZMA_FILTER_LZMA2): try: options = parse_filter_spec_lzma(**spec) except TypeError: -raise ValueError("Invalid...") +raise ValueError("Invalid filter specifier for LZMA filter") elif ret.id == m.LZMA_FILTER_DELTA: try: options = parse_filter_spec_delta(**spec) except TypeError: -raise ValueError("Invalid...") +raise ValueError("Invalid filter specifier for delta filter") elif ret.id in BCJ_FILTERS: try: options = parse_filter_spec_bcj(**spec) except TypeError: -raise ValueError("Invalid...") +raise ValueError("Invalid filter specifier for BCJ filter") else: raise ValueError("Invalid %d" % (ret.id,)) @@ -209,7 +209,9 @@ def parse_filter_chain_spec(filterspecs): if len(filterspecs) > m.LZMA_FILTERS_MAX: -raise ValueError("Too...") +raise ValueError( +"Too many filters - liblzma supports a maximum of %s" % +m.LZMA_FILTERS_MAX) filters = ffi.new('lzma_filter[]', m.LZMA_FILTERS_MAX+1) _owns[filters] = children = [] for i in range(m.LZMA_FILTERS_MAX+1): @@ -241,7 +243,7 @@ elif filter.id in BCJ_FILTERS: add_opts('lzma_options_bcj', 'start_offset') else: -raise ValueError("Invalid...") +raise ValueError("Invalid filter ID: %s" % filter.id) return spec def _decode_filter_properties(filter_id, encoded_props): @@ -425,25 +427,26 @@ For one-shot decompression, use the decompress() function instead. """ -def __init__(self, format=FORMAT_AUTO, memlimit=None, filters=None, header=None, check=None, unpadded_size=None): +def __init__(self, format=FORMAT_AUTO, memlimit=None, filters=None, + header=None, check=None, unpadded_size=None): decoder_flags = m.LZMA_TELL_ANY_CHECK | m.LZMA_TELL_NO_CHECK -#decoder_flags = 0 if memlimit is not None: if format == FORMAT_RAW: -raise ValueError("Cannot sp...") -#memlimit = long(memlimit) +raise ValueError("Cannot specify memory limit with FORMAT_RAW") else: memlimit = m.UINT64_MAX if format == FORMAT_RAW and filters is None: -raise ValueError("Must...") +raise ValueError("Must specify filters for FORMAT_RAW") elif format != FORMAT_RAW and filters is not None: -raise ValueError("Cannot...") +raise ValueError("Cannot specify filters except with FORMAT_RAW") if format == FORMAT_BLOCK and (header is None or unpadded_size is None or check is None): -raise ValueError("Must...") +raise ValueError("Must specify header, unpadded_size and check " + "with FORMAT_BLOCK") elif format != FORMAT_BLOCK and (header is not None or unpadded_size is not None or check is not None): -raise ValueError("Cannot...") +raise ValueError("Cannot specify header, unpadded_size or check " + "except with FORMAT_BLOCK") format = _parse_format(format) self.lock = threading.Lock() @@ -481,7 +484,7 @@ self.expected_size = block.compressed_size catch_lzma_error(m.lzma_block_decoder, self.lzs, block) else: -raise ValueError("invalid...") +raise
[pypy-commit] pypy py3.5: As os.link() implementation on Windows
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91654:16f97608b715 Date: 2017-05-06 11:46 +0200 http://bitbucket.org/pypy/pypy/changeset/16f97608b715/ Log:As os.link() implementation on Windows diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py --- a/pypy/module/posix/__init__.py +++ b/pypy/module/posix/__init__.py @@ -69,6 +69,7 @@ 'chmod': 'interp_posix.chmod', 'rename': 'interp_posix.rename', 'replace': 'interp_posix.replace', +'link': 'interp_posix.link', 'umask': 'interp_posix.umask', '_exit': 'interp_posix._exit', 'utime': 'interp_posix.utime', @@ -109,8 +110,6 @@ interpleveldefs['killpg'] = 'interp_posix.killpg' if hasattr(os, 'getpid'): interpleveldefs['getpid'] = 'interp_posix.getpid' -if hasattr(os, 'link'): -interpleveldefs['link'] = 'interp_posix.link' if hasattr(os, 'symlink'): interpleveldefs['symlink'] = 'interp_posix.symlink' if hasattr(os, 'readlink'): diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -1296,9 +1296,17 @@ @replace_os_function('link') @specialize.argtype(0, 1) def link(oldpath, newpath): -oldpath = _as_bytes0(oldpath) -newpath = _as_bytes0(newpath) -handle_posix_error('link', c_link(oldpath, newpath)) +if not _WIN32: +oldpath = _as_bytes0(oldpath) +newpath = _as_bytes0(newpath) +handle_posix_error('link', c_link(oldpath, newpath)) +else: +traits = _preferred_traits(path1) +win32traits = make_win32_traits(traits) +oldpath = traits.as_str0(oldpath) +newpath = traits.as_str0(newpath) +if not win32traits.CreateHardLink(newpath, oldpath, None): +raise rwin32.lastSavedWindowsError() @replace_os_function('symlink') @specialize.argtype(0, 1) diff --git a/rpython/rlib/rwin32file.py b/rpython/rlib/rwin32file.py --- a/rpython/rlib/rwin32file.py +++ b/rpython/rlib/rwin32file.py @@ -234,6 +234,12 @@ rwin32.BOOL, save_err=rffi.RFFI_SAVE_LASTERROR) +CreateHardLink = external( +'CreateHardLink' + suffix, +[traits.CCHARP, traits.CCHARP, rwin32.LPSECURITY_ATTRIBUTES], +rwin32.BOOL, +save_err=rffi.RFFI_SAVE_LASTERROR) + return Win32Traits def make_longlong(high, low): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: ast.parse(some_ast, ...) should return its first argument.
Author: Amaury Forgeot d'ArcBranch: Changeset: r91190:0a70dce2070a Date: 2017-05-05 19:01 +0200 http://bitbucket.org/pypy/pypy/changeset/0a70dce2070a/ Log:ast.parse(some_ast, ...) should return its first argument. diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py --- a/pypy/module/__builtin__/compiling.py +++ b/pypy/module/__builtin__/compiling.py @@ -38,6 +38,8 @@ "compile() arg 3 must be 'exec', 'eval' or 'single'") if space.isinstance_w(w_source, space.gettypeobject(ast.W_AST.typedef)): +if flags & consts.PyCF_ONLY_AST: +return w_source ast_node = ast.mod.from_object(space, w_source) return ec.compiler.compile_ast(ast_node, filename, mode, flags) diff --git a/pypy/module/__builtin__/test/test_compile.py b/pypy/module/__builtin__/test/test_compile.py --- a/pypy/module/__builtin__/test/test_compile.py +++ b/pypy/module/__builtin__/test/test_compile.py @@ -50,7 +50,8 @@ co1 = compile('print 1', '', 'exec', _ast.PyCF_ONLY_AST) raises(TypeError, compile, co1, '', 'eval') co2 = compile('1+1', '', 'eval', _ast.PyCF_ONLY_AST) -compile(co2, '', 'eval') +tree = compile(co2, '', 'eval') +assert compile(co2, '', 'eval', _ast.PyCF_ONLY_AST) is co2 def test_leading_newlines(self): src = """ ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Populate tp_descr_get and tp_descr_set slots
Author: Amaury Forgeot d'ArcBranch: Changeset: r91188:5b724c72fb87 Date: 2017-05-01 02:07 +0200 http://bitbucket.org/pypy/pypy/changeset/5b724c72fb87/ Log:Populate tp_descr_get and tp_descr_set slots diff --git a/pypy/module/cpyext/test/test_userslots.py b/pypy/module/cpyext/test/test_userslots.py --- a/pypy/module/cpyext/test/test_userslots.py +++ b/pypy/module/cpyext/test/test_userslots.py @@ -47,6 +47,33 @@ w_year = space.getattr(w_obj, space.newtext('year')) assert space.int_w(w_year) == 1 +def test_descr_slots(self, space, api): +w_descr = space.appexec([], """(): +class Descr(object): +def __get__(self, obj, type): +return 42 +def __set__(self, obj, value): +obj.append('set') +def __delete__(self, obj): +obj.append('del') +return Descr() +""") +w_descrtype = space.type(w_descr) +py_descr = make_ref(space, w_descr) +py_descrtype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_descrtype)) +w_obj = space.newlist([]) +py_obj = make_ref(space, w_obj) +w_res = generic_cpy_call(space, py_descrtype.c_tp_descr_get, + py_descr, py_obj, py_obj) +assert space.int_w(w_res) == 42 +assert generic_cpy_call( +space, py_descrtype.c_tp_descr_set, +py_descr, py_obj, make_ref(space, space.w_None)) == 0 +assert generic_cpy_call( +space, py_descrtype.c_tp_descr_set, +py_descr, py_obj, None) == 0 +assert space.eq_w(w_obj, space.wrap(['set', 'del'])) + class AppTestUserSlots(AppTestCpythonExtensionBase): def test_tp_hash_from_python(self): # to see that the functions are being used, diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py --- a/pypy/module/cpyext/userslot.py +++ b/pypy/module/cpyext/userslot.py @@ -109,4 +109,14 @@ def slot_tp_getattr(space, w_obj1, w_obj2): return space.getattr(w_obj1, w_obj2) +@slot_function([PyObject, PyObject, PyObject], PyObject) +def slot_tp_descr_get(space, w_self, w_obj, w_type): +return space.get(w_self, w_obj, w_type) +@slot_function([PyObject, PyObject, PyObject], rffi.INT_real, error=-1) +def slot_tp_descr_set(space, w_self, w_obj, w_value): +if w_value is not None: +space.set(w_self, w_obj, w_value) +else: +space.delete(w_self, w_obj) +return 0 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Issue 2551: Struct should be initialized in __init__, not __new__
Author: Amaury Forgeot d'ArcBranch: Changeset: r91189:f452cdf49d49 Date: 2017-05-04 00:23 +0200 http://bitbucket.org/pypy/pypy/changeset/f452cdf49d49/ Log:Issue 2551: Struct should be initialized in __init__, not __new__ diff --git a/pypy/module/struct/interp_struct.py b/pypy/module/struct/interp_struct.py --- a/pypy/module/struct/interp_struct.py +++ b/pypy/module/struct/interp_struct.py @@ -115,16 +115,17 @@ class W_Struct(W_Root): _immutable_fields_ = ["format", "size"] -def __init__(self, space, format): +format = "" +size = -1 + +def descr__new__(space, w_subtype, __args__): +return space.allocate_instance(W_Struct, w_subtype) + +@unwrap_spec(format='text') +def descr__init__(self, space, format): self.format = format self.size = _calcsize(space, format) -@unwrap_spec(format='text') -def descr__new__(space, w_subtype, format): -self = space.allocate_instance(W_Struct, w_subtype) -W_Struct.__init__(self, space, format) -return self - def descr_pack(self, space, args_w): return pack(space, jit.promote_string(self.format), args_w) @@ -141,6 +142,7 @@ W_Struct.typedef = TypeDef("Struct", __new__=interp2app(W_Struct.descr__new__.im_func), +__init__=interp2app(W_Struct.descr__init__), format=interp_attrproperty("format", cls=W_Struct, wrapfn="newbytes"), size=interp_attrproperty("size", cls=W_Struct, wrapfn="newint"), diff --git a/pypy/module/struct/test/test_struct.py b/pypy/module/struct/test/test_struct.py --- a/pypy/module/struct/test/test_struct.py +++ b/pypy/module/struct/test/test_struct.py @@ -429,6 +429,14 @@ assert s.unpack(s.pack(42)) == (42,) assert s.unpack_from(memoryview(s.pack(42))) == (42,) +def test_struct_subclass(self): +class S(self.struct.Struct): +def __init__(self): +assert self.size == -1 +super(S, self).__init__('c') +assert self.size == 1 +assert S().unpack('a') == ('a',) + def test_overflow(self): raises(self.struct.error, self.struct.pack, 'i', 1<<65) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Add a fake getwindowsversion()._platform_version, so that platform.win32_ver() can return something.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91175:09eee048800a Date: 2017-05-03 08:20 +0200 http://bitbucket.org/pypy/pypy/changeset/09eee048800a/ Log:Add a fake getwindowsversion()._platform_version, so that platform.win32_ver() can return something. (it will always be the "compatibility mode" version, I'm not sure what this really means) diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py --- a/pypy/module/sys/vm.py +++ b/pypy/module/sys/vm.py @@ -234,6 +234,7 @@ service_pack_minor = structseqfield(11, "Service Pack minor version number") suite_mask = structseqfield(12, "Bit mask identifying available product suites") product_type = structseqfield(13, "System product type") +_platform_version = structseqfield(14, "Diagnostic version number") ''') @@ -251,6 +252,9 @@ space.newint(info[6]), space.newint(info[7]), space.newint(info[8]), +# leave _platform_version empty, platform.py will use the main +# version numbers above. +space.w_None, ]) return space.call_function(w_windows_version_info, raw_version) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: oops, SetErrorMode is in kernel32.dll
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91174:c170bb968e18 Date: 2017-05-02 23:44 +0200 http://bitbucket.org/pypy/pypy/changeset/c170bb968e18/ Log:oops, SetErrorMode is in kernel32.dll diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py --- a/lib_pypy/msvcrt.py +++ b/lib_pypy/msvcrt.py @@ -16,6 +16,7 @@ import _rawffi from _pypy_winbase_cffi import ffi as _ffi _lib = _ffi.dlopen(_rawffi.get_libc().name) +_kernel32 = _ffi.dlopen('kernel32') import errno @@ -123,7 +124,7 @@ if _lib._ungetwch(ord(ch)) == -1: # EOF _ioerr() -SetErrorMode = _lib.SetErrorMode +SetErrorMode = _kernel32.SetErrorMode SEM_FAILCRITICALERRORS = _lib.SEM_FAILCRITICALERRORS SEM_NOGPFAULTERRORBOX = _lib.SEM_NOGPFAULTERRORBOX SEM_NOALIGNMENTFAULTEXCEPT = _lib.SEM_NOALIGNMENTFAULTEXCEPT ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Expose msvcrt.SetErrorMode
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91173:b2b8897fa2d1 Date: 2017-05-02 22:06 +0200 http://bitbucket.org/pypy/pypy/changeset/b2b8897fa2d1/ Log:Expose msvcrt.SetErrorMode diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py --- a/lib_pypy/msvcrt.py +++ b/lib_pypy/msvcrt.py @@ -122,3 +122,9 @@ def ungetwch(ch): if _lib._ungetwch(ord(ch)) == -1: # EOF _ioerr() + +SetErrorMode = _lib.SetErrorMode +SEM_FAILCRITICALERRORS = _lib.SEM_FAILCRITICALERRORS +SEM_NOGPFAULTERRORBOX = _lib.SEM_NOGPFAULTERRORBOX +SEM_NOALIGNMENTFAULTEXCEPT = _lib.SEM_NOALIGNMENTFAULTEXCEPT +SEM_NOOPENFILEERRORBOX = _lib.SEM_NOOPENFILEERRORBOX ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: hg merge default
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91162:7e5247599a57 Date: 2017-05-02 00:48 +0200 http://bitbucket.org/pypy/pypy/changeset/7e5247599a57/ Log:hg merge default diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py --- a/lib_pypy/_ctypes/structure.py +++ b/lib_pypy/_ctypes/structure.py @@ -233,6 +233,9 @@ if ('_abstract_' in cls.__dict__ or cls is Structure or cls is union.Union): raise TypeError("abstract class") +if hasattr(cls, '_swappedbytes_'): +raise NotImplementedError("missing in PyPy: structure/union with " + "swapped (non-native) byte ordering") if hasattr(cls, '_ffistruct_'): self.__dict__['_buffer'] = self._ffistruct_(autofree=True) return self diff --git a/lib_pypy/_pypy_winbase_build.py b/lib_pypy/_pypy_winbase_build.py --- a/lib_pypy/_pypy_winbase_build.py +++ b/lib_pypy/_pypy_winbase_build.py @@ -76,6 +76,9 @@ HANDLE WINAPI GetCurrentProcess(void); BOOL WINAPI DuplicateHandle(HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, BOOL, DWORD); +BOOL WINAPI CreateProcessA(char *, char *, void *, + void *, BOOL, DWORD, char *, + char *, LPSTARTUPINFO, LPPROCESS_INFORMATION); BOOL WINAPI CreateProcessW(wchar_t *, wchar_t *, void *, void *, BOOL, DWORD, wchar_t *, wchar_t *, LPSTARTUPINFO, LPPROCESS_INFORMATION); @@ -84,6 +87,12 @@ BOOL WINAPI TerminateProcess(HANDLE, UINT); HANDLE WINAPI GetStdHandle(DWORD); DWORD WINAPI GetModuleFileNameW(HANDLE, wchar_t *, DWORD); + +UINT WINAPI SetErrorMode(UINT); +#define SEM_FAILCRITICALERRORS 0x0001 +#define SEM_NOGPFAULTERRORBOX 0x0002 +#define SEM_NOALIGNMENTFAULTEXCEPT 0x0004 +#define SEM_NOOPENFILEERRORBOX 0x8000 """) # diff --git a/lib_pypy/_pypy_winbase_cffi.py b/lib_pypy/_pypy_winbase_cffi.py --- a/lib_pypy/_pypy_winbase_cffi.py +++ b/lib_pypy/_pypy_winbase_cffi.py @@ -3,8 +3,8 @@ ffi = _cffi_backend.FFI('_pypy_winbase_cffi', _version = 0x2601, -_types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x09\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x19\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x15\x03\x00\x00\x13\x11\x00\x00\x59\x03\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x08\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x16\x03\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x13\x11\x00\x00\x0A\x01\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x4C\x03\x00\x00\x2D\x11\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x2D\x11\x00\x00\x2D\x11\x00\x00\x54\x03\x00\x00\x53\x03\x00\x00\x02\x0F\x00\x00\x0D\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x16\x0D\x00\x00\x15\x11\x00\x 00\x0A\x01\x00\x00\x02\x0F\x00\x00\x16\x0D\x00\x00\x15\x11\x00\x00\x2D\x11\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x16\x0D\x00\x00\x02\x0F\x00\x00\x47\x0D\x00\x00\x06\x01\x00\x00\x00\x0F\x00\x00\x47\x0D\x00\x00\x00\x0F\x00\x00\x47\x0D\x00\x00\x10\x01\x00\x00\x00\x0F\x00\x00\x15\x0D\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x15\x0D\x00\x00\x02\x0F\x00\x00\x00\x09\x00\x00\x01\x09\x00\x00\x56\x03\x00\x00\x02\x01\x00\x00\x58\x03\x00\x00\x04\x01\x00\x00\x00\x01', -_globals = (b'\x00\x00\x18\x23CloseHandle',0,b'\x00\x00\x12\x23CreatePipe',0,b'\x00\x00\x2C\x23CreateProcessW',0,b'\x00\x00\x23\x23DuplicateHandle',0,b'\x00\x00\x51\x23GetCurrentProcess',0,b'\x00\x00\x1F\x23GetExitCodeProcess',0,b'\x00\x00\x3F\x23GetModuleFileNameW',0,b'\x00\x00\x4E\x23GetStdHandle',0,b'\x00\x00\x44\x23GetVersion',0,b'\x00\x00\x1B\x23TerminateProcess',0,b'\x00\x00\x3B\x23WaitForSingleObject',0,b'\x00\x00\x38\x23_get_osfhandle',0,b'\x00\x00\x10\x23_getch',0,b'\x00\x00\x10\x23_getche',0,b'\x00\x00\x49\x23_getwch',0,b'\x00\x00\x49\x23_getwche',0,b'\x00\x00\x10\x23_kbhit',0,b'\x00\x00\x07\x23_locking',0,b'\x00\x00\x0C\x23_open_osfhandle',0,b'\x00\x00\x00\x23_putch',0,b'\x00\x00\x4B\x23_putwch',0,b'\x00\x00\x03\x23_setmode',0,b'\x00\x00\x00\x23_ungetch',0,b'\x00\x00\x46\x23_ungetwch',0), -_struct_unions =
[pypy-commit] pypy py3.5: Disable lone surrogates in utf-16 and utf-32 encoders
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91155:1ca1708d0606 Date: 2017-04-19 15:28 +0200 http://bitbucket.org/pypy/pypy/changeset/1ca1708d0606/ Log:Disable lone surrogates in utf-16 and utf-32 encoders diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py --- a/pypy/module/_codecs/interp_codecs.py +++ b/pypy/module/_codecs/interp_codecs.py @@ -629,6 +629,21 @@ wrap_encoder.func_name = rname globals()[name] = wrap_encoder +def make_utf_encoder_wrapper(name): +rname = "unicode_encode_%s" % (name.replace("_encode", ""), ) +assert hasattr(runicode, rname) +@unwrap_spec(uni=unicode, errors='text_or_none') +def wrap_encoder(space, uni, errors="strict"): +if errors is None: +errors = 'strict' +state = space.fromcache(CodecState) +func = getattr(runicode, rname) +result = func(uni, len(uni), errors, state.encode_error_handler, + allow_surrogates=False) +return space.newtuple([space.newbytes(result), space.newint(len(uni))]) +wrap_encoder.func_name = rname +globals()[name] = wrap_encoder + def make_decoder_wrapper(name): rname = "str_decode_%s" % (name.replace("_decode", ""), ) assert hasattr(runicode, rname) @@ -650,16 +665,20 @@ "ascii_encode", "latin_1_encode", "utf_7_encode", + "unicode_escape_encode", + "raw_unicode_escape_encode", +]: +make_encoder_wrapper(encoder) + +for encoder in [ "utf_16_encode", "utf_16_be_encode", "utf_16_le_encode", "utf_32_encode", "utf_32_be_encode", "utf_32_le_encode", - "unicode_escape_encode", - "raw_unicode_escape_encode", ]: -make_encoder_wrapper(encoder) +make_utf_encoder_wrapper(encoder) for decoder in [ "ascii_decode", diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -758,6 +758,11 @@ s = "\u5678".encode("latin-1", "test.bad_handler") assert s == b'\xe9' +def test_lone_surrogates(self): +for encoding in ('utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', + 'utf-32', 'utf-32-le', 'utf-32-be'): +raises(UnicodeEncodeError, u'\ud800'.encode, encoding) + def test_charmap_encode(self): assert 'xxx'.encode('charmap') == b'xxx' ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Issue 2548: os.utime() would return incorrect errno.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91156:7f6e04d6d012 Date: 2017-05-01 00:13 +0200 http://bitbucket.org/pypy/pypy/changeset/7f6e04d6d012/ Log:Issue 2548: os.utime() would return incorrect errno. diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -582,8 +582,11 @@ def test_utime_raises(self): os = self.posix +import errno raises(TypeError, "os.utime('xxx', 3)") -raises(OSError, "os.utime('somefilewhichihopewouldneverappearhere', None)") +exc = raises(OSError, + "os.utime('somefilewhichihopewouldneverappearhere', None)") +assert exc.value.errno == errno.ENOENT for name in rposix.WAIT_MACROS: if hasattr(os, name): diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -2057,8 +2057,10 @@ raise OSError(get_saved_errno(), "execve failed") if HAVE_LINKAT: -c_linkat = external('linkat', -[rffi.INT, rffi.CCHARP, rffi.INT, rffi.CCHARP, rffi.INT], rffi.INT) +c_linkat = external( +'linkat', +[rffi.INT, rffi.CCHARP, rffi.INT, rffi.CCHARP, rffi.INT], rffi.INT, +save_err=rffi.RFFI_SAVE_ERRNO) def linkat(src, dst, src_dir_fd=AT_FDCWD, dst_dir_fd=AT_FDCWD, follow_symlinks=True): @@ -2073,7 +2075,8 @@ handle_posix_error('linkat', error) if HAVE_FUTIMENS: -c_futimens = external('futimens', [rffi.INT, TIMESPEC2P], rffi.INT) +c_futimens = external('futimens', [rffi.INT, TIMESPEC2P], rffi.INT, + save_err=rffi.RFFI_SAVE_ERRNO) def futimens(fd, atime, atime_ns, mtime, mtime_ns): l_times = lltype.malloc(TIMESPEC2P.TO, 2, flavor='raw') @@ -2086,8 +2089,10 @@ handle_posix_error('futimens', error) if HAVE_UTIMENSAT: -c_utimensat = external('utimensat', -[rffi.INT, rffi.CCHARP, TIMESPEC2P, rffi.INT], rffi.INT) +c_utimensat = external( +'utimensat', +[rffi.INT, rffi.CCHARP, TIMESPEC2P, rffi.INT], rffi.INT, +save_err=rffi.RFFI_SAVE_ERRNO) def utimensat(pathname, atime, atime_ns, mtime, mtime_ns, dir_fd=AT_FDCWD, follow_symlinks=True): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Chain exceptions when close() contains multiple operations that can fail.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91087:0f983f4075de Date: 2017-04-18 19:03 +0200 http://bitbucket.org/pypy/pypy/changeset/0f983f4075de/ Log:Chain exceptions when close() contains multiple operations that can fail. diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py --- a/pypy/module/_io/interp_bufferedio.py +++ b/pypy/module/_io/interp_bufferedio.py @@ -1030,7 +1030,12 @@ raise oefmt(space.w_ValueError, "I/O operation on uninitialized object") w_meth = space.getattr(self.w_reader, space.newtext("close")) -space.call_args(w_meth, __args__) +try: +space.call_args(w_meth, __args__) +except OperationError as e2: +if e: +e2.chain_exceptions(space, e) +e = e2 if e: raise e diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -528,13 +528,20 @@ def close_w(self, space): self._check_attached(space) -if not space.is_true(space.getattr(self.w_buffer, - space.newtext("closed"))): +if space.is_true(space.getattr(self.w_buffer, + space.newtext("closed"))): +return +try: +space.call_method(self, "flush") +except OperationError as e: try: -space.call_method(self, "flush") -finally: ret = space.call_method(self.w_buffer, "close") -return ret +except OperationError as e2: +e2.chain_exceptions(space, e) +raise +else: +ret = space.call_method(self.w_buffer, "close") +return ret def _dealloc_warn_w(self, space, w_source): space.call_method(self.w_buffer, "_dealloc_warn", w_source) diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py --- a/pypy/module/_io/test/test_bufferedio.py +++ b/pypy/module/_io/test/test_bufferedio.py @@ -707,6 +707,7 @@ pair = _io.BufferedRWPair(reader, writer) err = raises(NameError, pair.close) assert 'reader_non_existing' in str(err.value) +assert 'writer_non_existing' in str(err.value.__context__) assert not pair.closed assert not reader.closed assert not writer.closed diff --git a/pypy/module/_io/test/test_textio.py b/pypy/module/_io/test/test_textio.py --- a/pypy/module/_io/test/test_textio.py +++ b/pypy/module/_io/test/test_textio.py @@ -365,6 +365,22 @@ raises(IOError, txt.close) # exception not swallowed assert txt.closed +def test_close_error_on_close(self): +import _io as io +buffer = io.BytesIO(b'testdata') +def bad_flush(): +raise OSError('flush') +def bad_close(): +raise OSError('close') +buffer.close = bad_close +txt = io.TextIOWrapper(buffer, encoding="ascii") +txt.flush = bad_flush +err = raises(OSError, txt.close) +assert err.value.args == ('close',) +assert isinstance(err.value.__context__, OSError) +assert err.value.__context__.args == ('flush',) +assert not txt.closed + def test_illegal_decoder(self): import _io raises(LookupError, _io.TextIOWrapper, _io.BytesIO(), ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: CPython Issue #21396: write_through=True doesn't force a flush() on the underlying binary buffered object.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91088:15ee4ffa4842 Date: 2017-04-18 19:11 +0200 http://bitbucket.org/pypy/pypy/changeset/15ee4ffa4842/ Log:CPython Issue #21396: write_through=True doesn't force a flush() on the underlying binary buffered object. diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -801,9 +801,10 @@ text = space.unicode_w(w_text) needflush = False +text_needflush = False if self.write_through: -needflush = True -elif self.line_buffering and (haslf or text.find(u'\r') >= 0): +text_needflush = True +if self.line_buffering and (haslf or text.find(u'\r') >= 0): needflush = True # XXX What if we were just reading? @@ -820,7 +821,8 @@ self.pending_bytes.append(b) self.pending_bytes_count += len(b) -if self.pending_bytes_count > self.chunk_size or needflush: +if (self.pending_bytes_count > self.chunk_size or +needflush or text_needflush): self._writeflush(space) if needflush: diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py --- a/pypy/module/_io/test/test_bufferedio.py +++ b/pypy/module/_io/test/test_bufferedio.py @@ -291,6 +291,39 @@ raises(_io.UnsupportedOperation, bufio.seek, 0) raises(_io.UnsupportedOperation, bufio.tell) +def test_bufio_write_through(self): +import _io as io +# Issue #21396: write_through=True doesn't force a flush() +# on the underlying binary buffered object. +flush_called, write_called = [], [] +class BufferedWriter(io.BufferedWriter): +def flush(self, *args, **kwargs): +flush_called.append(True) +return super().flush(*args, **kwargs) +def write(self, *args, **kwargs): +write_called.append(True) +return super().write(*args, **kwargs) + +rawio = io.BytesIO() +data = b"a" +bufio = BufferedWriter(rawio, len(data)*2) +textio = io.TextIOWrapper(bufio, encoding='ascii', + write_through=True) +# write to the buffered io but don't overflow the buffer +text = data.decode('ascii') +textio.write(text) + +# buffer.flush is not called with write_through=True +assert not flush_called +# buffer.write *is* called with write_through=True +assert write_called +assert rawio.getvalue() == b"" # no flush + +write_called = [] # reset +textio.write(text * 10) # total content is larger than bufio buffer +assert write_called +assert rawio.getvalue() == data * 11 # all flushed + class AppTestBufferedReaderWithThreads(AppTestBufferedReader): spaceconfig = dict(usemodules=['_io', 'thread', 'time']) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Python Issue #21310: Fixed possible resource leak in failed open()
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91086:af84269c028b Date: 2017-04-18 18:37 +0200 http://bitbucket.org/pypy/pypy/changeset/af84269c028b/ Log:Python Issue #21310: Fixed possible resource leak in failed open() diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py --- a/pypy/module/_io/interp_io.py +++ b/pypy/module/_io/interp_io.py @@ -86,46 +86,61 @@ if binary and newline is not None: raise oefmt(space.w_ValueError, "binary mode doesn't take a newline argument") -w_raw = space.call_function( -space.gettypefor(W_FileIO), w_file, space.newtext(rawmode), -space.newbool(bool(closefd)), w_opener) -isatty = space.is_true(space.call_method(w_raw, "isatty")) -line_buffering = buffering == 1 or (buffering < 0 and isatty) -if line_buffering: -buffering = -1 +w_result = None +try: +w_raw = space.call_function( +space.gettypefor(W_FileIO), w_file, space.newtext(rawmode), +space.newbool(bool(closefd)), w_opener) +w_result = w_raw -if buffering < 0: -buffering = space.c_int_w(space.getattr(w_raw, space.newtext("_blksize"))) +isatty = space.is_true(space.call_method(w_raw, "isatty")) +line_buffering = buffering == 1 or (buffering < 0 and isatty) +if line_buffering: +buffering = -1 -if buffering < 0: -raise oefmt(space.w_ValueError, "invalid buffering size") +if buffering < 0: +buffering = space.c_int_w(space.getattr( +w_raw, space.newtext("_blksize"))) -if buffering == 0: -if not binary: -raise oefmt(space.w_ValueError, "can't have unbuffered text I/O") -return w_raw +if buffering < 0: +raise oefmt(space.w_ValueError, "invalid buffering size") -if updating: -buffer_cls = W_BufferedRandom -elif writing or creating or appending: -buffer_cls = W_BufferedWriter -elif reading: -buffer_cls = W_BufferedReader -else: -raise oefmt(space.w_ValueError, "unknown mode: '%s'", mode) -w_buffer = space.call_function( -space.gettypefor(buffer_cls), w_raw, space.newint(buffering) -) -if binary: -return w_buffer +if buffering == 0: +if not binary: +raise oefmt(space.w_ValueError, +"can't have unbuffered text I/O") +return w_result -w_wrapper = space.call_function(space.gettypefor(W_TextIOWrapper), -w_buffer, -space.newtext_or_none(encoding), -space.newtext_or_none(errors), -space.newtext_or_none(newline), -space.newbool(line_buffering) -) -space.setattr(w_wrapper, space.newtext("mode"), space.newtext(mode)) -return w_wrapper +if updating: +buffer_cls = W_BufferedRandom +elif writing or creating or appending: +buffer_cls = W_BufferedWriter +elif reading: +buffer_cls = W_BufferedReader +else: +raise oefmt(space.w_ValueError, "unknown mode: '%s'", mode) +w_buffer = space.call_function( +space.gettypefor(buffer_cls), w_raw, space.newint(buffering) +) +w_result = w_buffer +if binary: +return w_result + +w_wrapper = space.call_function(space.gettypefor(W_TextIOWrapper), +w_buffer, +space.newtext_or_none(encoding), +space.newtext_or_none(errors), +space.newtext_or_none(newline), +space.newbool(line_buffering) +) +w_result = w_wrapper +space.setattr(w_wrapper, space.newtext("mode"), space.newtext(mode)) +return w_result +except OperationError as e: +if w_result: +try: +space.call_method(w_result, "close") +except OperationError as e2: +e.chain_exceptions(space, e2) +raise diff --git a/pypy/module/_io/test/test_io.py b/pypy/module/_io/test/test_io.py --- a/pypy/module/_io/test/test_io.py +++ b/pypy/module/_io/test/test_io.py @@ -474,6 +474,22 @@ assert f.mode == 'x' raises(FileExistsError, _io.open, filename, 'x') +def test_nonbuffered_textio(self): +import warnings, _io as io +filename = self.tmpfile + '_x2' +warnings.simplefilter("always", category=ResourceWarning) +with warnings.catch_warnings(record=True) as recorded: +raises(ValueError, io.open, filename, 'w', buffering=0) +assert recorded == [] + +def test_invalid_newline(self): +import warnings, _io as io +filename = self.tmpfile + '_x2' +warnings.simplefilter("always", category=ResourceWarning) +with warnings.catch_warnings(record=True) as recorded: +raises(ValueError, io.open, filename, 'w', newline='invalid')
[pypy-commit] pypy py3.5: CPython Issue #22982: Improve BOM handling when seeking to multiple positions of a writable text file.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91089:32c611c850d8 Date: 2017-04-18 22:12 +0200 http://bitbucket.org/pypy/pypy/changeset/32c611c850d8/ Log:CPython Issue #22982: Improve BOM handling when seeking to multiple positions of a writable text file. diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -878,14 +878,18 @@ space.newtuple([space.newbytes(""), space.newint(cookie.dec_flags)])) -def _encoder_setstate(self, space, cookie): -if cookie.start_pos == 0 and cookie.dec_flags == 0: +def _encoder_reset(self, space, start_of_stream): +if start_of_stream: space.call_method(self.w_encoder, "reset") self.encoding_start_of_stream = True else: space.call_method(self.w_encoder, "setstate", space.newint(0)) self.encoding_start_of_stream = False +def _encoder_setstate(self, space, cookie): +self._encoder_reset(space, +cookie.start_pos == 0 and cookie.dec_flags == 0) + @unwrap_spec(whence=int) def seek_w(self, space, w_pos, whence=0): self._check_attached(space) @@ -913,8 +917,13 @@ self.snapshot = None if self.w_decoder: space.call_method(self.w_decoder, "reset") -return space.call_method(self.w_buffer, "seek", - w_pos, space.newint(whence)) +w_res = space.call_method(self.w_buffer, "seek", + w_pos, space.newint(whence)) +if self.w_encoder: +# If seek() == 0, we are at the start of stream +start_of_stream = space.eq_w(w_res, space.newint(0)) +self._encoder_reset(space, start_of_stream) +return w_res elif whence != 0: raise oefmt(space.w_ValueError, diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -302,6 +302,36 @@ return -1 raises(ValueError, _io.FileIO, "foo", 'r', opener=opener) +def test_seek_bom(self): +# The BOM is not written again when seeking manually +import _io +filename = self.tmpfile + '_x3' +for charset in ('utf-8-sig', 'utf-16', 'utf-32'): +with _io.open(filename, 'w', encoding=charset) as f: +f.write('aaa') +pos = f.tell() +with _io.open(filename, 'r+', encoding=charset) as f: +f.seek(pos) +f.write('zzz') +f.seek(0) +f.write('bbb') +with _io.open(filename, 'rb') as f: +assert f.read() == 'bbbzzz'.encode(charset) + +def test_seek_append_bom(self): +# Same test, but first seek to the start and then to the end +import _io, os +filename = self.tmpfile + '_x3' +for charset in ('utf-8-sig', 'utf-16', 'utf-32'): +with _io.open(filename, 'w', encoding=charset) as f: +f.write('aaa') +with _io.open(filename, 'a', encoding=charset) as f: +f.seek(0) +f.seek(0, os.SEEK_END) +f.write('xxx') +with _io.open(filename, 'rb') as f: +assert f.read() == 'aaaxxx'.encode(charset) + def test_flush_at_exit(): from pypy import conftest ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Add support for rejecting lone surrogates in utf16 and utf32 decoders.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91090:7ce52a9f8d1f Date: 2017-04-19 00:53 +0200 http://bitbucket.org/pypy/pypy/changeset/7ce52a9f8d1f/ Log:Add support for rejecting lone surrogates in utf16 and utf32 decoders. diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -591,7 +591,10 @@ def unicode_encode_utf_16_helper(s, size, errors, errorhandler=None, + allow_surrogates=True, byteorder='little'): +if errorhandler is None: +errorhandler = default_unicode_error_encode if size == 0: if byteorder == 'native': result = StringBuilder(2) @@ -604,34 +607,60 @@ _STORECHAR(result, 0xFEFF, BYTEORDER) byteorder = BYTEORDER -i = 0 -while i < size: -ch = ord(s[i]) -i += 1 -ch2 = 0 -if ch >= 0x1: -ch2 = 0xDC00 | ((ch-0x1) & 0x3FF) -ch = 0xD800 | ((ch-0x1) >> 10) +pos = 0 +while pos < size: +ch = ord(s[pos]) +pos += 1 -_STORECHAR(result, ch, byteorder) -if ch2: -_STORECHAR(result, ch2, byteorder) +if ch < 0xD800: +_STORECHAR(result, ch, byteorder) +elif ch >= 0x1: +_STORECHAR(result, 0xD800 | ((ch-0x1) >> 10), byteorder) +_STORECHAR(result, 0xDC00 | ((ch-0x1) & 0x3FF), byteorder) +elif ch >= 0xE000 or allow_surrogates: +_STORECHAR(result, ch, byteorder) +else: +ru, rs, pos = errorhandler(errors, 'utf16', + 'surrogates not allowed', + s, pos-1, pos) +if rs is not None: +# py3k only +if len(rs) % 2 != 0: +errorhandler('strict', 'utf16', + 'surrogates not allowed', + s, pos-1, pos) +result.append(rs) +continue +for ch in ru: +if ord(ch) < 0xD800: +_STORECHAR(result, ord(ch), byteorder) +else: +errorhandler('strict', 'utf16', + 'surrogates not allowed', + s, pos-1, pos) +continue return result.build() def unicode_encode_utf_16(s, size, errors, - errorhandler=None): -return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "native") + errorhandler=None, + allow_surrogates=True): +return unicode_encode_utf_16_helper(s, size, errors, errorhandler, +allow_surrogates, "native") def unicode_encode_utf_16_be(s, size, errors, - errorhandler=None): -return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "big") + errorhandler=None, + allow_surrogates=True): +return unicode_encode_utf_16_helper(s, size, errors, errorhandler, +allow_surrogates, "big") def unicode_encode_utf_16_le(s, size, errors, - errorhandler=None): -return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "little") + errorhandler=None, + allow_surrogates=True): +return unicode_encode_utf_16_helper(s, size, errors, errorhandler, +allow_surrogates, "little") # @@ -756,7 +785,10 @@ def unicode_encode_utf_32_helper(s, size, errors, errorhandler=None, + allow_surrogates=True, byteorder='little'): +if errorhandler is None: +errorhandler = default_unicode_error_encode if size == 0: if byteorder == 'native': result = StringBuilder(4) @@ -769,33 +801,57 @@ _STORECHAR32(result, 0xFEFF, BYTEORDER) byteorder = BYTEORDER -i = 0 -while i < size: -ch = ord(s[i]) -i += 1 +pos = 0 +while pos < size: +ch = ord(s[pos]) +pos += 1 ch2 = 0 -if MAXUNICODE < 65536 and 0xD800 <= ch <= 0xDBFF and i < size: -ch2 = ord(s[i]) -if 0xDC00 <= ch2 <= 0xDFFF: -ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x1; -i += 1 +if 0xD800 <= ch < 0xDC00: +if not allow_surrogates: +ru, rs, pos = errorhandler(errors, 'utf32', + 'surrogates not allowed',
[pypy-commit] pypy py3.5: CPython Issue #21057: TextIOWrapper now allows the underlying binary stream's read() or read1() method to return an arbitrary bytes-like object
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91085:77139bab65b2 Date: 2017-04-18 17:49 +0200 http://bitbucket.org/pypy/pypy/changeset/77139bab65b2/ Log:CPython Issue #21057: TextIOWrapper now allows the underlying binary stream's read() or read1() method to return an arbitrary bytes-like object (such as a memoryview). diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -1,6 +1,6 @@ import sys -from pypy.interpreter.baseobjspace import W_Root +from pypy.interpreter.baseobjspace import W_Root, BufferInterfaceNotFound from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec from pypy.interpreter.typedef import ( @@ -584,6 +584,10 @@ # Given this, we know there was a valid snapshot point # len(dec_buffer) bytes ago with decoder state (b'', dec_flags). w_dec_buffer, w_dec_flags = space.unpackiterable(w_state, 2) +if not space.isinstance_w(w_dec_buffer, space.w_bytes): +msg = "decoder getstate() should have returned a bytes " \ + "object not '%T'" +raise oefmt(space.w_TypeError, msg, w_dec_buffer) dec_buffer = space.bytes_w(w_dec_buffer) dec_flags = space.int_w(w_dec_flags) else: @@ -591,16 +595,18 @@ dec_flags = 0 # Read a chunk, decode it, and put the result in self._decoded_chars -w_input = space.call_method(self.w_buffer, -"read1" if self.has_read1 else "read", +func_name = "read1" if self.has_read1 else "read" +w_input = space.call_method(self.w_buffer, func_name, space.newint(self.chunk_size)) -if not space.isinstance_w(w_input, space.w_bytes): -msg = "decoder getstate() should have returned a bytes " \ - "object not '%T'" -raise oefmt(space.w_TypeError, msg, w_input) +try: +input_buf = w_input.buffer_w(space, space.BUF_SIMPLE) +except BufferInterfaceNotFound: +msg = ("underlying %s() should have returned a bytes-like " + "object, not '%T'") +raise oefmt(space.w_TypeError, msg, func_name, w_input) -eof = space.len_w(w_input) == 0 +eof = input_buf.getlength() == 0 w_decoded = space.call_method(self.w_decoder, "decode", w_input, space.newbool(eof)) check_decoded(space, w_decoded) @@ -611,7 +617,7 @@ if self.telling: # At the snapshot point, len(dec_buffer) bytes before the read, # the next input to be decoded is dec_buffer + input_chunk. -next_input = dec_buffer + space.bytes_w(w_input) +next_input = dec_buffer + input_buf.as_str() self.snapshot = PositionSnapshot(dec_flags, next_input) return not eof diff --git a/pypy/module/_io/test/test_textio.py b/pypy/module/_io/test/test_textio.py --- a/pypy/module/_io/test/test_textio.py +++ b/pypy/module/_io/test/test_textio.py @@ -1,5 +1,5 @@ class AppTestTextIO: -spaceconfig = dict(usemodules=['_io', '_locale']) +spaceconfig = dict(usemodules=['_io', '_locale', 'array']) def setup_class(cls): from rpython.rlib.rarithmetic import INT_MAX, UINT_MAX @@ -381,6 +381,38 @@ t = _io.TextIOWrapper(NonbytesStream(u'a')) raises(TypeError, t.read) +def test_read_byteslike(self): +import _io as io +import array + +class MemviewBytesIO(io.BytesIO): +'''A BytesIO object whose read method returns memoryviews + rather than bytes''' + +def read1(self, len_): +return _to_memoryview(super().read1(len_)) + +def read(self, len_): +return _to_memoryview(super().read(len_)) + +def _to_memoryview(buf): +'''Convert bytes-object *buf* to a non-trivial memoryview''' + +arr = array.array('i') +idx = len(buf) - len(buf) % arr.itemsize +arr.frombytes(buf[:idx]) +return memoryview(arr) + +r = MemviewBytesIO(b'Just some random string\n') +t = io.TextIOWrapper(r, 'utf-8') + +# TextIOwrapper will not read the full string, because +# we truncate it to a multiple of the native int size +# so that we can construct a more complex memoryview. +bytes_val = _to_memoryview(r.getvalue()).tobytes() + +assert t.read(200) == bytes_val.decode('utf-8') + def test_device_encoding(self): import os import sys ___ pypy-commit mailing list pypy-commit@python.org
[pypy-commit] pypy py3.5: Attempt to fix 'nonlocal' in class scopes.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91078:785e75435a92 Date: 2017-04-18 09:48 +0200 http://bitbucket.org/pypy/pypy/changeset/785e75435a92/ Log:Attempt to fix 'nonlocal' in class scopes. test_scope and test_super are passing again. diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py --- a/pypy/interpreter/astcompiler/symtable.py +++ b/pypy/interpreter/astcompiler/symtable.py @@ -135,7 +135,8 @@ err = "no binding for nonlocal '%s' found" % (name,) raise SyntaxError(err, self.lineno, self.col_offset) self.symbols[name] = SCOPE_FREE -self.free_vars.append(name) +if not self._hide_bound_from_nested_scopes: +self.free_vars.append(name) free[name] = None self.has_free = True elif flags & SYM_BOUND: ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Apply diffs from CPython, mainly:
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91075:991de0b87cdc Date: 2017-04-17 22:12 +0200 http://bitbucket.org/pypy/pypy/changeset/991de0b87cdc/ Log:Apply diffs from CPython, mainly: CPython rev 5453b9c59cd7: On systems with a functioning /proc/self/fd or /dev/fd interface the max is now ignored and all fds are closed. CPython rev e54b23d7afa6: close() must not be retried when it fails with EINTR This fixes the remaining failures in test_subprocess diff --git a/pypy/module/_posixsubprocess/_posixsubprocess.c b/pypy/module/_posixsubprocess/_posixsubprocess.c --- a/pypy/module/_posixsubprocess/_posixsubprocess.c +++ b/pypy/module/_posixsubprocess/_posixsubprocess.c @@ -18,7 +18,19 @@ #ifdef HAVE_SYS_SYSCALL_H #include #endif +#if defined(HAVE_SYS_RESOURCE_H) +#include +#endif +#ifdef HAVE_DIRENT_H #include +#endif + +#if defined(__ANDROID__) && !defined(SYS_getdents64) +/* Android doesn't expose syscalls, add the definition manually. */ +# include +# define SYS_getdents64 __NR_getdents64 +#endif + #include "_posixsubprocess.h" #if defined(sun) @@ -38,11 +50,7 @@ # define FD_DIR "/proc/self/fd" #endif -#define POSIX_CALL(call) if ((call) == -1) goto error - - -/* Maximum file descriptor, initialized on module load. */ -static long max_fd; +#define POSIX_CALL(call) do { if ((call) == -1) goto error; } while (0) /* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */ @@ -75,7 +83,7 @@ if (stat("/dev", _stat) != 0) return 0; if (stat(FD_DIR, _fd_stat) != 0) -return 0; +return 0; if (dev_stat.st_dev == dev_fd_stat.st_dev) return 0; /* / == /dev == /dev/fd means it is static. #fail */ return 1; @@ -130,15 +138,47 @@ } -/* Close all file descriptors in the range start_fd inclusive to - * end_fd exclusive except for those in py_fds_to_keep. If the - * range defined by [start_fd, end_fd) is large this will take a - * long time as it calls close() on EVERY possible fd. +/* Get the maximum file descriptor that could be opened by this process. + * This function is async signal safe for use between fork() and exec(). + */ +static long +safe_get_max_fd(void) +{ +long local_max_fd; +#if defined(__NetBSD__) +local_max_fd = fcntl(0, F_MAXFD); +if (local_max_fd >= 0) +return local_max_fd; +#endif +#if defined(HAVE_SYS_RESOURCE_H) && defined(__OpenBSD__) +struct rlimit rl; +/* Not on the POSIX async signal safe functions list but likely + * safe. TODO - Someone should audit OpenBSD to make sure. */ +if (getrlimit(RLIMIT_NOFILE, ) >= 0) +return (long) rl.rlim_max; +#endif +#ifdef _SC_OPEN_MAX +local_max_fd = sysconf(_SC_OPEN_MAX); +if (local_max_fd == -1) +#endif +local_max_fd = 256; /* Matches legacy Lib/subprocess.py behavior. */ +return local_max_fd; +} + + +/* Close all file descriptors in the range from start_fd and higher + * except for those in py_fds_to_keep. If the range defined by + * [start_fd, safe_get_max_fd()) is large this will take a long + * time as it calls close() on EVERY possible fd. + * + * It isn't possible to know for sure what the max fd to go up to + * is for processes with the capability of raising their maximum. */ static void -_close_fds_by_brute_force(int start_fd, int end_fd, long *py_fds_to_keep, +_close_fds_by_brute_force(long start_fd, long *py_fds_to_keep, ssize_t num_fds_to_keep) { +long end_fd = safe_get_max_fd(); ssize_t keep_seq_idx; int fd_num; /* As py_fds_to_keep is sorted we can loop through the list closing @@ -148,13 +188,13 @@ if (keep_fd < start_fd) continue; for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) { -while (close(fd_num) < 0 && errno == EINTR); +close(fd_num); } start_fd = keep_fd + 1; } if (start_fd <= end_fd) { for (fd_num = start_fd; fd_num < end_fd; ++fd_num) { -while (close(fd_num) < 0 && errno == EINTR); +close(fd_num); } } } @@ -175,8 +215,8 @@ char d_name[256]; /* Filename (null-terminated) */ }; -/* Close all open file descriptors in the range start_fd inclusive to end_fd - * exclusive. Do not close any in the sorted py_fds_to_keep list. +/* Close all open file descriptors in the range from start_fd and higher + * Do not close any in the sorted py_fds_to_keep list. * * This version is async signal safe as it does not make any unsafe C library * calls, malloc calls or handle any locks. It is _unfortunate_ to be forced @@ -191,12 +231,10 @@ * it with some cpp #define magic to work on other OSes as well if you want. */ static void -_close_open_fd_range_safe(int start_fd, int end_fd, long *py_fds_to_keep, +_close_open_fds_safe(int start_fd, long *py_fds_to_keep, ssize_t
[pypy-commit] pypy py3.5: Apply CPython rev 9180fb4eccc7: Raise our own SubprocessError rather than a RuntimeError
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91074:a402a0d7ee30 Date: 2017-04-17 21:35 +0200 http://bitbucket.org/pypy/pypy/changeset/a402a0d7ee30/ Log:Apply CPython rev 9180fb4eccc7: Raise our own SubprocessError rather than a RuntimeError when dealing with odd rare errors coming from the subprocess module. diff --git a/pypy/module/_posixsubprocess/_posixsubprocess.c b/pypy/module/_posixsubprocess/_posixsubprocess.c --- a/pypy/module/_posixsubprocess/_posixsubprocess.c +++ b/pypy/module/_posixsubprocess/_posixsubprocess.c @@ -491,7 +491,7 @@ /* We can't call strerror(saved_errno). It is not async signal safe. * The parent process will look the error message up. */ } else { -unused = write(errpipe_write, "RuntimeError:0:", 15); +unused = write(errpipe_write, "SubprocessError:0:", 18); unused = write(errpipe_write, err_msg, strlen(err_msg)); } if (unused) return; /* silly? yes! avoids gcc compiler warning. */ ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Use our space.objects_in_repr() dict, instead of the decorator in reprlib.py which imports too many things.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91071:6a485971d4fa Date: 2017-04-17 18:46 +0200 http://bitbucket.org/pypy/pypy/changeset/6a485971d4fa/ Log:Use our space.objects_in_repr() dict, instead of the decorator in reprlib.py which imports too many things. diff --git a/lib_pypy/_pypy_collections.py b/lib_pypy/_pypy_collections.py --- a/lib_pypy/_pypy_collections.py +++ b/lib_pypy/_pypy_collections.py @@ -1,6 +1,5 @@ -from __pypy__ import reversed_dict, move_to_end +from __pypy__ import reversed_dict, move_to_end, objects_in_repr from _operator import eq as _eq -from reprlib import recursive_repr as _recursive_repr import _collections_abc @@ -44,12 +43,21 @@ ''' return move_to_end(self, key, last) -@_recursive_repr() def __repr__(self): 'od.__repr__() <==> repr(od)' if not self: return '%s()' % (self.__class__.__name__,) -return '%s(%r)' % (self.__class__.__name__, list(self.items())) +currently_in_repr = objects_in_repr() +if self in currently_in_repr: +return '...' +currently_in_repr[self] = 1 +try: +return '%s(%r)' % (self.__class__.__name__, list(self.items())) +finally: +try: +del currently_in_repr[self] +except: +pass def __reduce__(self): 'Return state information for pickling' diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -67,6 +67,7 @@ interpleveldefs = { 'attach_gdb': 'interp_magic.attach_gdb', 'internal_repr' : 'interp_magic.internal_repr', +'objects_in_repr' : 'interp_magic.objects_in_repr', 'bytebuffer': 'bytebuffer.bytebuffer', 'identity_dict' : 'interp_identitydict.W_IdentityDict', 'debug_start' : 'interp_debug.debug_start', diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py --- a/pypy/module/__pypy__/interp_magic.py +++ b/pypy/module/__pypy__/interp_magic.py @@ -15,6 +15,14 @@ def internal_repr(space, w_object): return space.newtext('%r' % (w_object,)) +def objects_in_repr(space): +"""The identitydict of objects currently being repr(). + +This object is thread-local and can be used in a __repr__ method +to avoid recursion. +""" +return space.get_objects_in_repr() + def attach_gdb(space): """Run an interp-level gdb (or pdb when untranslated)""" diff --git a/pypy/module/_collections/test/test_ordereddict.py b/pypy/module/_collections/test/test_ordereddict.py --- a/pypy/module/_collections/test/test_ordereddict.py +++ b/pypy/module/_collections/test/test_ordereddict.py @@ -6,3 +6,9 @@ from _collections import OrderedDict assert issubclass(OrderedDict, dict) assert hasattr(OrderedDict, 'move_to_end') + +def test_recursive_repr(self): +from _collections import OrderedDict +d = OrderedDict() +d[1] = d +assert repr(d) == 'OrderedDict([(1, ...)])' ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Avoid importing the full locale module during _io initialization.
Author: Amaury Forgeot d'ArcBranch: py3.5 Changeset: r91066:db0c73821d75 Date: 2017-04-17 11:35 +0200 http://bitbucket.org/pypy/pypy/changeset/db0c73821d75/ Log:Avoid importing the full locale module during _io initialization. CPython change fbbf8b160e8d diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -290,7 +290,7 @@ try: w_locale = space.call_method(space.builtin, '__import__', - space.newtext('locale')) + space.newtext('_bootlocale')) w_encoding = space.call_method(w_locale, 'getpreferredencoding', space.w_False) except OperationError as e: ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit