2018-06-14 09:02:37 +02:00
|
|
|
import logging
|
|
|
|
|
2018-10-26 14:17:01 +02:00
|
|
|
import pretend
|
2015-01-15 00:53:15 +01:00
|
|
|
import pytest
|
2017-06-13 14:17:00 +02:00
|
|
|
|
2018-07-30 06:10:59 +02:00
|
|
|
from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS
|
2019-07-10 09:36:33 +02:00
|
|
|
from pip._internal.commands import create_command
|
2017-08-31 17:48:18 +02:00
|
|
|
from pip._internal.commands.search import (
|
2019-07-22 06:45:27 +02:00
|
|
|
highest_version,
|
|
|
|
print_results,
|
|
|
|
transform_hits,
|
2017-05-16 12:16:30 +02:00
|
|
|
)
|
2013-08-22 06:40:46 +02:00
|
|
|
from tests.lib import pyversion
|
2011-03-15 20:49:48 +01:00
|
|
|
|
|
|
|
if pyversion >= '3':
|
|
|
|
VERBOSE_FALSE = False
|
|
|
|
else:
|
|
|
|
VERBOSE_FALSE = 0
|
2010-02-24 11:24:55 +01:00
|
|
|
|
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_version_compare():
|
|
|
|
"""
|
|
|
|
Test version comparison.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-02-24 11:24:55 +01:00
|
|
|
assert highest_version(['1.0', '2.0', '0.1']) == '2.0'
|
|
|
|
assert highest_version(['1.0a1', '1.0']) == '1.0'
|
|
|
|
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_pypi_xml_transformation():
|
|
|
|
"""
|
2018-09-16 22:21:09 +02:00
|
|
|
Test transformation of data structures (PyPI xmlrpc to custom list).
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2014-01-28 15:17:51 +01:00
|
|
|
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',
|
|
|
|
},
|
|
|
|
]
|
2013-08-21 11:16:07 +02:00
|
|
|
assert transform_hits(pypi_hits) == expected
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2012-05-14 05:13:50 +02:00
|
|
|
|
2015-01-15 00:53:15 +01:00
|
|
|
@pytest.mark.network
|
2017-12-16 19:13:46 +01:00
|
|
|
def test_basic_search(script):
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
|
|
|
End to end test of search command.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2013-08-21 11:16:07 +02:00
|
|
|
output = script.pip('search', 'pip')
|
2014-01-28 15:17:51 +01:00
|
|
|
assert (
|
2015-09-11 14:04:21 +02:00
|
|
|
'The PyPA recommended tool for installing '
|
|
|
|
'Python packages.' in output.stdout
|
2014-01-28 15:17:51 +01:00
|
|
|
)
|
2010-02-24 11:24:55 +01:00
|
|
|
|
2010-07-02 14:27:22 +02:00
|
|
|
|
2015-01-15 00:53:15 +01:00
|
|
|
@pytest.mark.network
|
2018-04-16 21:59:47 +02:00
|
|
|
@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."),
|
|
|
|
)
|
2013-08-22 06:40:46 +02:00
|
|
|
def test_multiple_search(script):
|
2011-04-16 18:00:10 +02:00
|
|
|
"""
|
2011-04-16 22:03:03 +02:00
|
|
|
Test searching for multiple packages at once.
|
2011-04-16 18:00:10 +02:00
|
|
|
|
|
|
|
"""
|
2013-08-21 11:16:07 +02:00
|
|
|
output = script.pip('search', 'pip', 'INITools')
|
2014-01-28 15:17:51 +01:00
|
|
|
assert (
|
2015-09-11 14:04:21 +02:00
|
|
|
'The PyPA recommended tool for installing '
|
|
|
|
'Python packages.' in output.stdout
|
2014-01-28 15:17:51 +01:00
|
|
|
)
|
2011-04-16 22:03:03 +02:00
|
|
|
assert 'Tools for parsing and using INI-style files' in output.stdout
|
2011-04-16 18:00:10 +02:00
|
|
|
|
|
|
|
|
2013-08-22 06:40:46 +02:00
|
|
|
def test_search_missing_argument(script):
|
2011-07-20 20:46:16 +02:00
|
|
|
"""
|
|
|
|
Test missing required argument for search
|
|
|
|
"""
|
2013-08-21 11:16:07 +02:00
|
|
|
result = script.pip('search', expect_error=True)
|
2015-03-16 13:34:52 +01:00
|
|
|
assert 'ERROR: Missing required argument (search query).' in result.stderr
|
2011-08-02 19:16:18 +02:00
|
|
|
|
2012-01-30 07:26:12 +01:00
|
|
|
|
2015-01-15 00:53:15 +01:00
|
|
|
@pytest.mark.network
|
2015-12-26 23:58:23 +01:00
|
|
|
def test_run_method_should_return_success_when_find_packages():
|
2011-08-02 19:16:18 +02:00
|
|
|
"""
|
|
|
|
Test SearchCommand.run for found package
|
|
|
|
"""
|
2019-07-10 09:36:33 +02:00
|
|
|
command = create_command('search')
|
2018-04-13 14:08:51 +02:00
|
|
|
cmdline = "--index=https://pypi.org/pypi pip"
|
2019-09-03 00:48:15 +02:00
|
|
|
with command.main_context():
|
|
|
|
options, args = command.parse_args(cmdline.split())
|
|
|
|
status = command.run(options, args)
|
2011-08-02 19:16:18 +02:00
|
|
|
assert status == SUCCESS
|
|
|
|
|
2012-01-30 07:26:12 +01:00
|
|
|
|
2015-01-15 00:53:15 +01:00
|
|
|
@pytest.mark.network
|
2014-01-28 15:17:51 +01:00
|
|
|
def test_run_method_should_return_no_matches_found_when_does_not_find_pkgs():
|
2011-08-02 19:16:18 +02:00
|
|
|
"""
|
|
|
|
Test SearchCommand.run for no matches
|
|
|
|
"""
|
2019-07-10 09:36:33 +02:00
|
|
|
command = create_command('search')
|
2018-04-13 14:08:51 +02:00
|
|
|
cmdline = "--index=https://pypi.org/pypi nonexistentpackage"
|
2019-09-03 00:48:15 +02:00
|
|
|
with command.main_context():
|
|
|
|
options, args = command.parse_args(cmdline.split())
|
|
|
|
status = command.run(options, args)
|
2014-06-28 00:26:40 +02:00
|
|
|
assert status == NO_MATCHES_FOUND
|
2011-08-02 19:16:18 +02:00
|
|
|
|
2012-01-30 07:26:12 +01:00
|
|
|
|
2015-01-15 00:53:15 +01:00
|
|
|
@pytest.mark.network
|
2013-08-22 06:40:46 +02:00
|
|
|
def test_search_should_exit_status_code_zero_when_find_packages(script):
|
2011-08-02 19:16:18 +02:00
|
|
|
"""
|
|
|
|
Test search exit status code for package found
|
|
|
|
"""
|
2013-08-21 11:16:07 +02:00
|
|
|
result = script.pip('search', 'pip')
|
2011-08-02 19:16:18 +02:00
|
|
|
assert result.returncode == SUCCESS
|
|
|
|
|
2012-01-30 07:26:12 +01:00
|
|
|
|
2015-01-15 00:53:15 +01:00
|
|
|
@pytest.mark.network
|
2013-08-22 06:40:46 +02:00
|
|
|
def test_search_exit_status_code_when_finds_no_package(script):
|
2011-08-02 19:16:18 +02:00
|
|
|
"""
|
|
|
|
Test search exit status code for no matches
|
|
|
|
"""
|
2015-09-14 10:01:57 +02:00
|
|
|
result = script.pip('search', 'nonexistentpackage', expect_error=True)
|
2013-05-27 19:46:31 +02:00
|
|
|
assert result.returncode == NO_MATCHES_FOUND, result.returncode
|
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.
2017-01-10 00:43:29 +01:00
|
|
|
|
|
|
|
|
2018-10-26 14:17:01 +02:00
|
|
|
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._vendor.pkg_resources.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')]
|
|
|
|
|
|
|
|
|
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.
2017-01-10 00:43:29 +01:00
|
|
|
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']
|
|
|
|
}
|
|
|
|
]
|
2018-06-14 09:02:37 +02:00
|
|
|
|
|
|
|
with caplog.at_level(logging.INFO):
|
|
|
|
print_results(hits)
|
|
|
|
|
2017-10-02 19:33:52 +02:00
|
|
|
log_messages = sorted([r.getMessage() for r in caplog.records])
|
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.
2017-01-10 00:43:29 +01:00
|
|
|
assert log_messages[0].startswith('testlib1 (1.0.5)')
|
|
|
|
assert log_messages[1].startswith('testlib2 (2.0.3)')
|