_adapters.py (1862B)
- 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)