import re import textwrap from os.path import join import pytest @pytest.mark.network def test_simple_extras_install_from_pypi(script): """ Test installing a package from PyPI using extras dependency Paste[openid]. """ result = script.pip( 'install', 'Paste[openid]==1.7.5.1', expect_stderr=True, ) initools_folder = script.site_packages / 'openid' result.did_create(initools_folder) def test_extras_after_wheel(script, data): """ Test installing a package with extras after installing from a wheel. """ simple = script.site_packages / 'simple' no_extra = script.pip( 'install', '--no-index', '-f', data.find_links, 'requires_simple_extra', expect_stderr=True, ) no_extra.did_not_create(simple) extra = script.pip( 'install', '--no-index', '-f', data.find_links, 'requires_simple_extra[extra]', expect_stderr=True, ) extra.did_create(simple) @pytest.mark.network def test_no_extras_uninstall(script): """ No extras dependency gets uninstalled when the root package is uninstalled """ result = script.pip( 'install', 'Paste[openid]==1.7.5.1', expect_stderr=True, ) result.did_create(join(script.site_packages, 'paste')) result.did_create(join(script.site_packages, 'openid')) result2 = script.pip('uninstall', 'Paste', '-y') # openid should not be uninstalled initools_folder = script.site_packages / 'openid' assert initools_folder not in result2.files_deleted, result.files_deleted def test_nonexistent_extra_warns_user_no_wheel(script, data): """ A warning is logged telling the user that the extra option they requested does not exist in the project they are wishing to install. This exercises source installs. """ result = script.pip( 'install', '--no-binary=:all:', '--no-index', '--find-links=' + data.find_links, 'simple[nonexistent]', expect_stderr=True, ) assert ( "simple 3.0 does not provide the extra 'nonexistent'" in result.stderr ), str(result) def test_nonexistent_extra_warns_user_with_wheel(script, data): """ A warning is logged telling the user that the extra option they requested does not exist in the project they are wishing to install. This exercises wheel installs. """ result = script.pip( 'install', '--no-index', '--find-links=' + data.find_links, 'simplewheel[nonexistent]', expect_stderr=True, ) assert ( "simplewheel 2.0 does not provide the extra 'nonexistent'" in result.stderr ) def test_nonexistent_options_listed_in_order(script, data): """ Warn the user for each extra that doesn't exist. """ result = script.pip( 'install', '--no-index', '--find-links=' + data.find_links, 'simplewheel[nonexistent, nope]', expect_stderr=True, ) matches = re.findall( "WARNING: simplewheel 2.0 does not provide the extra '([a-z]*)'", result.stderr ) assert matches == ['nonexistent', 'nope'] def test_install_deprecated_extra(script, data): """ Warn about deprecated order of specifiers and extras. Test uses a requirements file to avoid a testing issue where the specifier gets interpreted as shell redirect. """ script.scratch_path.joinpath("requirements.txt").write_text( "requires_simple_extra>=0.1[extra]" ) simple = script.site_packages / 'simple' result = script.pip( 'install', '--no-index', '--find-links=' + data.find_links, '-r', script.scratch_path / 'requirements.txt', expect_stderr=True, ) result.did_create(simple) assert ("DEPRECATION: Extras after version" in result.stderr) def test_install_special_extra(script): # Check that uppercase letters and '-' are dealt with # make a dummy project pkga_path = script.scratch_path / 'pkga' pkga_path.mkdir() pkga_path.joinpath("setup.py").write_text(textwrap.dedent(""" from setuptools import setup setup(name='pkga', version='0.1', extras_require={'Hop_hOp-hoP': ['missing_pkg']}, ) """)) result = script.pip( 'install', '--no-index', '{pkga_path}[Hop_hOp-hoP]'.format(**locals()), expect_error=True) assert ( "Could not find a version that satisfies the requirement missing_pkg" ) in result.stderr, str(result) @pytest.mark.parametrize( "extra_to_install, simple_version", [ ['', '3.0'], pytest.param('[extra1]', '2.0', marks=pytest.mark.xfail), pytest.param('[extra2]', '1.0', marks=pytest.mark.xfail), pytest.param('[extra1,extra2]', '1.0', marks=pytest.mark.xfail), ]) def test_install_extra_merging(script, data, extra_to_install, simple_version): # Check that extra specifications in the extras section are honoured. pkga_path = script.scratch_path / 'pkga' pkga_path.mkdir() pkga_path.joinpath("setup.py").write_text(textwrap.dedent(""" from setuptools import setup setup(name='pkga', version='0.1', install_requires=['simple'], extras_require={'extra1': ['simple<3'], 'extra2': ['simple==1.*']}, ) """)) result = script.pip_install_local( '{pkga_path}{extra_to_install}'.format(**locals()), ) assert ('Successfully installed pkga-0.1 simple-{}'.format(simple_version) ) in result.stdout