-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
Copy pathtest_search.py
209 lines (175 loc) · 5.92 KB
/
test_search.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import logging
from typing import TYPE_CHECKING, Dict, List
from unittest import mock
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 PipTestEnvironment
if TYPE_CHECKING:
from pip._internal.commands.search import TransformedHit
def test_version_compare() -> None:
"""
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() -> None:
"""
Test transformation of data structures (PyPI xmlrpc to custom list).
"""
pypi_hits: List[Dict[str, str]] = [
{
"name": "foo",
"summary": "foo summary",
"version": "1.0",
},
{
"name": "foo",
"summary": "foo summary v2",
"version": "2.0",
},
{
"_pypi_ordering": 50, # type: ignore[dict-item]
"name": "bar",
"summary": "bar summary",
"version": "1.0",
},
]
expected: List[TransformedHit] = [
{
"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
@pytest.mark.search
def test_basic_search(script: PipTestEnvironment) -> None:
"""
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."
),
)
@pytest.mark.search
def test_multiple_search(script: PipTestEnvironment) -> None:
"""
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
@pytest.mark.search
def test_search_missing_argument(script: PipTestEnvironment) -> None:
"""
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
@pytest.mark.search
def test_run_method_should_return_success_when_find_packages() -> None:
"""
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
@pytest.mark.search
def test_run_method_should_return_no_matches_found_when_does_not_find_pkgs() -> None:
"""
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
@pytest.mark.search
def test_search_should_exit_status_code_zero_when_find_packages(
script: PipTestEnvironment,
) -> None:
"""
Test search exit status code for package found
"""
result = script.pip("search", "pip")
assert result.returncode == SUCCESS
@pytest.mark.network
@pytest.mark.search
def test_search_exit_status_code_when_finds_no_package(
script: PipTestEnvironment,
) -> None:
"""
Test search exit status code for no matches
"""
result = script.pip("search", "nonexistentpackage", expect_error=True)
assert result.returncode == NO_MATCHES_FOUND, result.returncode
@pytest.mark.search
def test_latest_prerelease_install_message(
caplog: pytest.LogCaptureFixture, monkeypatch: pytest.MonkeyPatch
) -> None:
"""
Test documentation for installing pre-release packages is displayed
"""
hits: List[TransformedHit] = [
{
"name": "ni",
"summary": "For knights who say Ni!",
"versions": ["1.0.0", "1.0.1a"],
}
]
installed_package = mock.Mock(project_name="ni")
monkeypatch.setattr("pip._vendor.pkg_resources.working_set", [installed_package])
get_dist = mock.Mock()
get_dist.return_value = mock.Mock(version="1.0.0")
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.call_args_list == [mock.call("ni")]
@pytest.mark.search
def test_search_print_results_should_contain_latest_versions(
caplog: pytest.LogCaptureFixture,
) -> None:
"""
Test that printed search results contain the latest package versions
"""
hits: List[TransformedHit] = [
{
"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)")