fix vendor

This commit is contained in:
2023-09-07 12:06:13 +03:00
parent 4963339b34
commit 731ddbc133
130 changed files with 253704 additions and 0 deletions

53
vendor/importlib_resources/__init__.py vendored Normal file
View File

@@ -0,0 +1,53 @@
"""Read resources contained within a package."""
import sys
from ._common import (
as_file, files,
)
# For compatibility. Ref #88.
# Also requires hook-importlib_resources.py (Ref #101).
__import__('importlib_resources.trees')
__all__ = [
'Package',
'Resource',
'ResourceReader',
'as_file',
'contents',
'files',
'is_resource',
'open_binary',
'open_text',
'path',
'read_binary',
'read_text',
]
if sys.version_info >= (3,):
from importlib_resources._py3 import (
Package,
Resource,
contents,
is_resource,
open_binary,
open_text,
path,
read_binary,
read_text,
)
from importlib_resources.abc import ResourceReader
else:
from importlib_resources._py2 import (
contents,
is_resource,
open_binary,
open_text,
path,
read_binary,
read_text,
)
del __all__[:3]

120
vendor/importlib_resources/_common.py vendored Normal file
View File

@@ -0,0 +1,120 @@
from __future__ import absolute_import
import os
import tempfile
import contextlib
import types
import importlib
from ._compat import (
Path, FileNotFoundError,
singledispatch, package_spec,
)
if False: # TYPE_CHECKING
from typing import Union, Any, Optional
from .abc import ResourceReader
Package = Union[types.ModuleType, str]
def files(package):
"""
Get a Traversable resource from a package
"""
return from_package(get_package(package))
def normalize_path(path):
# type: (Any) -> str
"""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('{!r} must be only a file name'.format(path))
return file_name
def get_resource_reader(package):
# type: (types.ModuleType) -> Optional[ResourceReader]
"""
Return the package's loader if it's a ResourceReader.
"""
# We can't use
# a issubclass() check here because apparently abc.'s __subclasscheck__()
# hook wants to create a weak reference to the object, but
# zipimport.zipimporter does not support weak references, resulting in a
# TypeError. That seems terrible.
spec = package.__spec__
reader = getattr(spec.loader, 'get_resource_reader', None)
if reader is None:
return None
return reader(spec.name)
def resolve(cand):
# type: (Package) -> types.ModuleType
return (
cand if isinstance(cand, types.ModuleType)
else importlib.import_module(cand)
)
def get_package(package):
# type: (Package) -> types.ModuleType
"""Take a package name or module object and return the module.
Raise an exception if the resolved module is not a package.
"""
resolved = resolve(package)
if package_spec(resolved).submodule_search_locations is None:
raise TypeError('{!r} is not a package'.format(package))
return resolved
def from_package(package):
"""
Return a Traversable object for the given package.
"""
spec = package_spec(package)
reader = spec.loader.get_resource_reader(spec.name)
return reader.files()
@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)
del reader
yield Path(raw_path)
finally:
try:
os.remove(raw_path)
except FileNotFoundError:
pass
@singledispatch
def as_file(path):
"""
Given a Traversable object, return that object as a
path on the local file system in a context manager.
"""
return _tempfile(path.read_bytes, suffix=path.name)
@as_file.register(Path)
@contextlib.contextmanager
def _(path):
"""
Degenerate behavior for pathlib.Path objects.
"""
yield path

139
vendor/importlib_resources/_compat.py vendored Normal file
View File

@@ -0,0 +1,139 @@
from __future__ import absolute_import
import sys
# flake8: noqa
if sys.version_info > (3,5):
from pathlib import Path, PurePath
else:
from pathlib2 import Path, PurePath # type: ignore
if sys.version_info > (3,):
from contextlib import suppress
else:
from contextlib2 import suppress # type: ignore
try:
from functools import singledispatch
except ImportError:
from singledispatch import singledispatch # type: ignore
try:
from abc import ABC # type: ignore
except ImportError:
from abc import ABCMeta
class ABC(object): # type: ignore
__metaclass__ = ABCMeta
try:
FileNotFoundError = FileNotFoundError # type: ignore
except NameError:
FileNotFoundError = OSError # type: ignore
try:
NotADirectoryError = NotADirectoryError # type: ignore
except NameError:
NotADirectoryError = OSError # type: ignore
try:
from zipfile import Path as ZipPath # type: ignore
except ImportError:
from zipp import Path as ZipPath # type: ignore
try:
from typing import runtime_checkable # type: ignore
except ImportError:
def runtime_checkable(cls): # type: ignore
return cls
try:
from typing import Protocol # type: ignore
except ImportError:
Protocol = ABC # type: ignore
__metaclass__ = type
class PackageSpec:
def __init__(self, **kwargs):
vars(self).update(kwargs)
class TraversableResourcesAdapter:
def __init__(self, spec):
self.spec = spec
self.loader = LoaderAdapter(spec)
def __getattr__(self, name):
return getattr(self.spec, name)
class LoaderAdapter:
"""
Adapt loaders to provide TraversableResources and other
compatibility.
"""
def __init__(self, spec):
self.spec = spec
@property
def path(self):
# Python < 3
return self.spec.origin
def get_resource_reader(self, name):
# Python < 3.9
from . import readers
def _zip_reader(spec):
with suppress(AttributeError):
return readers.ZipReader(spec.loader, spec.name)
def _namespace_reader(spec):
with suppress(AttributeError, ValueError):
return readers.NamespaceReader(spec.submodule_search_locations)
def _available_reader(spec):
with suppress(AttributeError):
return spec.loader.get_resource_reader(spec.name)
def _native_reader(spec):
reader = _available_reader(spec)
return reader if hasattr(reader, 'files') else None
return (
# native reader if it supplies 'files'
_native_reader(self.spec) or
# local ZipReader if a zip module
_zip_reader(self.spec) or
# local NamespaceReader if a namespace module
_namespace_reader(self.spec) or
# local FileReader
readers.FileReader(self)
)
def package_spec(package):
"""
Construct a minimal package spec suitable for
matching the interfaces this library relies upon
in later Python versions.
"""
spec = getattr(package, '__spec__', None) or \
PackageSpec(
origin=package.__file__,
loader=getattr(package, '__loader__', None),
name=package.__name__,
submodule_search_locations=getattr(package, '__path__', None),
)
return TraversableResourcesAdapter(spec)

107
vendor/importlib_resources/_py2.py vendored Normal file
View File

@@ -0,0 +1,107 @@
import os
import errno
from . import _common
from ._compat import FileNotFoundError
from io import BytesIO, TextIOWrapper, open as io_open
def open_binary(package, resource):
"""Return a file-like object opened for binary reading of the resource."""
resource = _common.normalize_path(resource)
package = _common.get_package(package)
# Using pathlib doesn't work well here due to the lack of 'strict' argument
# for pathlib.Path.resolve() prior to Python 3.6.
package_path = os.path.dirname(package.__file__)
relative_path = os.path.join(package_path, resource)
full_path = os.path.abspath(relative_path)
try:
return io_open(full_path, 'rb')
except IOError:
# This might be a package in a zip file. zipimport provides a loader
# with a functioning get_data() method, however we have to strip the
# archive (i.e. the .zip file's name) off the front of the path. This
# is because the zipimport loader in Python 2 doesn't actually follow
# PEP 302. It should allow the full path, but actually requires that
# the path be relative to the zip file.
try:
loader = package.__loader__
full_path = relative_path[len(loader.archive)+1:]
data = loader.get_data(full_path)
except (IOError, AttributeError):
package_name = package.__name__
message = '{!r} resource not found in {!r}'.format(
resource, package_name)
raise FileNotFoundError(message)
return BytesIO(data)
def open_text(package, resource, encoding='utf-8', errors='strict'):
"""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, resource):
"""Return the binary contents of the resource."""
with open_binary(package, resource) as fp:
return fp.read()
def read_text(package, resource, encoding='utf-8', errors='strict'):
"""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, resource):
"""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).
"""
path = _common.files(package).joinpath(_common.normalize_path(resource))
if not path.is_file():
raise FileNotFoundError(path)
return _common.as_file(path)
def is_resource(package, name):
"""True if name is a resource inside package.
Directories are *not* resources.
"""
package = _common.get_package(package)
_common.normalize_path(name)
try:
package_contents = set(contents(package))
except OSError as error:
if error.errno not in (errno.ENOENT, errno.ENOTDIR):
# We won't hit this in the Python 2 tests, so it'll appear
# uncovered. We could mock os.listdir() to return a non-ENOENT or
# ENOTDIR, but then we'd have to depend on another external
# library since Python 2 doesn't have unittest.mock. It's not
# worth it.
raise # pragma: nocover
return False
if name not in package_contents:
return False
return (_common.from_package(package) / name).is_file()
def contents(package):
"""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)
return list(item.name for item in _common.from_package(package).iterdir())

