test_install.py 8.5 KB

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