test_install.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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. check_path(cmd.install_platlib, libdir)
  48. check_path(cmd.install_purelib, libdir)
  49. check_path(cmd.install_headers,
  50. os.path.join(destination, "include", "python", "foopkg"))
  51. check_path(cmd.install_scripts, os.path.join(destination, "bin"))
  52. check_path(cmd.install_data, destination)
  53. def test_user_site(self):
  54. # test install with --user
  55. # preparing the environment for the test
  56. self.old_user_base = site.USER_BASE
  57. self.old_user_site = site.USER_SITE
  58. self.tmpdir = self.mkdtemp()
  59. self.user_base = os.path.join(self.tmpdir, 'B')
  60. self.user_site = os.path.join(self.tmpdir, 'S')
  61. site.USER_BASE = self.user_base
  62. site.USER_SITE = self.user_site
  63. install_module.USER_BASE = self.user_base
  64. install_module.USER_SITE = self.user_site
  65. def _expanduser(path):
  66. return self.tmpdir
  67. self.old_expand = os.path.expanduser
  68. os.path.expanduser = _expanduser
  69. def cleanup():
  70. site.USER_BASE = self.old_user_base
  71. site.USER_SITE = self.old_user_site
  72. install_module.USER_BASE = self.old_user_base
  73. install_module.USER_SITE = self.old_user_site
  74. os.path.expanduser = self.old_expand
  75. self.addCleanup(cleanup)
  76. for key in ('nt_user', 'unix_user'):
  77. self.assertIn(key, INSTALL_SCHEMES)
  78. dist = Distribution({'name': 'xx'})
  79. cmd = install(dist)
  80. # making sure the user option is there
  81. options = [name for name, short, lable in
  82. cmd.user_options]
  83. self.assertIn('user', options)
  84. # setting a value
  85. cmd.user = 1
  86. # user base and site shouldn't be created yet
  87. self.assertFalse(os.path.exists(self.user_base))
  88. self.assertFalse(os.path.exists(self.user_site))
  89. # let's run finalize
  90. cmd.ensure_finalized()
  91. # now they should
  92. self.assertTrue(os.path.exists(self.user_base))
  93. self.assertTrue(os.path.exists(self.user_site))
  94. self.assertIn('userbase', cmd.config_vars)
  95. self.assertIn('usersite', cmd.config_vars)
  96. def test_handle_extra_path(self):
  97. dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'})
  98. cmd = install(dist)
  99. # two elements
  100. cmd.handle_extra_path()
  101. self.assertEqual(cmd.extra_path, ['path', 'dirs'])
  102. self.assertEqual(cmd.extra_dirs, 'dirs')
  103. self.assertEqual(cmd.path_file, 'path')
  104. # one element
  105. cmd.extra_path = ['path']
  106. cmd.handle_extra_path()
  107. self.assertEqual(cmd.extra_path, ['path'])
  108. self.assertEqual(cmd.extra_dirs, 'path')
  109. self.assertEqual(cmd.path_file, 'path')
  110. # none
  111. dist.extra_path = cmd.extra_path = None
  112. cmd.handle_extra_path()
  113. self.assertEqual(cmd.extra_path, None)
  114. self.assertEqual(cmd.extra_dirs, '')
  115. self.assertEqual(cmd.path_file, None)
  116. # three elements (no way !)
  117. cmd.extra_path = 'path,dirs,again'
  118. self.assertRaises(DistutilsOptionError, cmd.handle_extra_path)
  119. def test_finalize_options(self):
  120. dist = Distribution({'name': 'xx'})
  121. cmd = install(dist)
  122. # must supply either prefix/exec-prefix/home or
  123. # install-base/install-platbase -- not both
  124. cmd.prefix = 'prefix'
  125. cmd.install_base = 'base'
  126. self.assertRaises(DistutilsOptionError, cmd.finalize_options)
  127. # must supply either home or prefix/exec-prefix -- not both
  128. cmd.install_base = None
  129. cmd.home = 'home'
  130. self.assertRaises(DistutilsOptionError, cmd.finalize_options)
  131. # can't combine user with prefix/exec_prefix/home or
  132. # install_(plat)base
  133. cmd.prefix = None
  134. cmd.user = 'user'
  135. self.assertRaises(DistutilsOptionError, cmd.finalize_options)
  136. def test_record(self):
  137. install_dir = self.mkdtemp()
  138. project_dir, dist = self.create_dist(py_modules=['hello'],
  139. scripts=['sayhi'])
  140. os.chdir(project_dir)
  141. self.write_file('hello.py', "def main(): print('o hai')")
  142. self.write_file('sayhi', 'from hello import main; main()')
  143. cmd = install(dist)
  144. dist.command_obj['install'] = cmd
  145. cmd.root = install_dir
  146. cmd.record = os.path.join(project_dir, 'filelist')
  147. cmd.ensure_finalized()
  148. cmd.run()
  149. f = open(cmd.record)
  150. try:
  151. content = f.read()
  152. finally:
  153. f.close()
  154. found = [os.path.basename(line) for line in content.splitlines()]
  155. expected = ['hello.py', 'hello.%s.pyc' % sys.implementation.cache_tag,
  156. 'sayhi',
  157. 'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
  158. self.assertEqual(found, expected)
  159. def test_record_extensions(self):
  160. cmd = test_support.missing_compiler_executable()
  161. if cmd is not None:
  162. self.skipTest('The %r command is not found' % cmd)
  163. install_dir = self.mkdtemp()
  164. project_dir, dist = self.create_dist(ext_modules=[
  165. Extension('xx', ['xxmodule.c'])])
  166. os.chdir(project_dir)
  167. support.copy_xxmodule_c(project_dir)
  168. buildextcmd = build_ext(dist)
  169. support.fixup_build_ext(buildextcmd)
  170. buildextcmd.ensure_finalized()
  171. cmd = install(dist)
  172. dist.command_obj['install'] = cmd
  173. dist.command_obj['build_ext'] = buildextcmd
  174. cmd.root = install_dir
  175. cmd.record = os.path.join(project_dir, 'filelist')
  176. cmd.ensure_finalized()
  177. cmd.run()
  178. f = open(cmd.record)
  179. try:
  180. content = f.read()
  181. finally:
  182. f.close()
  183. found = [os.path.basename(line) for line in content.splitlines()]
  184. expected = [_make_ext_name('xx'),
  185. 'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
  186. self.assertEqual(found, expected)
  187. def test_debug_mode(self):
  188. # this covers the code called when DEBUG is set
  189. old_logs_len = len(self.logs)
  190. install_module.DEBUG = True
  191. try:
  192. with captured_stdout():
  193. self.test_record()
  194. finally:
  195. install_module.DEBUG = False
  196. self.assertGreater(len(self.logs), old_logs_len)
  197. def test_suite():
  198. return unittest.makeSuite(InstallTestCase)
  199. if __name__ == "__main__":
  200. run_unittest(test_suite())