diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2021-03-04 13:43:00 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-04 13:43:00 -0500 |
commit | 67148254146948041a77d8a2989f41b88cdb2f99 (patch) | |
tree | 036bcb818e80090b34f0c59f57f8b6946b52b21d /Lib/importlib/_adapters.py | |
parent | fbf75b9997e280b1220755d0a17dbed71240d42e (diff) | |
download | cpython-git-67148254146948041a77d8a2989f41b88cdb2f99.tar.gz |
bpo-42129: Add support for resources in namespaces (GH-24670)
* Unify behavior in ResourceReaderDefaultsTests and align with the behavior found in importlib_resources.
* Equip NamespaceLoader with a NamespaceReader.
* Apply changes from importlib_resources 5.0.4
Diffstat (limited to 'Lib/importlib/_adapters.py')
-rw-r--r-- | Lib/importlib/_adapters.py | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/Lib/importlib/_adapters.py b/Lib/importlib/_adapters.py new file mode 100644 index 0000000000..eedde49dd0 --- /dev/null +++ b/Lib/importlib/_adapters.py @@ -0,0 +1,82 @@ +from contextlib import suppress + +from . import abc + + +class SpecLoaderAdapter: + """ + Adapt a package spec to adapt the underlying loader. + """ + + def __init__(self, spec, adapter=lambda spec: spec.loader): + self.spec = spec + self.loader = adapter(spec) + + def __getattr__(self, name): + return getattr(self.spec, name) + + +class TraversableResourcesLoader: + """ + Adapt a loader to provide TraversableResources. + """ + + def __init__(self, spec): + self.spec = spec + + def get_resource_reader(self, name): + return DegenerateFiles(self.spec)._native() + + +class DegenerateFiles: + """ + Adapter for an existing or non-existant resource reader + to provide a degenerate .files(). + """ + + class Path(abc.Traversable): + def iterdir(self): + return iter(()) + + def is_dir(self): + return False + + is_file = exists = is_dir # type: ignore + + def joinpath(self, other): + return DegenerateFiles.Path() + + def name(self): + return '' + + def open(self): + raise ValueError() + + def __init__(self, spec): + self.spec = spec + + @property + def _reader(self): + with suppress(AttributeError): + return self.spec.loader.get_resource_reader(self.spec.name) + + def _native(self): + """ + Return the native reader if it supports files(). + """ + reader = self._reader + return reader if hasattr(reader, 'files') else self + + def __getattr__(self, attr): + return getattr(self._reader, attr) + + def files(self): + return DegenerateFiles.Path() + + +def wrap_spec(package): + """ + Construct a package spec with traversable compatibility + on the spec/loader/reader. + """ + return SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) |