[pypy-commit] pypy dummy-importlib: import submodules with from ... import

antocuni pypy.commits at gmail.com
Thu Dec 19 19:37:34 EST 2019


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: dummy-importlib
Changeset: r98335:bc01efbafe27
Date: 2019-12-19 15:39 +0100
http://bitbucket.org/pypy/pypy/changeset/bc01efbafe27/

Log:	import submodules with from ... import

diff --git a/pypy/module/_dummy_importlib/interp_import.py b/pypy/module/_dummy_importlib/interp_import.py
--- a/pypy/module/_dummy_importlib/interp_import.py
+++ b/pypy/module/_dummy_importlib/interp_import.py
@@ -15,6 +15,14 @@
     """
     raise OperationError(space.w_ImportError, space.newtext(modname + '\n' + err))
 
+def try_getattr(space, w_obj, w_name):
+    try:
+        return space.getattr(w_obj, w_name)
+    except OperationError:
+        # ugh, but blame CPython :-/ this is supposed to emulate
+        # hasattr, which eats all exceptions.
+        return None
+
 
 @unwrap_spec(modname='text0', level=int)
 def importhook(space, modname, w_globals=None,
@@ -25,7 +33,17 @@
     This module is not meant to be translated. As such, we can use all sort of
     non-rpython tricks to implement it :)
     """
-    assert level == 0
+    if level == 0:
+        w_mod = _absolute_import(space, modname, w_fromlist)
+    else:
+        assert False
+
+    if w_mod is None:
+        raise_ImportError(space, modname)
+    return w_mod
+
+
+def _absolute_import(space, modname, w_fromlist):
     if modname in space.builtin_modules:
         return space.getbuiltinmodule(modname)
 
@@ -34,8 +52,6 @@
     if parts[-1] == '':
         del parts[-1]
 
-    ## if modname == 'dummypkg.mod':
-    ##     import pdb;pdb.set_trace()
     w_mod = None
     w_firstmod = None
     for part in parts:
@@ -44,7 +60,15 @@
             w_firstmod = w_mod
 
     if w_mod is None:
-        raise_ImportError(space, modname)
+        return None
+
+    if w_fromlist is not None:
+        for w_name in space.unpackiterable(w_fromlist):
+            if not try_getattr(space, w_mod, w_name):
+                # w_name does not exists in w_mod, so it must be a submodule
+                submodname = space.text0_w(w_name)
+                load_part(space, submodname, w_mod)
+
     return w_firstmod
 
 def load_part(space, modname, w_parent):
diff --git a/pypy/module/_dummy_importlib/test/test__dummy_importlib.py b/pypy/module/_dummy_importlib/test/test__dummy_importlib.py
--- a/pypy/module/_dummy_importlib/test/test__dummy_importlib.py
+++ b/pypy/module/_dummy_importlib/test/test__dummy_importlib.py
@@ -63,3 +63,11 @@
         import dummypkg.mod
         assert dummypkg.FOO == 42
         assert dummypkg.mod.BAR == 43
+
+    def test_from_import(self):
+        from dummypkg import FOO
+        assert FOO == 42
+
+    def test_from_import_mod(self):
+        from dummypkg import mod
+        assert mod.BAR == 43


More information about the pypy-commit mailing list