Skip to content

Commit

Permalink
_common: make as_file return the real file on os.PathLike
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
FFY00 committed Jul 29, 2021
1 parent 54a61c4 commit af4b710
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
9 changes: 9 additions & 0 deletions importlib_resources/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,12 @@ def _(path):
Degenerate behavior for pathlib.Path objects.
"""
yield path


@as_file.register(os.PathLike)
@contextlib.contextmanager
def _(path):
"""
Degenerate behavior for pathlib.Path objects.
"""
yield pathlib.Path(os.fspath(path))
40 changes: 40 additions & 0 deletions importlib_resources/tests/test_path.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import io
import os
import pathlib
import unittest

import importlib_resources as resources
from importlib_resources.abc import Traversable, TraversableResources
from . import data01
from . import util

Expand Down Expand Up @@ -57,5 +60,42 @@ def test_remove_in_context_manager(self):
path.unlink()


class PathLikeTests(PathTests, unittest.TestCase):
class PathLikeTraversable:
"""pathlib.Path proxy, is os.PathLike but is not pathlib.Path"""

def __init__(self, *args, **kwargs):
self._path = pathlib.Path(*args, **kwargs)

def __fspath__(self, *args, **kwargs):
return os.fspath(self._path)

def joinpath(self, other):
return self.__class__(self, other)

__truediv__ = joinpath

@property
def parent(self):
return self.__class__(self._path.parent)

def __getattr__(self, name):
return getattr(self._path, name)

class PathLikeResources(TraversableResources):
def __init__(self, loader):
self.path = PathLikeTests.PathLikeTraversable(loader.path).parent

def get_resource_reader(self, package):
return self

def files(self):
return self.path

def setUp(self):
reader = self.PathLikeResources(data01.__loader__)
self.data = util.create_package_from_loader(reader)


if __name__ == '__main__':
unittest.main()

0 comments on commit af4b710

Please sign in to comment.