summaryrefslogtreecommitdiffstats
path: root/Lib/importlib/resources.py
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2021-07-30 01:05:05 (GMT)
committerGitHub <noreply@github.com>2021-07-30 01:05:05 (GMT)
commitaaa83cdfab6817446285e631232f64b394ac6791 (patch)
treed41195f1412a533b1c7333b99adcc77f171329a1 /Lib/importlib/resources.py
parent851cca8c22795a2f143ad5ebc10adab3c7784ad0 (diff)
downloadcpython-aaa83cdfab6817446285e631232f64b394ac6791.zip
cpython-aaa83cdfab6817446285e631232f64b394ac6791.tar.gz
cpython-aaa83cdfab6817446285e631232f64b394ac6791.tar.bz2
bpo-44771: Apply changes from importlib_resources 5.2.1 (GH-27436)
* bpo-44771: Apply changes from importlib_resources@3b24bd6307 * Add blurb * Exclude namespacedata01 from eol conversion.
Diffstat (limited to 'Lib/importlib/resources.py')
-rw-r--r--Lib/importlib/resources.py186
1 files changed, 19 insertions, 167 deletions
diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py
index bb5c354..6cc4628 100644
--- a/Lib/importlib/resources.py
+++ b/Lib/importlib/resources.py
@@ -1,19 +1,23 @@
-import os
-import io
+"""Read resources contained within a package."""
-from . import _common
-from ._common import as_file, files
-from .abc import ResourceReader
-from contextlib import suppress
-from importlib.abc import ResourceLoader
-from importlib.machinery import ModuleSpec
-from io import BytesIO, TextIOWrapper
-from pathlib import Path
-from types import ModuleType
-from typing import ContextManager, Iterable, Union
-from typing import cast, BinaryIO, TextIO
-from collections.abc import Sequence
-from functools import singledispatch
+from ._common import (
+ as_file,
+ files,
+ Package,
+ Resource,
+)
+
+from ._legacy import (
+ contents,
+ open_binary,
+ read_binary,
+ open_text,
+ read_text,
+ is_resource,
+ path,
+)
+
+from importlib.abc import ResourceReader
__all__ = [
@@ -30,155 +34,3 @@ __all__ = [
'read_binary',
'read_text',
]
-
-
-Package = Union[str, ModuleType]
-Resource = Union[str, os.PathLike]
-
-
-def open_binary(package: Package, resource: Resource) -> BinaryIO:
- """Return a file-like object opened for binary reading of the resource."""
- resource = _common.normalize_path(resource)
- package = _common.get_package(package)
- reader = _common.get_resource_reader(package)
- if reader is not None:
- return reader.open_resource(resource)
- spec = cast(ModuleSpec, package.__spec__)
- # Using pathlib doesn't work well here due to the lack of 'strict'
- # argument for pathlib.Path.resolve() prior to Python 3.6.
- if spec.submodule_search_locations is not None:
- paths = spec.submodule_search_locations
- elif spec.origin is not None:
- paths = [os.path.dirname(os.path.abspath(spec.origin))]
-
- for package_path in paths:
- full_path = os.path.join(package_path, resource)
- try:
- return open(full_path, mode='rb')
- except OSError:
- # Just assume the loader is a resource loader; all the relevant
- # importlib.machinery loaders are and an AttributeError for
- # get_data() will make it clear what is needed from the loader.
- loader = cast(ResourceLoader, spec.loader)
- data = None
- if hasattr(spec.loader, 'get_data'):
- with suppress(OSError):
- data = loader.get_data(full_path)
- if data is not None:
- return BytesIO(data)
-
- raise FileNotFoundError(f'{resource!r} resource not found in {spec.name!r}')
-
-
-def open_text(
- package: Package,
- resource: Resource,
- encoding: str = 'utf-8',
- errors: str = 'strict',
-) -> TextIO:
- """Return a file-like object opened for text reading of the resource."""
- return TextIOWrapper(
- open_binary(package, resource), encoding=encoding, errors=errors
- )
-
-
-def read_binary(package: Package, resource: Resource) -> bytes:
- """Return the binary contents of the resource."""
- with open_binary(package, resource) as fp:
- return fp.read()
-
-
-def read_text(
- package: Package,
- resource: Resource,
- encoding: str = 'utf-8',
- errors: str = 'strict',
-) -> str:
- """Return the decoded string of the resource.
-
- The decoding-related arguments have the same semantics as those of
- bytes.decode().
- """
- with open_text(package, resource, encoding, errors) as fp:
- return fp.read()
-
-
-def path(
- package: Package,
- resource: Resource,
-) -> 'ContextManager[Path]':
- """A context manager providing a file path object to the resource.
-
- If the resource does not already exist on its own on the file system,
- a temporary file will be created. If the file was created, the file
- will be deleted upon exiting the context manager (no exception is
- raised if the file was deleted prior to the context manager
- exiting).
- """
- reader = _common.get_resource_reader(_common.get_package(package))
- return (
- _path_from_reader(reader, _common.normalize_path(resource))
- if reader
- else _common.as_file(
- _common.files(package).joinpath(_common.normalize_path(resource))
- )
- )
-
-
-def _path_from_reader(reader, resource):
- return _path_from_resource_path(reader, resource) or _path_from_open_resource(
- reader, resource
- )
-
-
-def _path_from_resource_path(reader, resource):
- with suppress(FileNotFoundError):
- return Path(reader.resource_path(resource))
-
-
-def _path_from_open_resource(reader, resource):
- saved = io.BytesIO(reader.open_resource(resource).read())
- return _common._tempfile(saved.read, suffix=resource)
-
-
-def is_resource(package: Package, name: str) -> bool:
- """True if 'name' is a resource inside 'package'.
-
- Directories are *not* resources.
- """
- package = _common.get_package(package)
- _common.normalize_path(name)
- reader = _common.get_resource_reader(package)
- if reader is not None:
- return reader.is_resource(name)
- package_contents = set(contents(package))
- if name not in package_contents:
- return False
- return (_common.from_package(package) / name).is_file()
-
-
-def contents(package: Package) -> Iterable[str]:
- """Return an iterable of entries in 'package'.
-
- Note that not all entries are resources. Specifically, directories are
- not considered resources. Use `is_resource()` on each entry returned here
- to check if it is a resource or not.
- """
- package = _common.get_package(package)
- reader = _common.get_resource_reader(package)
- if reader is not None:
- return _ensure_sequence(reader.contents())
- transversable = _common.from_package(package)
- if transversable.is_dir():
- return list(item.name for item in transversable.iterdir())
- return []
-
-
-@singledispatch
-def _ensure_sequence(iterable):
- return list(iterable)
-
-
-@_ensure_sequence.register(Sequence)
-def _(iterable):
- return iterable