160
vendor/importlib_resources/_py3.py vendored Normal file
View File

@@ -0,0 +1,160 @@
import os
import io
from . import _common
from contextlib import suppress
from importlib.abc import ResourceLoader
from io import BytesIO, TextIOWrapper
from pathlib import Path
from types import ModuleType
from typing import Iterable, Iterator, Optional, Set, Union # noqa: F401
from typing import cast
from typing.io import BinaryIO, TextIO
from collections.abc import Sequence
from functools import singledispatch
if False: # TYPE_CHECKING
from typing import ContextManager
Package = Union[ModuleType, str]
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)
# Using pathlib doesn't work well here due to the lack of 'strict'
# argument for pathlib.Path.resolve() prior to Python 3.6.
if package.__spec__.submodule_search_locations is not None:
paths = package.__spec__.submodule_search_locations
elif package.__spec__.origin is not None:
paths = [os.path.dirname(os.path.abspath(package.__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, package.__spec__.loader)
data = None
if hasattr(package.__spec__.loader, 'get_data'):
with suppress(OSError):
data = loader.get_data(full_path)
if data is not None:
return BytesIO(data)
raise FileNotFoundError('{!r} resource not found in {!r}'.format(
resource, package.__spec__.name))
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

142
vendor/importlib_resources/abc.py vendored Normal file
View File

@@ -0,0 +1,142 @@
from __future__ import absolute_import
import abc
from ._compat import ABC, FileNotFoundError, runtime_checkable, Protocol
# Use mypy's comment syntax for Python 2 compatibility
try:
from typing import BinaryIO, Iterable, Text
except ImportError:
pass
class ResourceReader(ABC):
"""Abstract base class for loaders to provide resource reading support."""
@abc.abstractmethod
def open_resource(self, resource):
# type: (Text) -> BinaryIO
"""Return an opened, file-like object for binary reading.
The 'resource' argument is expected to represent only a file name.
If the resource cannot be found, FileNotFoundError is raised.
"""
# This deliberately raises FileNotFoundError instead of
# NotImplementedError so that if this method is accidentally called,
# it'll still do the right thing.
raise FileNotFoundError
@abc.abstractmethod
def resource_path(self, resource):
# type: (Text) -> Text
"""Return the file system path to the specified resource.
The 'resource' argument is expected to represent only a file name.
If the resource does not exist on the file system, raise
FileNotFoundError.
"""
# This deliberately raises FileNotFoundError instead of
# NotImplementedError so that if this method is accidentally called,
# it'll still do the right thing.
raise FileNotFoundError
@abc.abstractmethod
def is_resource(self, path):
# type: (Text) -> bool
"""Return True if the named 'path' is a resource.
Files are resources, directories are not.
"""
raise FileNotFoundError
@abc.abstractmethod
def contents(self):
# type: () -> Iterable[str]
"""Return an iterable of entries in `package`."""
raise FileNotFoundError
@runtime_checkable
class Traversable(Protocol):
"""
An object with a subset of pathlib.Path methods suitable for
traversing directories and opening files.
"""
@abc.abstractmethod
def iterdir(self):
"""
Yield Traversable objects in self
"""
@abc.abstractmethod
def read_bytes(self):
"""
Read contents of self as bytes
"""
@abc.abstractmethod
def read_text(self, encoding=None):
"""
Read contents of self as bytes
"""
@abc.abstractmethod
def is_dir(self):
"""
Return True if self is a dir
"""
@abc.abstractmethod
def is_file(self):
"""
Return True if self is a file
"""
@abc.abstractmethod
def joinpath(self, child):
"""
Return Traversable child in self
"""
@abc.abstractmethod
def __truediv__(self, child):
"""
Return Traversable child in self
"""
@abc.abstractmethod
def open(self, mode='r', *args, **kwargs):
"""
mode may be 'r' or 'rb' to open as text or binary. Return a handle
suitable for reading (same as pathlib.Path.open).
When opening as text, accepts encoding parameters such as those
accepted by io.TextIOWrapper.
"""
@abc.abstractproperty
def name(self):
# type: () -> str
"""
The base name of this object without any parent references.
"""
class TraversableResources(ResourceReader):
@abc.abstractmethod
def files(self):
"""Return a Traversable object for the loaded package."""
def open_resource(self, resource):
return self.files().joinpath(resource).open('rb')
def resource_path(self, resource):
raise FileNotFoundError(resource)
def is_resource(self, path):
return self.files().joinpath(path).is_file()
def contents(self):
return (item.name for item in self.files().iterdir())

0
vendor/importlib_resources/py.typed vendored Normal file
View File

123
vendor/importlib_resources/readers.py vendored Normal file
View File

@@ -0,0 +1,123 @@
import os.path
from collections import OrderedDict
from . import abc
from ._compat import Path, ZipPath
from ._compat import FileNotFoundError, NotADirectoryError
class FileReader(abc.TraversableResources):
def __init__(self, loader):
self.path = Path(loader.path).parent
def resource_path(self, resource):
"""
Return the file system path to prevent
`resources.path()` from creating a temporary
copy.
"""
return str(self.path.joinpath(resource))
def files(self):
return self.path
class ZipReader(abc.TraversableResources):
def __init__(self, loader, module):
_, _, name = module.rpartition('.')
self.prefix = loader.prefix.replace('\\', '/') + name + '/'
self.archive = loader.archive
def open_resource(self, resource):
try:
return super().open_resource(resource)
except KeyError as exc:
raise FileNotFoundError(exc.args[0])
def is_resource(self, path):
# workaround for `zipfile.Path.is_file` returning true
# for non-existent paths.
target = self.files().joinpath(path)
return target.is_file() and target.exists()
def files(self):
return ZipPath(self.archive, self.prefix)
class MultiplexedPath(abc.Traversable):
"""
Given a series of Traversable objects, implement a merged
version of the interface across all objects. Useful for
namespace packages which may be multihomed at a single
name.
"""
def __init__(self, *paths):
paths = list(OrderedDict.fromkeys(paths)) # remove duplicates
self._paths = list(map(Path, paths))
if not self._paths:
message = 'MultiplexedPath must contain at least one path'
raise FileNotFoundError(message)
if any(not path.is_dir() for path in self._paths):
raise NotADirectoryError(
'MultiplexedPath only supports directories')
def iterdir(self):
visited = []
for path in self._paths:
for file in path.iterdir():
if file.name in visited:
continue
visited.append(file.name)
yield file
def read_bytes(self):
raise FileNotFoundError('{} is not a file'.format(self))
def read_text(self, *args, **kwargs):
raise FileNotFoundError('{} is not a file'.format(self))
def is_dir(self):
return True
def is_file(self):
return False
def joinpath(self, child):
# first try to find child in current paths
for file in self.iterdir():
if file.name == child:
return file
# if it does not exist, construct it with the first path
return self._paths[0] / child
__truediv__ = joinpath
def open(self, *args, **kwargs):
raise FileNotFoundError('{} is not a file'.format(self))
def name(self):
return os.path.basename(self._paths[0])
def __repr__(self):
return 'MultiplexedPath({})'.format(
', '.join("'{}'".format(path) for path in self._paths))
class NamespaceReader(abc.TraversableResources):
def __init__(self, namespace_path):
if 'NamespacePath' not in str(namespace_path):
raise ValueError('Invalid path')
self.path = MultiplexedPath(*list(namespace_path))
def resource_path(self, resource):
"""
Return the file system path to prevent
`resources.path()` from creating a temporary
copy.
"""
return str(self.path.joinpath(resource))
def files(self):
return self.path

View File

View File

@@ -0,0 +1,30 @@
try:
from test.support import import_helper # type: ignore
except ImportError:
try:
# Python 3.9 and earlier
class import_helper: # type: ignore
from test.support import modules_setup, modules_cleanup
except ImportError:
from . import py27compat
class import_helper: # type: ignore
modules_setup = staticmethod(py27compat.modules_setup)
modules_cleanup = staticmethod(py27compat.modules_cleanup)
try:
from os import fspath # type: ignore
except ImportError:
# Python 3.5
fspath = str # type: ignore
try:
# Python 3.10
from test.support.os_helper import unlink
except ImportError:
from test.support import unlink as _unlink
def unlink(target):
return _unlink(fspath(target))

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
Hello, UTF-8 world!

View File

View File

@@ -0,0 +1 @@
one resource

View File

@@ -0,0 +1 @@
two resource

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
Hello, UTF-8 world!

View File

@@ -0,0 +1,23 @@
import sys
def modules_setup():
return sys.modules.copy(),
def modules_cleanup(oldmodules):
# Encoders/decoders are registered permanently within the internal
# codec cache. If we destroy the corresponding modules their
# globals will be set to None which will trip up the cached functions.
encodings = [(k, v) for k, v in sys.modules.items()
if k.startswith('encodings.')]
sys.modules.clear()
sys.modules.update(encodings)
# XXX: This kind of problem can affect more than just encodings.
# In particular extension modules (such as _ssl) don't cope
# with reloading properly. Really, test modules should be cleaning
# out the test specific modules they know they added (ala test_runpy)
# rather than relying on this function (as test_importhooks and test_pkg
# do currently). Implicitly imported *real* modules should be left alone
# (see issue 10556).
sys.modules.update(oldmodules)

View File

@@ -0,0 +1,39 @@
import typing
import unittest
import importlib_resources as resources
from importlib_resources.abc import Traversable
from . import data01
from . import util
class FilesTests:
def test_read_bytes(self):
files = resources.files(self.data)
actual = files.joinpath('utf-8.file').read_bytes()
assert actual == b'Hello, UTF-8 world!\n'
def test_read_text(self):
files = resources.files(self.data)
actual = files.joinpath('utf-8.file').read_text()
assert actual == 'Hello, UTF-8 world!\n'
@unittest.skipUnless(
hasattr(typing, 'runtime_checkable'),
"Only suitable when typing supports runtime_checkable",
)
def test_traversable(self):
assert isinstance(resources.files(self.data), Traversable)
class OpenDiskTests(FilesTests, unittest.TestCase):
def setUp(self):
self.data = data01
class OpenZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
pass
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,84 @@
import sys
import unittest
import importlib_resources as resources
from . import data01
from . import util
from .._compat import FileNotFoundError
class CommonBinaryTests(util.CommonTests, unittest.TestCase):
def execute(self, package, path):
with resources.open_binary(package, path):
pass
class CommonTextTests(util.CommonTests, unittest.TestCase):
def execute(self, package, path):
with resources.open_text(package, path):
pass
class OpenTests:
def test_open_binary(self):
with resources.open_binary(self.data, 'utf-8.file') as fp:
result = fp.read()
self.assertEqual(result, b'Hello, UTF-8 world!\n')
def test_open_text_default_encoding(self):
with resources.open_text(self.data, 'utf-8.file') as fp:
result = fp.read()
self.assertEqual(result, 'Hello, UTF-8 world!\n')
def test_open_text_given_encoding(self):
with resources.open_text(
self.data, 'utf-16.file', 'utf-16', 'strict') as fp:
result = fp.read()
self.assertEqual(result, 'Hello, UTF-16 world!\n')
def test_open_text_with_errors(self):
# Raises UnicodeError without the 'errors' argument.
with resources.open_text(
self.data, 'utf-16.file', 'utf-8', 'strict') as fp:
self.assertRaises(UnicodeError, fp.read)
with resources.open_text(
self.data, 'utf-16.file', 'utf-8', 'ignore') as fp:
result = fp.read()
self.assertEqual(
result,
'H\x00e\x00l\x00l\x00o\x00,\x00 '
'\x00U\x00T\x00F\x00-\x001\x006\x00 '
'\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00')
def test_open_binary_FileNotFoundError(self):
self.assertRaises(
FileNotFoundError,
resources.open_binary, self.data, 'does-not-exist')
def test_open_text_FileNotFoundError(self):
self.assertRaises(
FileNotFoundError,
resources.open_text, self.data, 'does-not-exist')
class OpenDiskTests(OpenTests, unittest.TestCase):
def setUp(self):
self.data = data01
@unittest.skipUnless(
sys.version_info[0] >= 3,
'namespace packages not available on Python 2'
)
class OpenDiskNamespaceTests(OpenTests, unittest.TestCase):
def setUp(self):
from . import namespacedata01
self.data = namespacedata01
class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
pass
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,51 @@
import unittest
import importlib_resources as resources
from . import data01
from . import util
class CommonTests(util.CommonTests, unittest.TestCase):
def execute(self, package, path):
with resources.path(package, path):
pass
class PathTests:
def test_reading(self):
# Path should be readable.
# Test also implicitly verifies the returned object is a pathlib.Path
# instance.
with resources.path(self.data, 'utf-8.file') as path:
self.assertTrue(path.name.endswith("utf-8.file"), repr(path))
# pathlib.Path.read_text() was introduced in Python 3.5.
with path.open('r', encoding='utf-8') as file:
text = file.read()
self.assertEqual('Hello, UTF-8 world!\n', text)
class PathDiskTests(PathTests, unittest.TestCase):
data = data01
def test_natural_path(self):
"""
Guarantee the internal implementation detail that
file-system-backed resources do not get the tempdir
treatment.
"""
with resources.path(self.data, 'utf-8.file') as path:
assert 'data' in str(path)
class PathZipTests(PathTests, util.ZipSetup, unittest.TestCase):
def test_remove_in_context_manager(self):
# It is not an error if the file that was temporarily stashed on the
# file system is removed inside the `with` stanza.
with resources.path(self.data, 'utf-8.file') as path:
path.unlink()
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,63 @@
import unittest
import importlib_resources as resources
from . import data01
from . import util
from importlib import import_module
class CommonBinaryTests(util.CommonTests, unittest.TestCase):
def execute(self, package, path):
resources.read_binary(package, path)
class CommonTextTests(util.CommonTests, unittest.TestCase):
def execute(self, package, path):
resources.read_text(package, path)
class ReadTests:
def test_read_binary(self):
result = resources.read_binary(self.data, 'binary.file')
self.assertEqual(result, b'\0\1\2\3')
def test_read_text_default_encoding(self):
result = resources.read_text(self.data, 'utf-8.file')
self.assertEqual(result, 'Hello, UTF-8 world!\n')
def test_read_text_given_encoding(self):
result = resources.read_text(
self.data, 'utf-16.file', encoding='utf-16')
self.assertEqual(result, 'Hello, UTF-16 world!\n')
def test_read_text_with_errors(self):
# Raises UnicodeError without the 'errors' argument.
self.assertRaises(
UnicodeError, resources.read_text, self.data, 'utf-16.file')
result = resources.read_text(self.data, 'utf-16.file', errors='ignore')
self.assertEqual(
result,
'H\x00e\x00l\x00l\x00o\x00,\x00 '
'\x00U\x00T\x00F\x00-\x001\x006\x00 '
'\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00')
class ReadDiskTests(ReadTests, unittest.TestCase):
data = data01
class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
def test_read_submodule_resource(self):
submodule = import_module('ziptestdata.subdirectory')
result = resources.read_binary(
submodule, 'binary.file')
self.assertEqual(result, b'\0\1\2\3')
def test_read_submodule_resource_by_name(self):
result = resources.read_binary(
'ziptestdata.subdirectory', 'binary.file')
self.assertEqual(result, b'\0\1\2\3')
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,145 @@
import os.path
import sys
import unittest
from importlib import import_module
from importlib_resources.readers import MultiplexedPath, NamespaceReader
from .._compat import FileNotFoundError, NotADirectoryError
class MultiplexedPathTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.folder = os.path.abspath(
os.path.join(__file__, '..', 'namespacedata01')
)
def test_init_no_paths(self):
with self.assertRaises(FileNotFoundError):
MultiplexedPath()
def test_init_file(self):
with self.assertRaises(NotADirectoryError):
MultiplexedPath(os.path.join(self.folder, 'binary.file'))
def test_iterdir(self):
contents = {
path.name for path in MultiplexedPath(self.folder).iterdir()
}
try:
contents.remove('__pycache__')
except (KeyError, ValueError):
pass
self.assertEqual(
contents,
{'binary.file', 'utf-16.file', 'utf-8.file'}
)
def test_iterdir_duplicate(self):
data01 = os.path.abspath(
os.path.join(__file__, '..', 'data01')
)
contents = {
path.name for path in
MultiplexedPath(self.folder, data01).iterdir()
}
for remove in ('__pycache__', '__init__.pyc'):
try:
contents.remove(remove)
except (KeyError, ValueError):
pass
self.assertEqual(contents, {
'__init__.py',
'binary.file',
'subdirectory',
'utf-16.file',
'utf-8.file'
})
def test_is_dir(self):
self.assertEqual(MultiplexedPath(self.folder).is_dir(), True)
def test_is_file(self):
self.assertEqual(MultiplexedPath(self.folder).is_file(), False)
def test_open_file(self):
path = MultiplexedPath(self.folder)
with self.assertRaises(FileNotFoundError):
path.read_bytes()
with self.assertRaises(FileNotFoundError):
path.read_text()
with self.assertRaises(FileNotFoundError):
path.open()
def test_join_path(self):
print('test_join_path')
prefix = os.path.abspath(os.path.join(__file__, '..'))
data01 = os.path.join(prefix, 'data01')
path = MultiplexedPath(self.folder, data01)
self.assertEqual(
str(path.joinpath('binary.file'))[len(prefix)+1:],
os.path.join('namespacedata01', 'binary.file')
)
self.assertEqual(
str(path.joinpath('subdirectory'))[len(prefix)+1:],
os.path.join('data01', 'subdirectory')
)
self.assertEqual(
str(path.joinpath('imaginary'))[len(prefix)+1:],
os.path.join('namespacedata01', 'imaginary')
)
def test_repr(self):
self.assertEqual(
repr(MultiplexedPath(self.folder)),
"MultiplexedPath('{}')".format(self.folder)
)
class NamespaceReaderTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
sys.path.append(os.path.abspath(os.path.join(__file__, '..')))
def test_init_error(self):
with self.assertRaises(ValueError):
NamespaceReader(['path1', 'path2'])
@unittest.skipUnless(
sys.version_info[0] >= 3,
'namespace packages not available on Python 2'
)
def test_resource_path(self):
namespacedata01 = import_module('namespacedata01')
reader = NamespaceReader(
namespacedata01.__spec__.submodule_search_locations
)
root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01'))
self.assertEqual(reader.resource_path('binary.file'), os.path.join(
root, 'binary.file'
))
self.assertEqual(reader.resource_path('imaginary'), os.path.join(
root, 'imaginary'
))
@unittest.skipUnless(
sys.version_info[0] >= 3,
'namespace packages not available on Python 2'
)
def test_files(self):
namespacedata01 = import_module('namespacedata01')
reader = NamespaceReader(
namespacedata01.__spec__.submodule_search_locations
)
root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01'))
self.assertIsInstance(reader.files(), MultiplexedPath)
self.assertEqual(
repr(reader.files()),
"MultiplexedPath('{}')".format(root)
)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,256 @@
import os.path
import sys
import unittest
import importlib_resources as resources
import uuid
from importlib_resources._compat import Path
from . import data01
from . import zipdata01, zipdata02
from . import util
from importlib import import_module
from ._compat import import_helper, unlink
class ResourceTests:
# Subclasses are expected to set the `data` attribute.
def test_is_resource_good_path(self):
self.assertTrue(resources.is_resource(self.data, 'binary.file'))
def test_is_resource_missing(self):
self.assertFalse(resources.is_resource(self.data, 'not-a-file'))
def test_is_resource_subresource_directory(self):
# Directories are not resources.
self.assertFalse(resources.is_resource(self.data, 'subdirectory'))
def test_contents(self):
contents = set(resources.contents(self.data))
# There may be cruft in the directory listing of the data directory.
# Under Python 3 we could have a __pycache__ directory, and under
# Python 2 we could have .pyc files. These are both artifacts of the
# test suite importing these modules and writing these caches. They
# aren't germane to this test, so just filter them out.
contents.discard('__pycache__')
contents.discard('__init__.pyc')
contents.discard('__init__.pyo')
self.assertEqual(contents, {
'__init__.py',
'subdirectory',
'utf-8.file',
'binary.file',
'utf-16.file',
})
class ResourceDiskTests(ResourceTests, unittest.TestCase):
def setUp(self):
self.data = data01
class ResourceZipTests(ResourceTests, util.ZipSetup, unittest.TestCase):
pass
@unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2')
class ResourceLoaderTests(unittest.TestCase):
def test_resource_contents(self):
package = util.create_package(
file=data01, path=data01.__file__, contents=['A', 'B', 'C'])
self.assertEqual(
set(resources.contents(package)),
{'A', 'B', 'C'})
def test_resource_is_resource(self):
package = util.create_package(
file=data01, path=data01.__file__,
contents=['A', 'B', 'C', 'D/E', 'D/F'])
self.assertTrue(resources.is_resource(package, 'B'))
def test_resource_directory_is_not_resource(self):
package = util.create_package(
file=data01, path=data01.__file__,
contents=['A', 'B', 'C', 'D/E', 'D/F'])
self.assertFalse(resources.is_resource(package, 'D'))
def test_resource_missing_is_not_resource(self):
package = util.create_package(
file=data01, path=data01.__file__,
contents=['A', 'B', 'C', 'D/E', 'D/F'])
self.assertFalse(resources.is_resource(package, 'Z'))
class ResourceCornerCaseTests(unittest.TestCase):
def test_package_has_no_reader_fallback(self):
# Test odd ball packages which:
# 1. Do not have a ResourceReader as a loader
# 2. Are not on the file system
# 3. Are not in a zip file
module = util.create_package(
file=data01, path=data01.__file__, contents=['A', 'B', 'C'])
# Give the module a dummy loader.
module.__loader__ = object()
# Give the module a dummy origin.
module.__file__ = '/path/which/shall/not/be/named'
if sys.version_info >= (3,):
module.__spec__.loader = module.__loader__
module.__spec__.origin = module.__file__
self.assertFalse(resources.is_resource(module, 'A'))
class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase):
ZIP_MODULE = zipdata01 # type: ignore
def test_is_submodule_resource(self):
submodule = import_module('ziptestdata.subdirectory')
self.assertTrue(
resources.is_resource(submodule, 'binary.file'))
def test_read_submodule_resource_by_name(self):
self.assertTrue(
resources.is_resource('ziptestdata.subdirectory', 'binary.file'))
def test_submodule_contents(self):
submodule = import_module('ziptestdata.subdirectory')
self.assertEqual(
set(resources.contents(submodule)),
{'__init__.py', 'binary.file'})
def test_submodule_contents_by_name(self):
self.assertEqual(
set(resources.contents('ziptestdata.subdirectory')),
{'__init__.py', 'binary.file'})
class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase):
ZIP_MODULE = zipdata02 # type: ignore
def test_unrelated_contents(self):
"""
Test thata zip with two unrelated subpackages return
distinct resources. Ref python/importlib_resources#44.
"""
self.assertEqual(
set(resources.contents('ziptestdata.one')),
{'__init__.py', 'resource1.txt'})
self.assertEqual(
set(resources.contents('ziptestdata.two')),
{'__init__.py', 'resource2.txt'})
class DeletingZipsTest(unittest.TestCase):
"""Having accessed resources in a zip file should not keep an open
reference to the zip.
"""
ZIP_MODULE = zipdata01
def setUp(self):
modules = import_helper.modules_setup()
self.addCleanup(import_helper.modules_cleanup, *modules)
data_path = Path(self.ZIP_MODULE.__file__)
data_dir = data_path.parent
self.source_zip_path = data_dir / 'ziptestdata.zip'
self.zip_path = Path('{}.zip'.format(uuid.uuid4())).absolute()
self.zip_path.write_bytes(self.source_zip_path.read_bytes())
sys.path.append(str(self.zip_path))
self.data = import_module('ziptestdata')
def tearDown(self):
try:
sys.path.remove(str(self.zip_path))
except ValueError:
pass
try:
del sys.path_importer_cache[str(self.zip_path)]
del sys.modules[self.data.__name__]
except KeyError:
pass
try:
unlink(self.zip_path)
except OSError:
# If the test fails, this will probably fail too
pass
def test_contents_does_not_keep_open(self):
c = resources.contents('ziptestdata')
self.zip_path.unlink()
del c
def test_is_resource_does_not_keep_open(self):
c = resources.is_resource('ziptestdata', 'binary.file')
self.zip_path.unlink()
del c
def test_is_resource_failure_does_not_keep_open(self):
c = resources.is_resource('ziptestdata', 'not-present')
self.zip_path.unlink()
del c
@unittest.skip("Desired but not supported.")
def test_path_does_not_keep_open(self):
c = resources.path('ziptestdata', 'binary.file')
self.zip_path.unlink()
del c
def test_entered_path_does_not_keep_open(self):
# This is what certifi does on import to make its bundle
# available for the process duration.
c = resources.path('ziptestdata', 'binary.file').__enter__()
self.zip_path.unlink()
del c
def test_read_binary_does_not_keep_open(self):
c = resources.read_binary('ziptestdata', 'binary.file')
self.zip_path.unlink()
del c
def test_read_text_does_not_keep_open(self):
c = resources.read_text('ziptestdata', 'utf-8.file', encoding='utf-8')
self.zip_path.unlink()
del c
@unittest.skipUnless(
sys.version_info[0] >= 3,
'namespace packages not available on Python 2'
)
class ResourceFromNamespaceTest01(unittest.TestCase):
@classmethod
def setUpClass(cls):
sys.path.append(os.path.abspath(os.path.join(__file__, '..')))
def test_is_submodule_resource(self):
self.assertTrue(
resources.is_resource(
import_module('namespacedata01'), 'binary.file'))
def test_read_submodule_resource_by_name(self):
self.assertTrue(
resources.is_resource('namespacedata01', 'binary.file'))
def test_submodule_contents(self):
contents = set(resources.contents(import_module('namespacedata01')))
try:
contents.remove('__pycache__')
except KeyError:
pass
self.assertEqual(
contents, {'binary.file', 'utf-8.file', 'utf-16.file'})
def test_submodule_contents_by_name(self):
contents = set(resources.contents('namespacedata01'))
try:
contents.remove('__pycache__')
except KeyError:
pass
self.assertEqual(
contents, {'binary.file', 'utf-8.file', 'utf-16.file'})
if __name__ == '__main__':
unittest.main()

