123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528 |
- """Tests for distutils.dist."""
- import os
- import io
- import sys
- import unittest
- import warnings
- import textwrap
- from unittest import mock
- from distutils.dist import Distribution, fix_help_options
- from distutils.cmd import Command
- from test.support import (
- TESTFN, captured_stdout, captured_stderr, run_unittest
- )
- from distutils.tests import support
- from distutils import log
- class test_dist(Command):
- """Sample distutils extension command."""
- user_options = [
- ("sample-option=", "S", "help text"),
- ]
- def initialize_options(self):
- self.sample_option = None
- class TestDistribution(Distribution):
- """Distribution subclasses that avoids the default search for
- configuration files.
- The ._config_files attribute must be set before
- .parse_config_files() is called.
- """
- def find_config_files(self):
- return self._config_files
- class DistributionTestCase(support.LoggingSilencer,
- support.TempdirManager,
- support.EnvironGuard,
- unittest.TestCase):
- def setUp(self):
- super(DistributionTestCase, self).setUp()
- self.argv = sys.argv, sys.argv[:]
- del sys.argv[1:]
- def tearDown(self):
- sys.argv = self.argv[0]
- sys.argv[:] = self.argv[1]
- super(DistributionTestCase, self).tearDown()
- def create_distribution(self, configfiles=()):
- d = TestDistribution()
- d._config_files = configfiles
- d.parse_config_files()
- d.parse_command_line()
- return d
- def test_command_packages_unspecified(self):
- sys.argv.append("build")
- d = self.create_distribution()
- self.assertEqual(d.get_command_packages(), ["distutils.command"])
- def test_command_packages_cmdline(self):
- from distutils.tests.test_dist import test_dist
- sys.argv.extend(["--command-packages",
- "foo.bar,distutils.tests",
- "test_dist",
- "-Ssometext",
- ])
- d = self.create_distribution()
- # let's actually try to load our test command:
- self.assertEqual(d.get_command_packages(),
- ["distutils.command", "foo.bar", "distutils.tests"])
- cmd = d.get_command_obj("test_dist")
- self.assertIsInstance(cmd, test_dist)
- self.assertEqual(cmd.sample_option, "sometext")
- def test_venv_install_options(self):
- sys.argv.append("install")
- self.addCleanup(os.unlink, TESTFN)
- fakepath = '/somedir'
- with open(TESTFN, "w") as f:
- print(("[install]\n"
- "install-base = {0}\n"
- "install-platbase = {0}\n"
- "install-lib = {0}\n"
- "install-platlib = {0}\n"
- "install-purelib = {0}\n"
- "install-headers = {0}\n"
- "install-scripts = {0}\n"
- "install-data = {0}\n"
- "prefix = {0}\n"
- "exec-prefix = {0}\n"
- "home = {0}\n"
- "user = {0}\n"
- "root = {0}").format(fakepath), file=f)
- # Base case: Not in a Virtual Environment
- with mock.patch.multiple(sys, prefix='/a', base_prefix='/a') as values:
- d = self.create_distribution([TESTFN])
- option_tuple = (TESTFN, fakepath)
- result_dict = {
- 'install_base': option_tuple,
- 'install_platbase': option_tuple,
- 'install_lib': option_tuple,
- 'install_platlib': option_tuple,
- 'install_purelib': option_tuple,
- 'install_headers': option_tuple,
- 'install_scripts': option_tuple,
- 'install_data': option_tuple,
- 'prefix': option_tuple,
- 'exec_prefix': option_tuple,
- 'home': option_tuple,
- 'user': option_tuple,
- 'root': option_tuple,
- }
- self.assertEqual(
- sorted(d.command_options.get('install').keys()),
- sorted(result_dict.keys()))
- for (key, value) in d.command_options.get('install').items():
- self.assertEqual(value, result_dict[key])
- # Test case: In a Virtual Environment
- with mock.patch.multiple(sys, prefix='/a', base_prefix='/b') as values:
- d = self.create_distribution([TESTFN])
- for key in result_dict.keys():
- self.assertNotIn(key, d.command_options.get('install', {}))
- def test_command_packages_configfile(self):
- sys.argv.append("build")
- self.addCleanup(os.unlink, TESTFN)
- f = open(TESTFN, "w")
- try:
- print("[global]", file=f)
- print("command_packages = foo.bar, splat", file=f)
- finally:
- f.close()
- d = self.create_distribution([TESTFN])
- self.assertEqual(d.get_command_packages(),
- ["distutils.command", "foo.bar", "splat"])
- # ensure command line overrides config:
- sys.argv[1:] = ["--command-packages", "spork", "build"]
- d = self.create_distribution([TESTFN])
- self.assertEqual(d.get_command_packages(),
- ["distutils.command", "spork"])
- # Setting --command-packages to '' should cause the default to
- # be used even if a config file specified something else:
- sys.argv[1:] = ["--command-packages", "", "build"]
- d = self.create_distribution([TESTFN])
- self.assertEqual(d.get_command_packages(), ["distutils.command"])
- def test_empty_options(self):
- # an empty options dictionary should not stay in the
- # list of attributes
- # catching warnings
- warns = []
- def _warn(msg):
- warns.append(msg)
- self.addCleanup(setattr, warnings, 'warn', warnings.warn)
- warnings.warn = _warn
- dist = Distribution(attrs={'author': 'xxx', 'name': 'xxx',
- 'version': 'xxx', 'url': 'xxxx',
- 'options': {}})
- self.assertEqual(len(warns), 0)
- self.assertNotIn('options', dir(dist))
- def test_finalize_options(self):
- attrs = {'keywords': 'one,two',
- 'platforms': 'one,two'}
- dist = Distribution(attrs=attrs)
- dist.finalize_options()
- # finalize_option splits platforms and keywords
- self.assertEqual(dist.metadata.platforms, ['one', 'two'])
- self.assertEqual(dist.metadata.keywords, ['one', 'two'])
- attrs = {'keywords': 'foo bar',
- 'platforms': 'foo bar'}
- dist = Distribution(attrs=attrs)
- dist.finalize_options()
- self.assertEqual(dist.metadata.platforms, ['foo bar'])
- self.assertEqual(dist.metadata.keywords, ['foo bar'])
- def test_get_command_packages(self):
- dist = Distribution()
- self.assertEqual(dist.command_packages, None)
- cmds = dist.get_command_packages()
- self.assertEqual(cmds, ['distutils.command'])
- self.assertEqual(dist.command_packages,
- ['distutils.command'])
- dist.command_packages = 'one,two'
- cmds = dist.get_command_packages()
- self.assertEqual(cmds, ['distutils.command', 'one', 'two'])
- def test_announce(self):
- # make sure the level is known
- dist = Distribution()
- args = ('ok',)
- kwargs = {'level': 'ok2'}
- self.assertRaises(ValueError, dist.announce, args, kwargs)
- def test_find_config_files_disable(self):
- # Ticket #1180: Allow user to disable their home config file.
- temp_home = self.mkdtemp()
- if os.name == 'posix':
- user_filename = os.path.join(temp_home, ".pydistutils.cfg")
- else:
- user_filename = os.path.join(temp_home, "pydistutils.cfg")
- with open(user_filename, 'w') as f:
- f.write('[distutils]\n')
- def _expander(path):
- return temp_home
- old_expander = os.path.expanduser
- os.path.expanduser = _expander
- try:
- d = Distribution()
- all_files = d.find_config_files()
- d = Distribution(attrs={'script_args': ['--no-user-cfg']})
- files = d.find_config_files()
- finally:
- os.path.expanduser = old_expander
- # make sure --no-user-cfg disables the user cfg file
- self.assertEqual(len(all_files)-1, len(files))
- class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
- unittest.TestCase):
- def setUp(self):
- super(MetadataTestCase, self).setUp()
- self.argv = sys.argv, sys.argv[:]
- def tearDown(self):
- sys.argv = self.argv[0]
- sys.argv[:] = self.argv[1]
- super(MetadataTestCase, self).tearDown()
- def format_metadata(self, dist):
- sio = io.StringIO()
- dist.metadata.write_pkg_file(sio)
- return sio.getvalue()
- def test_simple_metadata(self):
- attrs = {"name": "package",
- "version": "1.0"}
- dist = Distribution(attrs)
- meta = self.format_metadata(dist)
- self.assertIn("Metadata-Version: 1.0", meta)
- self.assertNotIn("provides:", meta.lower())
- self.assertNotIn("requires:", meta.lower())
- self.assertNotIn("obsoletes:", meta.lower())
- def test_provides(self):
- attrs = {"name": "package",
- "version": "1.0",
- "provides": ["package", "package.sub"]}
- dist = Distribution(attrs)
- self.assertEqual(dist.metadata.get_provides(),
- ["package", "package.sub"])
- self.assertEqual(dist.get_provides(),
- ["package", "package.sub"])
- meta = self.format_metadata(dist)
- self.assertIn("Metadata-Version: 1.1", meta)
- self.assertNotIn("requires:", meta.lower())
- self.assertNotIn("obsoletes:", meta.lower())
- def test_provides_illegal(self):
- self.assertRaises(ValueError, Distribution,
- {"name": "package",
- "version": "1.0",
- "provides": ["my.pkg (splat)"]})
- def test_requires(self):
- attrs = {"name": "package",
- "version": "1.0",
- "requires": ["other", "another (==1.0)"]}
- dist = Distribution(attrs)
- self.assertEqual(dist.metadata.get_requires(),
- ["other", "another (==1.0)"])
- self.assertEqual(dist.get_requires(),
- ["other", "another (==1.0)"])
- meta = self.format_metadata(dist)
- self.assertIn("Metadata-Version: 1.1", meta)
- self.assertNotIn("provides:", meta.lower())
- self.assertIn("Requires: other", meta)
- self.assertIn("Requires: another (==1.0)", meta)
- self.assertNotIn("obsoletes:", meta.lower())
- def test_requires_illegal(self):
- self.assertRaises(ValueError, Distribution,
- {"name": "package",
- "version": "1.0",
- "requires": ["my.pkg (splat)"]})
- def test_requires_to_list(self):
- attrs = {"name": "package",
- "requires": iter(["other"])}
- dist = Distribution(attrs)
- self.assertIsInstance(dist.metadata.requires, list)
- def test_obsoletes(self):
- attrs = {"name": "package",
- "version": "1.0",
- "obsoletes": ["other", "another (<1.0)"]}
- dist = Distribution(attrs)
- self.assertEqual(dist.metadata.get_obsoletes(),
- ["other", "another (<1.0)"])
- self.assertEqual(dist.get_obsoletes(),
- ["other", "another (<1.0)"])
- meta = self.format_metadata(dist)
- self.assertIn("Metadata-Version: 1.1", meta)
- self.assertNotIn("provides:", meta.lower())
- self.assertNotIn("requires:", meta.lower())
- self.assertIn("Obsoletes: other", meta)
- self.assertIn("Obsoletes: another (<1.0)", meta)
- def test_obsoletes_illegal(self):
- self.assertRaises(ValueError, Distribution,
- {"name": "package",
- "version": "1.0",
- "obsoletes": ["my.pkg (splat)"]})
- def test_obsoletes_to_list(self):
- attrs = {"name": "package",
- "obsoletes": iter(["other"])}
- dist = Distribution(attrs)
- self.assertIsInstance(dist.metadata.obsoletes, list)
- def test_classifier(self):
- attrs = {'name': 'Boa', 'version': '3.0',
- 'classifiers': ['Programming Language :: Python :: 3']}
- dist = Distribution(attrs)
- self.assertEqual(dist.get_classifiers(),
- ['Programming Language :: Python :: 3'])
- meta = self.format_metadata(dist)
- self.assertIn('Metadata-Version: 1.1', meta)
- def test_classifier_invalid_type(self):
- attrs = {'name': 'Boa', 'version': '3.0',
- 'classifiers': ('Programming Language :: Python :: 3',)}
- with captured_stderr() as error:
- d = Distribution(attrs)
- # should have warning about passing a non-list
- self.assertIn('should be a list', error.getvalue())
- # should be converted to a list
- self.assertIsInstance(d.metadata.classifiers, list)
- self.assertEqual(d.metadata.classifiers,
- list(attrs['classifiers']))
- def test_keywords(self):
- attrs = {'name': 'Monty', 'version': '1.0',
- 'keywords': ['spam', 'eggs', 'life of brian']}
- dist = Distribution(attrs)
- self.assertEqual(dist.get_keywords(),
- ['spam', 'eggs', 'life of brian'])
- def test_keywords_invalid_type(self):
- attrs = {'name': 'Monty', 'version': '1.0',
- 'keywords': ('spam', 'eggs', 'life of brian')}
- with captured_stderr() as error:
- d = Distribution(attrs)
- # should have warning about passing a non-list
- self.assertIn('should be a list', error.getvalue())
- # should be converted to a list
- self.assertIsInstance(d.metadata.keywords, list)
- self.assertEqual(d.metadata.keywords, list(attrs['keywords']))
- def test_platforms(self):
- attrs = {'name': 'Monty', 'version': '1.0',
- 'platforms': ['GNU/Linux', 'Some Evil Platform']}
- dist = Distribution(attrs)
- self.assertEqual(dist.get_platforms(),
- ['GNU/Linux', 'Some Evil Platform'])
- def test_platforms_invalid_types(self):
- attrs = {'name': 'Monty', 'version': '1.0',
- 'platforms': ('GNU/Linux', 'Some Evil Platform')}
- with captured_stderr() as error:
- d = Distribution(attrs)
- # should have warning about passing a non-list
- self.assertIn('should be a list', error.getvalue())
- # should be converted to a list
- self.assertIsInstance(d.metadata.platforms, list)
- self.assertEqual(d.metadata.platforms, list(attrs['platforms']))
- def test_download_url(self):
- attrs = {'name': 'Boa', 'version': '3.0',
- 'download_url': 'http://example.org/boa'}
- dist = Distribution(attrs)
- meta = self.format_metadata(dist)
- self.assertIn('Metadata-Version: 1.1', meta)
- def test_long_description(self):
- long_desc = textwrap.dedent("""\
- example::
- We start here
- and continue here
- and end here.""")
- attrs = {"name": "package",
- "version": "1.0",
- "long_description": long_desc}
- dist = Distribution(attrs)
- meta = self.format_metadata(dist)
- meta = meta.replace('\n' + 8 * ' ', '\n')
- self.assertIn(long_desc, meta)
- def test_custom_pydistutils(self):
- # fixes #2166
- # make sure pydistutils.cfg is found
- if os.name == 'posix':
- user_filename = ".pydistutils.cfg"
- else:
- user_filename = "pydistutils.cfg"
- temp_dir = self.mkdtemp()
- user_filename = os.path.join(temp_dir, user_filename)
- f = open(user_filename, 'w')
- try:
- f.write('.')
- finally:
- f.close()
- try:
- dist = Distribution()
- # linux-style
- if sys.platform in ('linux', 'darwin'):
- os.environ['HOME'] = temp_dir
- files = dist.find_config_files()
- self.assertIn(user_filename, files)
- # win32-style
- if sys.platform == 'win32':
- # home drive should be found
- os.environ['USERPROFILE'] = temp_dir
- files = dist.find_config_files()
- self.assertIn(user_filename, files,
- '%r not found in %r' % (user_filename, files))
- finally:
- os.remove(user_filename)
- def test_fix_help_options(self):
- help_tuples = [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
- fancy_options = fix_help_options(help_tuples)
- self.assertEqual(fancy_options[0], ('a', 'b', 'c'))
- self.assertEqual(fancy_options[1], (1, 2, 3))
- def test_show_help(self):
- # smoke test, just makes sure some help is displayed
- self.addCleanup(log.set_threshold, log._global_log.threshold)
- dist = Distribution()
- sys.argv = []
- dist.help = 1
- dist.script_name = 'setup.py'
- with captured_stdout() as s:
- dist.parse_command_line()
- output = [line for line in s.getvalue().split('\n')
- if line.strip() != '']
- self.assertTrue(output)
- def test_read_metadata(self):
- attrs = {"name": "package",
- "version": "1.0",
- "long_description": "desc",
- "description": "xxx",
- "download_url": "http://example.com",
- "keywords": ['one', 'two'],
- "requires": ['foo']}
- dist = Distribution(attrs)
- metadata = dist.metadata
- # write it then reloads it
- PKG_INFO = io.StringIO()
- metadata.write_pkg_file(PKG_INFO)
- PKG_INFO.seek(0)
- metadata.read_pkg_file(PKG_INFO)
- self.assertEqual(metadata.name, "package")
- self.assertEqual(metadata.version, "1.0")
- self.assertEqual(metadata.description, "xxx")
- self.assertEqual(metadata.download_url, 'http://example.com')
- self.assertEqual(metadata.keywords, ['one', 'two'])
- self.assertEqual(metadata.platforms, ['UNKNOWN'])
- self.assertEqual(metadata.obsoletes, None)
- self.assertEqual(metadata.requires, ['foo'])
- def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(DistributionTestCase))
- suite.addTest(unittest.makeSuite(MetadataTestCase))
- return suite
- if __name__ == "__main__":
- run_unittest(test_suite())
|