[pypy-commit] pypy py3k: In python3.2, the import statement is absolute,

amauryfa noreply at buildbot.pypy.org
Fri Jun 28 22:50:07 CEST 2013


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r65084:d2cb525d01f4
Date: 2013-06-28 22:18 +0200
http://bitbucket.org/pypy/pypy/changeset/d2cb525d01f4/

Log:	In python3.2, the import statement is absolute, but __import__()
	still tries both relative and absolute. Test and fix.

	This is needed by IDLE.

diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -145,6 +145,9 @@
 
     if ctxt_package is not None:
         # __package__ is set, so use it
+        if ctxt_package == '' and level < 0:
+            return None, 0
+
         dot_position = _get_dot_position(ctxt_package, level - 1)
         if dot_position < 0:
             if len(ctxt_package) == 0:
@@ -226,9 +229,9 @@
 
 @unwrap_spec(name='str0', level=int)
 def importhook(space, name, w_globals=None,
-               w_locals=None, w_fromlist=None, level=0):
+               w_locals=None, w_fromlist=None, level=-1):
     modulename = name
-    if not modulename and level == 0:
+    if not modulename and level < 0:
         raise OperationError(
             space.w_ValueError,
             space.wrap("Empty module name"))
@@ -240,15 +243,31 @@
         fromlist_w = None
 
     rel_modulename = None
-    if (level > 0 and
+    if (level != 0 and
         w_globals is not None and
         space.isinstance_w(w_globals, space.w_dict)):
 
         rel_modulename, rel_level = _get_relative_name(space, modulename, level, w_globals)
 
         if rel_modulename:
-            w_mod = absolute_import(space, rel_modulename, rel_level,
-                                    fromlist_w, tentative=False)
+            # if no level was set, ignore import errors, and
+            # fall back to absolute import at the end of the
+            # function.
+            if level == -1:
+                # This check is a fast path to avoid redoing the
+                # following absolute_import() in the common case
+                w_mod = check_sys_modules_w(space, rel_modulename)
+                if w_mod is not None and space.is_w(w_mod, space.w_None):
+                    # if we already find space.w_None, it means that we
+                    # already tried and failed and fell back to the
+                    # end of this function.
+                    w_mod = None
+                else:
+                    w_mod = absolute_import(space, rel_modulename, rel_level,
+                                            fromlist_w, tentative=True)
+            else:
+                w_mod = absolute_import(space, rel_modulename, rel_level,
+                                        fromlist_w, tentative=False)
             if w_mod is not None:
                 return w_mod
 
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
@@ -59,6 +59,9 @@
              relative_c = "from __future__ import absolute_import\nfrom .struct import inpackage",
              relative_f = "from .imp import get_magic",
              relative_g = "import imp; from .imp import get_magic",
+             inpackage  = "inpackage = 1",
+             function_a = "g = {'__name__': 'pkg.a'}; __import__('inpackage', g); print(g)",
+             function_b = "g = {'__name__': 'not.a'}; __import__('inpackage', g); print(g)",
              )
     setuppkg("pkg.pkg1",
              __init__   = 'from . import a',
@@ -552,6 +555,16 @@
         check_absolute()
         raises(ValueError, check_relative)
 
+    def test_import_function(self):
+        # More tests for __import__
+        import sys
+        if sys.version < '3.3':
+            from pkg import function_a
+            assert function_a.g['__package__'] == 'pkg'
+            raises(ImportError, "from pkg import function_b")
+        else:
+            raises(ImportError, "from pkg import function_a")
+
     def test_universal_newlines(self):
         import pkg_univnewlines
         assert pkg_univnewlines.a == 5


More information about the pypy-commit mailing list