[pypy-commit] pypy py3.5: hg merge py3k

rlamy pypy.commits at gmail.com
Sun Sep 25 12:28:33 EDT 2016


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r87370:991b0bdd50ab
Date: 2016-09-25 17:27 +0100
http://bitbucket.org/pypy/pypy/changeset/991b0bdd50ab/

Log:	hg merge py3k

diff --git a/lib-python/3/idlelib/CallTips.py b/lib-python/3/idlelib/CallTips.py
--- a/lib-python/3/idlelib/CallTips.py
+++ b/lib-python/3/idlelib/CallTips.py
@@ -144,7 +144,8 @@
         fob = ob_call
     else:
         fob = ob
-    if isinstance(fob, (types.FunctionType, types.MethodType)):
+    if (isinstance(fob, (types.FunctionType, types.MethodType)) and
+            hasattr(fob.__code__, 'co_code')):  # PyPy: not on <builtin-code>
         argspec = inspect.formatargspec(*inspect.getfullargspec(fob))
         if (isinstance(ob, (type, types.MethodType)) or
                 isinstance(ob_call, types.MethodType)):
diff --git a/lib_pypy/_winapi.py b/lib_pypy/_winapi.py
--- a/lib_pypy/_winapi.py
+++ b/lib_pypy/_winapi.py
@@ -22,35 +22,13 @@
     code, message = _ffi.getwinerror()
     raise WindowsError(code, message)
 
-_INVALID_HANDLE_VALUE = _ffi.cast("HANDLE", -1)
+def _int2handle(val):
+    return _ffi.cast("HANDLE", val)
 
-class _handle(object):
-    def __init__(self, c_handle):
-        # 'c_handle' is a cffi cdata of type HANDLE, which is basically 'void *'
-        self.c_handle = c_handle
-        if int(self) != -1:
-            self.c_handle = _ffi.gc(self.c_handle, _kernel32.CloseHandle)
+def _handle2int(handle):
+    return int(_ffi.cast("intptr_t", handle))
 
-    def __int__(self):
-        return int(_ffi.cast("intptr_t", self.c_handle))
-
-    def __repr__(self):
-        return '<_subprocess.handle %d at 0x%x>' % (int(self), id(self))
-
-    def Detach(self):
-        h = int(self)
-        if h != -1:
-            c_handle = self.c_handle
-            self.c_handle = _INVALID_HANDLE_VALUE
-            _ffi.gc(c_handle, None)
-        return h
-
-    def Close(self):
-        if int(self) != -1:
-            c_handle = self.c_handle
-            self.c_handle = _INVALID_HANDLE_VALUE
-            _ffi.gc(c_handle, None)
-            _kernel32.CloseHandle(c_handle)
+_INVALID_HANDLE_VALUE = _int2handle(-1)
 
 def CreatePipe(attributes, size):
     handles = _ffi.new("HANDLE[2]")
@@ -60,25 +38,25 @@
     if not res:
         raise _WinError()
 
-    return _handle(handles[0]), _handle(handles[1])
+    return _handle2int(handles[0]), _handle2int(handles[1])
 
 def GetCurrentProcess():
-    return _handle(_kernel32.GetCurrentProcess())
+    return _handle2int(_kernel32.GetCurrentProcess())
 
 def DuplicateHandle(source_process, source, target_process, access, inherit, options=0):
     # CPython: the first three arguments are expected to be integers
     target = _ffi.new("HANDLE[1]")
 
     res = _kernel32.DuplicateHandle(
-        _ffi.cast("HANDLE", source_process),
-        _ffi.cast("HANDLE", source),
-        _ffi.cast("HANDLE", target_process),
+        _int2handle(source_process),
+        _int2handle(source),
+        _int2handle(target_process),
         target, access, inherit, options)
 
     if not res:
         raise _WinError()
 
-    return _handle(target[0])
+    return _handle2int(target[0])
 
 def _z(input):
     if input is None:
@@ -94,13 +72,14 @@
     if startup_info is not None:
         si.dwFlags = startup_info.dwFlags
         si.wShowWindow = startup_info.wShowWindow
-        # CPython: these three handles are expected to be _handle objects
+        # CPython: these three handles are expected to be
+        # subprocess.Handle (int) objects
         if startup_info.hStdInput:
-            si.hStdInput = startup_info.hStdInput.c_handle
+            si.hStdInput = _int2handle(startup_info.hStdInput)
         if startup_info.hStdOutput:
-            si.hStdOutput = startup_info.hStdOutput.c_handle
+            si.hStdOutput = _int2handle(startup_info.hStdOutput)
         if startup_info.hStdError:
-            si.hStdError = startup_info.hStdError.c_handle
+            si.hStdError = _int2handle(startup_info.hStdError)
 
     pi = _ffi.new("PROCESS_INFORMATION *")
     flags |= CREATE_UNICODE_ENVIRONMENT
