From 9a317d3b209a283fac36f2d0dcf41a4565eececb Mon Sep 17 00:00:00 2001 From: Albert Tugushev Date: Mon, 12 Aug 2019 11:34:21 +0300 Subject: [PATCH 1/5] Fix bypassed pip upgrade warning on Windows --- news/6841.bugfix | 1 + src/pip/_internal/utils/misc.py | 1 + tests/functional/test_install.py | 92 ++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 news/6841.bugfix diff --git a/news/6841.bugfix b/news/6841.bugfix new file mode 100644 index 00000000000..278caa64e54 --- /dev/null +++ b/news/6841.bugfix @@ -0,0 +1 @@ +Fix bypassed pip upgrade warning on Windows. diff --git a/src/pip/_internal/utils/misc.py b/src/pip/_internal/utils/misc.py index 576a25138ed..15eb01dc1de 100644 --- a/src/pip/_internal/utils/misc.py +++ b/src/pip/_internal/utils/misc.py @@ -1185,6 +1185,7 @@ def protect_pip_from_modification_on_windows(modifying_pip): python -m pip ... """ pip_names = [ + "pip", "pip.exe", "pip{}.exe".format(sys.version_info[0]), "pip{}.{}.exe".format(*sys.version_info[:2]) diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index 6e1e3dd400b..ba36a2844bf 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -7,6 +7,7 @@ import pytest +import pip from pip._internal import pep425tags from pip._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.models.index import PyPI, TestPyPI @@ -1527,3 +1528,94 @@ def test_target_install_ignores_distutils_config_install_prefix(script): (target - script.base_path) in result.files_created and (prefix - script.base_path) not in result.files_created ), str(result) + + +@pytest.mark.skipif("sys.platform != 'win32'") +def test_protect_pip_from_modification_on_windows(script): + """ + Test ``pip install --upgrade pip`` is raised an error on Windows. + """ + command = ['pip', 'install', '--upgrade', 'pip'] + result = script.run(*command, expect_error=True) + assert result.returncode != 0 + new_command = [sys.executable, '-m'] + command + assert 'To modify pip, please run the following command:\n{}'.format( + ' '.join(new_command)) in result.stderr, str(result) + + +@pytest.mark.skipif("sys.platform != 'win32'") +def test_protect_pip_from_modification_via_deps_on_windows(script, with_wheel): + """ + Test ``pip install pkga`` is raised and error on Windows + if `pkga` implicitly tries to upgrade pip. + """ + # Make a wheel for pkga which requires pip + script.scratch_path.joinpath('pkga').mkdir() + pkga_path = script.scratch_path / 'pkga' + pkga_path.joinpath('setup.py').write_text(textwrap.dedent(""" + from setuptools import setup + setup(name='pkga', + version='0.1', + install_requires = ["pip<{}"]) + """.format(pip.__version__))) + result = script.run( + 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkga_path + ) + assert result.returncode == 0 + + # Make sure pip install pkga is raised error + pkga_wheel_path = './pkga/dist/pkga-0.1-py2.py3-none-any.whl' + command = ['pip', 'install', pkga_wheel_path] + result = script.run(*command, expect_error=True) + assert result.returncode != 0 + new_command = [sys.executable, "-m"] + command + assert "To modify pip, please run the following command:\n{}".format( + " ".join(new_command)) in result.stderr, str(result) + + +@pytest.mark.skipif("sys.platform != 'win32'") +def test_protect_pip_from_modification_via_sub_deps_on_windows( + script, with_wheel +): + """ + Test ``pip install pkga`` is raised and error on Windows + if sub-dependencies of `pkga` implicitly tries to upgrade pip. + """ + # Make a wheel for pkga which requires pip + script.scratch_path.joinpath('pkga').mkdir() + pkga_path = script.scratch_path / 'pkga' + pkga_path.joinpath('setup.py').write_text(textwrap.dedent(""" + from setuptools import setup + setup(name='pkga', + version='0.1', + install_requires = ["pip<{}"]) + """.format(pip.__version__))) + result = script.run( + 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkga_path + ) + assert result.returncode == 0 + + # Make a wheel for pkgb which requires pkgb + script.scratch_path.joinpath('pkgb').mkdir() + pkgb_path = script.scratch_path / 'pkgb' + pkgb_path.joinpath('setup.py').write_text(textwrap.dedent(""" + from setuptools import setup + setup(name='pkgb', + version='0.1', + install_requires = ["pkga"]) + """)) + result = script.run( + 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkgb_path + ) + assert result.returncode == 0 + + # Make sure pip install pkgb is raised error + pkgb_wheel_path = './pkgb/dist/pkgb-0.1-py2.py3-none-any.whl' + command = [ + 'pip', 'install', pkgb_wheel_path, '--find-links', pkga_path / 'dist' + ] + result = script.run(*command, expect_error=True) + assert result.returncode != 0 + new_command = [sys.executable, '-m'] + command + assert 'To modify pip, please run the following command:\n{}'.format( + ' '.join(new_command)) in result.stderr, str(result) From a1fa84e57e6a15033a173ef21c0bfe13f193a9f2 Mon Sep 17 00:00:00 2001 From: Albert Tugushev Date: Tue, 13 Aug 2019 01:34:35 +0300 Subject: [PATCH 2/5] Address review comments Handle the case of invoking pip via pip3 and pip3.7 --- src/pip/_internal/utils/misc.py | 11 +++++------ tests/functional/test_install.py | 14 +++++++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/pip/_internal/utils/misc.py b/src/pip/_internal/utils/misc.py index 15eb01dc1de..5d359f62cbe 100644 --- a/src/pip/_internal/utils/misc.py +++ b/src/pip/_internal/utils/misc.py @@ -1184,12 +1184,11 @@ def protect_pip_from_modification_on_windows(modifying_pip): On Windows, any operation modifying pip should be run as: python -m pip ... """ - pip_names = [ - "pip", - "pip.exe", - "pip{}.exe".format(sys.version_info[0]), - "pip{}.{}.exe".format(*sys.version_info[:2]) - ] + pip_names = set() + for ext in ('', '.exe'): + pip_names.add('pip{0}'.format(ext)) + pip_names.add('pip{0}{1}'.format(sys.version_info[0], ext)) + pip_names.add('pip{0}.{1}{ext}'.format(*sys.version_info[:2], ext=ext)) # See https://github.com/pypa/pip/issues/1299 for more discussion should_show_use_python_msg = ( diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index ba36a2844bf..c0266067eef 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -1531,14 +1531,22 @@ def test_target_install_ignores_distutils_config_install_prefix(script): @pytest.mark.skipif("sys.platform != 'win32'") -def test_protect_pip_from_modification_on_windows(script): +@pytest.mark.parametrize('pip_name', [ + 'pip', + 'pip{}'.format(sys.version_info[0]), + 'pip{}.{}'.format(*sys.version_info[:2]), + 'pip.exe', + 'pip{}.exe'.format(sys.version_info[0]), + 'pip{}.{}.exe'.format(*sys.version_info[:2]) +]) +def test_protect_pip_from_modification_on_windows(script, pip_name): """ Test ``pip install --upgrade pip`` is raised an error on Windows. """ - command = ['pip', 'install', '--upgrade', 'pip'] + command = [pip_name, 'install', '--upgrade', 'pip'] result = script.run(*command, expect_error=True) assert result.returncode != 0 - new_command = [sys.executable, '-m'] + command + new_command = [sys.executable, '-m', 'pip'] + command[1:] assert 'To modify pip, please run the following command:\n{}'.format( ' '.join(new_command)) in result.stderr, str(result) From 94979001e091869112f8d1e5f88675bf484300c3 Mon Sep 17 00:00:00 2001 From: Albert Tugushev Date: Tue, 13 Aug 2019 12:46:18 +0300 Subject: [PATCH 3/5] Address review comments Fix typos and remove unneeded assertions. --- tests/functional/test_install.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index c0266067eef..ce2ecf5eaad 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -1554,7 +1554,7 @@ def test_protect_pip_from_modification_on_windows(script, pip_name): @pytest.mark.skipif("sys.platform != 'win32'") def test_protect_pip_from_modification_via_deps_on_windows(script, with_wheel): """ - Test ``pip install pkga`` is raised and error on Windows + Test ``pip install pkga`` is raised an error on Windows if `pkga` implicitly tries to upgrade pip. """ # Make a wheel for pkga which requires pip @@ -1566,10 +1566,9 @@ def test_protect_pip_from_modification_via_deps_on_windows(script, with_wheel): version='0.1', install_requires = ["pip<{}"]) """.format(pip.__version__))) - result = script.run( + script.run( 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkga_path ) - assert result.returncode == 0 # Make sure pip install pkga is raised error pkga_wheel_path = './pkga/dist/pkga-0.1-py2.py3-none-any.whl' @@ -1586,8 +1585,8 @@ def test_protect_pip_from_modification_via_sub_deps_on_windows( script, with_wheel ): """ - Test ``pip install pkga`` is raised and error on Windows - if sub-dependencies of `pkga` implicitly tries to upgrade pip. + Test ``pip install pkg`` is raised an error on Windows + if sub-dependencies of `pkg` implicitly tries to upgrade pip. """ # Make a wheel for pkga which requires pip script.scratch_path.joinpath('pkga').mkdir() @@ -1598,12 +1597,11 @@ def test_protect_pip_from_modification_via_sub_deps_on_windows( version='0.1', install_requires = ["pip<{}"]) """.format(pip.__version__))) - result = script.run( + script.run( 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkga_path ) - assert result.returncode == 0 - # Make a wheel for pkgb which requires pkgb + # Make a wheel for pkgb which requires pkga script.scratch_path.joinpath('pkgb').mkdir() pkgb_path = script.scratch_path / 'pkgb' pkgb_path.joinpath('setup.py').write_text(textwrap.dedent(""" @@ -1612,12 +1610,11 @@ def test_protect_pip_from_modification_via_sub_deps_on_windows( version='0.1', install_requires = ["pkga"]) """)) - result = script.run( + script.run( 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkgb_path ) - assert result.returncode == 0 - # Make sure pip install pkgb is raised error + # Make sure pip install pkgb is raised an error pkgb_wheel_path = './pkgb/dist/pkgb-0.1-py2.py3-none-any.whl' command = [ 'pip', 'install', pkgb_wheel_path, '--find-links', pkga_path / 'dist' From 173761c03070db2795349f61b7c0229eb666b3ef Mon Sep 17 00:00:00 2001 From: Albert Tugushev Date: Wed, 14 Aug 2019 11:23:38 +0300 Subject: [PATCH 4/5] Address review comments Rebased to the latest master Remove unneeded assertions Use create_basic_wheel_for_package Couple other nitpicks --- src/pip/_internal/utils/misc.py | 6 +- tests/functional/test_install.py | 100 ++++++++++++++----------------- 2 files changed, 47 insertions(+), 59 deletions(-) diff --git a/src/pip/_internal/utils/misc.py b/src/pip/_internal/utils/misc.py index 5d359f62cbe..2a6735b7f4a 100644 --- a/src/pip/_internal/utils/misc.py +++ b/src/pip/_internal/utils/misc.py @@ -1186,9 +1186,9 @@ def protect_pip_from_modification_on_windows(modifying_pip): """ pip_names = set() for ext in ('', '.exe'): - pip_names.add('pip{0}'.format(ext)) - pip_names.add('pip{0}{1}'.format(sys.version_info[0], ext)) - pip_names.add('pip{0}.{1}{ext}'.format(*sys.version_info[:2], ext=ext)) + pip_names.add('pip{ext}'.format(ext=ext)) + pip_names.add('pip{}{ext}'.format(sys.version_info[0], ext=ext)) + pip_names.add('pip{}.{}{ext}'.format(*sys.version_info[:2], ext=ext)) # See https://github.com/pypa/pip/issues/1299 for more discussion should_show_use_python_msg = ( diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index ce2ecf5eaad..ac8aad9a2ae 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -7,7 +7,7 @@ import pytest -import pip +from pip import __version__ as pip_current_version from pip._internal import pep425tags from pip._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.models.index import PyPI, TestPyPI @@ -1530,6 +1530,7 @@ def test_target_install_ignores_distutils_config_install_prefix(script): ), str(result) +@pytest.mark.network @pytest.mark.skipif("sys.platform != 'win32'") @pytest.mark.parametrize('pip_name', [ 'pip', @@ -1541,86 +1542,73 @@ def test_target_install_ignores_distutils_config_install_prefix(script): ]) def test_protect_pip_from_modification_on_windows(script, pip_name): """ - Test ``pip install --upgrade pip`` is raised an error on Windows. + Test that pip modification command using ``pip install ...`` + raises an error on Windows. """ - command = [pip_name, 'install', '--upgrade', 'pip'] + command = [pip_name, 'install', 'pip != {}'.format(pip_current_version)] result = script.run(*command, expect_error=True) - assert result.returncode != 0 new_command = [sys.executable, '-m', 'pip'] + command[1:] - assert 'To modify pip, please run the following command:\n{}'.format( - ' '.join(new_command)) in result.stderr, str(result) + expected_message = ( + 'To modify pip, please run the following command:\n{}' + .format(' '.join(new_command)) + ) + assert expected_message in result.stderr, str(result) +@pytest.mark.network @pytest.mark.skipif("sys.platform != 'win32'") -def test_protect_pip_from_modification_via_deps_on_windows(script, with_wheel): +def test_protect_pip_from_modification_via_deps_on_windows(script): """ Test ``pip install pkga`` is raised an error on Windows if `pkga` implicitly tries to upgrade pip. """ - # Make a wheel for pkga which requires pip - script.scratch_path.joinpath('pkga').mkdir() - pkga_path = script.scratch_path / 'pkga' - pkga_path.joinpath('setup.py').write_text(textwrap.dedent(""" - from setuptools import setup - setup(name='pkga', - version='0.1', - install_requires = ["pip<{}"]) - """.format(pip.__version__))) - script.run( - 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkga_path + pkga_wheel_path = create_basic_wheel_for_package( + script, + 'pkga', '0.1', + depends=['pip != {}'.format(pip_current_version)], ) - # Make sure pip install pkga is raised error - pkga_wheel_path = './pkga/dist/pkga-0.1-py2.py3-none-any.whl' + # Make sure pip install pkga is raised an error command = ['pip', 'install', pkga_wheel_path] result = script.run(*command, expect_error=True) - assert result.returncode != 0 new_command = [sys.executable, "-m"] + command - assert "To modify pip, please run the following command:\n{}".format( - " ".join(new_command)) in result.stderr, str(result) + expected_message = ( + 'To modify pip, please run the following command:\n{}' + .format(' '.join(new_command)) + ) + assert expected_message in result.stderr, str(result) +@pytest.mark.network @pytest.mark.skipif("sys.platform != 'win32'") -def test_protect_pip_from_modification_via_sub_deps_on_windows( - script, with_wheel -): +def test_protect_pip_from_modification_via_sub_deps_on_windows(script): """ - Test ``pip install pkg`` is raised an error on Windows - if sub-dependencies of `pkg` implicitly tries to upgrade pip. + Test ``pip install pkga`` is raised an error on Windows + if sub-dependencies of `pkga` implicitly tries to upgrade pip. """ - # Make a wheel for pkga which requires pip - script.scratch_path.joinpath('pkga').mkdir() - pkga_path = script.scratch_path / 'pkga' - pkga_path.joinpath('setup.py').write_text(textwrap.dedent(""" - from setuptools import setup - setup(name='pkga', - version='0.1', - install_requires = ["pip<{}"]) - """.format(pip.__version__))) - script.run( - 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkga_path + # Make a wheel for pkga which requires pkgb + pkga_wheel_path = create_basic_wheel_for_package( + script, + 'pkga', '0.1', + depends=['pkgb'], ) - # Make a wheel for pkgb which requires pkga - script.scratch_path.joinpath('pkgb').mkdir() - pkgb_path = script.scratch_path / 'pkgb' - pkgb_path.joinpath('setup.py').write_text(textwrap.dedent(""" - from setuptools import setup - setup(name='pkgb', - version='0.1', - install_requires = ["pkga"]) - """)) - script.run( - 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=pkgb_path + # Make a wheel for pkgb which requires pip + pkgb_wheel_path = create_basic_wheel_for_package( + script, + 'pkgb', '0.1', + depends=['pip != {}'.format(pip_current_version)], ) - # Make sure pip install pkgb is raised an error - pkgb_wheel_path = './pkgb/dist/pkgb-0.1-py2.py3-none-any.whl' + # Make sure pip install pkga is raised an error command = [ - 'pip', 'install', pkgb_wheel_path, '--find-links', pkga_path / 'dist' + 'pip', 'install', pkga_wheel_path, + '--find-links', pkgb_wheel_path.parent, ] result = script.run(*command, expect_error=True) - assert result.returncode != 0 new_command = [sys.executable, '-m'] + command - assert 'To modify pip, please run the following command:\n{}'.format( - ' '.join(new_command)) in result.stderr, str(result) + expected_message = ( + 'To modify pip, please run the following command:\n{}' + .format(' '.join(new_command)) + ) + assert expected_message in result.stderr, str(result) From f9fc6673257c0cb8854e3df03f11c6ec91b5b8a8 Mon Sep 17 00:00:00 2001 From: Albert Tugushev Date: Wed, 14 Aug 2019 18:59:46 +0300 Subject: [PATCH 5/5] Addrees review comments Fix typos Use script.pip instead of script.run --- tests/functional/test_install.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index ac8aad9a2ae..852f2dde8b3 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -1559,7 +1559,7 @@ def test_protect_pip_from_modification_on_windows(script, pip_name): @pytest.mark.skipif("sys.platform != 'win32'") def test_protect_pip_from_modification_via_deps_on_windows(script): """ - Test ``pip install pkga`` is raised an error on Windows + Test ``pip install pkga`` raises an error on Windows if `pkga` implicitly tries to upgrade pip. """ pkga_wheel_path = create_basic_wheel_for_package( @@ -1568,10 +1568,10 @@ def test_protect_pip_from_modification_via_deps_on_windows(script): depends=['pip != {}'.format(pip_current_version)], ) - # Make sure pip install pkga is raised an error - command = ['pip', 'install', pkga_wheel_path] - result = script.run(*command, expect_error=True) - new_command = [sys.executable, "-m"] + command + # Make sure pip install pkga raises an error + args = ['install', pkga_wheel_path] + result = script.pip(*args, expect_error=True, use_module=False) + new_command = [sys.executable, '-m', 'pip'] + args expected_message = ( 'To modify pip, please run the following command:\n{}' .format(' '.join(new_command)) @@ -1583,7 +1583,7 @@ def test_protect_pip_from_modification_via_deps_on_windows(script): @pytest.mark.skipif("sys.platform != 'win32'") def test_protect_pip_from_modification_via_sub_deps_on_windows(script): """ - Test ``pip install pkga`` is raised an error on Windows + Test ``pip install pkga`` raises an error on Windows if sub-dependencies of `pkga` implicitly tries to upgrade pip. """ # Make a wheel for pkga which requires pkgb @@ -1600,13 +1600,12 @@ def test_protect_pip_from_modification_via_sub_deps_on_windows(script): depends=['pip != {}'.format(pip_current_version)], ) - # Make sure pip install pkga is raised an error - command = [ - 'pip', 'install', pkga_wheel_path, - '--find-links', pkgb_wheel_path.parent, + # Make sure pip install pkga raises an error + args = [ + 'install', pkga_wheel_path, '--find-links', pkgb_wheel_path.parent ] - result = script.run(*command, expect_error=True) - new_command = [sys.executable, '-m'] + command + result = script.pip(*args, expect_error=True, use_module=False) + new_command = [sys.executable, '-m', 'pip'] + args expected_message = ( 'To modify pip, please run the following command:\n{}' .format(' '.join(new_command))