-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #752 from qwcode/pip_list
pip list
- Loading branch information
Showing
10 changed files
with
425 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
"""shared options and groups""" | ||
|
||
from optparse import make_option, OptionGroup | ||
|
||
def make_option_group(group, parser): | ||
""" | ||
Return an OptionGroup object | ||
group -- assumed to be dict with 'name' and 'options' keys | ||
parser -- an optparse Parser | ||
""" | ||
option_group = OptionGroup(parser, group['name']) | ||
for option in group['options']: | ||
option_group.add_option(option) | ||
return option_group | ||
|
||
########### | ||
# options # | ||
########### | ||
|
||
find_links = make_option( | ||
'-f', '--find-links', | ||
dest='find_links', | ||
action='append', | ||
default=[], | ||
metavar='URL', | ||
help='URL to look for packages at') | ||
|
||
index_url = make_option( | ||
'-i', '--index-url', '--pypi-url', | ||
dest='index_url', | ||
metavar='URL', | ||
default='http://pypi.python.org/simple/', | ||
help='Base URL of Python Package Index (default %default)') | ||
|
||
extra_index_url = make_option( | ||
'--extra-index-url', | ||
dest='extra_index_urls', | ||
metavar='URL', | ||
action='append', | ||
default=[], | ||
help='Extra URLs of package indexes to use in addition to --index-url') | ||
|
||
no_index = make_option( | ||
'--no-index', | ||
dest='no_index', | ||
action='store_true', | ||
default=False, | ||
help='Ignore package index (only looking at --find-links URLs instead)') | ||
|
||
use_mirrors = make_option( | ||
'-M', '--use-mirrors', | ||
dest='use_mirrors', | ||
action='store_true', | ||
default=False, | ||
help='Use the PyPI mirrors as a fallback in case the main index is down.') | ||
|
||
mirrors = make_option( | ||
'--mirrors', | ||
dest='mirrors', | ||
metavar='URL', | ||
action='append', | ||
default=[], | ||
help='Specific mirror URLs to query when --use-mirrors is used') | ||
|
||
|
||
########## | ||
# groups # | ||
########## | ||
|
||
index_group = { | ||
'name': 'Package Index Options', | ||
'options': [ | ||
find_links, | ||
index_url, | ||
extra_index_url, | ||
no_index, | ||
use_mirrors, | ||
mirrors | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import pkg_resources | ||
from pip.basecommand import Command | ||
from pip.exceptions import DistributionNotFound, BestVersionAlreadyInstalled | ||
from pip.index import PackageFinder | ||
from pip.log import logger | ||
from pip.req import InstallRequirement | ||
from pip.util import get_installed_distributions, dist_is_editable | ||
from pip.cmdoptions import make_option_group, index_group | ||
|
||
|
||
class ListCommand(Command): | ||
name = 'list' | ||
usage = '%prog [OPTIONS]' | ||
summary = 'List installed packages (including editables).' | ||
|
||
def __init__(self, *args, **kw): | ||
super(ListCommand, self).__init__(*args, **kw) | ||
|
||
|
||
cmd_opts = self.cmd_opts | ||
|
||
cmd_opts.add_option( | ||
'-o', '--outdated', | ||
action='store_true', | ||
default=False, | ||
help='List outdated packages (excluding editables)') | ||
cmd_opts.add_option( | ||
'-u', '--uptodate', | ||
action='store_true', | ||
default=False, | ||
help='List uptodate packages (excluding editables)') | ||
cmd_opts.add_option( | ||
'-e', '--editable', | ||
action='store_true', | ||
default=False, | ||
help='List editable packages.') | ||
cmd_opts.add_option( | ||
'-l', '--local', | ||
action='store_true', | ||
default=False, | ||
help='If in a virtualenv, do not list globally-installed packages') | ||
|
||
|
||
index_opts = make_option_group(index_group, self.parser) | ||
|
||
self.parser.insert_option_group(0, index_opts) | ||
self.parser.insert_option_group(0, cmd_opts) | ||
|
||
|
||
def _build_package_finder(self, options, index_urls): | ||
""" | ||
Create a package finder appropriate to this list command. | ||
""" | ||
return PackageFinder(find_links=options.find_links, | ||
index_urls=index_urls, | ||
use_mirrors=options.use_mirrors, | ||
mirrors=options.mirrors) | ||
|
||
def run(self, options, args): | ||
if options.outdated: | ||
self.run_outdated(options) | ||
elif options.uptodate: | ||
self.run_uptodate(options) | ||
elif options.editable: | ||
self.run_editables(options) | ||
else: | ||
self.run_listing(options) | ||
|
||
def run_outdated(self, options): | ||
for dist, remote_version_raw, remote_version_parsed in self.find_packages_latests_versions(options): | ||
if remote_version_parsed > dist.parsed_version: | ||
logger.notify('%s (Current: %s Latest: %s)' % (dist.project_name, | ||
dist.version, remote_version_raw)) | ||
|
||
def find_packages_latests_versions(self, options): | ||
index_urls = [options.index_url] + options.extra_index_urls | ||
if options.no_index: | ||
logger.notify('Ignoring indexes: %s' % ','.join(index_urls)) | ||
index_urls = [] | ||
|
||
dependency_links = [] | ||
for dist in get_installed_distributions(local_only=options.local): | ||
if dist.has_metadata('dependency_links.txt'): | ||
dependency_links.extend( | ||
dist.get_metadata_lines('dependency_links.txt'), | ||
) | ||
|
||
finder = self._build_package_finder(options, index_urls) | ||
finder.add_dependency_links(dependency_links) | ||
|
||
installed_packages = get_installed_distributions(local_only=options.local, include_editables=False) | ||
for dist in installed_packages: | ||
req = InstallRequirement.from_line(dist.key, None) | ||
try: | ||
link = finder.find_requirement(req, True) | ||
|
||
# If link is None, means installed version is most up-to-date | ||
if link is None: | ||
continue | ||
except DistributionNotFound: | ||
continue | ||
except BestVersionAlreadyInstalled: | ||
remote_version = req.installed_version | ||
else: | ||
# It might be a good idea that link or finder had a public method | ||
# that returned version | ||
remote_version = finder._link_package_versions(link, req.name)[0] | ||
remote_version_raw = remote_version[2] | ||
remote_version_parsed = remote_version[0] | ||
yield dist, remote_version_raw, remote_version_parsed | ||
|
||
def run_listing(self, options): | ||
installed_packages = get_installed_distributions(local_only=options.local) | ||
self.output_package_listing(installed_packages) | ||
|
||
def run_editables(self, options): | ||
installed_packages = get_installed_distributions(local_only=options.local, editables_only=True) | ||
self.output_package_listing(installed_packages) | ||
|
||
def output_package_listing(self, installed_packages): | ||
for dist in installed_packages: | ||
if dist_is_editable(dist): | ||
line = '%s (%s, %s)' % (dist.project_name, dist.version, dist.location) | ||
else: | ||
line = '%s (%s)' % (dist.project_name, dist.version) | ||
logger.notify(line) | ||
|
||
def run_uptodate(self, options): | ||
uptodate = [] | ||
for dist, remote_version_raw, remote_version_parsed in self.find_packages_latests_versions(options): | ||
if dist.parsed_version == remote_version_parsed: | ||
uptodate.append(dist) | ||
self.output_package_listing(uptodate) | ||
|
Oops, something went wrong.