summaryrefslogtreecommitdiffstats
path: root/Lib/importlib
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>2018-01-15 23:07:11 (GMT)
committerGitHub <noreply@github.com>2018-01-15 23:07:11 (GMT)
commit5ec0feeeecc1617987ec6cdc6d62b916e718a5cf (patch)
tree158c8a278acd9a7d2de71553c22199aa9b5b6ec6 /Lib/importlib
parent21102f0dc20cc347677191817c1b66e20ef7bf21 (diff)
downloadcpython-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.py38
-rw-r--r--Lib/importlib/abc.py5
-rw-r--r--Lib/importlib/resources.py6
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