ยปCore Development>Code coverage>Lib/test/test_importlib/source/test_finder.py

Python code coverage for Lib/test/test_importlib/source/test_finder.py

#countcontent
1n/afrom .. import abc
2n/afrom .. import util
3n/a
4n/amachinery = util.import_importlib('importlib.machinery')
5n/a
6n/aimport errno
7n/aimport os
8n/aimport py_compile
9n/aimport stat
10n/aimport sys
11n/aimport tempfile
12n/afrom test.support import make_legacy_pyc
13n/aimport unittest
14n/aimport warnings
15n/a
16n/a
17n/aclass FinderTests(abc.FinderTests):
18n/a
19n/a """For a top-level module, it should just be found directly in the
20n/a directory being searched. This is true for a directory with source
21n/a [top-level source], bytecode [top-level bc], or both [top-level both].
22n/a There is also the possibility that it is a package [top-level package], in
23n/a which case there will be a directory with the module name and an
24n/a __init__.py file. If there is a directory without an __init__.py an
25n/a ImportWarning is returned [empty dir].
26n/a
27n/a For sub-modules and sub-packages, the same happens as above but only use
28n/a the tail end of the name [sub module] [sub package] [sub empty].
29n/a
30n/a When there is a conflict between a package and module having the same name
31n/a in the same directory, the package wins out [package over module]. This is
32n/a so that imports of modules within the package can occur rather than trigger
33n/a an import error.
34n/a
35n/a When there is a package and module with the same name, always pick the
36n/a package over the module [package over module]. This is so that imports from
37n/a the package have the possibility of succeeding.
38n/a
39n/a """
40n/a
41n/a def get_finder(self, root):
42n/a loader_details = [(self.machinery.SourceFileLoader,
43n/a self.machinery.SOURCE_SUFFIXES),
44n/a (self.machinery.SourcelessFileLoader,
45n/a self.machinery.BYTECODE_SUFFIXES)]
46n/a return self.machinery.FileFinder(root, *loader_details)
47n/a
48n/a def import_(self, root, module):
49n/a finder = self.get_finder(root)
50n/a return self._find(finder, module, loader_only=True)
51n/a
52n/a def run_test(self, test, create=None, *, compile_=None, unlink=None):
53n/a """Test the finding of 'test' with the creation of modules listed in
54n/a 'create'.
55n/a
56n/a Any names listed in 'compile_' are byte-compiled. Modules
57n/a listed in 'unlink' have their source files deleted.
58n/a
59n/a """
60n/a if create is None:
61n/a create = {test}
62n/a with util.create_modules(*create) as mapping:
63n/a if compile_:
64n/a for name in compile_:
65n/a py_compile.compile(mapping[name])
66n/a if unlink:
67n/a for name in unlink:
68n/a os.unlink(mapping[name])
69n/a try:
70n/a make_legacy_pyc(mapping[name])
71n/a except OSError as error:
72n/a # Some tests do not set compile_=True so the source
73n/a # module will not get compiled and there will be no
74n/a # PEP 3147 pyc file to rename.
75n/a if error.errno != errno.ENOENT:
76n/a raise
77n/a loader = self.import_(mapping['.root'], test)
78n/a self.assertTrue(hasattr(loader, 'load_module'))
79n/a return loader
80n/a
81n/a def test_module(self):
82n/a # [top-level source]
83n/a self.run_test('top_level')
84n/a # [top-level bc]
85n/a self.run_test('top_level', compile_={'top_level'},
86n/a unlink={'top_level'})
87n/a # [top-level both]
88n/a self.run_test('top_level', compile_={'top_level'})
89n/a
90n/a # [top-level package]
91n/a def test_package(self):
92n/a # Source.
93n/a self.run_test('pkg', {'pkg.__init__'})
94n/a # Bytecode.
95n/a self.run_test('pkg', {'pkg.__init__'}, compile_={'pkg.__init__'},
96n/a unlink={'pkg.__init__'})
97n/a # Both.
98n/a self.run_test('pkg', {'pkg.__init__'}, compile_={'pkg.__init__'})
99n/a
100n/a # [sub module]
101n/a def test_module_in_package(self):
102n/a with util.create_modules('pkg.__init__', 'pkg.sub') as mapping:
103n/a pkg_dir = os.path.dirname(mapping['pkg.__init__'])
104n/a loader = self.import_(pkg_dir, 'pkg.sub')
105n/a self.assertTrue(hasattr(loader, 'load_module'))
106n/a
107n/a # [sub package]
108n/a def test_package_in_package(self):
109n/a context = util.create_modules('pkg.__init__', 'pkg.sub.__init__')
110n/a with context as mapping:
111n/a pkg_dir = os.path.dirname(mapping['pkg.__init__'])
112n/a loader = self.import_(pkg_dir, 'pkg.sub')
113n/a self.assertTrue(hasattr(loader, 'load_module'))
114n/a
115n/a # [package over modules]
116n/a def test_package_over_module(self):
117n/a name = '_temp'
118n/a loader = self.run_test(name, {'{0}.__init__'.format(name), name})
119n/a self.assertIn('__init__', loader.get_filename(name))
120n/a
121n/a def test_failure(self):
122n/a with util.create_modules('blah') as mapping:
123n/a nothing = self.import_(mapping['.root'], 'sdfsadsadf')
124n/a self.assertIsNone(nothing)
125n/a
126n/a def test_empty_string_for_dir(self):
127n/a # The empty string from sys.path means to search in the cwd.
128n/a finder = self.machinery.FileFinder('', (self.machinery.SourceFileLoader,
129n/a self.machinery.SOURCE_SUFFIXES))
130n/a with open('mod.py', 'w') as file:
131n/a file.write("# test file for importlib")
132n/a try:
133n/a loader = self._find(finder, 'mod', loader_only=True)
134n/a self.assertTrue(hasattr(loader, 'load_module'))
135n/a finally:
136n/a os.unlink('mod.py')
137n/a
138n/a def test_invalidate_caches(self):
139n/a # invalidate_caches() should reset the mtime.
140n/a finder = self.machinery.FileFinder('', (self.machinery.SourceFileLoader,
141n/a self.machinery.SOURCE_SUFFIXES))
142n/a finder._path_mtime = 42
143n/a finder.invalidate_caches()
144n/a self.assertEqual(finder._path_mtime, -1)
145n/a
146n/a # Regression test for http://bugs.python.org/issue14846
147n/a def test_dir_removal_handling(self):
148n/a mod = 'mod'
149n/a with util.create_modules(mod) as mapping:
150n/a finder = self.get_finder(mapping['.root'])
151n/a found = self._find(finder, 'mod', loader_only=True)
152n/a self.assertIsNotNone(found)
153n/a found = self._find(finder, 'mod', loader_only=True)
154n/a self.assertIsNone(found)
155n/a
156n/a @unittest.skipUnless(sys.platform != 'win32',
157n/a 'os.chmod() does not support the needed arguments under Windows')
158n/a def test_no_read_directory(self):
159n/a # Issue #16730
160n/a tempdir = tempfile.TemporaryDirectory()
161n/a original_mode = os.stat(tempdir.name).st_mode
162n/a def cleanup(tempdir):
163n/a """Cleanup function for the temporary directory.
164n/a
165n/a Since we muck with the permissions, we want to set them back to
166n/a their original values to make sure the directory can be properly
167n/a cleaned up.
168n/a
169n/a """
170n/a os.chmod(tempdir.name, original_mode)
171n/a # If this is not explicitly called then the __del__ method is used,
172n/a # but since already mucking around might as well explicitly clean
173n/a # up.
174n/a tempdir.__exit__(None, None, None)
175n/a self.addCleanup(cleanup, tempdir)
176n/a os.chmod(tempdir.name, stat.S_IWUSR | stat.S_IXUSR)
177n/a finder = self.get_finder(tempdir.name)
178n/a found = self._find(finder, 'doesnotexist')
179n/a self.assertEqual(found, self.NOT_FOUND)
180n/a
181n/a def test_ignore_file(self):
182n/a # If a directory got changed to a file from underneath us, then don't
183n/a # worry about looking for submodules.
184n/a with tempfile.NamedTemporaryFile() as file_obj:
185n/a finder = self.get_finder(file_obj.name)
186n/a found = self._find(finder, 'doesnotexist')
187n/a self.assertEqual(found, self.NOT_FOUND)
188n/a
189n/a
190n/aclass FinderTestsPEP451(FinderTests):
191n/a
192n/a NOT_FOUND = None
193n/a
194n/a def _find(self, finder, name, loader_only=False):
195n/a spec = finder.find_spec(name)
196n/a return spec.loader if spec is not None else spec
197n/a
198n/a
199n/a(Frozen_FinderTestsPEP451,
200n/a Source_FinderTestsPEP451
201n/a ) = util.test_both(FinderTestsPEP451, machinery=machinery)
202n/a
203n/a
204n/aclass FinderTestsPEP420(FinderTests):
205n/a
206n/a NOT_FOUND = (None, [])
207n/a
208n/a def _find(self, finder, name, loader_only=False):
209n/a with warnings.catch_warnings():
210n/a warnings.simplefilter("ignore", DeprecationWarning)
211n/a loader_portions = finder.find_loader(name)
212n/a return loader_portions[0] if loader_only else loader_portions
213n/a
214n/a
215n/a(Frozen_FinderTestsPEP420,
216n/a Source_FinderTestsPEP420
217n/a ) = util.test_both(FinderTestsPEP420, machinery=machinery)
218n/a
219n/a
220n/aclass FinderTestsPEP302(FinderTests):
221n/a
222n/a NOT_FOUND = None
223n/a
224n/a def _find(self, finder, name, loader_only=False):
225n/a with warnings.catch_warnings():
226n/a warnings.simplefilter("ignore", DeprecationWarning)
227n/a return finder.find_module(name)
228n/a
229n/a
230n/a(Frozen_FinderTestsPEP302,
231n/a Source_FinderTestsPEP302
232n/a ) = util.test_both(FinderTestsPEP302, machinery=machinery)
233n/a
234n/a
235n/aif __name__ == '__main__':
236n/a unittest.main()