mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-08-20 05:13:21 -07:00
Bump importlib-resources from 6.0.1 to 6.4.0 (#2285)
* Bump importlib-resources from 6.0.1 to 6.4.0 Bumps [importlib-resources](https://github.com/python/importlib_resources) from 6.0.1 to 6.4.0. - [Release notes](https://github.com/python/importlib_resources/releases) - [Changelog](https://github.com/python/importlib_resources/blob/main/NEWS.rst) - [Commits](https://github.com/python/importlib_resources/compare/v6.0.1...v6.4.0) --- updated-dependencies: - dependency-name: importlib-resources dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Update importlib-resources==6.4.0 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> [skip ci]
This commit is contained in:
parent
6c6fa34ba4
commit
b01b21ae05
34 changed files with 725 additions and 349 deletions
|
@ -1,32 +0,0 @@
|
|||
import os
|
||||
|
||||
|
||||
try:
|
||||
from test.support import import_helper # type: ignore
|
||||
except ImportError:
|
||||
# Python 3.9 and earlier
|
||||
class import_helper: # type: ignore
|
||||
from test.support import (
|
||||
modules_setup,
|
||||
modules_cleanup,
|
||||
DirsOnSysPath,
|
||||
CleanImport,
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
from test.support import os_helper # type: ignore
|
||||
except ImportError:
|
||||
# Python 3.9 compat
|
||||
class os_helper: # type:ignore
|
||||
from test.support import temp_dir
|
||||
|
||||
|
||||
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(os.fspath(target))
|
18
lib/importlib_resources/tests/compat/py312.py
Normal file
18
lib/importlib_resources/tests/compat/py312.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
import contextlib
|
||||
|
||||
from .py39 import import_helper
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def isolated_modules():
|
||||
"""
|
||||
Save modules on entry and cleanup on exit.
|
||||
"""
|
||||
(saved,) = import_helper.modules_setup()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
import_helper.modules_cleanup(saved)
|
||||
|
||||
|
||||
vars(import_helper).setdefault('isolated_modules', isolated_modules)
|
10
lib/importlib_resources/tests/compat/py39.py
Normal file
10
lib/importlib_resources/tests/compat/py39.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
"""
|
||||
Backward-compatability shims to support Python 3.9 and earlier.
|
||||
"""
|
||||
|
||||
from jaraco.test.cpython import from_test_support, try_import
|
||||
|
||||
import_helper = try_import('import_helper') or from_test_support(
|
||||
'modules_setup', 'modules_cleanup', 'DirsOnSysPath'
|
||||
)
|
||||
os_helper = try_import('os_helper') or from_test_support('temp_dir')
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
|
|
@ -31,8 +31,8 @@ class ContentsZipTests(ContentsTests, util.ZipSetup, unittest.TestCase):
|
|||
class ContentsNamespaceTests(ContentsTests, unittest.TestCase):
|
||||
expected = {
|
||||
# no __init__ because of namespace design
|
||||
# no subdirectory as incidental difference in fixture
|
||||
'binary.file',
|
||||
'subdirectory',
|
||||
'utf-16.file',
|
||||
'utf-8.file',
|
||||
}
|
||||
|
|
|
@ -3,9 +3,10 @@ import contextlib
|
|||
import pathlib
|
||||
|
||||
import importlib_resources as resources
|
||||
from .. import abc
|
||||
from ..abc import TraversableResources, ResourceReader
|
||||
from . import util
|
||||
from ._compat import os_helper
|
||||
from .compat.py39 import os_helper
|
||||
|
||||
|
||||
class SimpleLoader:
|
||||
|
@ -38,8 +39,9 @@ class CustomTraversableResourcesTests(unittest.TestCase):
|
|||
self.addCleanup(self.fixtures.close)
|
||||
|
||||
def test_custom_loader(self):
|
||||
temp_dir = self.fixtures.enter_context(os_helper.temp_dir())
|
||||
temp_dir = pathlib.Path(self.fixtures.enter_context(os_helper.temp_dir()))
|
||||
loader = SimpleLoader(MagicResources(temp_dir))
|
||||
pkg = util.create_package_from_loader(loader)
|
||||
files = resources.files(pkg)
|
||||
assert files is temp_dir
|
||||
assert isinstance(files, abc.Traversable)
|
||||
assert list(files.iterdir()) == []
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import typing
|
||||
import textwrap
|
||||
import unittest
|
||||
import warnings
|
||||
|
@ -10,7 +9,8 @@ from ..abc import Traversable
|
|||
from . import data01
|
||||
from . import util
|
||||
from . import _path
|
||||
from ._compat import os_helper, import_helper
|
||||
from .compat.py39 import os_helper
|
||||
from .compat.py312 import import_helper
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
|
@ -31,13 +31,14 @@ class FilesTests:
|
|||
actual = files.joinpath('utf-8.file').read_text(encoding='utf-8')
|
||||
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)
|
||||
|
||||
def test_joinpath_with_multiple_args(self):
|
||||
files = resources.files(self.data)
|
||||
binfile = files.joinpath('subdirectory', 'binary.file')
|
||||
self.assertTrue(binfile.is_file())
|
||||
|
||||
def test_old_parameter(self):
|
||||
"""
|
||||
Files used to take a 'package' parameter. Make sure anyone
|
||||
|
@ -63,13 +64,17 @@ class OpenNamespaceTests(FilesTests, unittest.TestCase):
|
|||
self.data = namespacedata01
|
||||
|
||||
|
||||
class OpenNamespaceZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
|
||||
ZIP_MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
class SiteDir:
|
||||
def setUp(self):
|
||||
self.fixtures = contextlib.ExitStack()
|
||||
self.addCleanup(self.fixtures.close)
|
||||
self.site_dir = self.fixtures.enter_context(os_helper.temp_dir())
|
||||
self.fixtures.enter_context(import_helper.DirsOnSysPath(self.site_dir))
|
||||
self.fixtures.enter_context(import_helper.CleanImport())
|
||||
self.fixtures.enter_context(import_helper.isolated_modules())
|
||||
|
||||
|
||||
class ModulesFilesTests(SiteDir, unittest.TestCase):
|
||||
|
|
242
lib/importlib_resources/tests/test_functional.py
Normal file
242
lib/importlib_resources/tests/test_functional.py
Normal file
|
@ -0,0 +1,242 @@
|
|||
import unittest
|
||||
import os
|
||||
import contextlib
|
||||
|
||||
try:
|
||||
from test.support.warnings_helper import ignore_warnings, check_warnings
|
||||
except ImportError:
|
||||
# older Python versions
|
||||
from test.support import ignore_warnings, check_warnings
|
||||
|
||||
import importlib_resources as resources
|
||||
|
||||
# Since the functional API forwards to Traversable, we only test
|
||||
# filesystem resources here -- not zip files, namespace packages etc.
|
||||
# We do test for two kinds of Anchor, though.
|
||||
|
||||
|
||||
class StringAnchorMixin:
|
||||
anchor01 = 'importlib_resources.tests.data01'
|
||||
anchor02 = 'importlib_resources.tests.data02'
|
||||
|
||||
|
||||
class ModuleAnchorMixin:
|
||||
from . import data01 as anchor01
|
||||
from . import data02 as anchor02
|
||||
|
||||
|
||||
class FunctionalAPIBase:
|
||||
def _gen_resourcetxt_path_parts(self):
|
||||
"""Yield various names of a text file in anchor02, each in a subTest"""
|
||||
for path_parts in (
|
||||
('subdirectory', 'subsubdir', 'resource.txt'),
|
||||
('subdirectory/subsubdir/resource.txt',),
|
||||
('subdirectory/subsubdir', 'resource.txt'),
|
||||
):
|
||||
with self.subTest(path_parts=path_parts):
|
||||
yield path_parts
|
||||
|
||||
def test_read_text(self):
|
||||
self.assertEqual(
|
||||
resources.read_text(self.anchor01, 'utf-8.file'),
|
||||
'Hello, UTF-8 world!\n',
|
||||
)
|
||||
self.assertEqual(
|
||||
resources.read_text(
|
||||
self.anchor02,
|
||||
'subdirectory',
|
||||
'subsubdir',
|
||||
'resource.txt',
|
||||
encoding='utf-8',
|
||||
),
|
||||
'a resource',
|
||||
)
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
self.assertEqual(
|
||||
resources.read_text(
|
||||
self.anchor02,
|
||||
*path_parts,
|
||||
encoding='utf-8',
|
||||
),
|
||||
'a resource',
|
||||
)
|
||||
# Use generic OSError, since e.g. attempting to read a directory can
|
||||
# fail with PermissionError rather than IsADirectoryError
|
||||
with self.assertRaises(OSError):
|
||||
resources.read_text(self.anchor01)
|
||||
with self.assertRaises(OSError):
|
||||
resources.read_text(self.anchor01, 'no-such-file')
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
resources.read_text(self.anchor01, 'utf-16.file')
|
||||
self.assertEqual(
|
||||
resources.read_text(
|
||||
self.anchor01,
|
||||
'binary.file',
|
||||
encoding='latin1',
|
||||
),
|
||||
'\x00\x01\x02\x03',
|
||||
)
|
||||
self.assertEqual(
|
||||
resources.read_text(
|
||||
self.anchor01,
|
||||
'utf-16.file',
|
||||
errors='backslashreplace',
|
||||
),
|
||||
'Hello, UTF-16 world!\n'.encode('utf-16').decode(
|
||||
errors='backslashreplace',
|
||||
),
|
||||
)
|
||||
|
||||
def test_read_binary(self):
|
||||
self.assertEqual(
|
||||
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',
|
||||
)
|
||||
|
||||
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')
|
||||
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')
|
||||
# Use generic OSError, since e.g. attempting to read a directory can
|
||||
# fail with PermissionError rather than IsADirectoryError
|
||||
with self.assertRaises(OSError):
|
||||
resources.open_text(self.anchor01)
|
||||
with self.assertRaises(OSError):
|
||||
resources.open_text(self.anchor01, 'no-such-file')
|
||||
with resources.open_text(self.anchor01, 'utf-16.file') as f:
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
f.read()
|
||||
with resources.open_text(
|
||||
self.anchor01,
|
||||
'binary.file',
|
||||
encoding='latin1',
|
||||
) as f:
|
||||
self.assertEqual(f.read(), '\x00\x01\x02\x03')
|
||||
with resources.open_text(
|
||||
self.anchor01,
|
||||
'utf-16.file',
|
||||
errors='backslashreplace',
|
||||
) as f:
|
||||
self.assertEqual(
|
||||
f.read(),
|
||||
'Hello, UTF-16 world!\n'.encode('utf-16').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')
|
||||
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')
|
||||
|
||||
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')
|
||||
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')
|
||||
|
||||
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'))
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
self.assertTrue(is_resource(self.anchor02, *path_parts))
|
||||
|
||||
def test_contents(self):
|
||||
with check_warnings((".*contents.*", DeprecationWarning)):
|
||||
c = resources.contents(self.anchor01)
|
||||
self.assertGreaterEqual(
|
||||
set(c),
|
||||
{'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'},
|
||||
)
|
||||
with contextlib.ExitStack() as cm:
|
||||
cm.enter_context(self.assertRaises(OSError))
|
||||
cm.enter_context(check_warnings((".*contents.*", DeprecationWarning)))
|
||||
|
||||
list(resources.contents(self.anchor01, 'utf-8.file'))
|
||||
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
with contextlib.ExitStack() as cm:
|
||||
cm.enter_context(self.assertRaises(OSError))
|
||||
cm.enter_context(check_warnings((".*contents.*", DeprecationWarning)))
|
||||
|
||||
list(resources.contents(self.anchor01, *path_parts))
|
||||
with check_warnings((".*contents.*", DeprecationWarning)):
|
||||
c = resources.contents(self.anchor01, 'subdirectory')
|
||||
self.assertGreaterEqual(
|
||||
set(c),
|
||||
{'binary.file'},
|
||||
)
|
||||
|
||||
@ignore_warnings(category=DeprecationWarning)
|
||||
def test_common_errors(self):
|
||||
for func in (
|
||||
resources.read_text,
|
||||
resources.read_binary,
|
||||
resources.open_text,
|
||||
resources.open_binary,
|
||||
resources.path,
|
||||
resources.is_resource,
|
||||
resources.contents,
|
||||
):
|
||||
with self.subTest(func=func):
|
||||
# Rejecting None anchor
|
||||
with self.assertRaises(TypeError):
|
||||
func(None)
|
||||
# Rejecting invalid anchor type
|
||||
with self.assertRaises((TypeError, AttributeError)):
|
||||
func(1234)
|
||||
# Unknown module
|
||||
with self.assertRaises(ModuleNotFoundError):
|
||||
func('$missing module$')
|
||||
|
||||
def test_text_errors(self):
|
||||
for func in (
|
||||
resources.read_text,
|
||||
resources.open_text,
|
||||
):
|
||||
with self.subTest(func=func):
|
||||
# Multiple path arguments need explicit encoding argument.
|
||||
with self.assertRaises(TypeError):
|
||||
func(
|
||||
self.anchor02,
|
||||
'subdirectory',
|
||||
'subsubdir',
|
||||
'resource.txt',
|
||||
)
|
||||
|
||||
|
||||
class FunctionalAPITest_StringAnchor(
|
||||
unittest.TestCase,
|
||||
FunctionalAPIBase,
|
||||
StringAnchorMixin,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
class FunctionalAPITest_ModuleAnchor(
|
||||
unittest.TestCase,
|
||||
FunctionalAPIBase,
|
||||
ModuleAnchorMixin,
|
||||
):
|
||||
pass
|
|
@ -24,7 +24,7 @@ class OpenTests:
|
|||
target = resources.files(self.data) / 'binary.file'
|
||||
with target.open('rb') as fp:
|
||||
result = fp.read()
|
||||
self.assertEqual(result, b'\x00\x01\x02\x03')
|
||||
self.assertEqual(result, bytes(range(4)))
|
||||
|
||||
def test_open_text_default_encoding(self):
|
||||
target = resources.files(self.data) / 'utf-8.file'
|
||||
|
@ -81,5 +81,9 @@ class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
|
|||
pass
|
||||
|
||||
|
||||
class OpenNamespaceZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
|
||||
ZIP_MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import io
|
||||
import pathlib
|
||||
import unittest
|
||||
|
||||
import importlib_resources as resources
|
||||
|
@ -15,18 +16,13 @@ class CommonTests(util.CommonTests, unittest.TestCase):
|
|||
class PathTests:
|
||||
def test_reading(self):
|
||||
"""
|
||||
Path should be readable.
|
||||
|
||||
Test also implicitly verifies the returned object is a pathlib.Path
|
||||
instance.
|
||||
Path should be readable and a pathlib.Path instance.
|
||||
"""
|
||||
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))
|
||||
# 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)
|
||||
self.assertEqual('Hello, UTF-8 world!\n', path.read_text(encoding='utf-8'))
|
||||
|
||||
|
||||
class PathDiskTests(PathTests, unittest.TestCase):
|
||||
|
|
|
@ -19,7 +19,7 @@ class CommonTextTests(util.CommonTests, unittest.TestCase):
|
|||
class ReadTests:
|
||||
def test_read_bytes(self):
|
||||
result = resources.files(self.data).joinpath('binary.file').read_bytes()
|
||||
self.assertEqual(result, b'\0\1\2\3')
|
||||
self.assertEqual(result, bytes(range(4)))
|
||||
|
||||
def test_read_text_default_encoding(self):
|
||||
result = (
|
||||
|
@ -58,17 +58,15 @@ class ReadDiskTests(ReadTests, unittest.TestCase):
|
|||
|
||||
class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
|
||||
def test_read_submodule_resource(self):
|
||||
submodule = import_module('ziptestdata.subdirectory')
|
||||
submodule = import_module('data01.subdirectory')
|
||||
result = resources.files(submodule).joinpath('binary.file').read_bytes()
|
||||
self.assertEqual(result, b'\0\1\2\3')
|
||||
self.assertEqual(result, bytes(range(4, 8)))
|
||||
|
||||
def test_read_submodule_resource_by_name(self):
|
||||
result = (
|
||||
resources.files('ziptestdata.subdirectory')
|
||||
.joinpath('binary.file')
|
||||
.read_bytes()
|
||||
resources.files('data01.subdirectory').joinpath('binary.file').read_bytes()
|
||||
)
|
||||
self.assertEqual(result, b'\0\1\2\3')
|
||||
self.assertEqual(result, bytes(range(4, 8)))
|
||||
|
||||
|
||||
class ReadNamespaceTests(ReadTests, unittest.TestCase):
|
||||
|
@ -78,5 +76,22 @@ class ReadNamespaceTests(ReadTests, unittest.TestCase):
|
|||
self.data = namespacedata01
|
||||
|
||||
|
||||
class ReadNamespaceZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
|
||||
ZIP_MODULE = 'namespacedata01'
|
||||
|
||||
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)))
|
||||
|
||||
def test_read_submodule_resource_by_name(self):
|
||||
result = (
|
||||
resources.files('namespacedata01.subdirectory')
|
||||
.joinpath('binary.file')
|
||||
.read_bytes()
|
||||
)
|
||||
self.assertEqual(result, bytes(range(12, 16)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -10,8 +10,7 @@ from importlib_resources.readers import MultiplexedPath, NamespaceReader
|
|||
class MultiplexedPathTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
path = pathlib.Path(__file__).parent / 'namespacedata01'
|
||||
cls.folder = str(path)
|
||||
cls.folder = pathlib.Path(__file__).parent / 'namespacedata01'
|
||||
|
||||
def test_init_no_paths(self):
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
|
@ -19,7 +18,7 @@ class MultiplexedPathTest(unittest.TestCase):
|
|||
|
||||
def test_init_file(self):
|
||||
with self.assertRaises(NotADirectoryError):
|
||||
MultiplexedPath(os.path.join(self.folder, 'binary.file'))
|
||||
MultiplexedPath(self.folder / 'binary.file')
|
||||
|
||||
def test_iterdir(self):
|
||||
contents = {path.name for path in MultiplexedPath(self.folder).iterdir()}
|
||||
|
@ -27,10 +26,12 @@ class MultiplexedPathTest(unittest.TestCase):
|
|||
contents.remove('__pycache__')
|
||||
except (KeyError, ValueError):
|
||||
pass
|
||||
self.assertEqual(contents, {'binary.file', 'utf-16.file', 'utf-8.file'})
|
||||
self.assertEqual(
|
||||
contents, {'subdirectory', 'binary.file', 'utf-16.file', 'utf-8.file'}
|
||||
)
|
||||
|
||||
def test_iterdir_duplicate(self):
|
||||
data01 = os.path.abspath(os.path.join(__file__, '..', 'data01'))
|
||||
data01 = pathlib.Path(__file__).parent.joinpath('data01')
|
||||
contents = {
|
||||
path.name for path in MultiplexedPath(self.folder, data01).iterdir()
|
||||
}
|
||||
|
@ -60,17 +61,17 @@ class MultiplexedPathTest(unittest.TestCase):
|
|||
path.open()
|
||||
|
||||
def test_join_path(self):
|
||||
prefix = os.path.abspath(os.path.join(__file__, '..'))
|
||||
data01 = os.path.join(prefix, 'data01')
|
||||
data01 = pathlib.Path(__file__).parent.joinpath('data01')
|
||||
prefix = str(data01.parent)
|
||||
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'),
|
||||
)
|
||||
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'),
|
||||
|
@ -82,9 +83,9 @@ class MultiplexedPathTest(unittest.TestCase):
|
|||
assert not path.joinpath('imaginary/foo.py').exists()
|
||||
|
||||
def test_join_path_common_subdir(self):
|
||||
prefix = os.path.abspath(os.path.join(__file__, '..'))
|
||||
data01 = os.path.join(prefix, 'data01')
|
||||
data02 = os.path.join(prefix, 'data02')
|
||||
data01 = pathlib.Path(__file__).parent.joinpath('data01')
|
||||
data02 = pathlib.Path(__file__).parent.joinpath('data02')
|
||||
prefix = str(data01.parent)
|
||||
path = MultiplexedPath(data01, data02)
|
||||
self.assertIsInstance(path.joinpath('subdirectory'), MultiplexedPath)
|
||||
self.assertEqual(
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
import contextlib
|
||||
import sys
|
||||
import unittest
|
||||
import importlib_resources as resources
|
||||
import uuid
|
||||
import pathlib
|
||||
|
||||
from . import data01
|
||||
from . import zipdata01, zipdata02
|
||||
from . import util
|
||||
from importlib import import_module
|
||||
from ._compat import import_helper, os_helper, unlink
|
||||
|
||||
|
||||
class ResourceTests:
|
||||
|
@ -89,34 +85,32 @@ class ResourceCornerCaseTests(unittest.TestCase):
|
|||
|
||||
|
||||
class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase):
|
||||
ZIP_MODULE = zipdata01 # type: ignore
|
||||
ZIP_MODULE = 'data01'
|
||||
|
||||
def test_is_submodule_resource(self):
|
||||
submodule = import_module('ziptestdata.subdirectory')
|
||||
submodule = import_module('data01.subdirectory')
|
||||
self.assertTrue(resources.files(submodule).joinpath('binary.file').is_file())
|
||||
|
||||
def test_read_submodule_resource_by_name(self):
|
||||
self.assertTrue(
|
||||
resources.files('ziptestdata.subdirectory')
|
||||
.joinpath('binary.file')
|
||||
.is_file()
|
||||
resources.files('data01.subdirectory').joinpath('binary.file').is_file()
|
||||
)
|
||||
|
||||
def test_submodule_contents(self):
|
||||
submodule = import_module('ziptestdata.subdirectory')
|
||||
submodule = import_module('data01.subdirectory')
|
||||
self.assertEqual(
|
||||
names(resources.files(submodule)), {'__init__.py', 'binary.file'}
|
||||
)
|
||||
|
||||
def test_submodule_contents_by_name(self):
|
||||
self.assertEqual(
|
||||
names(resources.files('ziptestdata.subdirectory')),
|
||||
names(resources.files('data01.subdirectory')),
|
||||
{'__init__.py', 'binary.file'},
|
||||
)
|
||||
|
||||
def test_as_file_directory(self):
|
||||
with resources.as_file(resources.files('ziptestdata')) as data:
|
||||
assert data.name == 'ziptestdata'
|
||||
with resources.as_file(resources.files('data01')) as data:
|
||||
assert data.name == 'data01'
|
||||
assert data.is_dir()
|
||||
assert data.joinpath('subdirectory').is_dir()
|
||||
assert len(list(data.iterdir()))
|
||||
|
@ -124,7 +118,7 @@ class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase):
|
|||
|
||||
|
||||
class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase):
|
||||
ZIP_MODULE = zipdata02 # type: ignore
|
||||
ZIP_MODULE = 'data02'
|
||||
|
||||
def test_unrelated_contents(self):
|
||||
"""
|
||||
|
@ -132,93 +126,48 @@ class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase):
|
|||
distinct resources. Ref python/importlib_resources#44.
|
||||
"""
|
||||
self.assertEqual(
|
||||
names(resources.files('ziptestdata.one')),
|
||||
names(resources.files('data02.one')),
|
||||
{'__init__.py', 'resource1.txt'},
|
||||
)
|
||||
self.assertEqual(
|
||||
names(resources.files('ziptestdata.two')),
|
||||
names(resources.files('data02.two')),
|
||||
{'__init__.py', 'resource2.txt'},
|
||||
)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def zip_on_path(dir):
|
||||
data_path = pathlib.Path(zipdata01.__file__)
|
||||
source_zip_path = data_path.parent.joinpath('ziptestdata.zip')
|
||||
zip_path = pathlib.Path(dir) / f'{uuid.uuid4()}.zip'
|
||||
zip_path.write_bytes(source_zip_path.read_bytes())
|
||||
sys.path.append(str(zip_path))
|
||||
import_module('ziptestdata')
|
||||
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
with contextlib.suppress(ValueError):
|
||||
sys.path.remove(str(zip_path))
|
||||
|
||||
with contextlib.suppress(KeyError):
|
||||
del sys.path_importer_cache[str(zip_path)]
|
||||
del sys.modules['ziptestdata']
|
||||
|
||||
with contextlib.suppress(OSError):
|
||||
unlink(zip_path)
|
||||
|
||||
|
||||
class DeletingZipsTest(unittest.TestCase):
|
||||
class DeletingZipsTest(util.ZipSetupBase, unittest.TestCase):
|
||||
"""Having accessed resources in a zip file should not keep an open
|
||||
reference to the zip.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.fixtures = contextlib.ExitStack()
|
||||
self.addCleanup(self.fixtures.close)
|
||||
|
||||
modules = import_helper.modules_setup()
|
||||
self.addCleanup(import_helper.modules_cleanup, *modules)
|
||||
|
||||
temp_dir = self.fixtures.enter_context(os_helper.temp_dir())
|
||||
self.fixtures.enter_context(zip_on_path(temp_dir))
|
||||
|
||||
def test_iterdir_does_not_keep_open(self):
|
||||
[item.name for item in resources.files('ziptestdata').iterdir()]
|
||||
[item.name for item in resources.files('data01').iterdir()]
|
||||
|
||||
def test_is_file_does_not_keep_open(self):
|
||||
resources.files('ziptestdata').joinpath('binary.file').is_file()
|
||||
resources.files('data01').joinpath('binary.file').is_file()
|
||||
|
||||
def test_is_file_failure_does_not_keep_open(self):
|
||||
resources.files('ziptestdata').joinpath('not-present').is_file()
|
||||
resources.files('data01').joinpath('not-present').is_file()
|
||||
|
||||
@unittest.skip("Desired but not supported.")
|
||||
def test_as_file_does_not_keep_open(self): # pragma: no cover
|
||||
resources.as_file(resources.files('ziptestdata') / 'binary.file')
|
||||
resources.as_file(resources.files('data01') / 'binary.file')
|
||||
|
||||
def test_entered_path_does_not_keep_open(self):
|
||||
"""
|
||||
Mimic what certifi does on import to make its bundle
|
||||
available for the process duration.
|
||||
"""
|
||||
resources.as_file(resources.files('ziptestdata') / 'binary.file').__enter__()
|
||||
resources.as_file(resources.files('data01') / 'binary.file').__enter__()
|
||||
|
||||
def test_read_binary_does_not_keep_open(self):
|
||||
resources.files('ziptestdata').joinpath('binary.file').read_bytes()
|
||||
resources.files('data01').joinpath('binary.file').read_bytes()
|
||||
|
||||
def test_read_text_does_not_keep_open(self):
|
||||
resources.files('ziptestdata').joinpath('utf-8.file').read_text(
|
||||
encoding='utf-8'
|
||||
)
|
||||
resources.files('data01').joinpath('utf-8.file').read_text(encoding='utf-8')
|
||||
|
||||
|
||||
class ResourceFromNamespaceTest01(unittest.TestCase):
|
||||
site_dir = str(pathlib.Path(__file__).parent)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
sys.path.append(cls.site_dir)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
sys.path.remove(cls.site_dir)
|
||||
|
||||
class ResourceFromNamespaceTests:
|
||||
def test_is_submodule_resource(self):
|
||||
self.assertTrue(
|
||||
resources.files(import_module('namespacedata01'))
|
||||
|
@ -237,7 +186,9 @@ class ResourceFromNamespaceTest01(unittest.TestCase):
|
|||
contents.remove('__pycache__')
|
||||
except KeyError:
|
||||
pass
|
||||
self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'})
|
||||
self.assertEqual(
|
||||
contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'}
|
||||
)
|
||||
|
||||
def test_submodule_contents_by_name(self):
|
||||
contents = names(resources.files('namespacedata01'))
|
||||
|
@ -245,7 +196,45 @@ class ResourceFromNamespaceTest01(unittest.TestCase):
|
|||
contents.remove('__pycache__')
|
||||
except KeyError:
|
||||
pass
|
||||
self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'})
|
||||
self.assertEqual(
|
||||
contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'}
|
||||
)
|
||||
|
||||
def test_submodule_sub_contents(self):
|
||||
contents = names(resources.files(import_module('namespacedata01.subdirectory')))
|
||||
try:
|
||||
contents.remove('__pycache__')
|
||||
except KeyError:
|
||||
pass
|
||||
self.assertEqual(contents, {'binary.file'})
|
||||
|
||||
def test_submodule_sub_contents_by_name(self):
|
||||
contents = names(resources.files('namespacedata01.subdirectory'))
|
||||
try:
|
||||
contents.remove('__pycache__')
|
||||
except KeyError:
|
||||
pass
|
||||
self.assertEqual(contents, {'binary.file'})
|
||||
|
||||
|
||||
class ResourceFromNamespaceDiskTests(ResourceFromNamespaceTests, unittest.TestCase):
|
||||
site_dir = str(pathlib.Path(__file__).parent)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
sys.path.append(cls.site_dir)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
sys.path.remove(cls.site_dir)
|
||||
|
||||
|
||||
class ResourceFromNamespaceZipTests(
|
||||
util.ZipSetupBase,
|
||||
ResourceFromNamespaceTests,
|
||||
unittest.TestCase,
|
||||
):
|
||||
ZIP_MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
"""
|
||||
Generate the zip test data files.
|
||||
|
||||
Run to build the tests/zipdataNN/ziptestdata.zip files from
|
||||
files in tests/dataNN.
|
||||
|
||||
Replaces the file with the working copy, but does commit anything
|
||||
to the source repo.
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import pathlib
|
||||
import zipfile
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
>>> from unittest import mock
|
||||
>>> monkeypatch = getfixture('monkeypatch')
|
||||
>>> monkeypatch.setattr(zipfile, 'ZipFile', mock.MagicMock())
|
||||
>>> print(); main() # print workaround for bpo-32509
|
||||
<BLANKLINE>
|
||||
...data01... -> ziptestdata/...
|
||||
...
|
||||
...data02... -> ziptestdata/...
|
||||
...
|
||||
"""
|
||||
suffixes = '01', '02'
|
||||
tuple(map(generate, suffixes))
|
||||
|
||||
|
||||
def generate(suffix):
|
||||
root = pathlib.Path(__file__).parent.relative_to(os.getcwd())
|
||||
zfpath = root / f'zipdata{suffix}/ziptestdata.zip'
|
||||
with zipfile.ZipFile(zfpath, 'w') as zf:
|
||||
for src, rel in walk(root / f'data{suffix}'):
|
||||
dst = 'ziptestdata' / pathlib.PurePosixPath(rel.as_posix())
|
||||
print(src, '->', dst)
|
||||
zf.write(src, dst)
|
||||
|
||||
|
||||
def walk(datapath):
|
||||
for dirpath, dirnames, filenames in os.walk(datapath):
|
||||
with contextlib.suppress(ValueError):
|
||||
dirnames.remove('__pycache__')
|
||||
for filename in filenames:
|
||||
res = pathlib.Path(dirpath) / filename
|
||||
rel = res.relative_to(datapath)
|
||||
yield res, rel
|
||||
|
||||
|
||||
__name__ == '__main__' and main()
|
|
@ -4,11 +4,12 @@ import io
|
|||
import sys
|
||||
import types
|
||||
import pathlib
|
||||
import contextlib
|
||||
|
||||
from . import data01
|
||||
from . import zipdata01
|
||||
from ..abc import ResourceReader
|
||||
from ._compat import import_helper
|
||||
from .compat.py39 import import_helper, os_helper
|
||||
from . import zip as zip_
|
||||
|
||||
|
||||
from importlib.machinery import ModuleSpec
|
||||
|
@ -141,39 +142,23 @@ class CommonTests(metaclass=abc.ABCMeta):
|
|||
|
||||
|
||||
class ZipSetupBase:
|
||||
ZIP_MODULE = None
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
data_path = pathlib.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
|
||||
ZIP_MODULE = 'data01'
|
||||
|
||||
def setUp(self):
|
||||
modules = import_helper.modules_setup()
|
||||
self.addCleanup(import_helper.modules_cleanup, *modules)
|
||||
self.fixtures = contextlib.ExitStack()
|
||||
self.addCleanup(self.fixtures.close)
|
||||
|
||||
self.fixtures.enter_context(import_helper.isolated_modules())
|
||||
|
||||
temp_dir = self.fixtures.enter_context(os_helper.temp_dir())
|
||||
modules = pathlib.Path(temp_dir) / 'zipped modules.zip'
|
||||
src_path = pathlib.Path(__file__).parent.joinpath(self.ZIP_MODULE)
|
||||
self.fixtures.enter_context(
|
||||
import_helper.DirsOnSysPath(str(zip_.make_zip_file(src_path, modules)))
|
||||
)
|
||||
|
||||
self.data = importlib.import_module(self.ZIP_MODULE)
|
||||
|
||||
|
||||
class ZipSetup(ZipSetupBase):
|
||||
ZIP_MODULE = zipdata01 # type: ignore
|
||||
pass
|
||||
|
|
32
lib/importlib_resources/tests/zip.py
Normal file
32
lib/importlib_resources/tests/zip.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
"""
|
||||
Generate zip test data files.
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import pathlib
|
||||
import zipfile
|
||||
|
||||
import zipp
|
||||
|
||||
|
||||
def make_zip_file(src, dst):
|
||||
"""
|
||||
Zip the files in src into a new zipfile at dst.
|
||||
"""
|
||||
with zipfile.ZipFile(dst, 'w') as zf:
|
||||
for src_path, rel in walk(src):
|
||||
dst_name = src.name / pathlib.PurePosixPath(rel.as_posix())
|
||||
zf.write(src_path, dst_name)
|
||||
zipp.CompleteDirs.inject(zf)
|
||||
return dst
|
||||
|
||||
|
||||
def walk(datapath):
|
||||
for dirpath, dirnames, filenames in os.walk(datapath):
|
||||
with contextlib.suppress(ValueError):
|
||||
dirnames.remove('__pycache__')
|
||||
for filename in filenames:
|
||||
res = pathlib.Path(dirpath) / filename
|
||||
rel = res.relative_to(datapath)
|
||||
yield res, rel
|
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue