ยปCore Development>Code coverage>Lib/distutils/tests/test_dist.py

Python code coverage for Lib/distutils/tests/test_dist.py

#countcontent
1n/a"""Tests for distutils.dist."""
2n/aimport os
3n/aimport io
4n/aimport sys
5n/aimport unittest
6n/aimport warnings
7n/aimport textwrap
8n/a
9n/afrom unittest import mock
10n/a
11n/afrom distutils.dist import Distribution, fix_help_options, DistributionMetadata
12n/afrom distutils.cmd import Command
13n/a
14n/afrom test.support import TESTFN, captured_stdout, run_unittest
15n/afrom distutils.tests import support
16n/afrom distutils import log
17n/a
18n/a
19n/aclass test_dist(Command):
20n/a """Sample distutils extension command."""
21n/a
22n/a user_options = [
23n/a ("sample-option=", "S", "help text"),
24n/a ]
25n/a
26n/a def initialize_options(self):
27n/a self.sample_option = None
28n/a
29n/a
30n/aclass TestDistribution(Distribution):
31n/a """Distribution subclasses that avoids the default search for
32n/a configuration files.
33n/a
34n/a The ._config_files attribute must be set before
35n/a .parse_config_files() is called.
36n/a """
37n/a
38n/a def find_config_files(self):
39n/a return self._config_files
40n/a
41n/a
42n/aclass DistributionTestCase(support.LoggingSilencer,
43n/a support.TempdirManager,
44n/a support.EnvironGuard,
45n/a unittest.TestCase):
46n/a
47n/a def setUp(self):
48n/a super(DistributionTestCase, self).setUp()
49n/a self.argv = sys.argv, sys.argv[:]
50n/a del sys.argv[1:]
51n/a
52n/a def tearDown(self):
53n/a sys.argv = self.argv[0]
54n/a sys.argv[:] = self.argv[1]
55n/a super(DistributionTestCase, self).tearDown()
56n/a
57n/a def create_distribution(self, configfiles=()):
58n/a d = TestDistribution()
59n/a d._config_files = configfiles
60n/a d.parse_config_files()
61n/a d.parse_command_line()
62n/a return d
63n/a
64n/a def test_command_packages_unspecified(self):
65n/a sys.argv.append("build")
66n/a d = self.create_distribution()
67n/a self.assertEqual(d.get_command_packages(), ["distutils.command"])
68n/a
69n/a def test_command_packages_cmdline(self):
70n/a from distutils.tests.test_dist import test_dist
71n/a sys.argv.extend(["--command-packages",
72n/a "foo.bar,distutils.tests",
73n/a "test_dist",
74n/a "-Ssometext",
75n/a ])
76n/a d = self.create_distribution()
77n/a # let's actually try to load our test command:
78n/a self.assertEqual(d.get_command_packages(),
79n/a ["distutils.command", "foo.bar", "distutils.tests"])
80n/a cmd = d.get_command_obj("test_dist")
81n/a self.assertIsInstance(cmd, test_dist)
82n/a self.assertEqual(cmd.sample_option, "sometext")
83n/a
84n/a def test_venv_install_options(self):
85n/a sys.argv.append("install")
86n/a self.addCleanup(os.unlink, TESTFN)
87n/a
88n/a fakepath = '/somedir'
89n/a
90n/a with open(TESTFN, "w") as f:
91n/a print(("[install]\n"
92n/a "install-base = {0}\n"
93n/a "install-platbase = {0}\n"
94n/a "install-lib = {0}\n"
95n/a "install-platlib = {0}\n"
96n/a "install-purelib = {0}\n"
97n/a "install-headers = {0}\n"
98n/a "install-scripts = {0}\n"
99n/a "install-data = {0}\n"
100n/a "prefix = {0}\n"
101n/a "exec-prefix = {0}\n"
102n/a "home = {0}\n"
103n/a "user = {0}\n"
104n/a "root = {0}").format(fakepath), file=f)
105n/a
106n/a # Base case: Not in a Virtual Environment
107n/a with mock.patch.multiple(sys, prefix='/a', base_prefix='/a') as values:
108n/a d = self.create_distribution([TESTFN])
109n/a
110n/a option_tuple = (TESTFN, fakepath)
111n/a
112n/a result_dict = {
113n/a 'install_base': option_tuple,
114n/a 'install_platbase': option_tuple,
115n/a 'install_lib': option_tuple,
116n/a 'install_platlib': option_tuple,
117n/a 'install_purelib': option_tuple,
118n/a 'install_headers': option_tuple,
119n/a 'install_scripts': option_tuple,
120n/a 'install_data': option_tuple,
121n/a 'prefix': option_tuple,
122n/a 'exec_prefix': option_tuple,
123n/a 'home': option_tuple,
124n/a 'user': option_tuple,
125n/a 'root': option_tuple,
126n/a }
127n/a
128n/a self.assertEqual(
129n/a sorted(d.command_options.get('install').keys()),
130n/a sorted(result_dict.keys()))
131n/a
132n/a for (key, value) in d.command_options.get('install').items():
133n/a self.assertEqual(value, result_dict[key])
134n/a
135n/a # Test case: In a Virtual Environment
136n/a with mock.patch.multiple(sys, prefix='/a', base_prefix='/b') as values:
137n/a d = self.create_distribution([TESTFN])
138n/a
139n/a for key in result_dict.keys():
140n/a self.assertNotIn(key, d.command_options.get('install', {}))
141n/a
142n/a def test_command_packages_configfile(self):
143n/a sys.argv.append("build")
144n/a self.addCleanup(os.unlink, TESTFN)
145n/a f = open(TESTFN, "w")
146n/a try:
147n/a print("[global]", file=f)
148n/a print("command_packages = foo.bar, splat", file=f)
149n/a finally:
150n/a f.close()
151n/a
152n/a d = self.create_distribution([TESTFN])
153n/a self.assertEqual(d.get_command_packages(),
154n/a ["distutils.command", "foo.bar", "splat"])
155n/a
156n/a # ensure command line overrides config:
157n/a sys.argv[1:] = ["--command-packages", "spork", "build"]
158n/a d = self.create_distribution([TESTFN])
159n/a self.assertEqual(d.get_command_packages(),
160n/a ["distutils.command", "spork"])
161n/a
162n/a # Setting --command-packages to '' should cause the default to
163n/a # be used even if a config file specified something else:
164n/a sys.argv[1:] = ["--command-packages", "", "build"]
165n/a d = self.create_distribution([TESTFN])
166n/a self.assertEqual(d.get_command_packages(), ["distutils.command"])
167n/a
168n/a def test_empty_options(self):
169n/a # an empty options dictionary should not stay in the
170n/a # list of attributes
171n/a
172n/a # catching warnings
173n/a warns = []
174n/a
175n/a def _warn(msg):
176n/a warns.append(msg)
177n/a
178n/a self.addCleanup(setattr, warnings, 'warn', warnings.warn)
179n/a warnings.warn = _warn
180n/a dist = Distribution(attrs={'author': 'xxx', 'name': 'xxx',
181n/a 'version': 'xxx', 'url': 'xxxx',
182n/a 'options': {}})
183n/a
184n/a self.assertEqual(len(warns), 0)
185n/a self.assertNotIn('options', dir(dist))
186n/a
187n/a def test_finalize_options(self):
188n/a attrs = {'keywords': 'one,two',
189n/a 'platforms': 'one,two'}
190n/a
191n/a dist = Distribution(attrs=attrs)
192n/a dist.finalize_options()
193n/a
194n/a # finalize_option splits platforms and keywords
195n/a self.assertEqual(dist.metadata.platforms, ['one', 'two'])
196n/a self.assertEqual(dist.metadata.keywords, ['one', 'two'])
197n/a
198n/a def test_get_command_packages(self):
199n/a dist = Distribution()
200n/a self.assertEqual(dist.command_packages, None)
201n/a cmds = dist.get_command_packages()
202n/a self.assertEqual(cmds, ['distutils.command'])
203n/a self.assertEqual(dist.command_packages,
204n/a ['distutils.command'])
205n/a
206n/a dist.command_packages = 'one,two'
207n/a cmds = dist.get_command_packages()
208n/a self.assertEqual(cmds, ['distutils.command', 'one', 'two'])
209n/a
210n/a def test_announce(self):
211n/a # make sure the level is known
212n/a dist = Distribution()
213n/a args = ('ok',)
214n/a kwargs = {'level': 'ok2'}
215n/a self.assertRaises(ValueError, dist.announce, args, kwargs)
216n/a
217n/a
218n/a def test_find_config_files_disable(self):
219n/a # Ticket #1180: Allow user to disable their home config file.
220n/a temp_home = self.mkdtemp()
221n/a if os.name == 'posix':
222n/a user_filename = os.path.join(temp_home, ".pydistutils.cfg")
223n/a else:
224n/a user_filename = os.path.join(temp_home, "pydistutils.cfg")
225n/a
226n/a with open(user_filename, 'w') as f:
227n/a f.write('[distutils]\n')
228n/a
229n/a def _expander(path):
230n/a return temp_home
231n/a
232n/a old_expander = os.path.expanduser
233n/a os.path.expanduser = _expander
234n/a try:
235n/a d = Distribution()
236n/a all_files = d.find_config_files()
237n/a
238n/a d = Distribution(attrs={'script_args': ['--no-user-cfg']})
239n/a files = d.find_config_files()
240n/a finally:
241n/a os.path.expanduser = old_expander
242n/a
243n/a # make sure --no-user-cfg disables the user cfg file
244n/a self.assertEqual(len(all_files)-1, len(files))
245n/a
246n/aclass MetadataTestCase(support.TempdirManager, support.EnvironGuard,
247n/a unittest.TestCase):
248n/a
249n/a def setUp(self):
250n/a super(MetadataTestCase, self).setUp()
251n/a self.argv = sys.argv, sys.argv[:]
252n/a
253n/a def tearDown(self):
254n/a sys.argv = self.argv[0]
255n/a sys.argv[:] = self.argv[1]
256n/a super(MetadataTestCase, self).tearDown()
257n/a
258n/a def format_metadata(self, dist):
259n/a sio = io.StringIO()
260n/a dist.metadata.write_pkg_file(sio)
261n/a return sio.getvalue()
262n/a
263n/a def test_simple_metadata(self):
264n/a attrs = {"name": "package",
265n/a "version": "1.0"}
266n/a dist = Distribution(attrs)
267n/a meta = self.format_metadata(dist)
268n/a self.assertIn("Metadata-Version: 1.0", meta)
269n/a self.assertNotIn("provides:", meta.lower())
270n/a self.assertNotIn("requires:", meta.lower())
271n/a self.assertNotIn("obsoletes:", meta.lower())
272n/a
273n/a def test_provides(self):
274n/a attrs = {"name": "package",
275n/a "version": "1.0",
276n/a "provides": ["package", "package.sub"]}
277n/a dist = Distribution(attrs)
278n/a self.assertEqual(dist.metadata.get_provides(),
279n/a ["package", "package.sub"])
280n/a self.assertEqual(dist.get_provides(),
281n/a ["package", "package.sub"])
282n/a meta = self.format_metadata(dist)
283n/a self.assertIn("Metadata-Version: 1.1", meta)
284n/a self.assertNotIn("requires:", meta.lower())
285n/a self.assertNotIn("obsoletes:", meta.lower())
286n/a
287n/a def test_provides_illegal(self):
288n/a self.assertRaises(ValueError, Distribution,
289n/a {"name": "package",
290n/a "version": "1.0",
291n/a "provides": ["my.pkg (splat)"]})
292n/a
293n/a def test_requires(self):
294n/a attrs = {"name": "package",
295n/a "version": "1.0",
296n/a "requires": ["other", "another (==1.0)"]}
297n/a dist = Distribution(attrs)
298n/a self.assertEqual(dist.metadata.get_requires(),
299n/a ["other", "another (==1.0)"])
300n/a self.assertEqual(dist.get_requires(),
301n/a ["other", "another (==1.0)"])
302n/a meta = self.format_metadata(dist)
303n/a self.assertIn("Metadata-Version: 1.1", meta)
304n/a self.assertNotIn("provides:", meta.lower())
305n/a self.assertIn("Requires: other", meta)
306n/a self.assertIn("Requires: another (==1.0)", meta)
307n/a self.assertNotIn("obsoletes:", meta.lower())
308n/a
309n/a def test_requires_illegal(self):
310n/a self.assertRaises(ValueError, Distribution,
311n/a {"name": "package",
312n/a "version": "1.0",
313n/a "requires": ["my.pkg (splat)"]})
314n/a
315n/a def test_obsoletes(self):
316n/a attrs = {"name": "package",
317n/a "version": "1.0",
318n/a "obsoletes": ["other", "another (<1.0)"]}
319n/a dist = Distribution(attrs)
320n/a self.assertEqual(dist.metadata.get_obsoletes(),
321n/a ["other", "another (<1.0)"])
322n/a self.assertEqual(dist.get_obsoletes(),
323n/a ["other", "another (<1.0)"])
324n/a meta = self.format_metadata(dist)
325n/a self.assertIn("Metadata-Version: 1.1", meta)
326n/a self.assertNotIn("provides:", meta.lower())
327n/a self.assertNotIn("requires:", meta.lower())
328n/a self.assertIn("Obsoletes: other", meta)
329n/a self.assertIn("Obsoletes: another (<1.0)", meta)
330n/a
331n/a def test_obsoletes_illegal(self):
332n/a self.assertRaises(ValueError, Distribution,
333n/a {"name": "package",
334n/a "version": "1.0",
335n/a "obsoletes": ["my.pkg (splat)"]})
336n/a
337n/a def test_classifier(self):
338n/a attrs = {'name': 'Boa', 'version': '3.0',
339n/a 'classifiers': ['Programming Language :: Python :: 3']}
340n/a dist = Distribution(attrs)
341n/a meta = self.format_metadata(dist)
342n/a self.assertIn('Metadata-Version: 1.1', meta)
343n/a
344n/a def test_download_url(self):
345n/a attrs = {'name': 'Boa', 'version': '3.0',
346n/a 'download_url': 'http://example.org/boa'}
347n/a dist = Distribution(attrs)
348n/a meta = self.format_metadata(dist)
349n/a self.assertIn('Metadata-Version: 1.1', meta)
350n/a
351n/a def test_long_description(self):
352n/a long_desc = textwrap.dedent("""\
353n/a example::
354n/a We start here
355n/a and continue here
356n/a and end here.""")
357n/a attrs = {"name": "package",
358n/a "version": "1.0",
359n/a "long_description": long_desc}
360n/a
361n/a dist = Distribution(attrs)
362n/a meta = self.format_metadata(dist)
363n/a meta = meta.replace('\n' + 8 * ' ', '\n')
364n/a self.assertIn(long_desc, meta)
365n/a
366n/a def test_custom_pydistutils(self):
367n/a # fixes #2166
368n/a # make sure pydistutils.cfg is found
369n/a if os.name == 'posix':
370n/a user_filename = ".pydistutils.cfg"
371n/a else:
372n/a user_filename = "pydistutils.cfg"
373n/a
374n/a temp_dir = self.mkdtemp()
375n/a user_filename = os.path.join(temp_dir, user_filename)
376n/a f = open(user_filename, 'w')
377n/a try:
378n/a f.write('.')
379n/a finally:
380n/a f.close()
381n/a
382n/a try:
383n/a dist = Distribution()
384n/a
385n/a # linux-style
386n/a if sys.platform in ('linux', 'darwin'):
387n/a os.environ['HOME'] = temp_dir
388n/a files = dist.find_config_files()
389n/a self.assertIn(user_filename, files)
390n/a
391n/a # win32-style
392n/a if sys.platform == 'win32':
393n/a # home drive should be found
394n/a os.environ['HOME'] = temp_dir
395n/a files = dist.find_config_files()
396n/a self.assertIn(user_filename, files,
397n/a '%r not found in %r' % (user_filename, files))
398n/a finally:
399n/a os.remove(user_filename)
400n/a
401n/a def test_fix_help_options(self):
402n/a help_tuples = [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
403n/a fancy_options = fix_help_options(help_tuples)
404n/a self.assertEqual(fancy_options[0], ('a', 'b', 'c'))
405n/a self.assertEqual(fancy_options[1], (1, 2, 3))
406n/a
407n/a def test_show_help(self):
408n/a # smoke test, just makes sure some help is displayed
409n/a self.addCleanup(log.set_threshold, log._global_log.threshold)
410n/a dist = Distribution()
411n/a sys.argv = []
412n/a dist.help = 1
413n/a dist.script_name = 'setup.py'
414n/a with captured_stdout() as s:
415n/a dist.parse_command_line()
416n/a
417n/a output = [line for line in s.getvalue().split('\n')
418n/a if line.strip() != '']
419n/a self.assertTrue(output)
420n/a
421n/a
422n/a def test_read_metadata(self):
423n/a attrs = {"name": "package",
424n/a "version": "1.0",
425n/a "long_description": "desc",
426n/a "description": "xxx",
427n/a "download_url": "http://example.com",
428n/a "keywords": ['one', 'two'],
429n/a "requires": ['foo']}
430n/a
431n/a dist = Distribution(attrs)
432n/a metadata = dist.metadata
433n/a
434n/a # write it then reloads it
435n/a PKG_INFO = io.StringIO()
436n/a metadata.write_pkg_file(PKG_INFO)
437n/a PKG_INFO.seek(0)
438n/a metadata.read_pkg_file(PKG_INFO)
439n/a
440n/a self.assertEqual(metadata.name, "package")
441n/a self.assertEqual(metadata.version, "1.0")
442n/a self.assertEqual(metadata.description, "xxx")
443n/a self.assertEqual(metadata.download_url, 'http://example.com')
444n/a self.assertEqual(metadata.keywords, ['one', 'two'])
445n/a self.assertEqual(metadata.platforms, ['UNKNOWN'])
446n/a self.assertEqual(metadata.obsoletes, None)
447n/a self.assertEqual(metadata.requires, ['foo'])
448n/a
449n/adef test_suite():
450n/a suite = unittest.TestSuite()
451n/a suite.addTest(unittest.makeSuite(DistributionTestCase))
452n/a suite.addTest(unittest.makeSuite(MetadataTestCase))
453n/a return suite
454n/a
455n/aif __name__ == "__main__":
456n/a run_unittest(test_suite())