test_dist.py revision 4f38317d5a5665aef199fd30870d14f3cc48ba9c
1# -*- coding: utf8 -*- 2 3"""Tests for distutils.dist.""" 4import os 5import StringIO 6import sys 7import unittest 8import warnings 9import textwrap 10 11from distutils.dist import Distribution, fix_help_options 12from distutils.cmd import Command 13import distutils.dist 14 15from test.test_support import TESTFN, captured_stdout 16from distutils.tests import support 17 18class test_dist(Command): 19 """Sample distutils extension command.""" 20 21 user_options = [ 22 ("sample-option=", "S", "help text"), 23 ] 24 25 def initialize_options(self): 26 self.sample_option = None 27 28 29class TestDistribution(Distribution): 30 """Distribution subclasses that avoids the default search for 31 configuration files. 32 33 The ._config_files attribute must be set before 34 .parse_config_files() is called. 35 """ 36 37 def find_config_files(self): 38 return self._config_files 39 40 41class DistributionTestCase(support.TempdirManager, 42 support.LoggingSilencer, 43 support.EnvironGuard, 44 unittest.TestCase): 45 46 def setUp(self): 47 super(DistributionTestCase, self).setUp() 48 self.argv = sys.argv, sys.argv[:] 49 del sys.argv[1:] 50 51 def tearDown(self): 52 sys.argv = self.argv[0] 53 sys.argv[:] = self.argv[1] 54 super(DistributionTestCase, self).tearDown() 55 56 def create_distribution(self, configfiles=()): 57 d = TestDistribution() 58 d._config_files = configfiles 59 d.parse_config_files() 60 d.parse_command_line() 61 return d 62 63 def test_debug_mode(self): 64 with open(TESTFN, "w") as f: 65 f.write("[global]") 66 f.write("command_packages = foo.bar, splat") 67 68 files = [TESTFN] 69 sys.argv.append("build") 70 71 with captured_stdout() as stdout: 72 self.create_distribution(files) 73 stdout.seek(0) 74 self.assertEquals(stdout.read(), '') 75 distutils.dist.DEBUG = True 76 try: 77 with captured_stdout() as stdout: 78 self.create_distribution(files) 79 stdout.seek(0) 80 self.assertEquals(stdout.read(), '') 81 finally: 82 distutils.dist.DEBUG = False 83 84 def test_command_packages_unspecified(self): 85 sys.argv.append("build") 86 d = self.create_distribution() 87 self.assertEqual(d.get_command_packages(), ["distutils.command"]) 88 89 def test_command_packages_cmdline(self): 90 from distutils.tests.test_dist import test_dist 91 sys.argv.extend(["--command-packages", 92 "foo.bar,distutils.tests", 93 "test_dist", 94 "-Ssometext", 95 ]) 96 d = self.create_distribution() 97 # let's actually try to load our test command: 98 self.assertEqual(d.get_command_packages(), 99 ["distutils.command", "foo.bar", "distutils.tests"]) 100 cmd = d.get_command_obj("test_dist") 101 self.assertTrue(isinstance(cmd, test_dist)) 102 self.assertEqual(cmd.sample_option, "sometext") 103 104 def test_command_packages_configfile(self): 105 sys.argv.append("build") 106 f = open(TESTFN, "w") 107 try: 108 print >>f, "[global]" 109 print >>f, "command_packages = foo.bar, splat" 110 f.close() 111 d = self.create_distribution([TESTFN]) 112 self.assertEqual(d.get_command_packages(), 113 ["distutils.command", "foo.bar", "splat"]) 114 115 # ensure command line overrides config: 116 sys.argv[1:] = ["--command-packages", "spork", "build"] 117 d = self.create_distribution([TESTFN]) 118 self.assertEqual(d.get_command_packages(), 119 ["distutils.command", "spork"]) 120 121 # Setting --command-packages to '' should cause the default to 122 # be used even if a config file specified something else: 123 sys.argv[1:] = ["--command-packages", "", "build"] 124 d = self.create_distribution([TESTFN]) 125 self.assertEqual(d.get_command_packages(), ["distutils.command"]) 126 127 finally: 128 os.unlink(TESTFN) 129 130 def test_write_pkg_file(self): 131 # Check DistributionMetadata handling of Unicode fields 132 tmp_dir = self.mkdtemp() 133 my_file = os.path.join(tmp_dir, 'f') 134 klass = Distribution 135 136 dist = klass(attrs={'author': u'Mister Café', 137 'name': 'my.package', 138 'maintainer': u'Café Junior', 139 'description': u'Café torréfié', 140 'long_description': u'Héhéhé'}) 141 142 143 # let's make sure the file can be written 144 # with Unicode fields. they are encoded with 145 # PKG_INFO_ENCODING 146 dist.metadata.write_pkg_file(open(my_file, 'w')) 147 148 # regular ascii is of course always usable 149 dist = klass(attrs={'author': 'Mister Cafe', 150 'name': 'my.package', 151 'maintainer': 'Cafe Junior', 152 'description': 'Cafe torrefie', 153 'long_description': 'Hehehe'}) 154 155 my_file2 = os.path.join(tmp_dir, 'f2') 156 dist.metadata.write_pkg_file(open(my_file, 'w')) 157 158 def test_empty_options(self): 159 # an empty options dictionary should not stay in the 160 # list of attributes 161 klass = Distribution 162 163 # catching warnings 164 warns = [] 165 def _warn(msg): 166 warns.append(msg) 167 168 old_warn = warnings.warn 169 warnings.warn = _warn 170 try: 171 dist = klass(attrs={'author': 'xxx', 172 'name': 'xxx', 173 'version': 'xxx', 174 'url': 'xxxx', 175 'options': {}}) 176 finally: 177 warnings.warn = old_warn 178 179 self.assertEquals(len(warns), 0) 180 181 def test_finalize_options(self): 182 183 attrs = {'keywords': 'one,two', 184 'platforms': 'one,two'} 185 186 dist = Distribution(attrs=attrs) 187 dist.finalize_options() 188 189 # finalize_option splits platforms and keywords 190 self.assertEquals(dist.metadata.platforms, ['one', 'two']) 191 self.assertEquals(dist.metadata.keywords, ['one', 'two']) 192 193 def test_get_command_packages(self): 194 dist = Distribution() 195 self.assertEquals(dist.command_packages, None) 196 cmds = dist.get_command_packages() 197 self.assertEquals(cmds, ['distutils.command']) 198 self.assertEquals(dist.command_packages, 199 ['distutils.command']) 200 201 dist.command_packages = 'one,two' 202 cmds = dist.get_command_packages() 203 self.assertEquals(cmds, ['distutils.command', 'one', 'two']) 204 205 206 def test_announce(self): 207 # make sure the level is known 208 dist = Distribution() 209 args = ('ok',) 210 kwargs = {'level': 'ok2'} 211 self.assertRaises(ValueError, dist.announce, args, kwargs) 212 213 def test_find_config_files_disable(self): 214 # Ticket #1180: Allow user to disable their home config file. 215 temp_home = self.mkdtemp() 216 if os.name == 'posix': 217 user_filename = os.path.join(temp_home, ".pydistutils.cfg") 218 else: 219 user_filename = os.path.join(temp_home, "pydistutils.cfg") 220 221 with open(user_filename, 'w') as f: 222 f.write('[distutils]\n') 223 224 def _expander(path): 225 return temp_home 226 227 old_expander = os.path.expanduser 228 os.path.expanduser = _expander 229 try: 230 d = distutils.dist.Distribution() 231 all_files = d.find_config_files() 232 233 d = distutils.dist.Distribution(attrs={'script_args': 234 ['--no-user-cfg']}) 235 files = d.find_config_files() 236 finally: 237 os.path.expanduser = old_expander 238 239 # make sure --no-user-cfg disables the user cfg file 240 self.assertEquals(len(all_files)-1, len(files)) 241 242class 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 f.write('.') 345 f.close() 346 347 try: 348 dist = Distribution() 349 350 # linux-style 351 if sys.platform in ('linux', 'darwin'): 352 os.environ['HOME'] = temp_dir 353 files = dist.find_config_files() 354 self.assertTrue(user_filename in files) 355 356 # win32-style 357 if sys.platform == 'win32': 358 # home drive should be found 359 os.environ['HOME'] = temp_dir 360 files = dist.find_config_files() 361 self.assertTrue(user_filename in files, 362 '%r not found in %r' % (user_filename, files)) 363 finally: 364 os.remove(user_filename) 365 366 def test_fix_help_options(self): 367 help_tuples = [('a', 'b', 'c', 'd'), (1, 2, 3, 4)] 368 fancy_options = fix_help_options(help_tuples) 369 self.assertEquals(fancy_options[0], ('a', 'b', 'c')) 370 self.assertEquals(fancy_options[1], (1, 2, 3)) 371 372 def test_show_help(self): 373 # smoke test, just makes sure some help is displayed 374 dist = Distribution() 375 sys.argv = [] 376 dist.help = 1 377 dist.script_name = 'setup.py' 378 with captured_stdout() as s: 379 dist.parse_command_line() 380 381 output = [line for line in s.getvalue().split('\n') 382 if line.strip() != ''] 383 self.assertTrue(len(output) > 0) 384 385 def test_long_description(self): 386 long_desc = textwrap.dedent("""\ 387 example:: 388 We start here 389 and continue here 390 and end here.""") 391 attrs = {"name": "package", 392 "version": "1.0", 393 "long_description": long_desc} 394 395 dist = distutils.dist.Distribution(attrs) 396 meta = self.format_metadata(dist) 397 meta = meta.replace('\n' + 8 * ' ', '\n') 398 self.assertTrue(long_desc in meta) 399 400def test_suite(): 401 suite = unittest.TestSuite() 402 suite.addTest(unittest.makeSuite(DistributionTestCase)) 403 suite.addTest(unittest.makeSuite(MetadataTestCase)) 404 return suite 405 406if __name__ == "__main__": 407 unittest.main(defaultTest="test_suite") 408