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