summaryrefslogtreecommitdiff
path: root/setuptools/tests/test_virtualenv.py
blob: acfe04e9ddb64ab05266a4e766ff621d4bd42b83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import os
import sys
import subprocess
from urllib.request import urlopen
from urllib.error import URLError

import pathlib

import pytest

from . import contexts
from .textwrap import DALS
from .test_easy_install import make_nspkg_sdist


@pytest.fixture(autouse=True)
def pytest_virtualenv_works(venv):
    """
    pytest_virtualenv may not work. if it doesn't, skip these
    tests. See #1284.
    """
    venv_prefix = venv.run(["python", "-c", "import sys; print(sys.prefix)"]).strip()
    if venv_prefix == sys.prefix:
        pytest.skip("virtualenv is broken (see pypa/setuptools#1284)")


def test_clean_env_install(venv_without_setuptools, setuptools_wheel):
    """
    Check setuptools can be installed in a clean environment.
    """
    cmd = ["python", "-m", "pip", "install", str(setuptools_wheel)]
    venv_without_setuptools.run(cmd)


def access_pypi():
    # Detect if tests are being run without connectivity
    if not os.environ.get('NETWORK_REQUIRED', False):  # pragma: nocover
        try:
            urlopen('https://pypi.org', timeout=1)
        except URLError:
            # No network, disable most of these tests
            return False

    return True


@pytest.mark.skipif(
    'platform.python_implementation() == "PyPy"',
    reason="https://github.com/pypa/setuptools/pull/2865#issuecomment-965834995",
)
@pytest.mark.skipif(not access_pypi(), reason="no network")
# ^-- Even when it is not necessary to install a different version of `pip`
#     the build process will still try to download `wheel`, see #3147 and #2986.
@pytest.mark.parametrize(
    'pip_version',
    [
        None,
        pytest.param(
            'pip<20.1',
            marks=pytest.mark.xfail(
                'sys.version_info > (3, 12)',
                reason="pip 22 requried for Python 3.12 and later",
            ),
        ),
        pytest.param(
            'pip<21',
            marks=pytest.mark.xfail(
                'sys.version_info > (3, 12)',
                reason="pip 22 requried for Python 3.12 and later",
            ),
        ),
        pytest.param(
            'pip<22',
            marks=pytest.mark.xfail(
                'sys.version_info > (3, 12)',
                reason="pip 22 requried for Python 3.12 and later",
            ),
        ),
        'pip<23',
        pytest.param(
            'https://github.com/pypa/pip/archive/main.zip',
            marks=pytest.mark.xfail(reason='#2975'),
        ),
    ],
)
def test_pip_upgrade_from_source(
    pip_version, venv_without_setuptools, setuptools_wheel, setuptools_sdist
):
    """
    Check pip can upgrade setuptools from source.
    """
    # Install pip/wheel, in a venv without setuptools (as it
    # should not be needed for bootstraping from source)
    venv = venv_without_setuptools
    venv.run(["pip", "install", "-U", "wheel"])
    if pip_version is not None:
        venv.run(["python", "-m", "pip", "install", "-U", pip_version, "--retries=1"])
    with pytest.raises(subprocess.CalledProcessError):
        # Meta-test to make sure setuptools is not installed
        venv.run(["python", "-c", "import setuptools"])

    # Then install from wheel.
    venv.run(["pip", "install", str(setuptools_wheel)])
    # And finally try to upgrade from source.
    venv.run(["pip", "install", "--no-cache-dir", "--upgrade", str(setuptools_sdist)])


def _check_test_command_install_requirements(venv, tmpdir):
    """
    Check the test command will install all required dependencies.
    """

    def sdist(distname, version):
        dist_path = tmpdir.join('%s-%s.tar.gz' % (distname, version))
        make_nspkg_sdist(str(dist_path), distname, version)
        return dist_path

    dependency_links = [
        pathlib.Path(str(dist_path)).as_uri()
        for dist_path in (
            sdist('foobar', '2.4'),
            sdist('bits', '4.2'),
            sdist('bobs', '6.0'),
            sdist('pieces', '0.6'),
        )
    ]
    with tmpdir.join('setup.py').open('w') as fp:
        fp.write(
            DALS(
                '''
            from setuptools import setup

            setup(
                dependency_links={dependency_links!r},
                install_requires=[
                    'barbazquux1; sys_platform in ""',
                    'foobar==2.4',
                ],
                setup_requires='bits==4.2',
                tests_require="""
                    bobs==6.0
                """,
                extras_require={{
                    'test': ['barbazquux2'],
                    ':"" in sys_platform': 'pieces==0.6',
                    ':python_version > "1"': """
                        pieces
                        foobar
                    """,
                }}
            )
            '''.format(
                    dependency_links=dependency_links
                )
            )
        )
    with tmpdir.join('test.py').open('w') as fp:
        fp.write(
            DALS(
                '''
            import foobar
            import bits
            import bobs
            import pieces

            open('success', 'w').close()
            '''
            )
        )

    cmd = ["python", 'setup.py', 'test', '-s', 'test']
    venv.run(cmd, cwd=str(tmpdir))
    assert tmpdir.join('success').check()


def test_test_command_install_requirements(venv, tmpdir, tmpdir_cwd):
    # Ensure pip/wheel packages are installed.
    venv.run(["python", "-c", "__import__('pkg_resources').require(['pip', 'wheel'])"])
    # disable index URL so bits and bobs aren't requested from PyPI
    with contexts.environment(PYTHONPATH=None, PIP_NO_INDEX="1"):
        _check_test_command_install_requirements(venv, tmpdir)


def test_no_missing_dependencies(bare_venv, request):
    """
    Quick and dirty test to ensure all external dependencies are vendored.
    """
    setuptools_dir = request.config.rootdir
    for command in ('upload',):  # sorted(distutils.command.__all__):
        bare_venv.run(['python', 'setup.py', command, '-h'], cwd=setuptools_dir)