From 2bdc93dd7b07c0f86fb589fe7c6d79875a92b583 Mon Sep 17 00:00:00 2001 From: Igor Kuzmitshov Date: Mon, 9 Jan 2017 23:43:29 +0000 Subject: [PATCH] Fix the latest version number in search results When listing found packages, `print_results()` uses the last version in the versions list of a package, but that version is not necessarily the latest. For example, `SearchCommand.search()` may return the following (tested with JFrog Artifactory PyPI repo): pypi_hits = command.search(args, options) [{'_pypi_ordering': 1, 'name': 'testlib', 'summary': 'Test library.', 'version': '1.0.5'}, {'_pypi_ordering': 0, 'name': 'testlib', 'summary': 'Test library.', 'version': '1.0.3'}] `pip.commands.search.transform_hits()` preserves the order of versions: hits = pip.commands.search.transform_hits(pypi_hits) [{'name': 'testlib', 'summary': 'Test library.', 'versions': ['1.0.5', '1.0.3']}] `pip.commands.search.print_results()` uses the last version in the list: pip.commands.search.print_results(hits) testlib (1.0.3) - Test library. Expected result: testlib (1.0.5) - Test library. `print_results()` uses `highest_version()` already to compare the installed version with the latest found version (for installed packages). Same function is used in this fix to show the latest versions of all found packages. --- pip/commands/search.py | 7 +++---- tests/functional/test_search.py | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/pip/commands/search.py b/pip/commands/search.py index bd2ea8ad3..d969c5497 100644 --- a/pip/commands/search.py +++ b/pip/commands/search.py @@ -96,7 +96,7 @@ def print_results(hits, name_column_width=None, terminal_width=None): return if name_column_width is None: name_column_width = max([ - len(hit['name']) + len(hit.get('versions', ['-'])[-1]) + len(hit['name']) + len(highest_version(hit.get('versions', ['-']))) for hit in hits ]) + 4 @@ -104,7 +104,7 @@ def print_results(hits, name_column_width=None, terminal_width=None): for hit in hits: name = hit['name'] summary = hit['summary'] or '' - version = hit.get('versions', ['-'])[-1] + latest = highest_version(hit.get('versions', ['-'])) if terminal_width is not None: target_width = terminal_width - name_column_width - 5 if target_width > 10: @@ -113,13 +113,12 @@ def print_results(hits, name_column_width=None, terminal_width=None): summary = ('\n' + ' ' * (name_column_width + 3)).join(summary) line = '%-*s - %s' % (name_column_width, - '%s (%s)' % (name, version), summary) + '%s (%s)' % (name, latest), summary) try: logger.info(line) if name in installed_packages: dist = pkg_resources.get_distribution(name) with indent_log(): - latest = highest_version(hit['versions']) if dist.version == latest: logger.info('INSTALLED: %s (latest)', dist.version) else: diff --git a/tests/functional/test_search.py b/tests/functional/test_search.py index 35b937f0f..be99ffbe7 100644 --- a/tests/functional/test_search.py +++ b/tests/functional/test_search.py @@ -1,5 +1,6 @@ import pytest from pip.commands.search import (highest_version, + print_results, transform_hits, SearchCommand) from pip.status_codes import NO_MATCHES_FOUND, SUCCESS @@ -134,3 +135,25 @@ def test_search_exit_status_code_when_finds_no_package(script): """ result = script.pip('search', 'nonexistentpackage', expect_error=True) assert result.returncode == NO_MATCHES_FOUND, result.returncode + + +def test_search_print_results_should_contain_latest_versions(caplog): + """ + Test that printed search results contain the latest package versions + """ + hits = [ + { + 'name': 'testlib1', + 'summary': 'Test library 1.', + 'versions': ['1.0.5', '1.0.3'] + }, + { + 'name': 'testlib2', + 'summary': 'Test library 1.', + 'versions': ['2.0.1', '2.0.3'] + } + ] + print_results(hits) + log_messages = sorted([r.getMessage() for r in caplog.records()]) + assert log_messages[0].startswith('testlib1 (1.0.5)') + assert log_messages[1].startswith('testlib2 (2.0.3)')