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