Skip to content

Commit f53085d

Browse files
committed
_common: make as_file return the real file on os.PathLike
We currently have custom handling for pathlib.Path, but that means that custom readers that do not using pathlib.Path will have their traversables copied to a temporary directory in as_file, which can be an expensive operation. By adding a dispatch for os.PathLike, we extend this behavior for all path-like objects. Signed-off-by: Filipe Laíns <lains@riseup.net>
1 parent 54a61c4 commit f53085d

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

importlib_resources/_common.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,17 @@ def as_file(path):
109109

110110
@as_file.register(pathlib.Path)
111111
@contextlib.contextmanager
112-
def _(path):
112+
def _as_file_pathlib(path):
113113
"""
114114
Degenerate behavior for pathlib.Path objects.
115115
"""
116116
yield path
117+
118+
119+
@as_file.register(os.PathLike)
120+
@contextlib.contextmanager
121+
def _as_file_pathlike(path):
122+
"""
123+
Degenerate behavior for os.PathLike objects.
124+
"""
125+
yield pathlib.Path(os.fspath(path))

importlib_resources/tests/test_path.py

+37
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import io
2+
import os
3+
import pathlib
24
import unittest
35

46
import importlib_resources as resources
7+
from importlib_resources.abc import TraversableResources
58
from . import data01
69
from . import util
710

@@ -57,5 +60,39 @@ def test_remove_in_context_manager(self):
5760
path.unlink()
5861

5962

63+
class PathLikeTests(PathTests, unittest.TestCase):
64+
class PathLikeTraversable:
65+
"""pathlib.Path proxy, is os.PathLike but is not pathlib.Path"""
66+
67+
def __init__(self, *args, **kwargs):
68+
self._path = pathlib.Path(*args, **kwargs)
69+
70+
def __fspath__(self):
71+
return os.fspath(self._path)
72+
73+
def joinpath(self, other):
74+
return self.__class__(self, other)
75+
76+
__truediv__ = joinpath
77+
78+
@property
79+
def parent(self):
80+
return self.__class__(self._path.parent)
81+
82+
class PathLikeResources(TraversableResources):
83+
def __init__(self, loader):
84+
self.path = PathLikeTests.PathLikeTraversable(loader.path).parent
85+
86+
def get_resource_reader(self, package):
87+
return self
88+
89+
def files(self):
90+
return self.path
91+
92+
def setUp(self):
93+
reader = self.PathLikeResources(data01.__loader__)
94+
self.data = util.create_package_from_loader(reader)
95+
96+
6097
if __name__ == '__main__':
6198
unittest.main()

0 commit comments

Comments
 (0)