Skip to content

Separate pip search command from operation #2410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 4 additions & 57 deletions pip/commands/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import textwrap

from pip.basecommand import Command, SUCCESS
from pip.download import PipXmlrpcTransport
from pip.index import PyPI
from pip.utils import get_terminal_size
from pip.utils.logging import indent_log
from pip.exceptions import CommandError
from pip.status_codes import NO_MATCHES_FOUND
from pip._vendor import pkg_resources
from pip._vendor.six.moves import xmlrpc_client

from pip.operations.search import highest_version, search, transform_hits


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -40,7 +40,8 @@ def run(self, options, args):
if not args:
raise CommandError('Missing required argument (search query).')
query = args
pypi_hits = self.search(query, options)
with self._build_session(options) as session:
pypi_hits = search(query, options.index, session)
hits = transform_hits(pypi_hits)

terminal_width = None
Expand All @@ -52,54 +53,6 @@ def run(self, options, args):
return SUCCESS
return NO_MATCHES_FOUND

def search(self, query, options):
index_url = options.index
with self._build_session(options) as session:
transport = PipXmlrpcTransport(index_url, session)
pypi = xmlrpc_client.ServerProxy(index_url, transport)
hits = pypi.search({'name': query, 'summary': query}, 'or')
return hits


def transform_hits(hits):
"""
The list from pypi is really a list of versions. We want a list of
packages with the list of versions stored inline. This converts the
list from pypi into one we can use.
"""
packages = {}
for hit in hits:
name = hit['name']
summary = hit['summary']
version = hit['version']
score = hit['_pypi_ordering']
if score is None:
score = 0

if name not in packages.keys():
packages[name] = {
'name': name,
'summary': summary,
'versions': [version],
'score': score,
}
else:
packages[name]['versions'].append(version)

# if this is the highest version, replace summary and score
if version == highest_version(packages[name]['versions']):
packages[name]['summary'] = summary
packages[name]['score'] = score

# each record has a unique name now, so we will convert the dict into a
# list sorted by score
package_list = sorted(
packages.values(),
key=lambda x: x['score'],
reverse=True,
)
return package_list


def print_results(hits, name_column_width=None, terminal_width=None):
if not hits:
Expand Down Expand Up @@ -131,9 +84,3 @@ def print_results(hits, name_column_width=None, terminal_width=None):
logger.info('LATEST: %s', latest)
except UnicodeEncodeError:
pass


def highest_version(versions):
return next(iter(
sorted(versions, key=pkg_resources.parse_version, reverse=True)
))
58 changes: 58 additions & 0 deletions pip/operations/search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# The guts of search

from pip.download import PipXmlrpcTransport
from pip._vendor.six.moves import xmlrpc_client
from pip._vendor import pkg_resources


def search(query, index_url, session):
transport = PipXmlrpcTransport(index_url, session)
pypi = xmlrpc_client.ServerProxy(index_url, transport)
hits = pypi.search({'name': query, 'summary': query}, 'or')
return hits


def transform_hits(hits):
"""
The list from pypi is really a list of versions. We want a list of
packages with the list of versions stored inline. This converts the
list from pypi into one we can use.
"""
packages = {}
for hit in hits:
name = hit['name']
summary = hit['summary']
version = hit['version']
score = hit['_pypi_ordering']
if score is None:
score = 0

if name not in packages.keys():
packages[name] = {
'name': name,
'summary': summary,
'versions': [version],
'score': score,
}
else:
packages[name]['versions'].append(version)

# if this is the highest version, replace summary and score
if version == highest_version(packages[name]['versions']):
packages[name]['summary'] = summary
packages[name]['score'] = score

# each record has a unique name now, so we will convert the dict into a
# list sorted by score
package_list = sorted(
packages.values(),
key=lambda x: x['score'],
reverse=True,
)
return package_list


def highest_version(versions):
return next(iter(
sorted(versions, key=pkg_resources.parse_version, reverse=True)
))