[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