Home | History | Annotate | Download | only in tests
      1 # -*- coding: utf8 -*-

      2 
      3 """Tests for distutils.dist."""
      4 import os
      5 import StringIO
      6 import sys
      7 import unittest
      8 import warnings
      9 import textwrap
     10 
     11 from distutils.dist import Distribution, fix_help_options, DistributionMetadata
     12 from distutils.cmd import Command
     13 import distutils.dist
     14 from test.test_support import TESTFN, captured_stdout, run_unittest
     15 from distutils.tests import support
     16 
     17 class test_dist(Command):
     18     """Sample distutils extension command."""
     19 
     20     user_options = [
     21         ("sample-option=", "S", "help text"),
     22         ]
     23 
     24     def initialize_options(self):
     25         self.sample_option = None
     26 
     27 
     28 class TestDistribution(Distribution):
     29     """Distribution subclasses that avoids the default search for
     30     configuration files.
     31 
     32     The ._config_files attribute must be set before
     33     .parse_config_files() is called.
     34     """
     35 
     36     def find_config_files(self):
     37         return self._config_files
     38 
     39 
     40 class DistributionTestCase(support.TempdirManager,
     41                            support.LoggingSilencer,
     42                            support.EnvironGuard,
     43                            unittest.TestCase):
     44 
     45     def setUp(self):
     46         super(DistributionTestCase, self).setUp()
     47         self.argv = sys.argv, sys.argv[:]
     48         del sys.argv[1:]
     49 
     50     def tearDown(self):
     51         sys.argv = self.argv[0]
     52         sys.argv[:] = self.argv[1]
     53         super(DistributionTestCase, self).tearDown()
     54 
     55     def create_distribution(self, configfiles=()):
     56         d = TestDistribution()
     57         d._config_files = configfiles
     58         d.parse_config_files()
     59         d.parse_command_line()
     60         return d
     61 
     62     def test_debug_mode(self):
     63         with open(TESTFN, "w") as f:
     64             f.write("[global]")
     65             f.write("command_packages = foo.bar, splat")
     66 
     67         files = [TESTFN]
     68         sys.argv.append("build")
     69 
     70         with captured_stdout() as stdout:
     71             self.create_distribution(files)
     72         stdout.seek(0)
     73         self.assertEqual(stdout.read(), '')
     74         distutils.dist.DEBUG = True
     75         try:
     76             with captured_stdout() as stdout:
     77                 self.create_distribution(files)
     78             stdout.seek(0)
     79             self.assertEqual(stdout.read(), '')
     80         finally:
     81             distutils.dist.DEBUG = False
     82 
     83     def test_command_packages_unspecified(self):
     84         sys.argv.append("build")
     85         d = self.create_distribution()
     86         self.assertEqual(d.get_command_packages(), ["distutils.command"])
     87 
     88     def test_command_packages_cmdline(self):
     89         from distutils.tests.test_dist import test_dist
     90         sys.argv.extend(["--command-packages",
     91                          "foo.bar,distutils.tests",
     92                          "test_dist",
     93                          "-Ssometext",
     94                          ])
     95         d = self.create_distribution()
     96         # let's actually try to load our test command:

     97         self.assertEqual(d.get_command_packages(),
     98                          ["distutils.command", "foo.bar", "distutils.tests"])
     99         cmd = d.get_command_obj("test_dist")
    100         self.assertTrue(isinstance(cmd, test_dist))
    101         self.assertEqual(cmd.sample_option, "sometext")
    102 
    103     def test_command_packages_configfile(self):
    104         sys.argv.append("build")
    105         self.addCleanup(os.unlink, TESTFN)
    106         f = open(TESTFN, "w")
    107         try:
    108             print >>f, "[global]"
    109             print >>f, "command_packages = foo.bar, splat"
    110         finally:
    111             f.close()
    112 
    113         d = self.create_distribution([TESTFN])
    114         self.assertEqual(d.get_command_packages(),
    115                          ["distutils.command", "foo.bar", "splat"])
    116 
    117         # ensure command line overrides config:

    118         sys.argv[1:] = ["--command-packages", "spork", "build"]
    119         d = self.create_distribution([TESTFN])
    120         self.assertEqual(d.get_command_packages(),
    121                          ["distutils.command", "spork"])
    122 
    123         # Setting --command-packages to '' should cause the default to

    124         # be used even if a config file specified something else:

    125         sys.argv[1:] = ["--command-packages", "", "build"]
    126         d = self.create_distribution([TESTFN])
    127         self.assertEqual(d.get_command_packages(), ["distutils.command"])
    128 
    129     def test_write_pkg_file(self):
    130         # Check DistributionMetadata handling of Unicode fields

    131         tmp_dir = self.mkdtemp()
    132         my_file = os.path.join(tmp_dir, 'f')
    133         klass = Distribution
    134 
    135         dist = klass(attrs={'author': u'Mister Caf',
    136                             'name': 'my.package',
    137                             'maintainer': u'Caf Junior',
    138                             'description': u'Caf torrfi',
    139                             'long_description': u'Hhh'})
    140 
    141 
    142         # let's make sure the file can be written

    143         # with Unicode fields. they are encoded with

    144         # PKG_INFO_ENCODING

    145         dist.metadata.write_pkg_file(open(my_file, 'w'))
    146 
    147         # regular ascii is of course always usable

    148         dist = klass(attrs={'author': 'Mister Cafe',
    149                             'name': 'my.package',
    150                             'maintainer': 'Cafe Junior',
    151                             'description': 'Cafe torrefie',
    152                             'long_description': 'Hehehe'})
    153 
    154         my_file2 = os.path.join(tmp_dir, 'f2')
    155         dist.metadata.write_pkg_file(open(my_file, 'w'))
    156 
    157     def test_empty_options(self):
    158         # an empty options dictionary should not stay in the

    159         # list of attributes

    160         klass = Distribution
    161 
    162         # catching warnings

    163         warns = []
    164         def _warn(msg):
    165             warns.append(msg)
    166 
    167         old_warn = warnings.warn
    168         warnings.warn = _warn
    169         try:
    170             dist = klass(attrs={'author': 'xxx',
    171                                 'name': 'xxx',
    172                                 'version': 'xxx',
    173                                 'url': 'xxxx',
    174                                 'options': {}})
    175         finally:
    176             warnings.warn = old_warn
    177 
    178         self.assertEqual(len(warns), 0)
    179 
    180     def test_finalize_options(self):
    181 
    182         attrs = {'keywords': 'one,two',
    183                  'platforms': 'one,two'}
    184 
    185         dist = Distribution(attrs=attrs)
    186         dist.finalize_options()
    187 
    188         # finalize_option splits platforms and keywords

    189         self.assertEqual(dist.metadata.platforms, ['one', 'two'])
    190         self.assertEqual(dist.metadata.keywords, ['one', 'two'])
    191 
    192     def test_get_command_packages(self):
    193         dist = Distribution()
    194         self.assertEqual(dist.command_packages, None)
    195         cmds = dist.get_command_packages()
    196         self.assertEqual(cmds, ['distutils.command'])
    197         self.assertEqual(dist.command_packages,
    198                          ['distutils.command'])
    199 
    200         dist.command_packages = 'one,two'
    201         cmds = dist.get_command_packages()
    202         self.assertEqual(cmds, ['distutils.command', 'one', 'two'])
    203 
    204 
    205     def test_announce(self):
    206         # make sure the level is known

    207         dist = Distribution()
    208         args = ('ok',)
    209         kwargs = {'level': 'ok2'}
    210         self.assertRaises(ValueError, dist.announce, args, kwargs)
    211 
    212     def test_find_config_files_disable(self):
    213         # Ticket #1180: Allow user to disable their home config file.

    214         temp_home = self.mkdtemp()
    215         if os.name == 'posix':
    216             user_filename = os.path.join(temp_home, ".pydistutils.cfg")
    217         else:
    218             user_filename = os.path.join(temp_home, "pydistutils.cfg")
    219 
    220         with open(user_filename, 'w') as f:
    221             f.write('[distutils]\n')
    222 
    223         def _expander(path):
    224             return temp_home
    225 
    226         old_expander = os.path.expanduser
    227         os.path.expanduser = _expander
    228         try:
    229             d = distutils.dist.Distribution()
    230             all_files = d.find_config_files()
    231 
    232             d = distutils.dist.Distribution(attrs={'script_args':
    233                                             ['--no-user-cfg']})
    234             files = d.find_config_files()
    235         finally:
    236             os.path.expanduser = old_expander
    237 
    238         # make sure --no-user-cfg disables the user cfg file

    239         self.assertEqual(len(all_files)-1, len(files))
    240 
    241 
    242 class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
    243                        unittest.TestCase):
    244 
    245     def setUp(self):
    246         super(MetadataTestCase, self).setUp()
    247         self.argv = sys.argv, sys.argv[:]
    248 
    249     def tearDown(self):
    250         sys.argv = self.argv[0]
    251         sys.argv[:] = self.argv[1]
    252         super(MetadataTestCase, self).tearDown()
    253 
    254     def test_simple_metadata(self):
    255         attrs = {"name": "package",
    256                  "version": "1.0"}
    257         dist = Distribution(attrs)
    258         meta = self.format_metadata(dist)
    259         self.assertTrue("Metadata-Version: 1.0" in meta)
    260         self.assertTrue("provides:" not in meta.lower())
    261         self.assertTrue("requires:" not in meta.lower())
    262         self.assertTrue("obsoletes:" not in meta.lower())
    263 
    264     def test_provides(self):
    265         attrs = {"name": "package",
    266                  "version": "1.0",
    267                  "provides": ["package", "package.sub"]}
    268         dist = Distribution(attrs)
    269         self.assertEqual(dist.metadata.get_provides(),
    270                          ["package", "package.sub"])
    271         self.assertEqual(dist.get_provides(),
    272                          ["package", "package.sub"])
    273         meta = self.format_metadata(dist)
    274         self.assertTrue("Metadata-Version: 1.1" in meta)
    275         self.assertTrue("requires:" not in meta.lower())
    276         self.assertTrue("obsoletes:" not in meta.lower())
    277 
    278     def test_provides_illegal(self):
    279         self.assertRaises(ValueError, Distribution,
    280                           {"name": "package",
    281                            "version": "1.0",
    282                            "provides": ["my.pkg (splat)"]})
    283 
    284     def test_requires(self):
    285         attrs = {"name": "package",
    286                  "version": "1.0",
    287                  "requires": ["other", "another (==1.0)"]}
    288         dist = Distribution(attrs)
    289         self.assertEqual(dist.metadata.get_requires(),
    290                          ["other", "another (==1.0)"])
    291         self.assertEqual(dist.get_requires(),
    292                          ["other", "another (==1.0)"])
    293         meta = self.format_metadata(dist)
    294         self.assertTrue("Metadata-Version: 1.1" in meta)
    295         self.assertTrue("provides:" not in meta.lower())
    296         self.assertTrue("Requires: other" in meta)
    297         self.assertTrue("Requires: another (==1.0)" in meta)
    298         self.assertTrue("obsoletes:" not in meta.lower())
    299 
    300     def test_requires_illegal(self):
    301         self.assertRaises(ValueError, Distribution,
    302                           {"name": "package",
    303                            "version": "1.0",
    304                            "requires": ["my.pkg (splat)"]})
    305 
    306     def test_obsoletes(self):
    307         attrs = {"name": "package",
    308                  "version": "1.0",
    309                  "obsoletes": ["other", "another (<1.0)"]}
    310         dist = Distribution(attrs)
    311         self.assertEqual(dist.metadata.get_obsoletes(),
    312                          ["other", "another (<1.0)"])
    313         self.assertEqual(dist.get_obsoletes(),
    314                          ["other", "another (<1.0)"])
    315         meta = self.format_metadata(dist)
    316         self.assertTrue("Metadata-Version: 1.1" in meta)
    317         self.assertTrue("provides:" not in meta.lower())
    318         self.assertTrue("requires:" not in meta.lower())
    319         self.assertTrue("Obsoletes: other" in meta)
    320         self.assertTrue("Obsoletes: another (<1.0)" in meta)
    321 
    322     def test_obsoletes_illegal(self):
    323         self.assertRaises(ValueError, Distribution,
    324                           {"name": "package",
    325                            "version": "1.0",
    326                            "obsoletes": ["my.pkg (splat)"]})
    327 
    328     def format_metadata(self, dist):
    329         sio = StringIO.StringIO()
    330         dist.metadata.write_pkg_file(sio)
    331         return sio.getvalue()
    332 
    333     def test_custom_pydistutils(self):
    334         # fixes #2166

    335         # make sure pydistutils.cfg is found

    336         if os.name == 'posix':
    337             user_filename = ".pydistutils.cfg"
    338         else:
    339             user_filename = "pydistutils.cfg"
    340 
    341         temp_dir = self.mkdtemp()
    342         user_filename = os.path.join(temp_dir, user_filename)
    343         f = open(user_filename, 'w')
    344         try:
    345             f.write('.')
    346         finally:
    347             f.close()
    348 
    349         try:
    350             dist = Distribution()
    351 
    352             # linux-style

    353             if sys.platform in ('linux', 'darwin'):
    354                 os.environ['HOME'] = temp_dir
    355                 files = dist.find_config_files()
    356                 self.assertTrue(user_filename in files)
    357 
    358             # win32-style

    359             if sys.platform == 'win32':
    360                 # home drive should be found

    361                 os.environ['HOME'] = temp_dir
    362                 files = dist.find_config_files()
    363                 self.assertTrue(user_filename in files,
    364                              '%r not found in %r' % (user_filename, files))
    365         finally:
    366             os.remove(user_filename)
    367 
    368     def test_fix_help_options(self):
    369         help_tuples = [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
    370         fancy_options = fix_help_options(help_tuples)
    371         self.assertEqual(fancy_options[0], ('a', 'b', 'c'))
    372         self.assertEqual(fancy_options[1], (1, 2, 3))
    373 
    374     def test_show_help(self):
    375         # smoke test, just makes sure some help is displayed

    376         dist = Distribution()
    377         sys.argv = []
    378         dist.help = 1
    379         dist.script_name = 'setup.py'
    380         with captured_stdout() as s:
    381             dist.parse_command_line()
    382 
    383         output = [line for line in s.getvalue().split('\n')
    384                   if line.strip() != '']
    385         self.assertTrue(len(output) > 0)
    386 
    387     def test_long_description(self):
    388         long_desc = textwrap.dedent("""\
    389         example::
    390               We start here
    391             and continue here
    392           and end here.""")
    393         attrs = {"name": "package",
    394                  "version": "1.0",
    395                  "long_description": long_desc}
    396 
    397         dist = distutils.dist.Distribution(attrs)
    398         meta = self.format_metadata(dist)
    399         meta = meta.replace('\n' + 8 * ' ', '\n')
    400         self.assertTrue(long_desc in meta)
    401 
    402     def test_read_metadata(self):
    403         attrs = {"name": "package",
    404                  "version": "1.0",
    405                  "long_description": "desc",
    406                  "description": "xxx",
    407                  "download_url": "http://example.com",
    408                  "keywords": ['one', 'two'],
    409                  "requires": ['foo']}
    410 
    411         dist = Distribution(attrs)
    412         metadata = dist.metadata
    413 
    414         # write it then reloads it

    415         PKG_INFO = StringIO.StringIO()
    416         metadata.write_pkg_file(PKG_INFO)
    417         PKG_INFO.seek(0)
    418         metadata.read_pkg_file(PKG_INFO)
    419 
    420         self.assertEqual(metadata.name, "package")
    421         self.assertEqual(metadata.version, "1.0")
    422         self.assertEqual(metadata.description, "xxx")
    423         self.assertEqual(metadata.download_url, 'http://example.com')
    424         self.assertEqual(metadata.keywords, ['one', 'two'])
    425         self.assertEqual(metadata.platforms, ['UNKNOWN'])
    426         self.assertEqual(metadata.obsoletes, None)
    427         self.assertEqual(metadata.requires, ['foo'])
    428 
    429 def test_suite():
    430     suite = unittest.TestSuite()
    431     suite.addTest(unittest.makeSuite(DistributionTestCase))
    432     suite.addTest(unittest.makeSuite(MetadataTestCase))
    433     return suite
    434 
    435 if __name__ == "__main__":
    436     run_unittest(test_suite())
    437