Also merges incidental changes from importlib_resources 7.1.
Co-authored by: Yuichiro Tachibana (Tsuchiya) <t.yic.yt@gmail.com>
import pathlib
import tempfile
import types
-from typing import cast, Optional, Union
+from typing import Optional, cast
from .abc import ResourceReader, Traversable
-Package = Union[types.ModuleType, str]
+Package = types.ModuleType | str
Anchor = Package
# 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) # type: ignore[union-attr]
+ reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore[union-attr]
if reader is None:
return None
return reader(spec.name) # type: ignore[union-attr]
@resolve.register
def _(cand: None) -> types.ModuleType:
- return resolve(_infer_caller().f_globals["__name__"])
+ return resolve(_infer_caller().f_globals['__name__'])
def _infer_caller():
return frame_info.filename == stack[0].filename
def is_wrapper(frame_info):
- return frame_info.function == "wrapper"
+ return frame_info.function == 'wrapper'
stack = inspect.stack()
not_this_file = itertools.filterfalse(is_this_file, stack)
return next(callers).frame
+def _assert_spec(package: types.ModuleType) -> None:
+ """
+ Provide a nicer error message when package is ``__main__``
+ and its ``__spec__`` is ``None``
+ (https://docs.python.org/3/reference/import.html#main-spec).
+ """
+ if package.__spec__ is None:
+ raise TypeError(
+ f"Cannot access resources for '{package.__name__}' "
+ "as it does not appear to correspond to an importable module (its __spec__ is None)."
+ )
+
+
def from_package(package: types.ModuleType):
"""
Return a Traversable object for the given package.
# deferred for performance (python/cpython#109829)
from ._adapters import wrap_spec
+ _assert_spec(package)
spec = wrap_spec(package)
reader = spec.loader.get_resource_reader(spec.name)
return reader.files()
@contextlib.contextmanager
def _tempfile(
reader,
- suffix="",
+ suffix='',
# gh-93353: Keep a reference to call os.remove() in late Python
# finalization.
*,
import itertools
import os
import pathlib
+from collections.abc import Iterable, Iterator
from typing import (
Any,
BinaryIO,
- Iterable,
- Iterator,
Literal,
NoReturn,
Optional,
Protocol,
Text,
TextIO,
- Union,
overload,
runtime_checkable,
)
-StrPath = Union[str, os.PathLike[str]]
+StrPath = str | os.PathLike[str]
__all__ = ["ResourceReader", "Traversable", "TraversableResources"]
def open(self, mode: Literal['rb'], *args: Any, **kwargs: Any) -> BinaryIO: ...
@abc.abstractmethod
- def open(
- self, mode: str = 'r', *args: Any, **kwargs: Any
- ) -> Union[TextIO, BinaryIO]:
+ def open(self, mode: str = 'r', *args: Any, **kwargs: Any) -> TextIO | BinaryIO:
"""
mode may be 'r' or 'rb' to open as text or binary. Return a handle
suitable for reading (same as pathlib.Path.open).
import abc
import io
import itertools
-from typing import BinaryIO, List
+from typing import BinaryIO
from .abc import Traversable, TraversableResources
"""
@abc.abstractmethod
- def children(self) -> List['SimpleReader']:
+ def children(self) -> list['SimpleReader']:
"""
Obtain an iterable of SimpleReader for available
child containers (e.g. directories).
"""
@abc.abstractmethod
- def resources(self) -> List[str]:
+ def resources(self) -> list[str]:
"""
Obtain available named resources for this virtual package.
"""
import functools
import pathlib
-from typing import Dict, Protocol, Union, runtime_checkable
+from typing import Protocol, Union, runtime_checkable
####
# from jaraco.path 3.7.1
"""
-FilesSpec = Dict[str, Union[str, bytes, Symlink, 'FilesSpec']]
+FilesSpec = dict[str, Union[str, bytes, Symlink, 'FilesSpec']]
@runtime_checkable
def symlink_to(self, target): ... # pragma: no cover
-def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker:
+def _ensure_tree_maker(obj: str | TreeMaker) -> TreeMaker:
return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore[return-value]
def build(
spec: FilesSpec,
- prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore[assignment]
+ prefix: str | TreeMaker = pathlib.Path(), # type: ignore[assignment]
):
"""
Build a set of files/directories, as described by the spec.
@functools.singledispatch
-def create(content: Union[str, bytes, FilesSpec], path):
+def create(content: str | bytes | FilesSpec, path):
path.mkdir(exist_ok=True)
build(content, prefix=path) # type: ignore[arg-type]
return resources.files(self.package)
def test_spec_path_iter(self):
- self.assertEqual(
- sorted(path.name for path in self.files.iterdir()),
- ['a', 'b', 'c'],
- )
+ assert sorted(path.name for path in self.files.iterdir()) == ['a', 'b', 'c']
def test_child_path_iter(self):
- self.assertEqual(list((self.files / 'a').iterdir()), [])
+ assert list((self.files / 'a').iterdir()) == []
def test_orphan_path_iter(self):
- self.assertEqual(list((self.files / 'a' / 'a').iterdir()), [])
- self.assertEqual(list((self.files / 'a' / 'a' / 'a').iterdir()), [])
+ assert list((self.files / 'a' / 'a').iterdir()) == []
+ assert list((self.files / 'a' / 'a' / 'a').iterdir()) == []
def test_spec_path_is(self):
- self.assertFalse(self.files.is_file())
- self.assertFalse(self.files.is_dir())
+ assert not self.files.is_file()
+ assert not self.files.is_dir()
def test_child_path_is(self):
- self.assertTrue((self.files / 'a').is_file())
- self.assertFalse((self.files / 'a').is_dir())
+ assert (self.files / 'a').is_file()
+ assert not (self.files / 'a').is_dir()
def test_orphan_path_is(self):
- self.assertFalse((self.files / 'a' / 'a').is_file())
- self.assertFalse((self.files / 'a' / 'a').is_dir())
- self.assertFalse((self.files / 'a' / 'a' / 'a').is_file())
- self.assertFalse((self.files / 'a' / 'a' / 'a').is_dir())
+ assert not (self.files / 'a' / 'a').is_file()
+ assert not (self.files / 'a' / 'a').is_dir()
+ assert not (self.files / 'a' / 'a' / 'a').is_file()
+ assert not (self.files / 'a' / 'a' / 'a').is_dir()
def test_spec_path_name(self):
- self.assertEqual(self.files.name, 'testingpackage')
+ assert self.files.name == 'testingpackage'
def test_child_path_name(self):
- self.assertEqual((self.files / 'a').name, 'a')
+ assert (self.files / 'a').name == 'a'
def test_orphan_path_name(self):
- self.assertEqual((self.files / 'a' / 'b').name, 'b')
- self.assertEqual((self.files / 'a' / 'b' / 'c').name, 'c')
+ assert (self.files / 'a' / 'b').name == 'b'
+ assert (self.files / 'a' / 'b' / 'c').name == 'c'
def test_spec_path_open(self):
- self.assertEqual(self.files.read_bytes(), b'Hello, world!')
- self.assertEqual(self.files.read_text(encoding='utf-8'), 'Hello, world!')
+ assert self.files.read_bytes() == b'Hello, world!'
+ assert self.files.read_text(encoding='utf-8') == 'Hello, world!'
def test_child_path_open(self):
- self.assertEqual((self.files / 'a').read_bytes(), b'Hello, world!')
- self.assertEqual(
- (self.files / 'a').read_text(encoding='utf-8'), 'Hello, world!'
- )
+ assert (self.files / 'a').read_bytes() == b'Hello, world!'
+ assert (self.files / 'a').read_text(encoding='utf-8') == 'Hello, world!'
def test_orphan_path_open(self):
with self.assertRaises(FileNotFoundError):
def test_wrap_spec(self):
spec = wrap_spec(self.package)
- self.assertIsInstance(spec.loader.get_resource_reader(None), CompatibilityFiles)
+ assert isinstance(spec.loader.get_resource_reader(None), CompatibilityFiles)
class CompatibilityFilesNoReaderTests(unittest.TestCase):
return resources.files(self.package)
def test_spec_path_joinpath(self):
- self.assertIsInstance(self.files / 'a', CompatibilityFiles.OrphanPath)
+ assert isinstance(self.files / 'a', CompatibilityFiles.OrphanPath)
def test_joinpath_with_multiple_args(self):
files = resources.files(self.data)
binfile = files.joinpath('subdirectory', 'binary.file')
- self.assertTrue(binfile.is_file())
+ assert binfile.is_file()
class OpenDiskTests(FilesTests, util.DiskSetup, unittest.TestCase):
with self.subTest(path_parts=path_parts):
yield path_parts
- def assertEndsWith(self, string, suffix):
- """Assert that `string` ends with `suffix`.
+ @staticmethod
+ def remove_utf16_bom(string):
+ """Remove an architecture-specific UTF-16 BOM prefix when present.
- Used to ignore an architecture-specific UTF-16 byte-order mark."""
- self.assertEqual(string[-len(suffix) :], suffix)
+ Some platforms surface UTF-16 BOM bytes as escaped text when the
+ fixture is intentionally decoded as UTF-8 with ``errors='backslashreplace'``.
+ Strip that prefix so assertions validate content consistently."""
+ for bom in ('\\xff\\xfe', '\\xfe\\xff', '\ufeff'):
+ if string.startswith(bom):
+ return string[len(bom) :]
+ return string
def test_read_text(self):
- self.assertEqual(
- resources.read_text(self.anchor01, 'utf-8.file'),
- 'Hello, UTF-8 world!\n',
+ assert (
+ resources.read_text(self.anchor01, 'utf-8.file') == 'Hello, UTF-8 world!\n'
)
- self.assertEqual(
+ assert (
resources.read_text(
self.anchor02,
'subdirectory',
'subsubdir',
'resource.txt',
encoding='utf-8',
- ),
- 'a resource',
+ )
+ == 'a resource'
)
for path_parts in self._gen_resourcetxt_path_parts():
- self.assertEqual(
+ assert (
resources.read_text(
self.anchor02,
*path_parts,
encoding='utf-8',
- ),
- 'a resource',
+ )
+ == 'a resource'
)
# Use generic OSError, since e.g. attempting to read a directory can
# fail with PermissionError rather than IsADirectoryError
resources.read_text(self.anchor01, 'no-such-file')
with self.assertRaises(UnicodeDecodeError):
resources.read_text(self.anchor01, 'utf-16.file')
- self.assertEqual(
+ assert (
resources.read_text(
self.anchor01,
'binary.file',
encoding='latin1',
- ),
- '\x00\x01\x02\x03',
+ )
+ == '\x00\x01\x02\x03'
)
- self.assertEndsWith( # ignore the BOM
+ assert self.remove_utf16_bom(
resources.read_text(
self.anchor01,
'utf-16.file',
errors='backslashreplace',
),
- 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode(
- errors='backslashreplace',
- ),
+ ) == 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode(
+ errors='backslashreplace',
)
def test_read_binary(self):
- self.assertEqual(
- resources.read_binary(self.anchor01, 'utf-8.file'),
- b'Hello, UTF-8 world!\n',
+ assert (
+ resources.read_binary(self.anchor01, 'utf-8.file')
+ == b'Hello, UTF-8 world!\n'
)
for path_parts in self._gen_resourcetxt_path_parts():
- self.assertEqual(
- resources.read_binary(self.anchor02, *path_parts),
- b'a resource',
- )
+ assert resources.read_binary(self.anchor02, *path_parts) == b'a resource'
def test_open_text(self):
with resources.open_text(self.anchor01, 'utf-8.file') as f:
- self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')
+ assert f.read() == 'Hello, UTF-8 world!\n'
for path_parts in self._gen_resourcetxt_path_parts():
with resources.open_text(
self.anchor02,
*path_parts,
encoding='utf-8',
) as f:
- self.assertEqual(f.read(), 'a resource')
+ assert f.read() == 'a resource'
# Use generic OSError, since e.g. attempting to read a directory can
# fail with PermissionError rather than IsADirectoryError
with self.assertRaises(OSError):
'binary.file',
encoding='latin1',
) as f:
- self.assertEqual(f.read(), '\x00\x01\x02\x03')
+ assert f.read() == '\x00\x01\x02\x03'
with resources.open_text(
self.anchor01,
'utf-16.file',
errors='backslashreplace',
) as f:
- self.assertEndsWith( # ignore the BOM
- f.read(),
- 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode(
- errors='backslashreplace',
- ),
+ assert self.remove_utf16_bom(f.read()) == 'Hello, UTF-16 world!\n'.encode(
+ 'utf-16-le'
+ ).decode(
+ errors='backslashreplace',
)
def test_open_binary(self):
with resources.open_binary(self.anchor01, 'utf-8.file') as f:
- self.assertEqual(f.read(), b'Hello, UTF-8 world!\n')
+ assert f.read() == b'Hello, UTF-8 world!\n'
for path_parts in self._gen_resourcetxt_path_parts():
with resources.open_binary(
self.anchor02,
*path_parts,
) as f:
- self.assertEqual(f.read(), b'a resource')
+ assert f.read() == b'a resource'
def test_path(self):
with resources.path(self.anchor01, 'utf-8.file') as path:
with open(str(path), encoding='utf-8') as f:
- self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')
+ assert f.read() == 'Hello, UTF-8 world!\n'
with resources.path(self.anchor01) as path:
with open(os.path.join(path, 'utf-8.file'), encoding='utf-8') as f:
- self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')
+ assert f.read() == 'Hello, UTF-8 world!\n'
def test_is_resource(self):
is_resource = resources.is_resource
- self.assertTrue(is_resource(self.anchor01, 'utf-8.file'))
- self.assertFalse(is_resource(self.anchor01, 'no_such_file'))
- self.assertFalse(is_resource(self.anchor01))
- self.assertFalse(is_resource(self.anchor01, 'subdirectory'))
+ assert is_resource(self.anchor01, 'utf-8.file')
+ assert not is_resource(self.anchor01, 'no_such_file')
+ assert not is_resource(self.anchor01)
+ assert not is_resource(self.anchor01, 'subdirectory')
for path_parts in self._gen_resourcetxt_path_parts():
- self.assertTrue(is_resource(self.anchor02, *path_parts))
+ assert is_resource(self.anchor02, *path_parts)
def test_contents(self):
with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)):
c = resources.contents(self.anchor01)
- self.assertGreaterEqual(
- set(c),
- {'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'},
- )
+ assert set(c) >= {'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'}
with (
self.assertRaises(OSError),
warnings_helper.check_warnings((
list(resources.contents(self.anchor01, *path_parts))
with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)):
c = resources.contents(self.anchor01, 'subdirectory')
- self.assertGreaterEqual(
- set(c),
- {'binary.file'},
- )
+ assert set(c) >= {'binary.file'}
@warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_common_errors(self):
target = resources.files(self.data) / 'binary.file'
with target.open('rb') as fp:
result = fp.read()
- self.assertEqual(result, bytes(range(4)))
+ assert result == bytes(range(4))
def test_open_text_default_encoding(self):
target = resources.files(self.data) / 'utf-8.file'
with target.open(encoding='utf-8') as fp:
result = fp.read()
- self.assertEqual(result, 'Hello, UTF-8 world!\n')
+ assert result == 'Hello, UTF-8 world!\n'
def test_open_text_given_encoding(self):
target = resources.files(self.data) / 'utf-16.file'
with target.open(encoding='utf-16', errors='strict') as fp:
result = fp.read()
- self.assertEqual(result, 'Hello, UTF-16 world!\n')
+ assert result == 'Hello, UTF-16 world!\n'
def test_open_text_with_errors(self):
"""
self.assertRaises(UnicodeError, fp.read)
with target.open(encoding='utf-8', errors='ignore') as fp:
result = fp.read()
- self.assertEqual(
- result,
+ assert result == (
'H\x00e\x00l\x00l\x00o\x00,\x00 '
'\x00U\x00T\x00F\x00-\x001\x006\x00 '
- '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00',
+ '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00'
)
def test_open_binary_FileNotFoundError(self):
"""
target = resources.files(self.data) / 'utf-8.file'
with resources.as_file(target) as path:
- self.assertIsInstance(path, pathlib.Path)
- self.assertTrue(path.name.endswith("utf-8.file"), repr(path))
- self.assertEqual('Hello, UTF-8 world!\n', path.read_text(encoding='utf-8'))
+ assert isinstance(path, pathlib.Path)
+ assert path.name.endswith("utf-8.file"), repr(path)
+ assert 'Hello, UTF-8 world!\n' == path.read_text(encoding='utf-8')
class PathDiskTests(PathTests, util.DiskSetup, unittest.TestCase):
class ReadTests:
def test_read_bytes(self):
result = resources.files(self.data).joinpath('binary.file').read_bytes()
- self.assertEqual(result, bytes(range(4)))
+ assert result == bytes(range(4))
def test_read_text_default_encoding(self):
result = (
- resources.files(self.data)
+ resources
+ .files(self.data)
.joinpath('utf-8.file')
.read_text(encoding='utf-8')
)
- self.assertEqual(result, 'Hello, UTF-8 world!\n')
+ assert result == 'Hello, UTF-8 world!\n'
def test_read_text_given_encoding(self):
result = (
- resources.files(self.data)
+ resources
+ .files(self.data)
.joinpath('utf-16.file')
.read_text(encoding='utf-16')
)
- self.assertEqual(result, 'Hello, UTF-16 world!\n')
+ assert result == 'Hello, UTF-16 world!\n'
def test_read_text_with_errors(self):
"""
target = resources.files(self.data) / 'utf-16.file'
self.assertRaises(UnicodeError, target.read_text, encoding='utf-8')
result = target.read_text(encoding='utf-8', errors='ignore')
- self.assertEqual(
- result,
+ assert result == (
'H\x00e\x00l\x00l\x00o\x00,\x00 '
'\x00U\x00T\x00F\x00-\x001\x006\x00 '
- '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00',
+ '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00'
)
def test_read_submodule_resource(self):
submodule = import_module('data01.subdirectory')
result = resources.files(submodule).joinpath('binary.file').read_bytes()
- self.assertEqual(result, bytes(range(4, 8)))
+ assert result == bytes(range(4, 8))
def test_read_submodule_resource_by_name(self):
result = (
resources.files('data01.subdirectory').joinpath('binary.file').read_bytes()
)
- self.assertEqual(result, bytes(range(4, 8)))
+ assert result == bytes(range(4, 8))
class ReadNamespaceTests(ReadTests, util.DiskSetup, unittest.TestCase):
def test_read_submodule_resource(self):
submodule = import_module('namespacedata01.subdirectory')
result = resources.files(submodule).joinpath('binary.file').read_bytes()
- self.assertEqual(result, bytes(range(12, 16)))
+ assert result == bytes(range(12, 16))
def test_read_submodule_resource_by_name(self):
result = (
- resources.files('namespacedata01.subdirectory')
+ resources
+ .files('namespacedata01.subdirectory')
.joinpath('binary.file')
.read_bytes()
)
- self.assertEqual(result, bytes(range(12, 16)))
+ assert result == bytes(range(12, 16))
if __name__ == '__main__':
contents.remove('__pycache__')
except (KeyError, ValueError):
pass
- self.assertEqual(
- contents, {'subdirectory', 'binary.file', 'utf-16.file', 'utf-8.file'}
- )
+ assert contents == {'subdirectory', 'binary.file', 'utf-16.file', 'utf-8.file'}
def test_iterdir_duplicate(self):
contents = {
contents.remove(remove)
except (KeyError, ValueError):
pass
- self.assertEqual(
- contents,
- {'__init__.py', 'binary.file', 'subdirectory', 'utf-16.file', 'utf-8.file'},
- )
+ assert 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)
+ assert MultiplexedPath(self.folder).is_dir()
def test_is_file(self):
- self.assertEqual(MultiplexedPath(self.folder).is_file(), False)
+ assert not MultiplexedPath(self.folder).is_file()
def test_open_file(self):
path = MultiplexedPath(self.folder)
def test_join_path(self):
prefix = str(self.folder.parent)
path = MultiplexedPath(self.folder, self.data01)
- self.assertEqual(
- str(path.joinpath('binary.file'))[len(prefix) + 1 :],
- os.path.join('namespacedata01', 'binary.file'),
+ assert str(path.joinpath('binary.file'))[len(prefix) + 1 :] == os.path.join(
+ 'namespacedata01', 'binary.file'
)
sub = path.joinpath('subdirectory')
assert isinstance(sub, MultiplexedPath)
assert 'namespacedata01' in str(sub)
assert 'data01' in str(sub)
- self.assertEqual(
- str(path.joinpath('imaginary'))[len(prefix) + 1 :],
- os.path.join('namespacedata01', 'imaginary'),
+ assert str(path.joinpath('imaginary'))[len(prefix) + 1 :] == os.path.join(
+ 'namespacedata01', 'imaginary'
)
- self.assertEqual(path.joinpath(), path)
+ assert path.joinpath() == path
def test_join_path_compound(self):
path = MultiplexedPath(self.folder)
def test_join_path_common_subdir(self):
prefix = str(self.data02.parent)
path = MultiplexedPath(self.data01, self.data02)
- self.assertIsInstance(path.joinpath('subdirectory'), MultiplexedPath)
- self.assertEqual(
- str(path.joinpath('subdirectory', 'subsubdir'))[len(prefix) + 1 :],
- os.path.join('data02', 'subdirectory', 'subsubdir'),
+ assert isinstance(path.joinpath('subdirectory'), MultiplexedPath)
+ assert str(path.joinpath('subdirectory', 'subsubdir'))[len(prefix) + 1 :] == (
+ os.path.join('data02', 'subdirectory', 'subsubdir')
)
def test_repr(self):
- self.assertEqual(
- repr(MultiplexedPath(self.folder)),
- f"MultiplexedPath('{self.folder}')",
- )
+ assert repr(MultiplexedPath(self.folder)) == f"MultiplexedPath('{self.folder}')"
def test_name(self):
- self.assertEqual(
- MultiplexedPath(self.folder).name,
- os.path.basename(self.folder),
- )
+ assert MultiplexedPath(self.folder).name == os.path.basename(self.folder)
class NamespaceReaderTest(util.DiskSetup, unittest.TestCase):
reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations)
root = self.data.__path__[0]
- self.assertEqual(
- reader.resource_path('binary.file'), os.path.join(root, 'binary.file')
- )
- self.assertEqual(
- reader.resource_path('imaginary'), os.path.join(root, 'imaginary')
- )
+ assert reader.resource_path('binary.file') == os.path.join(root, 'binary.file')
+ assert reader.resource_path('imaginary') == os.path.join(root, 'imaginary')
def test_files(self):
reader = NamespaceReader(self.data.__spec__.submodule_search_locations)
root = self.data.__path__[0]
- self.assertIsInstance(reader.files(), MultiplexedPath)
- self.assertEqual(repr(reader.files()), f"MultiplexedPath('{root}')")
+ assert isinstance(reader.files(), MultiplexedPath)
+ assert repr(reader.files()) == f"MultiplexedPath('{root}')"
if __name__ == '__main__':
import importlib.resources as resources
+import types
import unittest
from importlib import import_module
def test_is_file_exists(self):
target = resources.files(self.data) / 'binary.file'
- self.assertTrue(target.is_file())
+ assert target.is_file()
def test_is_file_missing(self):
target = resources.files(self.data) / 'not-a-file'
- self.assertFalse(target.is_file())
+ assert not target.is_file()
def test_is_dir(self):
target = resources.files(self.data) / 'subdirectory'
- self.assertFalse(target.is_file())
- self.assertTrue(target.is_dir())
+ assert not target.is_file()
+ assert target.is_dir()
class ResourceDiskTests(ResourceTests, util.DiskSetup, unittest.TestCase):
package = util.create_package(
file=self.data, path=self.data.__file__, contents=['A', 'B', 'C']
)
- self.assertEqual(names(resources.files(package)), {'A', 'B', 'C'})
+ assert names(resources.files(package)) == {'A', 'B', 'C'}
def test_is_file(self):
package = util.create_package(
path=self.data.__file__,
contents=['A', 'B', 'C', 'D/E', 'D/F'],
)
- self.assertTrue(resources.files(package).joinpath('B').is_file())
+ assert resources.files(package).joinpath('B').is_file()
def test_is_dir(self):
package = util.create_package(
path=self.data.__file__,
contents=['A', 'B', 'C', 'D/E', 'D/F'],
)
- self.assertTrue(resources.files(package).joinpath('D').is_dir())
+ assert resources.files(package).joinpath('D').is_dir()
def test_resource_missing(self):
package = util.create_package(
path=self.data.__file__,
contents=['A', 'B', 'C', 'D/E', 'D/F'],
)
- self.assertFalse(resources.files(package).joinpath('Z').is_file())
+ assert not resources.files(package).joinpath('Z').is_file()
class ResourceCornerCaseTests(util.DiskSetup, unittest.TestCase):
module.__file__ = '/path/which/shall/not/be/named'
module.__spec__.loader = module.__loader__
module.__spec__.origin = module.__file__
- self.assertFalse(resources.files(module).joinpath('A').is_file())
+ assert not resources.files(module).joinpath('A').is_file()
class ResourceFromZipsTest01(util.ZipSetup, unittest.TestCase):
def test_is_submodule_resource(self):
submodule = import_module('data01.subdirectory')
- self.assertTrue(resources.files(submodule).joinpath('binary.file').is_file())
+ assert resources.files(submodule).joinpath('binary.file').is_file()
def test_read_submodule_resource_by_name(self):
- self.assertTrue(
- resources.files('data01.subdirectory').joinpath('binary.file').is_file()
- )
+ assert resources.files('data01.subdirectory').joinpath('binary.file').is_file()
def test_submodule_contents(self):
submodule = import_module('data01.subdirectory')
- self.assertEqual(
- names(resources.files(submodule)), {'__init__.py', 'binary.file'}
- )
+ assert names(resources.files(submodule)) == {'__init__.py', 'binary.file'}
def test_submodule_contents_by_name(self):
- self.assertEqual(
- names(resources.files('data01.subdirectory')),
- {'__init__.py', 'binary.file'},
- )
+ assert names(resources.files('data01.subdirectory')) == {
+ '__init__.py',
+ 'binary.file',
+ }
def test_as_file_directory(self):
with resources.as_file(resources.files('data01')) as data:
Test thata zip with two unrelated subpackages return
distinct resources. Ref python/importlib_resources#44.
"""
- self.assertEqual(
- names(resources.files('data02.one')),
- {'__init__.py', 'resource1.txt'},
- )
- self.assertEqual(
- names(resources.files('data02.two')),
- {'__init__.py', 'resource2.txt'},
- )
+ assert names(resources.files('data02.one')) == {'__init__.py', 'resource1.txt'}
+ assert names(resources.files('data02.two')) == {'__init__.py', 'resource2.txt'}
class DeletingZipsTest(util.ZipSetup, unittest.TestCase):
class ResourceFromNamespaceTests:
def test_is_submodule_resource(self):
- self.assertTrue(
- resources.files(import_module('namespacedata01'))
+ assert (
+ resources
+ .files(import_module('namespacedata01'))
.joinpath('binary.file')
.is_file()
)
def test_read_submodule_resource_by_name(self):
- self.assertTrue(
- resources.files('namespacedata01').joinpath('binary.file').is_file()
- )
+ assert resources.files('namespacedata01').joinpath('binary.file').is_file()
def test_submodule_contents(self):
contents = names(resources.files(import_module('namespacedata01')))
contents.remove('__pycache__')
except KeyError:
pass
- self.assertEqual(
- contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'}
- )
+ assert contents == {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'}
def test_submodule_contents_by_name(self):
contents = names(resources.files('namespacedata01'))
contents.remove('__pycache__')
except KeyError:
pass
- self.assertEqual(
- contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'}
- )
+ assert contents == {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'}
def test_submodule_sub_contents(self):
contents = names(resources.files(import_module('namespacedata01.subdirectory')))
contents.remove('__pycache__')
except KeyError:
pass
- self.assertEqual(contents, {'binary.file'})
+ assert contents == {'binary.file'}
def test_submodule_sub_contents_by_name(self):
contents = names(resources.files('namespacedata01.subdirectory'))
contents.remove('__pycache__')
except KeyError:
pass
- self.assertEqual(contents, {'binary.file'})
+ assert contents == {'binary.file'}
class ResourceFromNamespaceDiskTests(
MODULE = 'namespacedata01'
+class MainModuleTests(unittest.TestCase):
+ def test_main_module_with_none_spec(self):
+ """
+ __main__ module with no spec should raise TypeError (for clarity).
+
+ See python/cpython#138531 for details.
+ """
+ # construct a __main__ module with no __spec__.
+ mainmodule = types.ModuleType("__main__")
+
+ assert mainmodule.__spec__ is None
+
+ with self.assertRaises(
+ TypeError,
+ msg="Cannot access resources for '__main__' as it does not appear to correspond to an importable module (its __spec__ is None).",
+ ):
+ resources.files(mainmodule)
+
+
if __name__ == '__main__':
unittest.main()
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')
+ assert package.__loader__._path == 'utf-8.file'
def test_extant_path(self):
# Attempting to open or read or request the path when the
path = __file__
package = create_package(file=bytes_data, path=path)
self.execute(package, 'utf-8.file')
- self.assertEqual(package.__loader__._path, 'utf-8.file')
+ assert package.__loader__._path == 'utf-8.file'
def test_useless_loader(self):
package = create_package(file=FileNotFoundError(), path=FileNotFoundError())
--- /dev/null
+``importlib.resources.files()`` now emits a more meaningful error message
+when module spec is None (as found in some ``__main__`` modules).