Home | History | Annotate | Download | only in tests
      1 """Tests for distutils.command.install."""
      2 
      3 import os
      4 import sys
      5 import unittest
      6 import site
      7 
      8 from test.test_support import captured_stdout, run_unittest
      9 
     10 from distutils import sysconfig
     11 from distutils.command.install import install
     12 from distutils.command import install as install_module
     13 from distutils.command.build_ext import build_ext
     14 from distutils.command.install import INSTALL_SCHEMES
     15 from distutils.core import Distribution
     16 from distutils.errors import DistutilsOptionError
     17 from distutils.extension import Extension
     18 
     19 from distutils.tests import support
     20 
     21 
     22 def _make_ext_name(modname):
     23     if os.name == 'nt' and sys.executable.endswith('_d.exe'):
     24         modname += '_d'
     25     return modname + sysconfig.get_config_var('SO')
     26 
     27 
     28 class InstallTestCase(support.TempdirManager,
     29                       support.LoggingSilencer,
     30                       unittest.TestCase):
     31 
     32     def test_home_installation_scheme(self):
     33         # This ensure two things:
     34         # - that --home generates the desired set of directory names
     35         # - test --home is supported on all platforms
     36         builddir = self.mkdtemp()
     37         destination = os.path.join(builddir, "installation")
     38 
     39         dist = Distribution({"name": "foopkg"})
     40         # script_name need not exist, it just need to be initialized
     41         dist.script_name = os.path.join(builddir, "setup.py")
     42         dist.command_obj["build"] = support.DummyCommand(
     43             build_base=builddir,
     44             build_lib=os.path.join(builddir, "lib"),
     45             )
     46 
     47         cmd = install(dist)
     48         cmd.home = destination
     49         cmd.ensure_finalized()
     50 
     51         self.assertEqual(cmd.install_base, destination)
     52         self.assertEqual(cmd.install_platbase, destination)
     53 
     54         def check_path(got, expected):
     55             got = os.path.normpath(got)
     56             expected = os.path.normpath(expected)
     57             self.assertEqual(got, expected)
     58 
     59         libdir = os.path.join(destination, "lib", "python")
     60         check_path(cmd.install_lib, libdir)
     61         check_path(cmd.install_platlib, libdir)
     62         check_path(cmd.install_purelib, libdir)
     63         check_path(cmd.install_headers,
     64                    os.path.join(destination, "include", "python", "foopkg"))
     65         check_path(cmd.install_scripts, os.path.join(destination, "bin"))
     66         check_path(cmd.install_data, destination)
     67 
     68     def test_user_site(self):
     69         # site.USER_SITE was introduced in 2.6
     70         if sys.version < '2.6':
     71             return
     72 
     73         # preparing the environment for the test
     74         self.old_user_base = site.USER_BASE
     75         self.old_user_site = site.USER_SITE
     76         self.tmpdir = self.mkdtemp()
     77         self.user_base = os.path.join(self.tmpdir, 'B')
     78         self.user_site = os.path.join(self.tmpdir, 'S')
     79         site.USER_BASE = self.user_base
     80         site.USER_SITE = self.user_site
     81         install_module.USER_BASE = self.user_base
     82         install_module.USER_SITE = self.user_site
     83 
     84         def _expanduser(path):
     85             return self.tmpdir
     86         self.old_expand = os.path.expanduser
     87         os.path.expanduser = _expanduser
     88 
     89         def cleanup():
     90             site.USER_BASE = self.old_user_base
     91             site.USER_SITE = self.old_user_site
     92             install_module.USER_BASE = self.old_user_base
     93             install_module.USER_SITE = self.old_user_site
     94             os.path.expanduser = self.old_expand
     95 
     96         self.addCleanup(cleanup)
     97 
     98         for key in ('nt_user', 'unix_user', 'os2_home'):
     99             self.assertIn(key, INSTALL_SCHEMES)
    100 
    101         dist = Distribution({'name': 'xx'})
    102         cmd = install(dist)
    103 
    104         # making sure the user option is there
    105         options = [name for name, short, lable in
    106                    cmd.user_options]
    107         self.assertIn('user', options)
    108 
    109         # setting a value
    110         cmd.user = 1
    111 
    112         # user base and site shouldn't be created yet
    113         self.assertFalse(os.path.exists(self.user_base))
    114         self.assertFalse(os.path.exists(self.user_site))
    115 
    116         # let's run finalize
    117         cmd.ensure_finalized()
    118 
    119         # now they should
    120         self.assertTrue(os.path.exists(self.user_base))
    121         self.assertTrue(os.path.exists(self.user_site))
    122 
    123         self.assertIn('userbase', cmd.config_vars)
    124         self.assertIn('usersite', cmd.config_vars)
    125 
    126     def test_handle_extra_path(self):
    127         dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'})
    128         cmd = install(dist)
    129 
    130         # two elements
    131         cmd.handle_extra_path()
    132         self.assertEqual(cmd.extra_path, ['path', 'dirs'])
    133         self.assertEqual(cmd.extra_dirs, 'dirs')
    134         self.assertEqual(cmd.path_file, 'path')
    135 
    136         # one element
    137         cmd.extra_path = ['path']
    138         cmd.handle_extra_path()
    139         self.assertEqual(cmd.extra_path, ['path'])
    140         self.assertEqual(cmd.extra_dirs, 'path')
    141         self.assertEqual(cmd.path_file, 'path')
    142 
    143         # none
    144         dist.extra_path = cmd.extra_path = None
    145         cmd.handle_extra_path()
    146         self.assertEqual(cmd.extra_path, None)
    147         self.assertEqual(cmd.extra_dirs, '')
    148         self.assertEqual(cmd.path_file, None)
    149 
    150         # three elements (no way !)
    151         cmd.extra_path = 'path,dirs,again'
    152         self.assertRaises(DistutilsOptionError, cmd.handle_extra_path)
    153 
    154     def test_finalize_options(self):
    155         dist = Distribution({'name': 'xx'})
    156         cmd = install(dist)
    157 
    158         # must supply either prefix/exec-prefix/home or
    159         # install-base/install-platbase -- not both
    160         cmd.prefix = 'prefix'
    161         cmd.install_base = 'base'
    162         self.assertRaises(DistutilsOptionError, cmd.finalize_options)
    163 
    164         # must supply either home or prefix/exec-prefix -- not both
    165         cmd.install_base = None
    166         cmd.home = 'home'
    167         self.assertRaises(DistutilsOptionError, cmd.finalize_options)
    168 
    169         # can't combine user with prefix/exec_prefix/home or
    170         # install_(plat)base
    171         cmd.prefix = None
    172         cmd.user = 'user'
    173         self.assertRaises(DistutilsOptionError, cmd.finalize_options)
    174 
    175     def test_record(self):
    176         install_dir = self.mkdtemp()
    177         project_dir, dist = self.create_dist(py_modules=['hello'],
    178                                              scripts=['sayhi'])
    179         os.chdir(project_dir)
    180         self.write_file('hello.py', "def main(): print 'o hai'")
    181         self.write_file('sayhi', 'from hello import main; main()')
    182 
    183         cmd = install(dist)
    184         dist.command_obj['install'] = cmd
    185         cmd.root = install_dir
    186         cmd.record = os.path.join(project_dir, 'filelist')
    187         cmd.ensure_finalized()
    188         cmd.run()
    189 
    190         f = open(cmd.record)
    191         try:
    192             content = f.read()
    193         finally:
    194             f.close()
    195 
    196         found = [os.path.basename(line) for line in content.splitlines()]
    197         expected = ['hello.py', 'hello.pyc', 'sayhi',
    198                     'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
    199         self.assertEqual(found, expected)
    200 
    201     def test_record_extensions(self):
    202         install_dir = self.mkdtemp()
    203         project_dir, dist = self.create_dist(ext_modules=[
    204             Extension('xx', ['xxmodule.c'])])
    205         os.chdir(project_dir)
    206         support.copy_xxmodule_c(project_dir)
    207 
    208         buildextcmd = build_ext(dist)
    209         support.fixup_build_ext(buildextcmd)
    210         buildextcmd.ensure_finalized()
    211 
    212         cmd = install(dist)
    213         dist.command_obj['install'] = cmd
    214         dist.command_obj['build_ext'] = buildextcmd
    215         cmd.root = install_dir
    216         cmd.record = os.path.join(project_dir, 'filelist')
    217         cmd.ensure_finalized()
    218         cmd.run()
    219 
    220         f = open(cmd.record)
    221         try:
    222             content = f.read()
    223         finally:
    224             f.close()
    225 
    226         found = [os.path.basename(line) for line in content.splitlines()]
    227         expected = [_make_ext_name('xx'),
    228                     'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
    229         self.assertEqual(found, expected)
    230 
    231     def test_debug_mode(self):
    232         # this covers the code called when DEBUG is set
    233         old_logs_len = len(self.logs)
    234         install_module.DEBUG = True
    235         try:
    236             with captured_stdout():
    237                 self.test_record()
    238         finally:
    239             install_module.DEBUG = False
    240         self.assertTrue(len(self.logs) > old_logs_len)
    241 
    242 
    243 def test_suite():
    244     return unittest.makeSuite(InstallTestCase)
    245 
    246 if __name__ == "__main__":
    247     run_unittest(test_suite())
    248