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