forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bpo-39791: Add files() to importlib.resources (pythonGH-19722)
* bpo-39791: Update importlib.resources to support files() API (importlib_resources 1.5). * ππ€ Added by blurb_it. * Add some documentation about the new objects added. Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
- Loading branch information
1 parent
d10091a
commit 7f7e706
Showing
7 changed files
with
295 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import os | ||
import pathlib | ||
import zipfile | ||
import tempfile | ||
import functools | ||
import contextlib | ||
|
||
|
||
def from_package(package): | ||
""" | ||
Return a Traversable object for the given package. | ||
""" | ||
spec = package.__spec__ | ||
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 = pathlib.Path(spec.origin).parent | ||
try: | ||
archive_path = spec.loader.archive | ||
rel_path = package_directory.relative_to(archive_path) | ||
return zipfile.Path(archive_path, str(rel_path) + '/') | ||
except Exception: | ||
pass | ||
return package_directory | ||
|
||
|
||
@contextlib.contextmanager | ||
def _tempfile(reader, suffix=''): | ||
# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try' | ||
# blocks due to the need to close the temporary file to work on Windows | ||
# properly. | ||
fd, raw_path = tempfile.mkstemp(suffix=suffix) | ||
try: | ||
os.write(fd, reader()) | ||
os.close(fd) | ||
yield pathlib.Path(raw_path) | ||
finally: | ||
try: | ||
os.remove(raw_path) | ||
except FileNotFoundError: | ||
pass | ||
|
||
|
||
@functools.singledispatch | ||
@contextlib.contextmanager | ||
def as_file(path): | ||
""" | ||
Given a Traversable object, return that object as a | ||
path on the local file system in a context manager. | ||
""" | ||
with _tempfile(path.read_bytes, suffix=path.name) as local: | ||
yield local | ||
|
||
|
||
@as_file.register(pathlib.Path) | ||
@contextlib.contextmanager | ||
def _(path): | ||
""" | ||
Degenerate behavior for pathlib.Path objects. | ||
""" | ||
yield path |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.