2022-01-06 01:12:46 +00:00
|
|
|
import functools
|
|
|
|
import os
|
|
|
|
import pathlib
|
|
|
|
import types
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
from typing import Union, Iterable, ContextManager, BinaryIO, TextIO, Any
|
|
|
|
|
|
|
|
from . import _common
|
|
|
|
|
|
|
|
Package = Union[types.ModuleType, str]
|
|
|
|
Resource = str
|
|
|
|
|
|
|
|
|
|
|
|
def deprecated(func):
|
|
|
|
@functools.wraps(func)
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
warnings.warn(
|
|
|
|
f"{func.__name__} is deprecated. Use files() instead. "
|
|
|
|
"Refer to https://importlib-resources.readthedocs.io"
|
|
|
|
"/en/latest/using.html#migrating-from-legacy for migration advice.",
|
|
|
|
DeprecationWarning,
|
|
|
|
stacklevel=2,
|
|
|
|
)
|
|
|
|
return func(*args, **kwargs)
|
|
|
|
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
2022-11-07 18:06:49 +00:00
|
|
|
def normalize_path(path: Any) -> str:
|
2022-01-06 01:12:46 +00:00
|
|
|
"""Normalize a path by ensuring it is a string.
|
|
|
|
|
|
|
|
If the resulting string contains path separators, an exception is raised.
|
|
|
|
"""
|
|
|
|
str_path = str(path)
|
|
|
|
parent, file_name = os.path.split(str_path)
|
|
|
|
if parent:
|
|
|
|
raise ValueError(f'{path!r} must be only a file name')
|
|
|
|
return file_name
|
|
|
|
|
|
|
|
|
|
|
|
@deprecated
|
|
|
|
def open_binary(package: Package, resource: Resource) -> BinaryIO:
|
|
|
|
"""Return a file-like object opened for binary reading of the resource."""
|
|
|
|
return (_common.files(package) / normalize_path(resource)).open('rb')
|
|
|
|
|
|
|
|
|
|
|
|
@deprecated
|
|
|
|
def read_binary(package: Package, resource: Resource) -> bytes:
|
|
|
|
"""Return the binary contents of the resource."""
|
|
|
|
return (_common.files(package) / normalize_path(resource)).read_bytes()
|
|
|
|
|
|
|
|
|
|
|
|
@deprecated
|
|
|
|
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 (_common.files(package) / normalize_path(resource)).open(
|
|
|
|
'r', encoding=encoding, errors=errors
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@deprecated
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
|
|
@deprecated
|
|
|
|
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.
|
|
|
|
"""
|
|
|
|
return [path.name for path in _common.files(package).iterdir()]
|
|
|
|
|
|
|
|
|
|
|
|
@deprecated
|
|
|
|
def is_resource(package: Package, name: str) -> bool:
|
|
|
|
"""True if `name` is a resource inside `package`.
|
|
|
|
|
|
|
|
Directories are *not* resources.
|
|
|
|
"""
|
|
|
|
resource = normalize_path(name)
|
|
|
|
return any(
|
|
|
|
traversable.name == resource and traversable.is_file()
|
|
|
|
for traversable in _common.files(package).iterdir()
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@deprecated
|
|
|
|
def path(
|
|
|
|
package: Package,
|
|
|
|
resource: Resource,
|
|
|
|
) -> ContextManager[pathlib.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).
|
|
|
|
"""
|
|
|
|
return _common.as_file(_common.files(package) / normalize_path(resource))
|