-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
The simplest way to make your custom importer, should also be the easiest : reusing existing classes directly should not come with surprises.
We should integrate the pattern I use in most FileFinder even if I they dont do much, only to integrate with existing python and work around some pitfalls :
class MyFileFinder(FileFinder):
def __init__(self, path, *loader_details):
super(MyFileFinder, self).__init__(path, *loader_details)
def __repr__(self):
return 'MyFileFinder({!r})'.format(self.path)
@classmethod
def path_hook(cls, *loader_details):
"""A class method which returns a closure to use on sys.path_hook
which will return an instance using the specified loaders and the path
called on the closure.
If the path called on the closure is not a directory, or doesnt contain
any files with the supported extension, ImportError is raised.
This is different from default python behavior
but prevent polluting the cache with custom finders
"""
def path_hook_for_MyFileFinder(path):
"""Path hook for importlib.machinery.FileFinder."""
if not (os.path.isdir(path)):
raise ImportError('only directories are supported')
exts = [x for ld in loader_details for x in ld[1]]
if not any(fname.endswith(ext) for fname in os.listdir(path) for ext in exts):
raise ImportError(
'only directories containing {ext} files are supported'.format(ext=", ".join(exts)))
return cls(path, *loader_details)
return path_hook_for_MyFileFinder
def find_spec(self, fullname, target=None):
"""
Try to find a spec for the specified module.
:param fullname: the name of the package we are trying to import
:return: the matching spec, or None if not found.
"""
# We attempt to load a .my file as a module
tail_module = fullname.rpartition('.')[2]
base_path = os.path.join(self.path, tail_module)
for suffix, loader_class in self._loaders:
full_path = base_path + suffix
if os.path.isfile(full_path): # maybe we need more checks here (importlib filefinder checks its cache...)
return self._get_spec(loader_class, fullname, full_path, None, target)
# Otherwise, we try find python modules
return super(MyFileFinder, self).find_spec(fullname=fullname, target=target)
[...]There are probably similar changes that would be useful in PathFinder. I haven't used it enough yet to know which ones would be useful.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels