test_install.py 8.4 KB

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