[pypy-commit] pypy py3.6: Add support for FsPath to os.unlink()

2019-01-01 Thread amauryfa
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

2019-01-01 Thread amauryfa
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,

2018-12-30 Thread amauryfa
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.

2018-12-30 Thread amauryfa
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,

2018-12-29 Thread amauryfa
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()

2018-12-29 Thread amauryfa
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()

2018-12-29 Thread amauryfa
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

2018-12-29 Thread amauryfa
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''.

2018-12-29 Thread amauryfa
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

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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()

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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:

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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...

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-04-22 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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'

2018-03-05 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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__.

2018-03-05 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-03-05 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-03-05 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-03-05 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-03-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-03-01 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-03-01 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-03-01 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-02-25 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-02-25 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-02-25 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-01-06 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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

2018-01-04 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-01-04 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-01-04 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-01-04 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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.

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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()

2018-01-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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.

2017-12-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-12-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-12-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-12-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-12-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-12-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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.

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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.

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-13 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-12 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-12 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-12-12 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-11 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-11 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-11 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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()

2017-12-11 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-11 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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+'

2017-12-11 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-10 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-12-10 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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=""

2017-10-21 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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.

2017-09-27 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-06-28 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-06-27 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-06-27 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-06-27 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-05-05 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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

2017-05-05 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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__

2017-05-05 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 
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.

2017-05-03 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-05-02 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-05-02 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-05-01 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-04-30 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-04-30 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-04-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-04-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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()

2017-04-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-04-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-04-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-04-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-04-18 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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:

2017-04-17 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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

2017-04-17 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-04-17 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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.

2017-04-17 Thread amauryfa
Author: Amaury Forgeot d'Arc 
Branch: 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


  1   2   3   4   5   6   7   8   9   10   >