[Python-checkins] r52217 - sandbox/trunk/import_in_py/importer.py

brett.cannon python-checkins at python.org
Sat Oct 7 01:36:39 CEST 2006


Author: brett.cannon
Date: Sat Oct  7 01:36:38 2006
New Revision: 52217

Modified:
   sandbox/trunk/import_in_py/importer.py
Log:
Initial (untested) stab at a filesystem path hook, importer, and loader along
with a handler for Python source modules.

Doing the bytecode importer should help with working out possible kinks in the
API.  But it will probably require adding package support before that really
comes about.

Also started a list of possible improvements to the import machinery for Py3K
based on experience from this re-implementation.


Modified: sandbox/trunk/import_in_py/importer.py
==============================================================================
--- sandbox/trunk/import_in_py/importer.py	(original)
+++ sandbox/trunk/import_in_py/importer.py	Sat Oct  7 01:36:38 2006
@@ -17,9 +17,24 @@
 an ImportError if a call to load_module() on a loader fails to load a module.
 PEP 302 does not specify what to do in the failing case.
 
+Possible Py3K improvements:
+    * Have __import__ check for sys.modules entry to alleviate need for every
+      loader to do so.
+    * Have __import__ pass in module to initialize for imported module so to
+      alleviate loader from having to pull from sys.modules.
+    * Put importer objects directly into sys.path to remove need for
+      sys.path_importer_cache.  Could leave string entries on sys.path that do
+      not have an importer that can handle them so they can be retried at the
+      next needed import (that was not found in sys.modules).
+
 """
+from __future__ import with_statement
+
 import imp
 import sys
+# XXX Importing os will not work in the end as it is implemented in Python
+# itself.
+import os
 
 
 class BuiltinFrozen_Importer(object):
@@ -81,3 +96,101 @@
 
     _find = imp.is_frozen
     _load = imp.init_frozen
+
+
+class FileSystemFactory(object):
+
+    """Factory object for sys.path_hooks for directory entries on sys.path."""
+
+    def __init__(self, *handlers):
+        """Store handlers to be used in attempting to import.
+
+        The order that the handlers are specified are the order in which
+        files will be considered for importing.
+
+        """
+        self.handlers = handlers
+
+    def __call__(self, path_entry):
+        """If path_entry is a directory, return an importer object for it, else
+        raise ImportError."""
+        if os.path.isdir(path_entry):
+            return FileSystemImporter(path_entry, *self.handlers)
+        else:
+            raise ImportError("can only handle directory entries from "
+                                "sys.path")
+
+
+class FileSystemImporter(object):
+
+    """Importer for the filesystem."""
+
+    def __init__(self, path_entry, *handlers):
+        self.path_entry = path_entry
+        self.handlers = handlers
+
+    def find_module(self, fullname, path=None):
+        """Determine if this path entry can handle this import."""
+        # XXX Ignores 'path' at the moment.
+        # XXX Does not worry about case-insensitive filesystems.
+        for handler in self.handlers:
+            file_name = fullname + '.' + handler.handles
+            possible_file = os.path.join(self.path_entry, file_name)
+            if os.path.isfile(possible_file):
+                break
+        else:
+            return None
+        return FileSystemLoader(file_path, handler)
+
+
+class FileSystemLoader(object):
+
+    """Loader for the filesystem."""
+
+    def __init__(self, file_path, handler):
+        self.file_path = file_path
+        self.handler = handler
+
+    def load_module(self, fullname, path=None):
+        """Load the module from self.path using self.handler."""
+        # XXX Ignores 'path' at the moment.
+        try:
+            return sys.modules[fullname]
+        except KeyError:
+            module = imp.new_module(fullname)
+            sys.modules[fullname] = module
+            self.handler.handle_file(module, fullname, path, self.file_path)
+            return module
+
+
+class PySourceHandler(object):
+
+    """Handler for importing Python source modules."""
+
+    # XXX Does not generate a .pyc at the moment.
+
+    handles = 'py'
+
+    def handle_file(self, module, fullname, path, file_path):
+        """Import the Python source file at 'path' and use it to initialize
+        'module'."""
+        module.__file__ = file_path
+        module.__name__ = fullname
+        with open(file_path) as source_file:
+            source_code = source_file.read()
+        compiled_code = compile(source_code, file_path, 'exec')
+        exec compiled_code in module.__dict__
+        return module
+
+
+class PyBytecodeHandler(object):
+
+    """Handler for importing .pyc/.pyo modules."""
+
+    # XXX 'handles' should be a property that returns based on whether -O was
+    # specified when running the interpreter.
+    
+    # XXX Should probably add a handle_string() method to PySourceHandler() so
+    # that if the .pyc is outdated it can easily use PySourceHandler to do the
+    # import for it and then write out the new .pyc .
+    # XXX Writing out a new .pyc should be made optional.


More information about the Python-checkins mailing list