test_develop.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. """develop tests
  2. """
  3. import os
  4. import site
  5. import sys
  6. import io
  7. import subprocess
  8. import platform
  9. from setuptools.command import test
  10. import pytest
  11. from setuptools.command.develop import develop
  12. from setuptools.dist import Distribution
  13. from setuptools.tests import ack_2to3
  14. from . import contexts
  15. from . import namespaces
  16. SETUP_PY = """\
  17. from setuptools import setup
  18. setup(name='foo',
  19. packages=['foo'],
  20. use_2to3=True,
  21. )
  22. """
  23. INIT_PY = """print "foo"
  24. """
  25. @pytest.fixture
  26. def temp_user(monkeypatch):
  27. with contexts.tempdir() as user_base:
  28. with contexts.tempdir() as user_site:
  29. monkeypatch.setattr('site.USER_BASE', user_base)
  30. monkeypatch.setattr('site.USER_SITE', user_site)
  31. yield
  32. @pytest.fixture
  33. def test_env(tmpdir, temp_user):
  34. target = tmpdir
  35. foo = target.mkdir('foo')
  36. setup = target / 'setup.py'
  37. if setup.isfile():
  38. raise ValueError(dir(target))
  39. with setup.open('w') as f:
  40. f.write(SETUP_PY)
  41. init = foo / '__init__.py'
  42. with init.open('w') as f:
  43. f.write(INIT_PY)
  44. with target.as_cwd():
  45. yield target
  46. class TestDevelop:
  47. in_virtualenv = hasattr(sys, 'real_prefix')
  48. in_venv = hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix
  49. @pytest.mark.skipif(
  50. in_virtualenv or in_venv,
  51. reason="Cannot run when invoked in a virtualenv or venv")
  52. @ack_2to3
  53. def test_2to3_user_mode(self, test_env):
  54. settings = dict(
  55. name='foo',
  56. packages=['foo'],
  57. use_2to3=True,
  58. version='0.0',
  59. )
  60. dist = Distribution(settings)
  61. dist.script_name = 'setup.py'
  62. cmd = develop(dist)
  63. cmd.user = 1
  64. cmd.ensure_finalized()
  65. cmd.install_dir = site.USER_SITE
  66. cmd.user = 1
  67. with contexts.quiet():
  68. cmd.run()
  69. # let's see if we got our egg link at the right place
  70. content = os.listdir(site.USER_SITE)
  71. content.sort()
  72. assert content == ['easy-install.pth', 'foo.egg-link']
  73. # Check that we are using the right code.
  74. fn = os.path.join(site.USER_SITE, 'foo.egg-link')
  75. with io.open(fn) as egg_link_file:
  76. path = egg_link_file.read().split()[0].strip()
  77. fn = os.path.join(path, 'foo', '__init__.py')
  78. with io.open(fn) as init_file:
  79. init = init_file.read().strip()
  80. expected = 'print("foo")'
  81. assert init == expected
  82. def test_console_scripts(self, tmpdir):
  83. """
  84. Test that console scripts are installed and that they reference
  85. only the project by name and not the current version.
  86. """
  87. pytest.skip(
  88. "TODO: needs a fixture to cause 'develop' "
  89. "to be invoked without mutating environment.")
  90. settings = dict(
  91. name='foo',
  92. packages=['foo'],
  93. version='0.0',
  94. entry_points={
  95. 'console_scripts': [
  96. 'foocmd = foo:foo',
  97. ],
  98. },
  99. )
  100. dist = Distribution(settings)
  101. dist.script_name = 'setup.py'
  102. cmd = develop(dist)
  103. cmd.ensure_finalized()
  104. cmd.install_dir = tmpdir
  105. cmd.run()
  106. # assert '0.0' not in foocmd_text
  107. class TestResolver:
  108. """
  109. TODO: These tests were written with a minimal understanding
  110. of what _resolve_setup_path is intending to do. Come up with
  111. more meaningful cases that look like real-world scenarios.
  112. """
  113. def test_resolve_setup_path_cwd(self):
  114. assert develop._resolve_setup_path('.', '.', '.') == '.'
  115. def test_resolve_setup_path_one_dir(self):
  116. assert develop._resolve_setup_path('pkgs', '.', 'pkgs') == '../'
  117. def test_resolve_setup_path_one_dir_trailing_slash(self):
  118. assert develop._resolve_setup_path('pkgs/', '.', 'pkgs') == '../'
  119. class TestNamespaces:
  120. @staticmethod
  121. def install_develop(src_dir, target):
  122. develop_cmd = [
  123. sys.executable,
  124. 'setup.py',
  125. 'develop',
  126. '--install-dir', str(target),
  127. ]
  128. with src_dir.as_cwd():
  129. with test.test.paths_on_pythonpath([str(target)]):
  130. subprocess.check_call(develop_cmd)
  131. @pytest.mark.skipif(
  132. bool(os.environ.get("APPVEYOR")),
  133. reason="https://github.com/pypa/setuptools/issues/851",
  134. )
  135. @pytest.mark.skipif(
  136. platform.python_implementation() == 'PyPy',
  137. reason="https://github.com/pypa/setuptools/issues/1202",
  138. )
  139. def test_namespace_package_importable(self, tmpdir):
  140. """
  141. Installing two packages sharing the same namespace, one installed
  142. naturally using pip or `--single-version-externally-managed`
  143. and the other installed using `develop` should leave the namespace
  144. in tact and both packages reachable by import.
  145. """
  146. pkg_A = namespaces.build_namespace_package(tmpdir, 'myns.pkgA')
  147. pkg_B = namespaces.build_namespace_package(tmpdir, 'myns.pkgB')
  148. target = tmpdir / 'packages'
  149. # use pip to install to the target directory
  150. install_cmd = [
  151. sys.executable,
  152. '-m',
  153. 'pip',
  154. 'install',
  155. str(pkg_A),
  156. '-t', str(target),
  157. ]
  158. subprocess.check_call(install_cmd)
  159. self.install_develop(pkg_B, target)
  160. namespaces.make_site_dir(target)
  161. try_import = [
  162. sys.executable,
  163. '-c', 'import myns.pkgA; import myns.pkgB',
  164. ]
  165. with test.test.paths_on_pythonpath([str(target)]):
  166. subprocess.check_call(try_import)
  167. # additionally ensure that pkg_resources import works
  168. pkg_resources_imp = [
  169. sys.executable,
  170. '-c', 'import pkg_resources',
  171. ]
  172. with test.test.paths_on_pythonpath([str(target)]):
  173. subprocess.check_call(pkg_resources_imp)