From 94fcd18ed4d537b4da2b427df99a8141787c03a4 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Fri, 6 Mar 2015 01:22:34 -0800 Subject: [PATCH] Fix for #770: pip install -U shouldn't look at pypi if not needed If an exact version is specified for install, and that version is already installed, then there is no point going to pypi as no install is needed. Adds a test called `test_upgrade_no_look_at_pypi_if_exact_version_installed`. This is a rework of PR #771, because that PR is old and has merge conflicts that were easier to fix by applying the changes manually. --- pip/req/req_set.py | 7 +++++- tests/unit/test_req.py | 55 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/pip/req/req_set.py b/pip/req/req_set.py index 9c382650a46..1b80f191ef8 100644 --- a/pip/req/req_set.py +++ b/pip/req/req_set.py @@ -225,7 +225,12 @@ def prepare_files(self, finder): if not self.ignore_installed and not req_to_install.editable: req_to_install.check_if_exists() if req_to_install.satisfied_by: - if self.upgrade: + # check that we don't already have an exact version match + # i.e. with at least one strict req operator + strict_req = set(('==', '===')) & set( + op for op, _ in req_to_install.req.specs) + if self.upgrade and (not strict_req or + self.force_reinstall): if not (self.force_reinstall or req_to_install.link): try: link = finder.find_requirement( diff --git a/tests/unit/test_req.py b/tests/unit/test_req.py index 35d7cd11ac2..7f38cfdcc9c 100644 --- a/tests/unit/test_req.py +++ b/tests/unit/test_req.py @@ -8,6 +8,7 @@ from mock import Mock, patch, mock_open from pip.exceptions import ( PreviousBuildDirError, InvalidWheelFilename, UnsupportedWheel, + BestVersionAlreadyInstalled, ) from pip.download import PipSession from pip.index import PackageFinder @@ -54,6 +55,60 @@ def test_no_reuse_existing_build_dir(self, data): finder, ) + @patch( + 'pip.req.req_install.pkg_resources.get_distribution', + lambda x: pkg_resources.Distribution( + project_name='Pygments', + version='2.0.2', + location='/python', + ) + ) + def test_upgrade_no_look_at_pypi_if_exact_version_installed( + self, data): + """ + If an exact version is specified for install, and that version is + already installed, then there is no point going to pypi as no install + is needed. + """ + reqset = self.basic_reqset() + reqset.upgrade = True + req = InstallRequirement.from_line('pygments==2.0.2') + req.url = None + reqset.add_requirement(req) + finder = PackageFinder([data.find_links], [], session=PipSession()) + with patch.object(finder, 'find_requirement') as find_requirement: + find_requirement.side_effect = AssertionError( + 'find_requirement should NOT be called') + reqset.prepare_files(finder) + + @patch( + 'pip.req.req_install.pkg_resources.get_distribution', + lambda x: pkg_resources.Distribution( + project_name='Pygments', + version='2.0.2', + location='/python', + ) + ) + def test_upgrade_look_at_pypi_if_exact_version_installed_and_force( + self, data): + """ + If an exact version is specified for install, and that version is + already installed, but --force-reinstall was provided, we should hit + PyPI. + """ + reqset = self.basic_reqset() + reqset.upgrade = True + reqset.force_reinstall = True + req = InstallRequirement.from_line('pygments==2.0.2') + req.url = None + reqset.add_requirement(req) + finder = PackageFinder([data.find_links], [], session=PipSession()) + with patch.object(finder, 'find_requirement') as find_requirement: + find_requirement.side_effect = BestVersionAlreadyInstalled + with pytest.raises(BestVersionAlreadyInstalled): + reqset.prepare_files(finder) + find_requirement.assert_called_once() + def test_environment_marker_extras(self, data): """ Test that the environment marker extras are used with