@@ -120,12 +99,14 @@
     if not res:
         raise _WinError()
 
-    return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessId, pi.dwThreadId
+    return (_handle2int(pi.hProcess),
+            _handle2int(pi.hThread),
+            pi.dwProcessId,
+            pi.dwThreadId)
 
 def WaitForSingleObject(handle, milliseconds):
     # CPython: the first argument is expected to be an integer.
-    res = _kernel32.WaitForSingleObject(_ffi.cast("HANDLE", handle),
-                                        milliseconds)
+    res = _kernel32.WaitForSingleObject(_int2handle(handle), milliseconds)
     if res < 0:
         raise _WinError()
 
@@ -135,7 +116,7 @@
     # CPython: the first argument is expected to be an integer.
     code = _ffi.new("DWORD[1]")
 
-    res = _kernel32.GetExitCodeProcess(_ffi.cast("HANDLE", handle), code)
+    res = _kernel32.GetExitCodeProcess(_int2handle(handle), code)
 
     if not res:
         raise _WinError()
@@ -145,7 +126,7 @@
 def TerminateProcess(handle, exitcode):
     # CPython: the first argument is expected to be an integer.
     # The second argument is silently wrapped in a UINT.
-    res = _kernel32.TerminateProcess(_ffi.cast("HANDLE", handle),
+    res = _kernel32.TerminateProcess(_int2handle(handle),
                                      _ffi.cast("UINT", exitcode))
 
     if not res:
@@ -158,19 +139,17 @@
     if not res:
         return None
     else:
-        # note: returns integer, not handle object
-        return int(_ffi.cast("intptr_t", res))
+        return _handle2int(res)
 
 def CloseHandle(handle):
-    res = _kernel32.CloseHandle(_ffi.cast("HANDLE", handle))
+    res = _kernel32.CloseHandle(_int2handle(handle))
 
     if not res:
         raise _WinError()
 
 def GetModuleFileName(module):
     buf = _ffi.new("wchar_t[]", _MAX_PATH)
-    res = _kernel32.GetModuleFileNameW(_ffi.cast("HANDLE", module),
-                                       buf, _MAX_PATH)
+    res = _kernel32.GetModuleFileNameW(_int2handle(module), buf, _MAX_PATH)
 
     if not res:
         raise _WinError()
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -252,6 +252,7 @@
         missing_positional = []
         missing_kwonly = []
         more_filling = (input_argcount < co_argcount + co_kwonlyargcount)
+        def_first = 0
         if more_filling:
             def_first = co_argcount - (0 if defaults_w is None else len(defaults_w))
             j = 0
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -558,16 +558,6 @@
         'parser', 'fcntl', '_codecs', 'binascii'
     ]
 
-    # These modules are treated like CPython treats built-in modules,
-    # i.e. they always shadow any xx.py.  The other modules are treated
-    # like CPython treats extension modules, and are loaded in sys.path
-    # order by the fake entry '.../lib_pypy/__extensions__'.
-    MODULES_THAT_ALWAYS_SHADOW = dict.fromkeys([
-        '__builtin__', '__pypy__', '_ast', '_codecs', '_sre', '_warnings',
-        '_weakref', 'errno', '__exceptions__', 'gc', 'imp', 'marshal',
-        'posix', 'nt', 'pwd', 'signal', 'sys', 'thread', 'zipimport',
-    ], None)
-
     def make_builtins(self):
         "NOT_RPYTHON: only for initializing the space."
 
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -582,3 +582,16 @@
     if module:
         space.setattr(w_exc, space.wrap("__module__"), space.wrap(module))
     return w_exc
+
+def new_import_error(space, w_msg, w_name, w_path):
+    """Create a new instance of ImportError.
+
+    The result corresponds to ImportError(msg, name=name, path=path)
+    """
+    return space.appexec(
+        [w_msg, w_name, w_path], """(msg, name, path):
+            return ImportError(msg, name=name, path=path)""")
+
+def raise_import_error(space, w_msg, w_name, w_path):
+    w_exc = new_import_error(space, w_msg, w_name, w_path)
+    raise OperationError(space.w_ImportError, w_exc)
diff --git a/pypy/interpreter/interactive.py b/pypy/interpreter/interactive.py
--- a/pypy/interpreter/interactive.py
+++ b/pypy/interpreter/interactive.py
@@ -169,7 +169,8 @@
 
     def runsource(self, source, ignored_filename="<input>", symbol="single"):
         # the following hacked file name is recognized specially by error.py
-        hacked_filename = '<inline>\n' + source
+        hacked_filename = '<inline>\n' + source.encode(
+                                            'ascii', 'backslashreplace')
         compiler = self.space.getexecutioncontext().compiler
 
         # CPython 2.6 turns console input into unicode
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -107,6 +107,7 @@
         self.co_varnames = varnames
         self.co_freevars = freevars
         self.co_cellvars = cellvars
