Skip to content

Commit 41175a1

Browse files
committed
Separate pip search command from operation
By extracting the logic into `pip.operations.search`, the hope is that folks could do a `search` programmatically more easily. It also has greater separation of concerns and should allow people to work in parallel with less chance of merge conflicts. Continuing work started in #2173 and #2404.
1 parent 7538303 commit 41175a1

File tree

3 files changed

+62
-59
lines changed

3 files changed

+62
-59
lines changed

pip/commands/search.py

+4-57
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import textwrap
66

77
from pip.basecommand import Command, SUCCESS
8-
from pip.download import PipXmlrpcTransport
98
from pip.index import PyPI
109
from pip.utils import get_terminal_size
1110
from pip.utils.logging import indent_log
1211
from pip.exceptions import CommandError
1312
from pip.status_codes import NO_MATCHES_FOUND
1413
from pip._vendor import pkg_resources
15-
from pip._vendor.six.moves import xmlrpc_client
14+
15+
from pip.operations.search import highest_version, search, transform_hits
1616

1717

1818
logger = logging.getLogger(__name__)
@@ -40,7 +40,8 @@ def run(self, options, args):
4040
if not args:
4141
raise CommandError('Missing required argument (search query).')
4242
query = args
43-
pypi_hits = self.search(query, options)
43+
with self._build_session(options) as session:
44+
pypi_hits = search(query, options.index, session)
4445
hits = transform_hits(pypi_hits)
4546

4647
terminal_width = None
@@ -52,54 +53,6 @@ def run(self, options, args):
5253
return SUCCESS
5354
return NO_MATCHES_FOUND
5455

55-
def search(self, query, options):
56-
index_url = options.index
57-
with self._build_session(options) as session:
58-
transport = PipXmlrpcTransport(index_url, session)
59-
pypi = xmlrpc_client.ServerProxy(index_url, transport)
60-
hits = pypi.search({'name': query, 'summary': query}, 'or')
61-
return hits
62-
63-
64-
def transform_hits(hits):
65-
"""
66-
The list from pypi is really a list of versions. We want a list of
67-
packages with the list of versions stored inline. This converts the
68-
list from pypi into one we can use.
69-
"""
70-
packages = {}
71-
for hit in hits:
72-
name = hit['name']
73-
summary = hit['summary']
74-
version = hit['version']
75-
score = hit['_pypi_ordering']
76-
if score is None:
77-
score = 0
78-
79-
if name not in packages.keys():
80-
packages[name] = {
81-
'name': name,
82-
'summary': summary,
83-
'versions': [version],
84-
'score': score,
85-
}
86-
else:
87-
packages[name]['versions'].append(version)
88-
89-
# if this is the highest version, replace summary and score
90-
if version == highest_version(packages[name]['versions']):
91-
packages[name]['summary'] = summary
92-
packages[name]['score'] = score
93-
94-
# each record has a unique name now, so we will convert the dict into a
95-
# list sorted by score
96-
package_list = sorted(
97-
packages.values(),
98-
key=lambda x: x['score'],
99-
reverse=True,
100-
)
101-
return package_list
102-
10356

10457
def print_results(hits, name_column_width=None, terminal_width=None):
10558
if not hits:
@@ -131,9 +84,3 @@ def print_results(hits, name_column_width=None, terminal_width=None):
13184
logger.info('LATEST: %s', latest)
13285
except UnicodeEncodeError:
13386
pass
134-
135-
136-
def highest_version(versions):
137-
return next(iter(
138-
sorted(versions, key=pkg_resources.parse_version, reverse=True)
139-
))

pip/operations/search.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# The guts of search
2+
3+
from pip.download import PipXmlrpcTransport
4+
from pip._vendor.six.moves import xmlrpc_client
5+
from pip._vendor import pkg_resources
6+
7+
8+
def search(query, index_url, session):
9+
transport = PipXmlrpcTransport(index_url, session)
10+
pypi = xmlrpc_client.ServerProxy(index_url, transport)
11+
hits = pypi.search({'name': query, 'summary': query}, 'or')
12+
return hits
13+
14+
15+
def transform_hits(hits):
16+
"""
17+
The list from pypi is really a list of versions. We want a list of
18+
packages with the list of versions stored inline. This converts the
19+
list from pypi into one we can use.
20+
"""
21+
packages = {}
22+
for hit in hits:
23+
name = hit['name']
24+
summary = hit['summary']
25+
version = hit['version']
26+
score = hit['_pypi_ordering']
27+
if score is None:
28+
score = 0
29+
30+
if name not in packages.keys():
31+
packages[name] = {
32+
'name': name,
33+
'summary': summary,
34+
'versions': [version],
35+
'score': score,
36+
}
37+
else:
38+
packages[name]['versions'].append(version)
39+
40+
# if this is the highest version, replace summary and score
41+
if version == highest_version(packages[name]['versions']):
42+
packages[name]['summary'] = summary
43+
packages[name]['score'] = score
44+
45+
# each record has a unique name now, so we will convert the dict into a
46+
# list sorted by score
47+
package_list = sorted(
48+
packages.values(),
49+
key=lambda x: x['score'],
50+
reverse=True,
51+
)
52+
return package_list
53+
54+
55+
def highest_version(versions):
56+
return next(iter(
57+
sorted(versions, key=pkg_resources.parse_version, reverse=True)
58+
))

tox.ini

-2
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@ commands = check-manifest
2121
[testenv:pep8]
2222
basepython = python2.7
2323
deps = flake8
24-
pep8<1.6
2524
commands = flake8 .
2625

2726
[testenv:py3pep8]
2827
basepython = python3.3
2928
deps = flake8
30-
pep8<1.6
3129
commands = flake8 .
3230

3331
[flake8]

0 commit comments

Comments
 (0)