Skip to content

Commit

Permalink
trees.from_package now supports TraversableResources loaders. Closes p…
Browse files Browse the repository at this point in the history
  • Loading branch information
jaraco committed Mar 1, 2020
1 parent cc74d38 commit 54debaf
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 28 deletions.
4 changes: 2 additions & 2 deletions importlib_resources/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ problems of ``pkg_resources``.

In our terminology, a *resource* is a file tree that is located within an
importable `Python package`_. Resources can live on the file system or in a
zip file, with limited support for loader_ supporting the appropriate API for
reading resources.
zip file, with support for other loader_ classes that implement the appropriate
API for reading resources.

``importlib_resources`` is a backport of Python 3.9's standard library
`importlib.resources`_ module for Python 2.7, and 3.5 through 3.8. Users of
Expand Down
33 changes: 10 additions & 23 deletions importlib_resources/docs/using.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,6 @@ the ``data.one`` package, and
``data`` package.


Caveats
=======

Subdirectory Access
-------------------

Prior to importlib_resources 1.1 and the ``files()`` API, resources that were
not direct descendents of a package's folder were inaccessible through the
API, so in the example above ``resources1/resource1.1`` is not a resource of
the ``data.one`` package and ``two/resource2.txt`` is not a resource of the
``data`` package. Therefore, if subdirectory access is required, use the
``files()`` API.

Resource Reader Support
-----------------------

Due to the limitations on resource readers to access files beyond direct
descendents of a package, the ``files()`` API does not rely
on the importlib ResourceReader interface and thus only supports resources
exposed by the built-in path and zipfile loaders. If support for arbitrary
resource readers is required, the other API functions still support loading
those resources.

Example
=======

Expand Down Expand Up @@ -187,6 +164,16 @@ manager.
Both relative and absolute paths work for Python 3.7 and newer.


Extending
=========

Starting with Python 3.9 and ``importlib_resources`` 1.2, this package
provides an interface for non-standard loaders, such as those used by
executable bundlers, to supply resources. These loaders should subclass
from the ``TraversableResources`` abstract class and implement the
``files()`` method to return a ``Traversable`` object.


.. rubric:: Footnotes

.. [#fn1] We're ignoring `PEP 420
Expand Down
22 changes: 19 additions & 3 deletions importlib_resources/trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,24 @@ def __truediv__(self, child):


def from_package(package):
"""Return a Traversable object for the given package"""
"""
Return a Traversable object for the given package.
"""
spec = package_spec(package)
return from_traversable_resources(spec) or fallback_resources(spec)


def from_traversable_resources(spec):
"""
If the spec.loader implements TraversableResources,
directly or implicitly, it will have a ``files()`` method.
"""
with contextlib.suppress(AttributeError):
return spec.loader.files()


def fallback_resources(spec):
package_directory = Path(spec.origin).parent
try:
archive_path = spec.loader.archive
Expand Down Expand Up @@ -94,7 +110,7 @@ def _tempfile(reader):
@contextlib.contextmanager
def as_file(path):
"""
Given a path-like object, return that object as a
Given a Traversable object, return that object as a
path on the local file system in a context manager.
"""
with _tempfile(path.read_bytes) as local:
Expand All @@ -105,6 +121,6 @@ def as_file(path):
@contextlib.contextmanager
def _(path):
"""
Degenerate behavior for pathlib.Path objects
Degenerate behavior for pathlib.Path objects.
"""
yield path

0 comments on commit 54debaf

Please sign in to comment.