ยปCore Development>Code coverage>Lib/test/test_namespace_pkgs.py

Python code coverage for Lib/test/test_namespace_pkgs.py

#countcontent
1n/aimport contextlib
2n/afrom importlib._bootstrap import NamespaceLoader
3n/aimport importlib.abc
4n/aimport importlib.machinery
5n/aimport os
6n/aimport sys
7n/aimport types
8n/aimport unittest
9n/a
10n/afrom test.test_importlib import util
11n/afrom test.support import run_unittest
12n/a
13n/a# needed tests:
14n/a#
15n/a# need to test when nested, so that the top-level path isn't sys.path
16n/a# need to test dynamic path detection, both at top-level and nested
17n/a# with dynamic path, check when a loader is returned on path reload (that is,
18n/a# trying to switch from a namespace package to a regular package)
19n/a
20n/a
21n/a@contextlib.contextmanager
22n/adef sys_modules_context():
23n/a """
24n/a Make sure sys.modules is the same object and has the same content
25n/a when exiting the context as when entering.
26n/a
27n/a Similar to importlib.test.util.uncache, but doesn't require explicit
28n/a names.
29n/a """
30n/a sys_modules_saved = sys.modules
31n/a sys_modules_copy = sys.modules.copy()
32n/a try:
33n/a yield
34n/a finally:
35n/a sys.modules = sys_modules_saved
36n/a sys.modules.clear()
37n/a sys.modules.update(sys_modules_copy)
38n/a
39n/a
40n/a@contextlib.contextmanager
41n/adef namespace_tree_context(**kwargs):
42n/a """
43n/a Save import state and sys.modules cache and restore it on exit.
44n/a Typical usage:
45n/a
46n/a >>> with namespace_tree_context(path=['/tmp/xxyy/portion1',
47n/a ... '/tmp/xxyy/portion2']):
48n/a ... pass
49n/a """
50n/a # use default meta_path and path_hooks unless specified otherwise
51n/a kwargs.setdefault('meta_path', sys.meta_path)
52n/a kwargs.setdefault('path_hooks', sys.path_hooks)
53n/a import_context = util.import_state(**kwargs)
54n/a with import_context, sys_modules_context():
55n/a yield
56n/a
57n/aclass NamespacePackageTest(unittest.TestCase):
58n/a """
59n/a Subclasses should define self.root and self.paths (under that root)
60n/a to be added to sys.path.
61n/a """
62n/a root = os.path.join(os.path.dirname(__file__), 'namespace_pkgs')
63n/a
64n/a def setUp(self):
65n/a self.resolved_paths = [
66n/a os.path.join(self.root, path) for path in self.paths
67n/a ]
68n/a self.ctx = namespace_tree_context(path=self.resolved_paths)
69n/a self.ctx.__enter__()
70n/a
71n/a def tearDown(self):
72n/a # TODO: will we ever want to pass exc_info to __exit__?
73n/a self.ctx.__exit__(None, None, None)
74n/a
75n/aclass SingleNamespacePackage(NamespacePackageTest):
76n/a paths = ['portion1']
77n/a
78n/a def test_simple_package(self):
79n/a import foo.one
80n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
81n/a
82n/a def test_cant_import_other(self):
83n/a with self.assertRaises(ImportError):
84n/a import foo.two
85n/a
86n/a def test_module_repr(self):
87n/a import foo.one
88n/a self.assertEqual(repr(foo), "<module 'foo' (namespace)>")
89n/a
90n/a
91n/aclass DynamicPatheNamespacePackage(NamespacePackageTest):
92n/a paths = ['portion1']
93n/a
94n/a def test_dynamic_path(self):
95n/a # Make sure only 'foo.one' can be imported
96n/a import foo.one
97n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
98n/a
99n/a with self.assertRaises(ImportError):
100n/a import foo.two
101n/a
102n/a # Now modify sys.path
103n/a sys.path.append(os.path.join(self.root, 'portion2'))
104n/a
105n/a # And make sure foo.two is now importable
106n/a import foo.two
107n/a self.assertEqual(foo.two.attr, 'portion2 foo two')
108n/a
109n/a
110n/aclass CombinedNamespacePackages(NamespacePackageTest):
111n/a paths = ['both_portions']
112n/a
113n/a def test_imports(self):
114n/a import foo.one
115n/a import foo.two
116n/a self.assertEqual(foo.one.attr, 'both_portions foo one')
117n/a self.assertEqual(foo.two.attr, 'both_portions foo two')
118n/a
119n/a
120n/aclass SeparatedNamespacePackages(NamespacePackageTest):
121n/a paths = ['portion1', 'portion2']
122n/a
123n/a def test_imports(self):
124n/a import foo.one
125n/a import foo.two
126n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
127n/a self.assertEqual(foo.two.attr, 'portion2 foo two')
128n/a
129n/a
130n/aclass SeparatedOverlappingNamespacePackages(NamespacePackageTest):
131n/a paths = ['portion1', 'both_portions']
132n/a
133n/a def test_first_path_wins(self):
134n/a import foo.one
135n/a import foo.two
136n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
137n/a self.assertEqual(foo.two.attr, 'both_portions foo two')
138n/a
139n/a def test_first_path_wins_again(self):
140n/a sys.path.reverse()
141n/a import foo.one
142n/a import foo.two
143n/a self.assertEqual(foo.one.attr, 'both_portions foo one')
144n/a self.assertEqual(foo.two.attr, 'both_portions foo two')
145n/a
146n/a def test_first_path_wins_importing_second_first(self):
147n/a import foo.two
148n/a import foo.one
149n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
150n/a self.assertEqual(foo.two.attr, 'both_portions foo two')
151n/a
152n/a
153n/aclass SingleZipNamespacePackage(NamespacePackageTest):
154n/a paths = ['top_level_portion1.zip']
155n/a
156n/a def test_simple_package(self):
157n/a import foo.one
158n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
159n/a
160n/a def test_cant_import_other(self):
161n/a with self.assertRaises(ImportError):
162n/a import foo.two
163n/a
164n/a
165n/aclass SeparatedZipNamespacePackages(NamespacePackageTest):
166n/a paths = ['top_level_portion1.zip', 'portion2']
167n/a
168n/a def test_imports(self):
169n/a import foo.one
170n/a import foo.two
171n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
172n/a self.assertEqual(foo.two.attr, 'portion2 foo two')
173n/a self.assertIn('top_level_portion1.zip', foo.one.__file__)
174n/a self.assertNotIn('.zip', foo.two.__file__)
175n/a
176n/a
177n/aclass SingleNestedZipNamespacePackage(NamespacePackageTest):
178n/a paths = ['nested_portion1.zip/nested_portion1']
179n/a
180n/a def test_simple_package(self):
181n/a import foo.one
182n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
183n/a
184n/a def test_cant_import_other(self):
185n/a with self.assertRaises(ImportError):
186n/a import foo.two
187n/a
188n/a
189n/aclass SeparatedNestedZipNamespacePackages(NamespacePackageTest):
190n/a paths = ['nested_portion1.zip/nested_portion1', 'portion2']
191n/a
192n/a def test_imports(self):
193n/a import foo.one
194n/a import foo.two
195n/a self.assertEqual(foo.one.attr, 'portion1 foo one')
196n/a self.assertEqual(foo.two.attr, 'portion2 foo two')
197n/a fn = os.path.join('nested_portion1.zip', 'nested_portion1')
198n/a self.assertIn(fn, foo.one.__file__)
199n/a self.assertNotIn('.zip', foo.two.__file__)
200n/a
201n/a
202n/aclass LegacySupport(NamespacePackageTest):
203n/a paths = ['not_a_namespace_pkg', 'portion1', 'portion2', 'both_portions']
204n/a
205n/a def test_non_namespace_package_takes_precedence(self):
206n/a import foo.one
207n/a with self.assertRaises(ImportError):
208n/a import foo.two
209n/a self.assertIn('__init__', foo.__file__)
210n/a self.assertNotIn('namespace', str(foo.__loader__).lower())
211n/a
212n/a
213n/aclass DynamicPathCalculation(NamespacePackageTest):
214n/a paths = ['project1', 'project2']
215n/a
216n/a def test_project3_fails(self):
217n/a import parent.child.one
218n/a self.assertEqual(len(parent.__path__), 2)
219n/a self.assertEqual(len(parent.child.__path__), 2)
220n/a import parent.child.two
221n/a self.assertEqual(len(parent.__path__), 2)
222n/a self.assertEqual(len(parent.child.__path__), 2)
223n/a
224n/a self.assertEqual(parent.child.one.attr, 'parent child one')
225n/a self.assertEqual(parent.child.two.attr, 'parent child two')
226n/a
227n/a with self.assertRaises(ImportError):
228n/a import parent.child.three
229n/a
230n/a self.assertEqual(len(parent.__path__), 2)
231n/a self.assertEqual(len(parent.child.__path__), 2)
232n/a
233n/a def test_project3_succeeds(self):
234n/a import parent.child.one
235n/a self.assertEqual(len(parent.__path__), 2)
236n/a self.assertEqual(len(parent.child.__path__), 2)
237n/a import parent.child.two
238n/a self.assertEqual(len(parent.__path__), 2)
239n/a self.assertEqual(len(parent.child.__path__), 2)
240n/a
241n/a self.assertEqual(parent.child.one.attr, 'parent child one')
242n/a self.assertEqual(parent.child.two.attr, 'parent child two')
243n/a
244n/a with self.assertRaises(ImportError):
245n/a import parent.child.three
246n/a
247n/a # now add project3
248n/a sys.path.append(os.path.join(self.root, 'project3'))
249n/a import parent.child.three
250n/a
251n/a # the paths dynamically get longer, to include the new directories
252n/a self.assertEqual(len(parent.__path__), 3)
253n/a self.assertEqual(len(parent.child.__path__), 3)
254n/a
255n/a self.assertEqual(parent.child.three.attr, 'parent child three')
256n/a
257n/a
258n/aclass ZipWithMissingDirectory(NamespacePackageTest):
259n/a paths = ['missing_directory.zip']
260n/a
261n/a @unittest.expectedFailure
262n/a def test_missing_directory(self):
263n/a # This will fail because missing_directory.zip contains:
264n/a # Length Date Time Name
265n/a # --------- ---------- ----- ----
266n/a # 29 2012-05-03 18:13 foo/one.py
267n/a # 0 2012-05-03 20:57 bar/
268n/a # 38 2012-05-03 20:57 bar/two.py
269n/a # --------- -------
270n/a # 67 3 files
271n/a
272n/a # Because there is no 'foo/', the zipimporter currently doesn't
273n/a # know that foo is a namespace package
274n/a
275n/a import foo.one
276n/a
277n/a def test_present_directory(self):
278n/a # This succeeds because there is a "bar/" in the zip file
279n/a import bar.two
280n/a self.assertEqual(bar.two.attr, 'missing_directory foo two')
281n/a
282n/a
283n/aclass ModuleAndNamespacePackageInSameDir(NamespacePackageTest):
284n/a paths = ['module_and_namespace_package']
285n/a
286n/a def test_module_before_namespace_package(self):
287n/a # Make sure we find the module in preference to the
288n/a # namespace package.
289n/a import a_test
290n/a self.assertEqual(a_test.attr, 'in module')
291n/a
292n/a
293n/aclass ABCTests(unittest.TestCase):
294n/a
295n/a def setUp(self):
296n/a self.loader = NamespaceLoader('foo', ['pkg'],
297n/a importlib.machinery.PathFinder)
298n/a
299n/a def test_is_package(self):
300n/a self.assertTrue(self.loader.is_package('foo'))
301n/a
302n/a def test_get_code(self):
303n/a self.assertTrue(isinstance(self.loader.get_code('foo'), types.CodeType))
304n/a
305n/a def test_get_source(self):
306n/a self.assertEqual(self.loader.get_source('foo'), '')
307n/a
308n/a def test_abc_isinstance(self):
309n/a self.assertTrue(isinstance(self.loader, importlib.abc.InspectLoader))
310n/a
311n/a
312n/aif __name__ == "__main__":
313n/a unittest.main()