Spaces:
Running
Running
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, mode='rb', *args, **kwargs): | |
raise ValueError() | |
def __init__(self, spec): | |
self.spec = spec | |
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) | |