@@ -174,51 +174,43 @@ def load_module(cls, fullname):
174174 raise
175175
176176
177- class ChainedImporter (object ):
177+ def chained_path_hook (* path_hooks ):
178+ """Create a closure which sequentially checks path hooks to see which ones
179+ (if any) can work with a path."""
180+ def path_hook (entry ):
181+ """Check to see if 'entry' matches any of the enclosed path hooks."""
182+ finders = []
183+ for hook in path_hooks :
184+ try :
185+ finder = hook (entry )
186+ except ImportError :
187+ continue
188+ else :
189+ finders .append (finder )
190+ if not finders :
191+ raise ImportError ("no finder found" )
192+ else :
193+ return ChainedFinder (* finders )
194+
195+ return path_hook
196+
197+
198+ class ChainedFinder :
178199
179200 """Finder that sequentially calls other finders."""
180201
181- def __init__ (self , * importers ):
182- self ._importers = importers
202+ def __init__ (self , * finders ):
203+ self ._finders = finders
183204
184205 def find_module (self , fullname , path = None ):
185- for importer in self ._importers :
186- result = importer .find_module (fullname , path )
206+ for finder in self ._finders :
207+ result = finder .find_module (fullname , path )
187208 if result :
188209 return result
189210 else :
190211 return None
191212
192213
193- # XXX Don't make filesystem-specific and instead make generic for any path
194- # hooks.
195- def chaining_fs_path_hook (* path_hooks ):
196- """Create a closure which calls the path hooks sequentially looking for
197- which path hooks can handle a path entry.
198-
199-
200- Passed-in path hooks work as any other path hooks, raising ImportError if
201- they cannot handle the path, otherwise returning a finder.
202-
203- """
204- def chained_fs_path_hook (path_entry ):
205- """Closure which sees which of the captured path hooks can handle the
206- path entry."""
207- absolute_path = _path_absolute (path_entry )
208- if not _path_isdir (absolute_path ):
209- raise ImportError ("only directories are supported" )
210- accepted = []
211- for path_hook in path_hooks :
212- try :
213- accepted .append (path_hook (absolute_path ))
214- except ImportError :
215- continue
216- if not accepted :
217- raise ImportError ("no path hooks could handle %s" % path_entry )
218- return ChainedImporter (* accepted )
219- return chained_fs_path_hook
220-
221-
222214def check_name (method ):
223215 """Decorator to verify that the module being requested matches the one the
224216 loader can handle.
@@ -235,11 +227,11 @@ def inner(self, name, *args, **kwargs):
235227 return inner
236228
237229
238- class _ExtensionFileLoader ( object ) :
230+ class _ExtensionFileLoader :
239231
240232 """Loader for extension modules.
241233
242- The constructor is designed to work with FileImporter .
234+ The constructor is designed to work with FileFinder .
243235
244236 """
245237
@@ -323,10 +315,10 @@ def decorated(self, fullname):
323315 return decorated
324316
325317
326- class _PyFileLoader ( object ) :
318+ class _PyFileLoader :
327319 # XXX Still smart to have this as a separate class? Or would it work
328- # better to integrate with PyFileImporter ? Could cache _is_pkg info.
329- # FileImporter can be changed to return self instead of a specific loader
320+ # better to integrate with PyFileFinder ? Could cache _is_pkg info.
321+ # FileFinder can be changed to return self instead of a specific loader
330322 # call. Otherwise _base_path can be calculated on the fly without issue if
331323 # it is known whether a module should be treated as a path or package to
332324 # minimize stat calls. Could even go as far as to stat the directory the
@@ -515,9 +507,9 @@ def is_package(self, fullname):
515507 return self ._is_pkg
516508
517509
518- class FileImporter ( object ) :
510+ class FileFinder :
519511
520- """Base class for file importers .
512+ """Base class for file finders .
521513
522514 Subclasses are expected to define the following attributes:
523515
@@ -541,10 +533,13 @@ def __init__(self, path_entry):
541533 Can be used as an entry on sys.path_hook.
542534
543535 """
544- self ._path_entry = path_entry
536+ absolute_path = _path_absolute (path_entry )
537+ if not _path_isdir (absolute_path ):
538+ raise ImportError ("only directories are supported" )
539+ self ._path_entry = absolute_path
545540
546541 def find_module (self , fullname , path = None ):
547- tail_module = fullname .rsplit ('.' , 1 )[ - 1 ]
542+ tail_module = fullname .rpartition ('.' )[ 2 ]
548543 package_directory = None
549544 if self ._possible_package :
550545 for ext in self ._suffixes :
@@ -571,7 +566,7 @@ def find_module(self, fullname, path=None):
571566 return None
572567
573568
574- class ExtensionFileImporter ( FileImporter ):
569+ class ExtensionFileFinder ( FileFinder ):
575570
576571 """Importer for extension files."""
577572
@@ -582,10 +577,10 @@ def __init__(self, path_entry):
582577 # Assigning to _suffixes here instead of at the class level because
583578 # imp is not imported at the time of class creation.
584579 self ._suffixes = suffix_list (imp .C_EXTENSION )
585- super (ExtensionFileImporter , self ).__init__ (path_entry )
580+ super ().__init__ (path_entry )
586581
587582
588- class PyFileImporter ( FileImporter ):
583+ class PyFileFinder ( FileFinder ):
589584
590585 """Importer for source/bytecode files."""
591586
@@ -598,7 +593,7 @@ def __init__(self, path_entry):
598593 # optimization by the loader.
599594 self ._suffixes = suffix_list (imp .PY_SOURCE )
600595 self ._suffixes += suffix_list (imp .PY_COMPILED )
601- super (PyFileImporter , self ).__init__ (path_entry )
596+ super ().__init__ (path_entry )
602597
603598
604599class PathFinder :
@@ -664,31 +659,30 @@ def find_module(cls, fullname, path=None):
664659 return None
665660
666661
662+ _DEFAULT_PATH_HOOK = chained_path_hook (ExtensionFileFinder , PyFileFinder )
663+
667664class _DefaultPathFinder (PathFinder ):
668665
669666 """Subclass of PathFinder that implements implicit semantics for
670667 __import__."""
671668
672- _default_hook = staticmethod (chaining_fs_path_hook (ExtensionFileImporter ,
673- PyFileImporter ))
674-
675669 @classmethod
676670 def _path_hooks (cls , path ):
677671 """Search sys.path_hooks as well as implicit path hooks."""
678672 try :
679673 return super ()._path_hooks (path )
680674 except ImportError :
681- implicit_hooks = [cls . _default_hook , imp .NullImporter ]
675+ implicit_hooks = [_DEFAULT_PATH_HOOK , imp .NullImporter ]
682676 return super ()._path_hooks (path , implicit_hooks )
683677
684678 @classmethod
685679 def _path_importer_cache (cls , path ):
686680 """Use the default path hook when None is stored in
687681 sys.path_importer_cache."""
688- return super ()._path_importer_cache (path , cls . _default_hook )
682+ return super ()._path_importer_cache (path , _DEFAULT_PATH_HOOK )
689683
690684
691- class ImportLockContext ( object ) :
685+ class ImportLockContext :
692686
693687 """Context manager for the import lock."""
694688
0 commit comments