1"""Tests for distutils.command.install.""" 2 3import os 4import sys 5import unittest 6import site 7 8from test.support import captured_stdout, run_unittest 9 10from distutils import sysconfig 11from distutils.command.install import install 12from distutils.command import install as install_module 13from distutils.command.build_ext import build_ext 14from distutils.command.install import INSTALL_SCHEMES 15from distutils.core import Distribution 16from distutils.errors import DistutilsOptionError 17from distutils.extension import Extension 18 19from distutils.tests import support 20from test import support as test_support 21 22 23def _make_ext_name(modname): 24 return modname + sysconfig.get_config_var('EXT_SUFFIX') 25 26 27class InstallTestCase(support.TempdirManager, 28 support.EnvironGuard, 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 # test install with --user 70 # preparing the environment for the test 71 self.old_user_base = site.USER_BASE 72 self.old_user_site = site.USER_SITE 73 self.tmpdir = self.mkdtemp() 74 self.user_base = os.path.join(self.tmpdir, 'B') 75 self.user_site = os.path.join(self.tmpdir, 'S') 76 site.USER_BASE = self.user_base 77 site.USER_SITE = self.user_site 78 install_module.USER_BASE = self.user_base 79 install_module.USER_SITE = self.user_site 80 81 def _expanduser(path): 82 return self.tmpdir 83 self.old_expand = os.path.expanduser 84 os.path.expanduser = _expanduser 85 86 def cleanup(): 87 site.USER_BASE = self.old_user_base 88 site.USER_SITE = self.old_user_site 89 install_module.USER_BASE = self.old_user_base 90 install_module.USER_SITE = self.old_user_site 91 os.path.expanduser = self.old_expand 92 93 self.addCleanup(cleanup) 94 95 for key in ('nt_user', 'unix_user'): 96 self.assertIn(key, INSTALL_SCHEMES) 97 98 dist = Distribution({'name': 'xx'}) 99 cmd = install(dist) 100 101 # making sure the user option is there 102 options = [name for name, short, lable in 103 cmd.user_options] 104 self.assertIn('user', options) 105 106 # setting a value 107 cmd.user = 1 108 109 # user base and site shouldn't be created yet 110 self.assertFalse(os.path.exists(self.user_base)) 111 self.assertFalse(os.path.exists(self.user_site)) 112 113 # let's run finalize 114 cmd.ensure_finalized() 115 116 # now they should 117 self.assertTrue(os.path.exists(self.user_base)) 118 self.assertTrue(os.path.exists(self.user_site)) 119 120 self.assertIn('userbase', cmd.config_vars) 121 self.assertIn('usersite', cmd.config_vars) 122 123 def test_handle_extra_path(self): 124 dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'}) 125 cmd = install(dist) 126 127 # two elements 128 cmd.handle_extra_path() 129 self.assertEqual(cmd.extra_path, ['path', 'dirs']) 130 self.assertEqual(cmd.extra_dirs, 'dirs') 131 self.assertEqual(cmd.path_file, 'path') 132 133 # one element 134 cmd.extra_path = ['path'] 135 cmd.handle_extra_path() 136 self.assertEqual(cmd.extra_path, ['path']) 137 self.assertEqual(cmd.extra_dirs, 'path') 138 self.assertEqual(cmd.path_file, 'path') 139 140 # none 141 dist.extra_path = cmd.extra_path = None 142 cmd.handle_extra_path() 143 self.assertEqual(cmd.extra_path, None) 144 self.assertEqual(cmd.extra_dirs, '') 145 self.assertEqual(cmd.path_file, None) 146 147 # three elements (no way !) 148 cmd.extra_path = 'path,dirs,again' 149 self.assertRaises(DistutilsOptionError, cmd.handle_extra_path) 150 151 def test_finalize_options(self): 152 dist = Distribution({'name': 'xx'}) 153 cmd = install(dist) 154 155 # must supply either prefix/exec-prefix/home or 156 # install-base/install-platbase -- not both 157 cmd.prefix = 'prefix' 158 cmd.install_base = 'base' 159 self.assertRaises(DistutilsOptionError, cmd.finalize_options) 160 161 # must supply either home or prefix/exec-prefix -- not both 162 cmd.install_base = None 163 cmd.home = 'home' 164 self.assertRaises(DistutilsOptionError, cmd.finalize_options) 165 166 # can't combine user with prefix/exec_prefix/home or 167 # install_(plat)base 168 cmd.prefix = None 169 cmd.user = 'user' 170 self.assertRaises(DistutilsOptionError, cmd.finalize_options) 171 172 def test_record(self): 173 install_dir = self.mkdtemp() 174 project_dir, dist = self.create_dist(py_modules=['hello'], 175 scripts=['sayhi']) 176 os.chdir(project_dir) 177 self.write_file('hello.py', "def main(): print('o hai')") 178 self.write_file('sayhi', 'from hello import main; main()') 179 180 cmd = install(dist) 181 dist.command_obj['install'] = cmd 182 cmd.root = install_dir 183 cmd.record = os.path.join(project_dir, 'filelist') 184 cmd.ensure_finalized() 185 cmd.run() 186 187 f = open(cmd.record) 188 try: 189 content = f.read() 190 finally: 191 f.close() 192 193 found = [os.path.basename(line) for line in content.splitlines()] 194 expected = ['hello.py', 'hello.%s.pyc' % sys.implementation.cache_tag, 195 'sayhi', 196 'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]] 197 self.assertEqual(found, expected) 198 199 def test_record_extensions(self): 200 cmd = test_support.missing_compiler_executable() 201 if cmd is not None: 202 self.skipTest('The %r command is not found' % cmd) 203 install_dir = self.mkdtemp() 204 project_dir, dist = self.create_dist(ext_modules=[ 205 Extension('xx', ['xxmodule.c'])]) 206 os.chdir(project_dir) 207 support.copy_xxmodule_c(project_dir) 208 209 buildextcmd = build_ext(dist) 210 support.fixup_build_ext(buildextcmd) 211 buildextcmd.ensure_finalized() 212 213 cmd = install(dist) 214 dist.command_obj['install'] = cmd 215 dist.command_obj['build_ext'] = buildextcmd 216 cmd.root = install_dir 217 cmd.record = os.path.join(project_dir, 'filelist') 218 cmd.ensure_finalized() 219 cmd.run() 220 221 f = open(cmd.record) 222 try: 223 content = f.read() 224 finally: 225 f.close() 226 227 found = [os.path.basename(line) for line in content.splitlines()] 228 expected = [_make_ext_name('xx'), 229 'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]] 230 self.assertEqual(found, expected) 231 232 def test_debug_mode(self): 233 # this covers the code called when DEBUG is set 234 old_logs_len = len(self.logs) 235 install_module.DEBUG = True 236 try: 237 with captured_stdout(): 238 self.test_record() 239 finally: 240 install_module.DEBUG = False 241 self.assertGreater(len(self.logs), old_logs_len) 242 243 244def test_suite(): 245 return unittest.makeSuite(InstallTestCase) 246 247if __name__ == "__main__": 248 run_unittest(test_suite()) 249