[Python-checkins] r55757 - sandbox/trunk/import_in_py/pseudocode.py

brett.cannon python-checkins at python.org
Tue Jun 5 04:05:07 CEST 2007


Author: brett.cannon
Date: Tue Jun  5 04:05:02 2007
New Revision: 55757

Modified:
   sandbox/trunk/import_in_py/pseudocode.py
Log:
Flesh out pseudocode for import machinery.  Leaves out details of how importing
built-in, frozen, extension, and Python source/bytecode modules work.  But
where and how import looks for modules is all done.


Modified: sandbox/trunk/import_in_py/pseudocode.py
==============================================================================
--- sandbox/trunk/import_in_py/pseudocode.py	(original)
+++ sandbox/trunk/import_in_py/pseudocode.py	Tue Jun  5 04:05:02 2007
@@ -1,24 +1,131 @@
 raise ImportError("module is just pseudocode")
 
+import sys
+
 def __import__(name, globals, locals, fromlist, level):
     """Pseudocode to explain how importing works.
 
     Caveats:
-        + Classic relative import semantics are not currently covered.
+        + Classic relative import semantics are not covered.
         + Assume all code runs with the import lock held.
 
     """
-    if level != 0:  # Relative import.
-        name = resolve_name(name, level)  # XXX
-    # Import each parent in the name, starting at root.
-    # Skipping over details of constructing each parent name and setting the
-    # proper attribute on the parent for newly imported modules.
-    for parent in name:
+    path = globals.get('__path__')
+    # If a relative import, figure out absolute name of requested module.
+    if level != 0:
+        # Adjust relative import based on whether caller is a package and
+        # the specified level.
+        # Make sure import does not go beyond top-level.
+        name = resolve_name(name, globals['__name__'], path, level)
+    # Import each parent in the name, starting at the top.
+    # Assume each_parent iterates through each parent of the module request,
+    # starting at the top-level parent.
+    # Since loaders are required to set the module in sys.modules, a successful
+    # import should be followed by 'continue' to let the next module be
+    # imported.
+    for parent in each_parent(name):
         if parent in sys.modules:
             continue
+        # Search sys.meta_path.
         for meta_importer in sys.meta_path:
-            check_meta_path(parent, meta_importer)  # XXX
+            loader = meta_importer.find_module(name, path)
+            if loader:
+                loader.load_module(name)
+                continue
+        # Check built-in and frozen modules.
+        else:
+            for module_finder in (builtin_importer, frozen_importer):
+                loader = module_finder(name, path)
+                if loader:
+                    loader.load_module(name)
+                    continue
+        # With sys.meta_path, built-ins, and frozen modules checked, now look
+        # at sys.path.
         for path_entry in sys.path:
-            check_path(parent, path_entry)  # XXX
-        # XXX error: not found
-    return module_to_return(path, fromlist)  # XXX
+            # Look for a cached importer.
+            if path_entry in sys.path_importer_cache:
+                importer = sys.path_importer_cache[path_entry]
+                # Found an importer.
+                if importer:
+                    loader = importer.find_module(name)
+                    # If the import can handle the module, load it.  Otherwise
+                    # fall through to the default import.
+                    if loader:
+                        loader.load_module(name)
+                        continue
+            # A pre-existing importer was not found; try to make one.
+            else:
+                for importer_factory in sys.path_hooks:
+                    try:
+                        # If an importer is found, cache it and try to use it.
+                        # If it can't be used, then fall through to the default
+                        # import.
+                        importer = importer_factory(path_entry)
+                        sys.path_importer_cache[path_entry] = importer
+                        loader = importer.find_module(name)
+                        if loader:
+                            loader.load_module(name)
+                    except ImportError:
+                        continue
+                else:
+                    # No importer could be created, so set to None in
+                    # sys.path_import_cache to skip trying to make one in the
+                    # future, then fall through to the default import.
+                    sys.path_importer_cache[path_entry] = None
+            # As no importer was found for the sys.path entry, use the default
+            # importer for extension modules, Python bytecode, and Python
+            # source modules.
+            loader = find_extension_module(name, path_entry)
+            if loader:
+                loader.load_module(name)
+                continue
+            loader = find_py_pyc_module(name, path_entry)
+            if loader:
+                loader.load_module(name)
+                continue
+        # All available places to look for a module have been exhausted; raise
+        # an ImportError.
+        raise ImportError
+    # With the module now imported and store in sys.modules, figure out exactly
+    # what module to return based on fromlist and how the module name was
+    # specified.
+    # If fromlist is empty, return the module top-most parent module based on
+    # whether the import was relative or not.
+    if not fromlist:
+        if level:
+            return top_relative_name(name, level)
+        else:
+            return sys.modules[name.split('.', 1)[0]]
+    # If fromlist is not empty, return the module as directly specified in the
+    # import.
+    # Must also handle possible imports of modules if the module imported was a
+    # package and thus names in the fromlist are modules within the package and
+    # not object within a module.
+    else:
+        module = sys.modules[name]
+        # If not a module, then can just return the module as the names
+        # specified in fromlist are supposed to be attributes on the module.
+        if not hasattr(module, '__path__'):
+            return module
+        # The imported module was a package, which means everything in the
+        # fromlist are supposed to be modules within the package.  That means
+        # that an *attempt* must be made to try to import every name in
+        # fromlist.
+        if '*' in fromlist and hasattr(module, '__all__'):
+            fromlist = list(fromlist).extend(module.__all__)
+        for item in fromlist:
+            if item == '*':
+                continue
+            if not hasattr(module, item):
+                try:
+                    __import__('.'.join([name, item]), module.__dict__, level=0)
+                except ImportError:
+                    pass
+        return module
+
+
+def find_extension_module(name, path_entry):
+    pass
+
+def find_py_pyc_module(name, path_entry):
+    pass


More information about the Python-checkins mailing list