+        assert isinstance(filename, str)
         rstring.check_str0(filename)
         self.co_filename = filename
         self.co_name = name
diff --git a/pypy/interpreter/test/test_error.py b/pypy/interpreter/test/test_error.py
--- a/pypy/interpreter/test/test_error.py
+++ b/pypy/interpreter/test/test_error.py
@@ -3,7 +3,7 @@
 import py, os, errno
 from pypy.interpreter.error import (
     OperationError, decompose_valuefmt, get_operrcls2, new_exception_class,
-    oefmt, wrap_oserror)
+    oefmt, wrap_oserror, new_import_error)
 
 
 def test_decompose_valuefmt():
@@ -154,3 +154,8 @@
     assert operr.match(space, space.w_ValueError)
     assert operr.match(space, space.w_TypeError)
 
+def test_import_error(space):
+    w_exc = new_import_error(
+        space, space.wrap(u'msg'), space.wrap(u'name'), space.wrap(u'path'))
+    assert space.getattr(w_exc, space.wrap(u'name')).unwrap(space) == u'name'
+    assert space.getattr(w_exc, space.wrap(u'path')).unwrap(space) == u'path'
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -20,7 +20,7 @@
 from rpython.tool.udir import udir
 from rpython.translator import platform
 from pypy.module.cpyext.state import State
-from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.error import OperationError, oefmt, raise_import_error
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.interpreter.nestedscope import Cell
@@ -982,7 +982,7 @@
     py_fatalerror = rffi.llexternal('%s_FatalError' % prefix,
                                     [CONST_STRING], lltype.Void,
                                     compilation_info=eci)
-    _reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [], 
+    _reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [],
                                   lltype.Void, compilation_info=eci)
     def reinit_tls(space):
         _reinit_tls()
@@ -1523,9 +1523,10 @@
         finally:
             lltype.free(ll_libname, flavor='raw')
     except rdynload.DLOpenError as e:
-        raise oefmt(space.w_ImportError,
-                    "unable to load extension module '%s': %s",
-                    path, e.msg)
+        w_name = space.newunicode(name.decode('ascii'))
+        w_path = space.wrap_fsdecoded(path)
+        raise raise_import_error(space,
+            space.wrap_fsdecoded(e.msg), w_name, w_path)
     look_for = None
     #
     if space.config.objspace.usemodules._cffi_backend:
@@ -1555,9 +1556,12 @@
             look_for += ' or ' + also_look_for
         else:
             look_for = also_look_for
-    #
-    raise oefmt(space.w_ImportError,
-                "function %s not found in library %s", look_for, path)
+    msg = u"function %s not found in library %s" % (
+        unicode(look_for), space.unicode_w(space.wrap_fsdecoded(path)))
+    w_name = space.newunicode(name.decode('ascii'))
+    w_path = space.wrap_fsdecoded(path)
+    raise_import_error(space, space.newunicode(msg), w_name, w_path)
+
 
 initfunctype = lltype.Ptr(lltype.FuncType([], PyObject))
 
diff --git a/pypy/module/imp/test/test_app.py b/pypy/module/imp/test/test_app.py
--- a/pypy/module/imp/test/test_app.py
+++ b/pypy/module/imp/test/test_app.py
@@ -3,8 +3,10 @@
 
 
 class AppTestImpModule:
+    # cpyext is required for _imp.create_dynamic()
     spaceconfig = {
-        'usemodules': ['binascii', 'imp', 'itertools', 'time', 'struct'],
+        'usemodules': [
+            'binascii', 'imp', 'itertools', 'time', 'struct', 'cpyext'],
     }
 
     def setup_class(cls):
@@ -55,12 +57,21 @@
             del sys.path[0]
 
     def test_create_dynamic(self):
-        import imp
+        import _imp
+        PATH = 'this/path/does/not/exist'
         class FakeSpec:
-            name = 'foo'
-            origin = 'this/path/does/not/exist'
-        raises(ImportError, imp.create_dynamic, FakeSpec())
-        raises(ImportError, imp.create_dynamic, FakeSpec(), "unused")
+            origin = PATH
+            def __init__(self, name):
+                self.name = name
+
+        excinfo = raises(ImportError, _imp.create_dynamic, FakeSpec('foo'))
+        assert excinfo.value.name == 'foo'
+        assert excinfo.value.path == PATH
+        # Note: On CPython, the behavior changes slightly if a 2nd argument is
+        # passed in, whose value is ignored. We don't implement that.
+        #raises(IOError, _imp.create_dynamic, FakeSpec(), "unused")
+
+        raises(ImportError, _imp.create_dynamic, FakeSpec(b'foo'))
 
     def test_suffixes(self):
         import imp
diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -63,8 +63,6 @@
                     test_reload = "def test():\n    raise ValueError\n",
                     infinite_reload = "import infinite_reload, imp; imp.reload(infinite_reload)",
                     del_sys_module = "import sys\ndel sys.modules['del_sys_module']\n",
-                    _md5 = "hello_world = 42\n",
-                    _pypyjson = "hello_world = 42\n",
                     gc = "should_never_be_seen = 42\n",
                     )
     root.ensure("packagenamespace", dir=1)    # empty, no __init__.py
@@ -158,7 +156,7 @@
 
 def _setup_path(space, path):
     return space.appexec([space.wrap(path)], """
-        (dn): 
+        (dn):
             import sys
             path = list(sys.path)
             sys.path.insert(0, dn)
@@ -660,52 +658,6 @@
                                      ) == 'a/b/c.py'
         raises(ValueError, imp.source_from_cache, 'a/b/c.py')
 
-    def test_shadow_builtin(self):
-        if self.runappdirect: skip("hard to test: module is already imported")
-        # 'import gc' is supposed to always find the built-in module;
-        # like CPython, it is a built-in module, so it shadows everything,
-        # even though there is a gc.py.
-        import sys
-        assert 'gc' not in sys.modules
-        import gc
-        assert not hasattr(gc, 'should_never_be_seen')
-        assert '(built-in)' in repr(gc)
-        del sys.modules['gc']
-
-    def test_shadow_extension_1(self):
-        if not self.runappdirect:
-            skip("I don't understand why it fails, but it works in -A "
-                 "on top of a translated PyPy.  Good enough...")
-        # 'import _pypyjson' is supposed to find _pypyjson.py if there is
-        # one in sys.path.
-        import sys
-        assert '_pypyjson' not in sys.modules
-        try:
-            import _pypyjson
-            assert hasattr(_pypyjson, 'hello_world')
-            assert '(built-in)' not in repr(_pypyjson)
-        finally:
-            sys.modules.pop('_pypyjson', None)
-
-    def test_shadow_extension_2(self):
-        if self.runappdirect: skip("hard to test: module is already imported")
-        # 'import _md5' is supposed to find the built-in module even
-        # if there is also one in sys.path as long as it is *after* the
-        # special entry '.../lib_pypy/__extensions__'.  (Note that for now
-        # there is one in lib_pypy/_md5.py, which should not be seen
-        # either; hence the (built-in) test below.)
-        import sys
-        assert '_md5' not in sys.modules
-        sys.path.append(sys.path.pop(0))
-        try:
-            import _md5
-            assert not hasattr(_md5, 'hello_world')
-            assert hasattr(_md5, 'md5')
-            assert '(built-in)' in repr(_md5)
-        finally:
-            sys.path.insert(0, sys.path.pop())
-            sys.modules.pop('_md5', None)
-
     def test_invalid_pathname(self):
         skip("This test fails on CPython 3.3, but passes on CPython 3.4+")
         import imp
@@ -993,11 +945,11 @@
         assert s.no_nul
 
 
-def test_PYTHONPATH_takes_precedence(space): 
+def test_PYTHONPATH_takes_precedence(space):
     if sys.platform == "win32":
         py.test.skip("unresolved issues with win32 shell quoting rules")
-    from pypy.interpreter.test.test_zpy import pypypath 
-    extrapath = udir.ensure("pythonpath", dir=1) 
+    from pypy.interpreter.test.test_zpy import pypypath
+    extrapath = udir.ensure("pythonpath", dir=1)
     extrapath.join("sched.py").write("print(42)\n")
     old = os.environ.get('PYTHONPATH', None)
     oldlang = os.environ.pop('LANG', None)
diff --git a/pypy/objspace/test/test_descriptor.py b/pypy/objspace/test/test_descriptor.py
--- a/pypy/objspace/test/test_descriptor.py
+++ b/pypy/objspace/test/test_descriptor.py
@@ -73,6 +73,10 @@
         raises(AttributeError, X.v.__delete__, x)
 
     def test_invalid_unicode_identifier(self):
+        skip("utf-8 encoding before translation accepts lone surrogates, "
+             "because it is Python 2.7, but after translation it does not. "
+             "Moreover, CPython 3.x accepts such unicode attributes anyway. "
+             "This makes this test half-wrong for now.")
         class X(object):
             pass
         x = X()
diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py
--- a/pypy/tool/pytest/apptest.py
+++ b/pypy/tool/pytest/apptest.py
@@ -142,6 +142,9 @@
             # They may be extension modules on CPython
             name = None
             for name in missing.copy():
+                if name == 'cpyext':
+                    missing.remove(name)
+                    continue
                 try:
                     __import__(name)
                 except ImportError:


More information about the pypy-commit mailing list