diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2021-07-30 01:05:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-30 01:05:05 (GMT) |
commit | aaa83cdfab6817446285e631232f64b394ac6791 (patch) | |
tree | d41195f1412a533b1c7333b99adcc77f171329a1 /Lib/test/test_importlib | |
parent | 851cca8c22795a2f143ad5ebc10adab3c7784ad0 (diff) | |
download | cpython-aaa83cdfab6817446285e631232f64b394ac6791.zip cpython-aaa83cdfab6817446285e631232f64b394ac6791.tar.gz cpython-aaa83cdfab6817446285e631232f64b394ac6791.tar.bz2 |
bpo-44771: Apply changes from importlib_resources 5.2.1 (GH-27436)
* bpo-44771: Apply changes from importlib_resources@3b24bd6307
* Add blurb
* Exclude namespacedata01 from eol conversion.
Diffstat (limited to 'Lib/test/test_importlib')
-rw-r--r-- | Lib/test/test_importlib/resources/__init__.py | 0 | ||||
-rw-r--r-- | Lib/test/test_importlib/resources/util.py | 190 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_compatibilty_files.py | 102 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_contents.py | 42 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_files.py | 9 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_open.py | 6 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_path.py | 4 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_read.py | 13 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_resource.py | 12 | ||||
-rw-r--r-- | Lib/test/test_importlib/util.py | 172 |
10 files changed, 363 insertions, 187 deletions
diff --git a/Lib/test/test_importlib/resources/__init__.py b/Lib/test/test_importlib/resources/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Lib/test/test_importlib/resources/__init__.py diff --git a/Lib/test/test_importlib/resources/util.py b/Lib/test/test_importlib/resources/util.py new file mode 100644 index 0000000..d7a049b --- /dev/null +++ b/Lib/test/test_importlib/resources/util.py @@ -0,0 +1,190 @@ +import abc +import importlib +import io +import sys +import types +from pathlib import Path, PurePath + +from .. import data01 +from .. import zipdata01 +from importlib.abc import ResourceReader +from test.support import import_helper + + +from importlib.machinery import ModuleSpec + + +class Reader(ResourceReader): + def __init__(self, **kwargs): + vars(self).update(kwargs) + + def get_resource_reader(self, package): + return self + + def open_resource(self, path): + self._path = path + if isinstance(self.file, Exception): + raise self.file + return self.file + + def resource_path(self, path_): + self._path = path_ + if isinstance(self.path, Exception): + raise self.path + return self.path + + def is_resource(self, path_): + self._path = path_ + if isinstance(self.path, Exception): + raise self.path + + def part(entry): + return entry.split('/') + + return any( + len(parts) == 1 and parts[0] == path_ for parts in map(part, self._contents) + ) + + def contents(self): + if isinstance(self.path, Exception): + raise self.path + yield from self._contents + + +def create_package_from_loader(loader, is_package=True): + name = 'testingpackage' + module = types.ModuleType(name) + spec = ModuleSpec(name, loader, origin='does-not-exist', is_package=is_package) + module.__spec__ = spec + module.__loader__ = loader + return module + + +def create_package(file=None, path=None, is_package=True, contents=()): + return create_package_from_loader( + Reader(file=file, path=path, _contents=contents), + is_package, + ) + + +class CommonTests(metaclass=abc.ABCMeta): + """ + Tests shared by test_open, test_path, and test_read. + """ + + @abc.abstractmethod + def execute(self, package, path): + """ + Call the pertinent legacy API function (e.g. open_text, path) + on package and path. + """ + + 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) + + 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['test.test_importlib.resources.util'] + self.execute(module, 'utf-8.file') + + def test_missing_path(self): + # Attempting to open or read or request the path for a + # non-existent path should succeed if open_resource + # can return a viable data stream. + 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') + + def test_extant_path(self): + # Attempting to open or read or request the path when the + # path does exist should still succeed. Does not assert + # anything about the result. + bytes_data = io.BytesIO(b'Hello, world!') + # any path that exists + 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 diff --git a/Lib/test/test_importlib/test_compatibilty_files.py b/Lib/test/test_importlib/test_compatibilty_files.py new file mode 100644 index 0000000..d703c06 --- /dev/null +++ b/Lib/test/test_importlib/test_compatibilty_files.py @@ -0,0 +1,102 @@ +import io +import unittest + +from importlib import resources + +from importlib._adapters import ( + CompatibilityFiles, + wrap_spec, +) + +from .resources import util + + +class CompatibilityFilesTests(unittest.TestCase): + @property + def package(self): + bytes_data = io.BytesIO(b'Hello, world!') + return util.create_package( + file=bytes_data, + path='some_path', + contents=('a', 'b', 'c'), + ) + + @property + def files(self): + 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'], + ) + + def test_child_path_iter(self): + self.assertEqual(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()), []) + + def test_spec_path_is(self): + self.assertFalse(self.files.is_file()) + self.assertFalse(self.files.is_dir()) + + def test_child_path_is(self): + self.assertTrue((self.files / 'a').is_file()) + self.assertFalse((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()) + + def test_spec_path_name(self): + self.assertEqual(self.files.name, 'testingpackage') + + def test_child_path_name(self): + self.assertEqual((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') + + def test_spec_path_open(self): + self.assertEqual(self.files.read_bytes(), b'Hello, world!') + self.assertEqual(self.files.read_text(), '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(), 'Hello, world!') + + def test_orphan_path_open(self): + with self.assertRaises(FileNotFoundError): + (self.files / 'a' / 'b').read_bytes() + with self.assertRaises(FileNotFoundError): + (self.files / 'a' / 'b' / 'c').read_bytes() + + def test_open_invalid_mode(self): + with self.assertRaises(ValueError): + self.files.open('0') + + def test_orphan_path_invalid(self): + with self.assertRaises(ValueError): + CompatibilityFiles.OrphanPath() + + def test_wrap_spec(self): + spec = wrap_spec(self.package) + self.assertIsInstance(spec.loader.get_resource_reader(None), CompatibilityFiles) + + +class CompatibilityFilesNoReaderTests(unittest.TestCase): + @property + def package(self): + return util.create_package_from_loader(None) + + @property + def files(self): + return resources.files(self.package) + + def test_spec_path_joinpath(self): + self.assertIsInstance(self.files / 'a', CompatibilityFiles.OrphanPath) diff --git a/Lib/test/test_importlib/test_contents.py b/Lib/test/test_importlib/test_contents.py new file mode 100644 index 0000000..0f3aa84 --- /dev/null +++ b/Lib/test/test_importlib/test_contents.py @@ -0,0 +1,42 @@ +import unittest +from importlib import resources + +from . import data01 +from .resources import util + + +class ContentsTests: + expected = { + '__init__.py', + 'binary.file', + 'subdirectory', + 'utf-16.file', + 'utf-8.file', + } + + def test_contents(self): + assert self.expected <= set(resources.contents(self.data)) + + +class ContentsDiskTests(ContentsTests, unittest.TestCase): + def setUp(self): + self.data = data01 + + +class ContentsZipTests(ContentsTests, util.ZipSetup, unittest.TestCase): + pass + + +class ContentsNamespaceTests(ContentsTests, unittest.TestCase): + expected = { + # no __init__ because of namespace design + # no subdirectory as incidental difference in fixture + 'binary.file', + 'utf-16.file', + 'utf-8.file', + } + + def setUp(self): + from . import namespacedata01 + + self.data = namespacedata01 diff --git a/Lib/test/test_importlib/test_files.py b/Lib/test/test_importlib/test_files.py index 481829b..b9170d8 100644 --- a/Lib/test/test_importlib/test_files.py +++ b/Lib/test/test_importlib/test_files.py @@ -4,7 +4,7 @@ import unittest from importlib import resources from importlib.abc import Traversable from . import data01 -from . import util +from .resources import util class FilesTests: @@ -35,5 +35,12 @@ class OpenZipTests(FilesTests, util.ZipSetup, unittest.TestCase): pass +class OpenNamespaceTests(FilesTests, unittest.TestCase): + def setUp(self): + from . import namespacedata01 + + self.data = namespacedata01 + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_importlib/test_open.py b/Lib/test/test_importlib/test_open.py index b75675f..6f88ff7 100644 --- a/Lib/test/test_importlib/test_open.py +++ b/Lib/test/test_importlib/test_open.py @@ -2,16 +2,16 @@ import unittest from importlib import resources from . import data01 -from . import util +from .resources import util -class CommonBinaryTests(util.CommonResourceTests, unittest.TestCase): +class CommonBinaryTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): with resources.open_binary(package, path): pass -class CommonTextTests(util.CommonResourceTests, unittest.TestCase): +class CommonTextTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): with resources.open_text(package, path): pass diff --git a/Lib/test/test_importlib/test_path.py b/Lib/test/test_importlib/test_path.py index d6ed09a..4436d7f 100644 --- a/Lib/test/test_importlib/test_path.py +++ b/Lib/test/test_importlib/test_path.py @@ -3,10 +3,10 @@ import unittest from importlib import resources from . import data01 -from . import util +from .resources import util -class CommonTests(util.CommonResourceTests, unittest.TestCase): +class CommonTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): with resources.path(package, path): pass diff --git a/Lib/test/test_importlib/test_read.py b/Lib/test/test_importlib/test_read.py index f6ec13a..3579801 100644 --- a/Lib/test/test_importlib/test_read.py +++ b/Lib/test/test_importlib/test_read.py @@ -2,15 +2,15 @@ import unittest from importlib import import_module, resources from . import data01 -from . import util +from .resources import util -class CommonBinaryTests(util.CommonResourceTests, unittest.TestCase): +class CommonBinaryTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): resources.read_binary(package, path) -class CommonTextTests(util.CommonResourceTests, unittest.TestCase): +class CommonTextTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): resources.read_text(package, path) @@ -55,5 +55,12 @@ class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase): self.assertEqual(result, b'\0\1\2\3') +class ReadNamespaceTests(ReadTests, unittest.TestCase): + def setUp(self): + from . import namespacedata01 + + self.data = namespacedata01 + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_importlib/test_resource.py b/Lib/test/test_importlib/test_resource.py index 003f7e9..612bada 100644 --- a/Lib/test/test_importlib/test_resource.py +++ b/Lib/test/test_importlib/test_resource.py @@ -5,7 +5,7 @@ import pathlib from . import data01 from . import zipdata01, zipdata02 -from . import util +from .resources import util from importlib import resources, import_module from test.support import import_helper from test.support.os_helper import unlink @@ -33,14 +33,14 @@ class ResourceTests: # are not germane to this test, so just filter them out. contents.discard('__pycache__') self.assertEqual( - contents, - { + sorted(contents), + [ '__init__.py', - 'subdirectory', - 'utf-8.file', 'binary.file', + 'subdirectory', 'utf-16.file', - }, + 'utf-8.file', + ], ) diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index ca0d8c9..c07ac2a 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -1,17 +1,11 @@ -import abc import builtins import contextlib import errno import functools -import importlib from importlib import machinery, util, invalidate_caches -from importlib.abc import ResourceReader -import io import marshal import os import os.path -from pathlib import Path, PurePath -from test import support from test.support import import_helper from test.support import os_helper import unittest @@ -19,9 +13,6 @@ import sys import tempfile import types -from . import data01 -from . import zipdata01 - BUILTINS = types.SimpleNamespace() BUILTINS.good_name = None @@ -417,166 +408,3 @@ class CASEOKTestBase: if any(x in self.importlib._bootstrap_external._os.environ for x in possibilities) != should_exist: self.skipTest('os.environ changes not reflected in _os.environ') - - -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' - # Unfortunately importlib.util.module_from_spec() was not introduced until - # Python 3.5. - module = types.ModuleType(name) - loader = Reader() - spec = machinery.ModuleSpec( - name, loader, - origin='does-not-exist', - is_package=is_package) - module.__spec__ = spec - module.__loader__ = loader - return module - - -class CommonResourceTests(abc.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 relative 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['test.test_importlib.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 |