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

Python code coverage for Lib/test/test_importlib/test_namespace_pkgs.py

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