Christoph Reiter avatar Christoph Reiter committed 36b875a

cpyext: implement PyImport_ImportModuleLevel, PyImport_ImportModuleEx

Comments (0)

Files changed (2)

pypy/module/cpyext/import_.py

 from pypy.interpreter.pycode import PyCode
 from pypy.module.imp import importing
 
+def _import(space, w_builtin, w_name, w_globals, w_locals, w_fromlist, w_level):
+    # Get the __import__ function from the builtins
+    if space.isinstance_w(w_builtin, space.w_dict):
+        w_import = space.getitem(w_builtin, space.wrap("__import__"))
+    else:
+        w_import = space.getattr(w_builtin, space.wrap("__import__"))
+
+    # Call the __import__ function with the proper argument list
+    return space.call_function(w_import,
+                               w_name, w_globals, w_locals, w_fromlist, w_level)
+
+@cpython_api([PyObject, PyObject, PyObject, PyObject, rffi.INT_real], PyObject)
+def PyImport_ImportModuleLevel(space, w_name, w_globals, w_locals, w_fromlist, w_level):
+    """
+    Import a module. This is best described by referring to the built-in
+    Python function __import__(), as the standard __import__() function
+    calls this function directly.
+
+    The return value is a new reference to the imported module or top-level
+    package, or NULL with an exception set on failure. Like for
+    __import__(), the return value when a submodule of a package was
+    requested is normally the top-level package, unless a non-empty
+    fromlist was given."""
+    caller = space.getexecutioncontext().gettopframe_nohidden()
+    if caller is not None:
+        w_builtin = space.getitem(w_globals, space.wrap('__builtins__'))
+    else:
+        w_builtin = space.getbuiltinmodule('__builtin__')
+
+    return _import(space, w_builtin, w_name, w_globals, w_locals,
+                   w_fromlist, w_level)
+
+@cpython_api([PyObject, PyObject, PyObject, PyObject], PyObject)
+def PyImport_ImportModuleEx(space, w_name, w_globals, w_locals, w_fromlist):
+    """
+    Import a module. This is best described by referring to the built-in
+    Python function __import__(), as the standard __import__() function
+    calls this function directly.
+
+    The return value is a new reference to the imported module or top-level
+    package, or NULL with an exception set on failure (before Python 2.4,
+    the module may still be created in this case). Like for __import__(),
+    the return value when a submodule of a package was requested is
+    normally the top-level package, unless a non-empty fromlist was given.
+
+    Failing imports remove incomplete module objects.
+
+    The function is an alias for PyImport_ImportModuleLevel() with -1 as level,
+    meaning relative import."""
+    caller = space.getexecutioncontext().gettopframe_nohidden()
+    if caller is not None:
+        w_builtin = space.getitem(w_globals, space.wrap('__builtins__'))
+    else:
+        w_builtin = space.getbuiltinmodule('__builtin__')
+
+    return _import(space, w_builtin, w_name, w_globals, w_locals,
+                   w_fromlist, space.wrap(-1))
+
 @cpython_api([PyObject], PyObject)
 def PyImport_Import(space, w_name):
     """
         w_globals = space.newdict()
         space.setitem(w_globals, space.wrap("__builtins__"), w_builtin)
 
-    # Get the __import__ function from the builtins
-    if space.isinstance_w(w_builtin, space.w_dict):
-        w_import = space.getitem(w_builtin, space.wrap("__import__"))
-    else:
-        w_import = space.getattr(w_builtin, space.wrap("__import__"))
+    w_fromlist = space.newlist([space.wrap("__doc__")])
 
-    # Call the __import__ function with the proper argument list
-    # Always use absolute import here.
-    return space.call_function(w_import,
-                               w_name, w_globals, w_globals,
-                               space.newlist([space.wrap("__doc__")]))
+    return _import(space, w_builtin, w_name, w_globals, w_globals,
+                   w_fromlist, space.wrap(0))
 
 @cpython_api([CONST_STRING], PyObject)
 def PyImport_ImportModule(space, name):

pypy/module/cpyext/test/test_import.py

         assert stat
         assert space.getattr(stat, space.wrap("S_IMODE"))
 
+    def test_import_ext(self, space, api):
+        ospath_w = api.PyImport_ImportModuleEx(
+            space.wrap("os.path"), None, None, space.wrap(["foo"]))
+        assert ospath_w
+
+        import os.path as ospath
+        assert space.unwrap(space.getattr(ospath_w, space.wrap('__name__'))) == ospath.__name__
+
+    def test_import_module_level(self, space, api):
+        stat = api.PyImport_ImportModuleLevel(
+            space.wrap("stat"), None, None, space.newdict(), space.wrap(0))
+        assert stat
+
     def test_addmodule(self, space, api):
         with rffi.scoped_str2charp("sys") as modname:
             w_sys = api.PyImport_AddModule(modname)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.