@@ -589,6 +589,82 @@ def __init__(self, path_entry):
589589 super (PyFileImporter , self ).__init__ (path_entry )
590590
591591
592+ class SysPathFinder :
593+
594+ """Meta path finder for sys.(path|path_hooks|path_importer_cache)."""
595+
596+ def _default_hook (self , path ):
597+ """Use the default hook on 'path'.
598+
599+ If the path will not work for the default hook then raise ImportError.
600+
601+ """
602+ # TODO(brett.cannon) Implement
603+ raise ImportError
604+
605+ # The list of implicit hooks cannot be a class attribute because of
606+ # bootstrapping issues for accessing imp.
607+ def _implicit_hooks (self , path ):
608+ """Return a list of the implicit path hooks."""
609+ return [self ._default_hook , imp .NullImporter ]
610+
611+ def _path_hooks (self , path ):
612+ """Search sys.path_hooks for a finder for 'path'.
613+
614+ Guaranteed to return a finder for the path as NullImporter is the
615+ default importer for any path that does not have an explicit finder.
616+
617+ """
618+ for hook in sys .path_hooks + self ._implicit_hooks ():
619+ try :
620+ return hook (path )
621+ except ImportError :
622+ continue
623+ else :
624+ # This point should never be reached thanks to NullImporter.
625+ raise SystemError ("no hook could find an importer for "
626+ "{0}" .format (path ))
627+
628+ def _path_importer_cache (self , path ):
629+ """Get the finder for the path from sys.path_importer_cache.
630+
631+ If the path is not in the cache, find the appropriate finder and cache
632+ it. If None is cached, get the default finder and cache that
633+ (if applicable).
634+
635+ Because of NullImporter, some finder should be returned. The only
636+ explicit fail case is if None is cached but the path cannot be used for
637+ the default hook, for which ImportError is raised.
638+
639+ """
640+ try :
641+ finder = sys .path_importer_cache (path );
642+ except KeyError :
643+ finder = self ._path_hooks (path )
644+ sys .path_importer_cache [path ] = finder
645+ else :
646+ if finder is None :
647+ # Raises ImportError on failure.
648+ finder = self ._default_hook (path )
649+ sys .path_importer_cache [path ] = finder
650+ return finder
651+
652+ def find_module (self , fullname , path = None ):
653+ """Find the module on sys.path or 'path'."""
654+ if not path :
655+ path = sys .path
656+ for entry in path :
657+ try :
658+ finder = self ._path_importer_cache (entry )
659+ except ImportError :
660+ continue
661+ loader = finder .find_module (fullname )
662+ if loader :
663+ return loader
664+ else :
665+ return None
666+
667+
592668class ImportLockContext (object ):
593669
594670 """Context manager for the import lock."""
0 commit comments