diff options
author | Brett Cannon <bcannon@gmail.com> | 2009-02-02 19:19:36 (GMT) |
---|---|---|
committer | Brett Cannon <bcannon@gmail.com> | 2009-02-02 19:19:36 (GMT) |
commit | 1d376687b7176fc0e52e85f0a6cd98b53fd77d41 (patch) | |
tree | 8425e48e55c2e4290297a97bc672a875f5f4b818 | |
parent | 7e11b3f52247f0a0fd8be8879873a74d4ec02b38 (diff) | |
download | cpython-1d376687b7176fc0e52e85f0a6cd98b53fd77d41.zip cpython-1d376687b7176fc0e52e85f0a6cd98b53fd77d41.tar.gz cpython-1d376687b7176fc0e52e85f0a6cd98b53fd77d41.tar.bz2 |
To prevent another screw-up on my part where my prototype gets lost thanks to
an ``svn revert`` (gee, maybe more atomic commits by use of something like a
DVCS would help with this? Wish someone would get on that ...), I am checking
in an untested, work-in-progress meta path finder to handle sys.path.
-rw-r--r-- | Lib/importlib/_bootstrap.py | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index ca62911..d59fa85 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -589,6 +589,82 @@ class PyFileImporter(FileImporter): super(PyFileImporter, self).__init__(path_entry) +class SysPathFinder: + + """Meta path finder for sys.(path|path_hooks|path_importer_cache).""" + + def _default_hook(self, path): + """Use the default hook on 'path'. + + If the path will not work for the default hook then raise ImportError. + + """ + # TODO(brett.cannon) Implement + raise ImportError + + # The list of implicit hooks cannot be a class attribute because of + # bootstrapping issues for accessing imp. + def _implicit_hooks(self, path): + """Return a list of the implicit path hooks.""" + return [self._default_hook, imp.NullImporter] + + def _path_hooks(self, path): + """Search sys.path_hooks for a finder for 'path'. + + Guaranteed to return a finder for the path as NullImporter is the + default importer for any path that does not have an explicit finder. + + """ + for hook in sys.path_hooks + self._implicit_hooks(): + try: + return hook(path) + except ImportError: + continue + else: + # This point should never be reached thanks to NullImporter. + raise SystemError("no hook could find an importer for " + "{0}".format(path)) + + def _path_importer_cache(self, path): + """Get the finder for the path from sys.path_importer_cache. + + If the path is not in the cache, find the appropriate finder and cache + it. If None is cached, get the default finder and cache that + (if applicable). + + Because of NullImporter, some finder should be returned. The only + explicit fail case is if None is cached but the path cannot be used for + the default hook, for which ImportError is raised. + + """ + try: + finder = sys.path_importer_cache(path); + except KeyError: + finder = self._path_hooks(path) + sys.path_importer_cache[path] = finder + else: + if finder is None: + # Raises ImportError on failure. + finder = self._default_hook(path) + sys.path_importer_cache[path] = finder + return finder + + def find_module(self, fullname, path=None): + """Find the module on sys.path or 'path'.""" + if not path: + path = sys.path + for entry in path: + try: + finder = self._path_importer_cache(entry) + except ImportError: + continue + loader = finder.find_module(fullname) + if loader: + return loader + else: + return None + + class ImportLockContext(object): """Context manager for the import lock.""" |