diff options
author | Barry Warsaw <barry@python.org> | 2018-01-15 23:07:11 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-15 23:07:11 (GMT) |
commit | 5ec0feeeecc1617987ec6cdc6d62b916e718a5cf (patch) | |
tree | 158c8a278acd9a7d2de71553c22199aa9b5b6ec6 /Lib/importlib | |
parent | 21102f0dc20cc347677191817c1b66e20ef7bf21 (diff) | |
download | cpython-5ec0feeeecc1617987ec6cdc6d62b916e718a5cf.zip cpython-5ec0feeeecc1617987ec6cdc6d62b916e718a5cf.tar.gz cpython-5ec0feeeecc1617987ec6cdc6d62b916e718a5cf.tar.bz2 |
Implement the get_resource_reader() API for file system imports (#5168)
Diffstat (limited to 'Lib/importlib')
-rw-r--r-- | Lib/importlib/_bootstrap_external.py | 38 | ||||
-rw-r--r-- | Lib/importlib/abc.py | 5 | ||||
-rw-r--r-- | Lib/importlib/resources.py | 6 |
3 files changed, 40 insertions, 9 deletions
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index e808507..cf75719 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -6,12 +6,11 @@ such it requires the injection of specific modules and attributes in order to work. One should use importlib as the public-facing version of this module. """ -# -# IMPORTANT: Whenever making changes to this module, be sure to run -# a top-level make in order to get the frozen version of the module -# updated. Not doing so will result in the Makefile to fail for -# all others who don't have a ./python around to freeze the module -# in the early stages of compilation. +# IMPORTANT: Whenever making changes to this module, be sure to run a top-level +# `make regen-importlib` followed by `make` in order to get the frozen version +# of the module updated. Not doing so will result in the Makefile to fail for +# all others who don't have a ./python around to freeze the module in the early +# stages of compilation. # # See importlib._setup() for what is injected into the global namespace. @@ -911,6 +910,33 @@ class FileLoader: with _io.FileIO(path, 'r') as file: return file.read() + # ResourceReader ABC API. + + @_check_name + def get_resource_reader(self, module): + if self.is_package(module): + return self + return None + + def open_resource(self, resource): + path = _path_join(_path_split(self.path)[0], resource) + return _io.FileIO(path, 'r') + + def resource_path(self, resource): + if not self.is_resource(resource): + raise FileNotFoundError + path = _path_join(_path_split(self.path)[0], resource) + return path + + def is_resource(self, name): + if path_sep in name: + return False + path = _path_join(_path_split(self.path)[0], name) + return _path_isfile(path) + + def contents(self): + return iter(_os.listdir(_path_split(self.path)[0])) + class SourceFileLoader(FileLoader, SourceLoader): diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py index bbff7af..d2f4509 100644 --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -342,7 +342,7 @@ class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLo _register(SourceLoader, machinery.SourceFileLoader) -class ResourceReader: +class ResourceReader(metaclass=abc.ABCMeta): """Abstract base class to provide resource-reading support. @@ -383,3 +383,6 @@ class ResourceReader: def contents(self): """Return an iterator of strings over the contents of the package.""" return iter([]) + + +_register(ResourceReader, machinery.SourceFileLoader) diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py index 8511f24..20888df 100644 --- a/Lib/importlib/resources.py +++ b/Lib/importlib/resources.py @@ -59,8 +59,10 @@ def _get_resource_reader( # hook wants to create a weak reference to the object, but # zipimport.zipimporter does not support weak references, resulting in a # TypeError. That seems terrible. - if hasattr(package.__spec__.loader, 'open_resource'): - return cast(resources_abc.ResourceReader, package.__spec__.loader) + spec = package.__spec__ + if hasattr(spec.loader, 'get_resource_reader'): + return cast(resources_abc.ResourceReader, + spec.loader.get_resource_reader(spec.name)) return None |