import logging import pretend import pytest from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS from pip._internal.commands import create_command from pip._internal.commands.search import highest_version, print_results, transform_hits from tests.lib import pyversion if pyversion >= '3': VERBOSE_FALSE = False else: VERBOSE_FALSE = 0 def test_version_compare(): """ Test version comparison. """ assert highest_version(['1.0', '2.0', '0.1']) == '2.0' assert highest_version(['1.0a1', '1.0']) == '1.0' def test_pypi_xml_transformation(): """ Test transformation of data structures (PyPI xmlrpc to custom list). """ pypi_hits = [ { 'name': 'foo', 'summary': 'foo summary', 'version': '1.0', }, { 'name': 'foo', 'summary': 'foo summary v2', 'version': '2.0', }, { '_pypi_ordering': 50, 'name': 'bar', 'summary': 'bar summary', 'version': '1.0', }, ] expected = [ { 'versions': ['1.0', '2.0'], 'name': 'foo', 'summary': 'foo summary v2', }, { 'versions': ['1.0'], 'name': 'bar', 'summary': 'bar summary', }, ] assert transform_hits(pypi_hits) == expected @pytest.mark.network def test_basic_search(script): """ End to end test of search command. """ output = script.pip('search', 'pip') assert ( 'The PyPA recommended tool for installing ' 'Python packages.' in output.stdout ) @pytest.mark.network @pytest.mark.skip( reason=("Warehouse search behavior is different and no longer returns " "multiple results. See " "https://github.com/pypa/warehouse/issues/3717 for more " "information."), ) def test_multiple_search(script): """ Test searching for multiple packages at once. """ output = script.pip('search', 'pip', 'INITools') assert ( 'The PyPA recommended tool for installing ' 'Python packages.' in output.stdout ) assert 'Tools for parsing and using INI-style files' in output.stdout def test_search_missing_argument(script): """ Test missing required argument for search """ result = script.pip('search', expect_error=True) assert 'ERROR: Missing required argument (search query).' in result.stderr @pytest.mark.network def test_run_method_should_return_success_when_find_packages(): """ Test SearchCommand.run for found package """ command = create_command('search') cmdline = "--index=https://pypi.org/pypi pip" with command.main_context(): options, args = command.parse_args(cmdline.split()) status = command.run(options, args) assert status == SUCCESS @pytest.mark.network def test_run_method_should_return_no_matches_found_when_does_not_find_pkgs(): """ Test SearchCommand.run for no matches """ command = create_command('search') cmdline = "--index=https://pypi.org/pypi nonexistentpackage" with command.main_context(): options, args = command.parse_args(cmdline.split()) status = command.run(options, args) assert status == NO_MATCHES_FOUND @pytest.mark.network def test_search_should_exit_status_code_zero_when_find_packages(script): """ Test search exit status code for package found """ result = script.pip('search', 'pip') assert result.returncode == SUCCESS @pytest.mark.network def test_search_exit_status_code_when_finds_no_package(script): """ Test search exit status code for no matches """ result = script.pip('search', 'nonexistentpackage', expect_error=True) assert result.returncode == NO_MATCHES_FOUND, result.returncode def test_latest_prerelease_install_message(caplog, monkeypatch): """ Test documentation for installing pre-release packages is displayed """ hits = [ { 'name': 'ni', 'summary': 'For knights who say Ni!', 'versions': ['1.0.0', '1.0.1a'] } ] installed_package = pretend.stub(project_name="ni") monkeypatch.setattr("pip._vendor.pkg_resources.working_set", [installed_package]) dist = pretend.stub(version="1.0.0") get_dist = pretend.call_recorder(lambda x: dist) monkeypatch.setattr("pip._internal.commands.search.get_distribution", get_dist) with caplog.at_level(logging.INFO): print_results(hits) message = caplog.records[-1].getMessage() assert 'pre-release; install with "pip install --pre"' in message assert get_dist.calls == [pretend.call('ni')] 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'] } ] with caplog.at_level(logging.INFO): 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)')