1import sys 2import unittest 3import uuid 4import pathlib 5 6from . import data01 7from . import zipdata01, zipdata02 8from . import util 9from importlib import resources, import_module 10from test.support import import_helper 11from test.support.os_helper import unlink 12 13 14class ResourceTests: 15 # Subclasses are expected to set the `data` attribute. 16 17 def test_is_resource_good_path(self): 18 self.assertTrue(resources.is_resource(self.data, 'binary.file')) 19 20 def test_is_resource_missing(self): 21 self.assertFalse(resources.is_resource(self.data, 'not-a-file')) 22 23 def test_is_resource_subresource_directory(self): 24 # Directories are not resources. 25 self.assertFalse(resources.is_resource(self.data, 'subdirectory')) 26 27 def test_contents(self): 28 contents = set(resources.contents(self.data)) 29 # There may be cruft in the directory listing of the data directory. 30 # It could have a __pycache__ directory, 31 # an artifact of the 32 # test suite importing these modules, which 33 # are not germane to this test, so just filter them out. 34 contents.discard('__pycache__') 35 self.assertEqual( 36 contents, 37 { 38 '__init__.py', 39 'subdirectory', 40 'utf-8.file', 41 'binary.file', 42 'utf-16.file', 43 }, 44 ) 45 46 47class ResourceDiskTests(ResourceTests, unittest.TestCase): 48 def setUp(self): 49 self.data = data01 50 51 52class ResourceZipTests(ResourceTests, util.ZipSetup, unittest.TestCase): 53 pass 54 55 56class ResourceLoaderTests(unittest.TestCase): 57 def test_resource_contents(self): 58 package = util.create_package( 59 file=data01, path=data01.__file__, contents=['A', 'B', 'C'] 60 ) 61 self.assertEqual(set(resources.contents(package)), {'A', 'B', 'C'}) 62 63 def test_resource_is_resource(self): 64 package = util.create_package( 65 file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] 66 ) 67 self.assertTrue(resources.is_resource(package, 'B')) 68 69 def test_resource_directory_is_not_resource(self): 70 package = util.create_package( 71 file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] 72 ) 73 self.assertFalse(resources.is_resource(package, 'D')) 74 75 def test_resource_missing_is_not_resource(self): 76 package = util.create_package( 77 file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] 78 ) 79 self.assertFalse(resources.is_resource(package, 'Z')) 80 81 82class ResourceCornerCaseTests(unittest.TestCase): 83 def test_package_has_no_reader_fallback(self): 84 # Test odd ball packages which: 85 # 1. Do not have a ResourceReader as a loader 86 # 2. Are not on the file system 87 # 3. Are not in a zip file 88 module = util.create_package( 89 file=data01, path=data01.__file__, contents=['A', 'B', 'C'] 90 ) 91 # Give the module a dummy loader. 92 module.__loader__ = object() 93 # Give the module a dummy origin. 94 module.__file__ = '/path/which/shall/not/be/named' 95 module.__spec__.loader = module.__loader__ 96 module.__spec__.origin = module.__file__ 97 self.assertFalse(resources.is_resource(module, 'A')) 98 99 100class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase): 101 ZIP_MODULE = zipdata01 # type: ignore 102 103 def test_is_submodule_resource(self): 104 submodule = import_module('ziptestdata.subdirectory') 105 self.assertTrue(resources.is_resource(submodule, 'binary.file')) 106 107 def test_read_submodule_resource_by_name(self): 108 self.assertTrue( 109 resources.is_resource('ziptestdata.subdirectory', 'binary.file') 110 ) 111 112 def test_submodule_contents(self): 113 submodule = import_module('ziptestdata.subdirectory') 114 self.assertEqual( 115 set(resources.contents(submodule)), {'__init__.py', 'binary.file'} 116 ) 117 118 def test_submodule_contents_by_name(self): 119 self.assertEqual( 120 set(resources.contents('ziptestdata.subdirectory')), 121 {'__init__.py', 'binary.file'}, 122 ) 123 124 125class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase): 126 ZIP_MODULE = zipdata02 # type: ignore 127 128 def test_unrelated_contents(self): 129 """ 130 Test thata zip with two unrelated subpackages return 131 distinct resources. Ref python/importlib_resources#44. 132 """ 133 self.assertEqual( 134 set(resources.contents('ziptestdata.one')), {'__init__.py', 'resource1.txt'} 135 ) 136 self.assertEqual( 137 set(resources.contents('ziptestdata.two')), {'__init__.py', 'resource2.txt'} 138 ) 139 140 141class DeletingZipsTest(unittest.TestCase): 142 """Having accessed resources in a zip file should not keep an open 143 reference to the zip. 144 """ 145 146 ZIP_MODULE = zipdata01 147 148 def setUp(self): 149 modules = import_helper.modules_setup() 150 self.addCleanup(import_helper.modules_cleanup, *modules) 151 152 data_path = pathlib.Path(self.ZIP_MODULE.__file__) 153 data_dir = data_path.parent 154 self.source_zip_path = data_dir / 'ziptestdata.zip' 155 self.zip_path = pathlib.Path(f'{uuid.uuid4()}.zip').absolute() 156 self.zip_path.write_bytes(self.source_zip_path.read_bytes()) 157 sys.path.append(str(self.zip_path)) 158 self.data = import_module('ziptestdata') 159 160 def tearDown(self): 161 try: 162 sys.path.remove(str(self.zip_path)) 163 except ValueError: 164 pass 165 166 try: 167 del sys.path_importer_cache[str(self.zip_path)] 168 del sys.modules[self.data.__name__] 169 except KeyError: 170 pass 171 172 try: 173 unlink(self.zip_path) 174 except OSError: 175 # If the test fails, this will probably fail too 176 pass 177 178 def test_contents_does_not_keep_open(self): 179 c = resources.contents('ziptestdata') 180 self.zip_path.unlink() 181 del c 182 183 def test_is_resource_does_not_keep_open(self): 184 c = resources.is_resource('ziptestdata', 'binary.file') 185 self.zip_path.unlink() 186 del c 187 188 def test_is_resource_failure_does_not_keep_open(self): 189 c = resources.is_resource('ziptestdata', 'not-present') 190 self.zip_path.unlink() 191 del c 192 193 @unittest.skip("Desired but not supported.") 194 def test_path_does_not_keep_open(self): 195 c = resources.path('ziptestdata', 'binary.file') 196 self.zip_path.unlink() 197 del c 198 199 def test_entered_path_does_not_keep_open(self): 200 # This is what certifi does on import to make its bundle 201 # available for the process duration. 202 c = resources.path('ziptestdata', 'binary.file').__enter__() 203 self.zip_path.unlink() 204 del c 205 206 def test_read_binary_does_not_keep_open(self): 207 c = resources.read_binary('ziptestdata', 'binary.file') 208 self.zip_path.unlink() 209 del c 210 211 def test_read_text_does_not_keep_open(self): 212 c = resources.read_text('ziptestdata', 'utf-8.file', encoding='utf-8') 213 self.zip_path.unlink() 214 del c 215 216 217class ResourceFromNamespaceTest01(unittest.TestCase): 218 site_dir = str(pathlib.Path(__file__).parent) 219 220 @classmethod 221 def setUpClass(cls): 222 sys.path.append(cls.site_dir) 223 224 @classmethod 225 def tearDownClass(cls): 226 sys.path.remove(cls.site_dir) 227 228 def test_is_submodule_resource(self): 229 self.assertTrue( 230 resources.is_resource(import_module('namespacedata01'), 'binary.file') 231 ) 232 233 def test_read_submodule_resource_by_name(self): 234 self.assertTrue(resources.is_resource('namespacedata01', 'binary.file')) 235 236 def test_submodule_contents(self): 237 contents = set(resources.contents(import_module('namespacedata01'))) 238 try: 239 contents.remove('__pycache__') 240 except KeyError: 241 pass 242 self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'}) 243 244 def test_submodule_contents_by_name(self): 245 contents = set(resources.contents('namespacedata01')) 246 try: 247 contents.remove('__pycache__') 248 except KeyError: 249 pass 250 self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'}) 251 252 253if __name__ == '__main__': 254 unittest.main() 255