183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""
283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehImport utilities
383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehExported classes:
583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    ImportManager   Manage the import process
683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Importer        Base class for replacing standard import functions
883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    BuiltinImporter Emulate the import mechanism for builtin and frozen modules
983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    DynLoadSuffixImporter
1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""
1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom warnings import warnpy3k
1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwarnpy3k("the imputil module has been removed in Python 3.0", stacklevel=2)
1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdel warnpy3k
1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# note: avoid importing non-builtin modules
1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport imp                      ### not available in Jython?
1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys
1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport __builtin__
2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# for the DirectoryImporter
2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport struct
2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport marshal
2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh__all__ = ["ImportManager","Importer","BuiltinImporter"]
2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_StringType = type('')
2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_ModuleType = type(sys)         ### doesn't work in Jython...
2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ImportManager:
3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    "Manage the import process."
3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def install(self, namespace=vars(__builtin__)):
3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "Install this ImportManager into the specified namespace."
3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(namespace, _ModuleType):
3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            namespace = vars(namespace)
3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Note: we have no notion of "chaining"
4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Record the previous import hook, then install our own.
4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.previous_importer = namespace['__import__']
4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.namespace = namespace
4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        namespace['__import__'] = self._import_hook
4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ### fix this
4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #namespace['reload'] = self._reload_hook
4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def uninstall(self):
5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "Restore the previous import mechanism."
5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.namespace['__import__'] = self.previous_importer
5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def add_suffix(self, suffix, importFunc):
5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert hasattr(importFunc, '__call__')
5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.fs_imp.add_suffix(suffix, importFunc)
5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    ######################################################################
5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #
5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # PRIVATE METHODS
6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #
6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    clsFilesystemImporter = None
6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, fs_imp=None):
6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # we're definitely going to be importing something in the future,
6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # so let's just load the OS-related facilities.
6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not _os_stat:
6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            _os_bootstrap()
6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # This is the Importer that we use for grabbing stuff from the
7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # filesystem. It defines one more method (import_from_dir) for our use.
7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if fs_imp is None:
7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            cls = self.clsFilesystemImporter or _FilesystemImporter
7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            fs_imp = cls()
7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.fs_imp = fs_imp
7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Initialize the set of suffixes that we recognize and import.
7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # The default will import dynamic-load modules first, followed by
7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # .py files (or a .py file's cached bytecode)
8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for desc in imp.get_suffixes():
8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if desc[2] == imp.C_EXTENSION:
8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.add_suffix(desc[0],
8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                DynLoadSuffixImporter(desc).import_file)
8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.add_suffix('.py', py_suffix_importer)
8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _import_hook(self, fqname, globals=None, locals=None, fromlist=None):
8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Python calls this hook to locate and import a module."""
8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        parts = fqname.split('.')
9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # determine the context of this import
9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        parent = self._determine_import_context(globals)
9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # if there is a parent, then its importer should manage this import
9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if parent:
9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            module = parent.__importer__._do_import(parent, parts, fromlist)
9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if module:
9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return module
9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # has the top module already been imported?
10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            top_module = sys.modules[parts[0]]
10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except KeyError:
10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # look for the topmost module
10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            top_module = self._import_top_module(parts[0])
10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not top_module:
10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # the topmost module wasn't found at all.
10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                raise ImportError, 'No module named ' + fqname
11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # fast-path simple imports
11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if len(parts) == 1:
11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not fromlist:
11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return top_module
11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not top_module.__dict__.get('__ispkg__'):
11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # __ispkg__ isn't defined (the module was not imported by us),
11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # or it is zero.
11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                #
12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # In the former case, there is no way that we could import
12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # sub-modules that occur in the fromlist (but we can't raise an
12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # error because it may just be names) because we don't know how
12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # to deal with packages that were imported by other systems.
12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                #
12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # In the latter case (__ispkg__ == 0), there can't be any sub-
12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # modules present, so we can just return.
12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                #
12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # In both cases, since len(parts) == 1, the top_module is also
12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # the "bottom" which is the defined return when a fromlist
13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # exists.
13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return top_module
13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        importer = top_module.__dict__.get('__importer__')
13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if importer:
13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return importer._finish_import(top_module, parts[1:], fromlist)
13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Grrr, some people "import os.path" or do "from os.path import ..."
13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if len(parts) == 2 and hasattr(top_module, parts[1]):
13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if fromlist:
14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return getattr(top_module, parts[1])
14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return top_module
14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # If the importer does not exist, then we have to bail. A missing
14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # importer means that something else imported the module, and we have
14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # no knowledge of how to get sub-modules out of the thing.
14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise ImportError, 'No module named ' + fqname
14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _determine_import_context(self, globals):
15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Returns the context in which a module should be imported.
15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The context could be a loaded (package) module and the imported module
15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        will be looked for within that package. The context could also be None,
15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        meaning there is no context -- the module should be looked for as a
15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "top-level" module.
15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not globals or not globals.get('__importer__'):
15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # globals does not refer to one of our modules or packages. That
16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # implies there is no relative import context (as far as we are
16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # concerned), and it should just pick it off the standard path.
16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # The globals refer to a module or package of ours. It will define
16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # the context of the new import. Get the module/package fqname.
16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        parent_fqname = globals['__name__']
16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # if a package is performing the import, then return itself (imports
16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # refer to pkg contents)
17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if globals['__ispkg__']:
17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            parent = sys.modules[parent_fqname]
17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert globals is parent.__dict__
17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return parent
17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        i = parent_fqname.rfind('.')
17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # a module outside of a package has no particular import context
17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if i == -1:
17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # if a module in a package is performing the import, then return the
18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # package (imports refer to siblings)
18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        parent_fqname = parent_fqname[:i]
18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        parent = sys.modules[parent_fqname]
18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert parent.__name__ == parent_fqname
18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return parent
18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _import_top_module(self, name):
18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # scan sys.path looking for a location in the filesystem that contains
19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # the module, or an Importer object that can import the module.
19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for item in sys.path:
19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if isinstance(item, _StringType):
19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                module = self.fs_imp.import_from_dir(item, name)
19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                module = item.import_top(name)
19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if module:
19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return module
19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return None
19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _reload_hook(self, module):
20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "Python calls this hook to reload a module."
20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # reloading of a module may or may not be possible (depending on the
20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # importer), but at least we can validate that it's ours to reload
20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        importer = module.__dict__.get('__importer__')
20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not importer:
20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ### oops. now what...
20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            pass
20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # okay. it is using the imputil system, and we must delegate it, but
21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # we don't know what to do (yet)
21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ### we should blast the module dict and do another get_code(). need to
21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ### flesh this out and add proper docco...
21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise SystemError, "reload not yet implemented"
21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Importer:
21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    "Base class for replacing standard import functions."
21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def import_top(self, name):
22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "Import a top-level module."
22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._import_one(None, name, name)
22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    ######################################################################
22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #
22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # PRIVATE METHODS
22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #
22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _finish_import(self, top, parts, fromlist):
22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # if "a.b.c" was provided, then load the ".b.c" portion down from
23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # below the top-level module.
23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        bottom = self._load_tail(top, parts)
23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # if the form is "import a.b.c", then return "a"
23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not fromlist:
23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # no fromlist: return the top of the import tree
23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return top
23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # the top module was imported by self.
23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #
24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # this means that the bottom module was also imported by self (just
24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # now, or in the past and we fetched it from sys.modules).
24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #
24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # since we imported/handled the bottom module, this means that we can
24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # also handle its fromlist (and reliably use __ispkg__).
24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # if the bottom node is a package, then (potentially) import some
24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # modules.
24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #
24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # note: if it is not a package, then "fromlist" refers to names in
25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #       the bottom module rather than modules.
25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # note: for a mix of names and modules in the fromlist, we will
25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #       import all modules and insert those into the namespace of
25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #       the package module. Python will pick up all fromlist names
25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #       from the bottom (package) module; some will be modules that
25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #       we imported and stored in the namespace, others are expected
25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #       to be present already.
25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if bottom.__ispkg__:
25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._import_fromlist(bottom, fromlist)
25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # if the form is "from a.b import c, d" then return "b"
26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return bottom
26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _import_one(self, parent, modname, fqname):
26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "Import a single module."
26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # has the module already been imported?
26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return sys.modules[fqname]
26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except KeyError:
27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            pass
27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # load the module's code, or fetch the module itself
27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        result = self.get_code(parent, modname, fqname)
27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if result is None:
27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module = self._process_result(result, fqname)
27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # insert the module into its parent
28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if parent:
28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            setattr(parent, modname, module)
28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return module
28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _process_result(self, result, fqname):
28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ispkg, code, values = result
28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # did get_code() return an actual module? (rather than a code object)
28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        is_module = isinstance(code, _ModuleType)
28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # use the returned module, or create a new one to exec code into
29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if is_module:
29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            module = code
29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            module = imp.new_module(fqname)
29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ### record packages a bit differently??
29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module.__importer__ = self
29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module.__ispkg__ = ispkg
29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # insert additional values into the module (before executing the code)
30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module.__dict__.update(values)
30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # the module is almost ready... make it visible
30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sys.modules[fqname] = module
30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # execute the code within the module's namespace
30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not is_module:
30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                exec code in module.__dict__
30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except:
31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if fqname in sys.modules:
31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    del sys.modules[fqname]
31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                raise
31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # fetch from sys.modules instead of returning module directly.
31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # also make module's __name__ agree with fqname, in case
31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # the "exec code in module.__dict__" played games on us.
31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module = sys.modules[fqname]
31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module.__name__ = fqname
31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return module
32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _load_tail(self, m, parts):
32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Import the rest of the modules, down from the top-level module.
32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Returns the last module in the dotted list of modules.
32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for part in parts:
32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            fqname = "%s.%s" % (m.__name__, part)
32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            m = self._import_one(m, part, fqname)
32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not m:
33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                raise ImportError, "No module named " + fqname
33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return m
33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _import_fromlist(self, package, fromlist):
33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        'Import any sub-modules in the "from" list.'
33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # if '*' is present in the fromlist, then look for the '__all__'
33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # variable to find additional items (modules) to import.
33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if '*' in fromlist:
33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            fromlist = list(fromlist) + \
34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                       list(package.__dict__.get('__all__', []))
34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for sub in fromlist:
34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # if the name is already present, then don't try to import it (it
34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # might not be a module!).
34583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if sub != '*' and not hasattr(package, sub):
34683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                subname = "%s.%s" % (package.__name__, sub)
34783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                submod = self._import_one(package, sub, subname)
34883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if not submod:
34983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    raise ImportError, "cannot import name " + subname
35083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _do_import(self, parent, parts, fromlist):
35283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Attempt to import the module relative to parent.
35383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This method is used when the import context specifies that <self>
35583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        imported the parent module.
35683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
35783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        top_name = parts[0]
35883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        top_fqname = parent.__name__ + '.' + top_name
35983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        top_module = self._import_one(parent, top_name, top_fqname)
36083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not top_module:
36183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # this importer and parent could not find the module (relatively)
36283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
36383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._finish_import(top_module, parts[1:], fromlist)
36583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    ######################################################################
36783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #
36883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # METHODS TO OVERRIDE
36983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #
37083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_code(self, parent, modname, fqname):
37183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Find and retrieve the code for the given module.
37283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
37383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        parent specifies a parent module to define a context for importing. It
37483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        may be None, indicating no particular context for the search.
37583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
37683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        modname specifies a single module (not dotted) within the parent.
37783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
37883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        fqname specifies the fully-qualified module name. This is a
37983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        (potentially) dotted name from the "root" of the module namespace
38083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        down to the modname.
38183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        If there is no parent, then modname==fqname.
38283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This method should return None, or a 3-tuple.
38483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        * If the module was not found, then None should be returned.
38683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        * The first item of the 2- or 3-tuple should be the integer 0 or 1,
38883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            specifying whether the module that was found is a package or not.
38983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
39083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        * The second item is the code object for the module (it will be
39183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            executed within the new module's namespace). This item can also
39283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            be a fully-loaded module object (e.g. loaded from a shared lib).
39383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
39483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        * The third item is a dictionary of name/value pairs that will be
39583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            inserted into new module before the code object is executed. This
39683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            is provided in case the module's code expects certain values (such
39783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            as where the module was found). When the second item is a module
39883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            object, then these names/values will be inserted *after* the module
39983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            has been loaded/initialized.
40083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
40183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise RuntimeError, "get_code not implemented"
40283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh######################################################################
40583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
40683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Some handy stuff for the Importers
40783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
40883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# byte-compiled file suffix character
41083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_suffix_char = __debug__ and 'c' or 'o'
41183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# byte-compiled file suffix
41383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_suffix = '.py' + _suffix_char
41483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _compile(pathname, timestamp):
41683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Compile (and cache) a Python source file.
41783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    The file specified by <pathname> is compiled to a code object and
41983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    returned.
42083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Presuming the appropriate privileges exist, the bytecodes will be
42283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    saved back to the filesystem for future imports. The source file's
42383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    modification timestamp must be provided as a Long value.
42483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
42583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    codestring = open(pathname, 'rU').read()
42683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if codestring and codestring[-1] != '\n':
42783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        codestring = codestring + '\n'
42883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    code = __builtin__.compile(codestring, pathname, 'exec')
42983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
43083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # try to cache the compiled code
43183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    try:
43283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f = open(pathname + _suffix_char, 'wb')
43383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    except IOError:
43483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
43583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    else:
43683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f.write('\0\0\0\0')
43783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f.write(struct.pack('<I', timestamp))
43883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        marshal.dump(code, f)
43983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f.flush()
44083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f.seek(0, 0)
44183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f.write(imp.get_magic())
44283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f.close()
44383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    return code
44583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_os_stat = _os_path_join = None
44783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _os_bootstrap():
44883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    "Set up 'os' module replacement functions for use during import bootstrap."
44983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    names = sys.builtin_module_names
45183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    join = None
45383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if 'posix' in names:
45483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sep = '/'
45583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        from posix import stat
45683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    elif 'nt' in names:
45783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sep = '\\'
45883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        from nt import stat
45983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    elif 'dos' in names:
46083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sep = '\\'
46183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        from dos import stat
46283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    elif 'os2' in names:
46383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sep = '\\'
46483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        from os2 import stat
46583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    else:
46683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise ImportError, 'no os specific module found'
46783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
46883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if join is None:
46983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def join(a, b, sep=sep):
47083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if a == '':
47183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return b
47283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            lastchar = a[-1:]
47383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if lastchar == '/' or lastchar == sep:
47483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return a + b
47583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return a + sep + b
47683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
47783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    global _os_stat
47883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    _os_stat = stat
47983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    global _os_path_join
48183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    _os_path_join = join
48283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _os_path_isdir(pathname):
48483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    "Local replacement for os.path.isdir()."
48583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    try:
48683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        s = _os_stat(pathname)
48783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    except OSError:
48883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return None
48983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    return (s.st_mode & 0170000) == 0040000
49083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _timestamp(pathname):
49283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    "Return the file modification time as a Long."
49383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    try:
49483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        s = _os_stat(pathname)
49583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    except OSError:
49683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return None
49783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    return long(s.st_mtime)
49883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
50083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh######################################################################
50183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
50283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Emulate the import mechanism for builtin and frozen modules
50383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
50483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass BuiltinImporter(Importer):
50583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_code(self, parent, modname, fqname):
50683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if parent:
50783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # these modules definitely do not occur within a package context
50883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
50983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # look for the module
51183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if imp.is_builtin(modname):
51283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            type = imp.C_BUILTIN
51383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        elif imp.is_frozen(modname):
51483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            type = imp.PY_FROZEN
51583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
51683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # not found
51783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
51883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # got it. now load and return it.
52083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module = imp.load_module(modname, None, modname, ('', '', type))
52183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return 0, module, { }
52283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
52383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
52483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh######################################################################
52583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
52683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Internal importer used for importing from the filesystem
52783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
52883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass _FilesystemImporter(Importer):
52983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self):
53083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.suffixes = [ ]
53183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
53283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def add_suffix(self, suffix, importFunc):
53383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert hasattr(importFunc, '__call__')
53483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.suffixes.append((suffix, importFunc))
53583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
53683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def import_from_dir(self, dir, fqname):
53783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        result = self._import_pathname(_os_path_join(dir, fqname), fqname)
53883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if result:
53983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return self._process_result(result, fqname)
54083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return None
54183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
54283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_code(self, parent, modname, fqname):
54383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # This importer is never used with an empty parent. Its existence is
54483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # private to the ImportManager. The ImportManager uses the
54583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # import_from_dir() method to import top-level modules/packages.
54683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # This method is only used when we look for a module within a package.
54783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert parent
54883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
54983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for submodule_path in parent.__path__:
55083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            code = self._import_pathname(_os_path_join(submodule_path, modname), fqname)
55183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if code is not None:
55283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return code
55383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._import_pathname(_os_path_join(parent.__pkgdir__, modname),
55483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                     fqname)
55583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
55683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _import_pathname(self, pathname, fqname):
55783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if _os_path_isdir(pathname):
55883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            result = self._import_pathname(_os_path_join(pathname, '__init__'),
55983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                           fqname)
56083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if result:
56183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                values = result[2]
56283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                values['__pkgdir__'] = pathname
56383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                values['__path__'] = [ pathname ]
56483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return 1, result[1], values
56583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
56683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
56783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for suffix, importFunc in self.suffixes:
56883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            filename = pathname + suffix
56983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
57083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                finfo = _os_stat(filename)
57183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except OSError:
57283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                pass
57383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
57483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return importFunc(filename, finfo, fqname)
57583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return None
57683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
57783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh######################################################################
57883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
57983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# SUFFIX-BASED IMPORTERS
58083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
58183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
58283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef py_suffix_importer(filename, finfo, fqname):
58383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    file = filename[:-3] + _suffix
58483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    t_py = long(finfo[8])
58583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    t_pyc = _timestamp(file)
58683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
58783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    code = None
58883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if t_pyc is not None and t_pyc >= t_py:
58983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f = open(file, 'rb')
59083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if f.read(4) == imp.get_magic():
59183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            t = struct.unpack('<I', f.read(4))[0]
59283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if t == t_py:
59383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                code = marshal.load(f)
59483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f.close()
59583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if code is None:
59683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        file = filename
59783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        code = _compile(file, t_py)
59883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
59983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    return 0, code, { '__file__' : file }
60083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
60183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass DynLoadSuffixImporter:
60283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, desc):
60383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.desc = desc
60483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
60583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def import_file(self, filename, finfo, fqname):
60683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        fp = open(filename, self.desc[1])
60783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module = imp.load_module(fqname, fp, filename, self.desc)
60883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        module.__file__ = filename
60983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return 0, module, { }
61083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh######################################################################
61383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _print_importers():
61583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    items = sys.modules.items()
61683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    items.sort()
61783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    for name, module in items:
61883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if module:
61983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print name, module.__dict__.get('__importer__', '-- no importer')
62083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
62183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print name, '-- non-existent module'
62283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _test_revamp():
62483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    ImportManager().install()
62583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sys.path.insert(0, BuiltinImporter())
62683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh######################################################################
62883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
63083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# TODO
63183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
63283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# from Finn Bock:
63383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   type(sys) is not a module in Jython. what to use instead?
63483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   imp.C_EXTENSION is not in Jython. same for get_suffixes and new_module
63583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
63683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   given foo.py of:
63783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#      import sys
63883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#      sys.modules['foo'] = sys
63983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
64083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   ---- standard import mechanism
64183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   >>> import foo
64283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   >>> foo
64383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   <module 'sys' (built-in)>
64483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
64583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   ---- revamped import mechanism
64683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   >>> import imputil
64783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   >>> imputil._test_revamp()
64883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   >>> import foo
64983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   >>> foo
65083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   <module 'foo' from 'foo.py'>
65183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
65283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
65383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# from MAL:
65483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   should BuiltinImporter exist in sys.path or hard-wired in ImportManager?
65583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   need __path__ processing
65683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   performance
65783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   move chaining to a subclass [gjs: it's been nuked]
65883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   deinstall should be possible
65983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   query mechanism needed: is a specific Importer installed?
66083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   py/pyc/pyo piping hooks to filter/process these files
66183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   wish list:
66283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#     distutils importer hooked to list of standard Internet repositories
66383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#     module->file location mapper to speed FS-based imports
66483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#     relative imports
66583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#     keep chaining so that it can play nice with other import hooks
66683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
66783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# from Gordon:
66883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   push MAL's mapper into sys.path[0] as a cache (hard-coded for apps)
66983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
67083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# from Guido:
67183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   need to change sys.* references for rexec environs
67283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   need hook for MAL's walk-me-up import strategy, or Tim's absolute strategy
67383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   watch out for sys.modules[...] is None
67483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   flag to force absolute imports? (speeds _determine_import_context and
67583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#       checking for a relative module)
67683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   insert names of archives into sys.path  (see quote below)
67783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   note: reload does NOT blast module dict
67883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   shift import mechanisms and policies around; provide for hooks, overrides
67983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#       (see quote below)
68083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   add get_source stuff
68183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   get_topcode and get_subcode
68283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   CRLF handling in _compile
68383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   race condition in _compile
68483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   refactoring of os.py to deal with _os_bootstrap problem
68583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   any special handling to do for importing a module with a SyntaxError?
68683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#       (e.g. clean up the traceback)
68783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   implement "domain" for path-type functionality using pkg namespace
68883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#       (rather than FS-names like __path__)
68983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#   don't use the word "private"... maybe "internal"
69083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
69183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
69283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Guido's comments on sys.path caching:
69383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
69483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# We could cache this in a dictionary: the ImportManager can have a
69583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# cache dict mapping pathnames to importer objects, and a separate
69683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# method for coming up with an importer given a pathname that's not yet
69783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# in the cache.  The method should do a stat and/or look at the
69883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# extension to decide which importer class to use; you can register new
69983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# importer classes by registering a suffix or a Boolean function, plus a
70083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# class.  If you register a new importer class, the cache is zapped.
70183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# The cache is independent from sys.path (but maintained per
70283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# ImportManager instance) so that rearrangements of sys.path do the
70383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# right thing.  If a path is dropped from sys.path the corresponding
70483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# cache entry is simply no longer used.
70583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
70683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# My/Guido's comments on factoring ImportManager and Importer:
70783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
70883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# > However, we still have a tension occurring here:
70983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# >
71083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# > 1) implementing policy in ImportManager assists in single-point policy
71183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# >    changes for app/rexec situations
71283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# > 2) implementing policy in Importer assists in package-private policy
71383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# >    changes for normal, operating conditions
71483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# >
71583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# > I'll see if I can sort out a way to do this. Maybe the Importer class will
71683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# > implement the methods (which can be overridden to change policy) by
71783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# > delegating to ImportManager.
71883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
71983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Maybe also think about what kind of policies an Importer would be
72083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# likely to want to change.  I have a feeling that a lot of the code
72183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# there is actually not so much policy but a *necessity* to get things
72283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# working given the calling conventions for the __import__ hook: whether
72383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# to return the head or tail of a dotted name, or when to do the "finish
72483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# fromlist" stuff.
72583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
726