diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | pip/basecommand.py | 2 | ||||
-rw-r--r-- | pip/models/index.py | 1 | ||||
-rw-r--r-- | pip/utils/outdated.py | 29 | ||||
-rw-r--r-- | setup.py | 10 | ||||
-rw-r--r-- | tests/unit/test_unit_outdated.py | 104 |
6 files changed, 93 insertions, 54 deletions
diff --git a/.gitignore b/.gitignore index 1eac77423..9ed67ea95 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ MANIFEST .tox .cache *.egg +*.eggs *.py[cod] *~ .coverage diff --git a/pip/basecommand.py b/pip/basecommand.py index 49c134071..bd2f788a1 100644 --- a/pip/basecommand.py +++ b/pip/basecommand.py @@ -248,7 +248,7 @@ class Command(object): options, retries=0, timeout=min(5, options.timeout)) as session: - pip_version_check(session) + pip_version_check(session, options) return SUCCESS diff --git a/pip/models/index.py b/pip/models/index.py index be9911988..3d0042e3a 100644 --- a/pip/models/index.py +++ b/pip/models/index.py @@ -7,7 +7,6 @@ class Index(object): self.netloc = urllib_parse.urlsplit(url).netloc self.simple_url = self.url_to_path('simple') self.pypi_url = self.url_to_path('pypi') - self.pip_json_url = self.url_to_path('pypi/pip/json') def url_to_path(self, path): return urllib_parse.urljoin(self.url, path) diff --git a/pip/utils/outdated.py b/pip/utils/outdated.py index 78ca2bbeb..fe08eb45c 100644 --- a/pip/utils/outdated.py +++ b/pip/utils/outdated.py @@ -11,6 +11,7 @@ from pip._vendor.packaging import version as packaging_version from pip.compat import WINDOWS from pip.models import PyPI +from pip.index import PackageFinder from pip.locations import USER_CACHE_DIR, running_under_virtualenv from pip.utils import ensure_dir, get_installed_version from pip.utils.filesystem import check_path_owner @@ -92,7 +93,7 @@ def load_selfcheck_statefile(): return GlobalSelfCheckState() -def pip_version_check(session): +def pip_version_check(session, options): """Check for an update for pip. Limit the frequency of checks to once per week. State is stored either in @@ -100,7 +101,7 @@ def pip_version_check(session): of the pip script path. """ installed_version = get_installed_version("pip") - if installed_version is None: + if not installed_version: return pip_version = packaging_version.parse(installed_version) @@ -121,18 +122,19 @@ def pip_version_check(session): # Refresh the version if we need to or just see if we need to warn if pypi_version is None: - resp = session.get( - PyPI.pip_json_url, - headers={"Accept": "application/json"}, + # Lets use PackageFinder to see what the latest pip version is + finder = PackageFinder( + find_links=options.find_links, + index_urls=[options.index_url] + options.extra_index_urls, + allow_all_prereleases=False, # Explicitly set to False + trusted_hosts=options.trusted_hosts, + process_dependency_links=options.process_dependency_links, + session=session, ) - resp.raise_for_status() - pypi_version = [ - v for v in sorted( - list(resp.json()["releases"]), - key=packaging_version.parse, - ) - if not packaging_version.parse(v).is_prerelease - ][-1] + all_candidates = finder.find_all_candidates("pip") + if not all_candidates: + return + pypi_version = max(all_candidates, key=lambda c: c.version).version # save that we've performed a check state.save(pypi_version, current_time) @@ -154,7 +156,6 @@ def pip_version_check(session): "'%s install --upgrade pip' command.", pip_version, pypi_version, pip_cmd ) - except Exception: logger.debug( "There was an error checking the latest version of pip", @@ -42,8 +42,14 @@ def find_version(*file_paths): long_description = read('README.rst') -tests_require = ['pytest', 'virtualenv>=1.10', 'scripttest>=1.3', 'mock', - 'pretend'] +tests_require = [ + 'pytest', + 'mock', + 'pretend' + 'scripttest>=1.3', + 'virtualenv>=1.10', + 'freezegun', +] setup( diff --git a/tests/unit/test_unit_outdated.py b/tests/unit/test_unit_outdated.py index d2d9c3f14..24313c8f3 100644 --- a/tests/unit/test_unit_outdated.py +++ b/tests/unit/test_unit_outdated.py @@ -8,43 +8,73 @@ import pytest import pretend from pip._vendor import lockfile +from pip.index import InstallationCandidate from pip.utils import outdated +class MockPackageFinder(object): + + BASE_URL = 'https://pypi.python.org/simple/pip-{0}.tar.gz' + PIP_PROJECT_NAME = 'pip' + INSTALLATION_CANDIDATES = [ + InstallationCandidate(PIP_PROJECT_NAME, '6.9.0', + BASE_URL.format('6.9.0')), + InstallationCandidate(PIP_PROJECT_NAME, '3.3.1', + BASE_URL.format('3.3.1')), + InstallationCandidate(PIP_PROJECT_NAME, '1.0', + BASE_URL.format('1.0')), + ] + + def __init__(self, *args, **kwargs): + pass + + def find_all_candidates(self, project_name): + return self.INSTALLATION_CANDIDATES + + +def _options(): + ''' Some default options that we pass to outdated.pip_version_check ''' + return pretend.stub( + find_links=False, extra_index_urls=[], index_url='default_url', + pre=False, trusted_hosts=False, process_dependency_links=False, + ) + + @pytest.mark.parametrize( - ['stored_time', 'newver', 'check', 'warn'], [ - ('1970-01-01T10:00:00Z', '2.0', True, True), - ('1970-01-01T10:00:00Z', '1.0', True, False), - ('1970-01-06T10:00:00Z', '1.0', False, False), - ('1970-01-06T10:00:00Z', '2.0', False, True), + 'stored_time', + 'installed_ver', + 'new_ver', + 'check_if_upgrade_required', + 'check_warn_logs', + ], + [ + # Test we return None when installed version is None + ('1970-01-01T10:00:00Z', None, '1.0', False, False), + # Need an upgrade - upgrade warning should print + ('1970-01-01T10:00:00Z', '1.0', '6.9.0', True, True), + # No upgrade - upgrade warning should not print + ('1970-01-9T10:00:00Z', '6.9.0', '6.9.0', False, False), ] ) -def test_pip_version_check(monkeypatch, stored_time, newver, check, warn): - monkeypatch.setattr(outdated, 'get_installed_version', lambda name: '1.0') - - resp = pretend.stub( - raise_for_status=pretend.call_recorder(lambda: None), - json=pretend.call_recorder(lambda: {"releases": {newver: {}}}), - ) - session = pretend.stub( - get=pretend.call_recorder(lambda u, headers=None: resp), - ) +def test_pip_version_check(monkeypatch, stored_time, installed_ver, new_ver, + check_if_upgrade_required, check_warn_logs): + monkeypatch.setattr(outdated, 'get_installed_version', + lambda name: installed_ver) + monkeypatch.setattr(outdated, 'PackageFinder', MockPackageFinder) + monkeypatch.setattr(outdated.logger, 'warning', + pretend.call_recorder(lambda *a, **kw: None)) + monkeypatch.setattr(outdated.logger, 'debug', + pretend.call_recorder(lambda s, exc_info=None: None)) fake_state = pretend.stub( - state={"last_check": stored_time, 'pypi_version': '1.0'}, + state={"last_check": stored_time, 'pypi_version': installed_ver}, save=pretend.call_recorder(lambda v, t: None), ) - monkeypatch.setattr( outdated, 'load_selfcheck_statefile', lambda: fake_state ) - monkeypatch.setattr(outdated.logger, 'warning', - pretend.call_recorder(lambda *a, **kw: None)) - monkeypatch.setattr(outdated.logger, 'debug', - pretend.call_recorder(lambda s, exc_info=None: None)) - with freezegun.freeze_time( "1970-01-09 10:00:00", ignore=[ @@ -52,26 +82,28 @@ def test_pip_version_check(monkeypatch, stored_time, newver, check, warn): "pip._vendor.six.moves", "pip._vendor.requests.packages.urllib3.packages.six.moves", ]): - outdated.pip_version_check(session) + latest_pypi_version = outdated.pip_version_check(None, _options()) - assert not outdated.logger.debug.calls - - if check: - assert session.get.calls == [pretend.call( - "https://pypi.python.org/pypi/pip/json", - headers={"Accept": "application/json"} - )] + # See we return None if not installed_version + if not installed_ver: + assert not latest_pypi_version + # See that we saved the correct version + elif check_if_upgrade_required: assert fake_state.save.calls == [ - pretend.call(newver, datetime.datetime(1970, 1, 9, 10, 00, 00)), + pretend.call(new_ver, datetime.datetime(1970, 1, 9, 10, 00, 00)), ] - if warn: - assert len(outdated.logger.warning.calls) == 1 - else: - assert len(outdated.logger.warning.calls) == 0 else: - assert session.get.calls == [] + # Make sure no Exceptions + assert not outdated.logger.debug.calls + # See that save was not called assert fake_state.save.calls == [] + # Ensure we warn the user or not + if check_warn_logs: + assert len(outdated.logger.warning.calls) == 1 + else: + assert len(outdated.logger.warning.calls) == 0 + def test_virtualenv_state(monkeypatch): CONTENT = '{"last_check": "1970-01-02T11:00:00Z", "pypi_version": "1.0"}' |