diff --git a/importlib_resources/_common.py b/importlib_resources/_common.py index 3c6de1cf..c5cd43be 100644 --- a/importlib_resources/_common.py +++ b/importlib_resources/_common.py @@ -12,7 +12,8 @@ from typing import Union, Optional, cast from .abc import ResourceReader, Traversable -from ._compat import wrap_spec +from ._compat import ZipPath, wrap_spec +from .readers import EnterablePath, EnterableZip Package = Union[types.ModuleType, str] Anchor = Package @@ -53,7 +54,14 @@ def files(anchor: Optional[Anchor] = None) -> Traversable: """ Get a Traversable resource for an anchor. """ - return from_package(resolve(anchor)) + f = from_package(resolve(anchor)) + if isinstance(f, ZipPath): + return EnterableZip(f.root, f.at) + elif isinstance(f, pathlib.Path): + return EnterablePath(f) + else: + # `with f as g:` will fail for MultiplexedPath + return f def get_resource_reader(package: types.ModuleType) -> Optional[ResourceReader]: diff --git a/importlib_resources/readers.py b/importlib_resources/readers.py index 1e2d1bac..ce12eb6c 100644 --- a/importlib_resources/readers.py +++ b/importlib_resources/readers.py @@ -170,3 +170,20 @@ def resource_path(self, resource): def files(self): return self.path + + +class EnterablePath(pathlib.Path): + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + pass + +class EnterableZip(ZipPath): + def __enter__(self): + from ._common import as_file + self._as_file = as_file(self) + return self._as_file.__enter__() + + def __exit__(self, exc_type, exc_value, traceback): + self._as_file.__exit__(exc_type, exc_value, traceback)