190
vendor/importlib_resources/tests/util.py vendored Normal file
View File

@@ -0,0 +1,190 @@
import abc
import importlib
import io
import sys
import types
import unittest
from . import data01
from . import zipdata01
from .._compat import ABC, Path, PurePath, FileNotFoundError
from ..abc import ResourceReader
from ._compat import import_helper
try:
from importlib.machinery import ModuleSpec
except ImportError:
ModuleSpec = None # type: ignore
def create_package(file, path, is_package=True, contents=()):
class Reader(ResourceReader):
def get_resource_reader(self, package):
return self
def open_resource(self, path):
self._path = path
if isinstance(file, Exception):
raise file
else:
return file
def resource_path(self, path_):
self._path = path_
if isinstance(path, Exception):
raise path
else:
return path
def is_resource(self, path_):
self._path = path_
if isinstance(path, Exception):
raise path
for entry in contents:
parts = entry.split('/')
if len(parts) == 1 and parts[0] == path_:
return True
return False
def contents(self):
if isinstance(path, Exception):
raise path
# There's no yield from in baseball, er, Python 2.
for entry in contents:
yield entry
name = 'testingpackage'
# Unforunately importlib.util.module_from_spec() was not introduced until
# Python 3.5.
module = types.ModuleType(name)
if ModuleSpec is None:
# Python 2.
module.__name__ = name
module.__file__ = 'does-not-exist'
if is_package:
module.__path__ = []
else:
# Python 3.
loader = Reader()
spec = ModuleSpec(
name, loader,
origin='does-not-exist',
is_package=is_package)
module.__spec__ = spec
module.__loader__ = loader
return module
class CommonTests(ABC):
@abc.abstractmethod
def execute(self, package, path):
raise NotImplementedError
def test_package_name(self):
# Passing in the package name should succeed.
self.execute(data01.__name__, 'utf-8.file')
def test_package_object(self):
# Passing in the package itself should succeed.
self.execute(data01, 'utf-8.file')
def test_string_path(self):
# Passing in a string for the path should succeed.
path = 'utf-8.file'
self.execute(data01, path)
@unittest.skipIf(sys.version_info < (3, 6), 'requires os.PathLike support')
def test_pathlib_path(self):
# Passing in a pathlib.PurePath object for the path should succeed.
path = PurePath('utf-8.file')
self.execute(data01, path)
def test_absolute_path(self):
# An absolute path is a ValueError.
path = Path(__file__)
full_path = path.parent/'utf-8.file'
with self.assertRaises(ValueError):
self.execute(data01, full_path)
def test_relative_path(self):
# A reative path is a ValueError.
with self.assertRaises(ValueError):
self.execute(data01, '../data01/utf-8.file')
def test_importing_module_as_side_effect(self):
# The anchor package can already be imported.
del sys.modules[data01.__name__]
self.execute(data01.__name__, 'utf-8.file')
def test_non_package_by_name(self):
# The anchor package cannot be a module.
with self.assertRaises(TypeError):
self.execute(__name__, 'utf-8.file')
def test_non_package_by_package(self):
# The anchor package cannot be a module.
with self.assertRaises(TypeError):
module = sys.modules['importlib_resources.tests.util']
self.execute(module, 'utf-8.file')
@unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2')
def test_resource_opener(self):
bytes_data = io.BytesIO(b'Hello, world!')
package = create_package(file=bytes_data, path=FileNotFoundError())
self.execute(package, 'utf-8.file')
self.assertEqual(package.__loader__._path, 'utf-8.file')
@unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2')
def test_resource_path(self):
bytes_data = io.BytesIO(b'Hello, world!')
path = __file__
package = create_package(file=bytes_data, path=path)
self.execute(package, 'utf-8.file')
self.assertEqual(package.__loader__._path, 'utf-8.file')
def test_useless_loader(self):
package = create_package(file=FileNotFoundError(),
path=FileNotFoundError())
with self.assertRaises(FileNotFoundError):
self.execute(package, 'utf-8.file')
class ZipSetupBase:
ZIP_MODULE = None
@classmethod
def setUpClass(cls):
data_path = Path(cls.ZIP_MODULE.__file__)
data_dir = data_path.parent
cls._zip_path = str(data_dir / 'ziptestdata.zip')
sys.path.append(cls._zip_path)
cls.data = importlib.import_module('ziptestdata')
@classmethod
def tearDownClass(cls):
try:
sys.path.remove(cls._zip_path)
except ValueError:
pass
try:
del sys.path_importer_cache[cls._zip_path]
del sys.modules[cls.data.__name__]
except KeyError:
pass
try:
del cls.data
del cls._zip_path
except AttributeError:
pass
def setUp(self):
modules = import_helper.modules_setup()
self.addCleanup(import_helper.modules_cleanup, *modules)
class ZipSetup(ZipSetupBase):
ZIP_MODULE = zipdata01 # type: ignore

View File

Binary file not shown.

View File

Binary file not shown.

6
vendor/importlib_resources/trees.py vendored Normal file
View File

@@ -0,0 +1,6 @@
# for compatibility with 1.1, continue to expose as_file here.
from ._common import as_file
__all__ = ['as_file']