mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
6aec23cafe
With wheel autobuilding in place a release blocker is some granular way to opt-out of wheels for known-bad packages. This patch introduces two new options: --no-binary and --only-binary to control what archives we are willing to use on both a global and per-package basis. This also closes #2084
202 lines
7.1 KiB
Python
202 lines
7.1 KiB
Python
from __future__ import absolute_import
|
|
|
|
import logging
|
|
|
|
from pip._vendor import pkg_resources
|
|
|
|
from pip.basecommand import Command
|
|
from pip.exceptions import DistributionNotFound
|
|
from pip.index import FormatControl, fmt_ctl_formats, PackageFinder, Search
|
|
from pip.req import InstallRequirement
|
|
from pip.utils import get_installed_distributions, dist_is_editable
|
|
from pip.wheel import WheelCache
|
|
from pip.cmdoptions import make_option_group, index_group
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ListCommand(Command):
|
|
"""
|
|
List installed packages, including editables.
|
|
|
|
Packages are listed in a case-insensitive sorted order.
|
|
"""
|
|
name = 'list'
|
|
usage = """
|
|
%prog [options]"""
|
|
summary = 'List installed packages.'
|
|
|
|
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 projects.')
|
|
cmd_opts.add_option(
|
|
'-l', '--local',
|
|
action='store_true',
|
|
default=False,
|
|
help=('If in a virtualenv that has global access, do not list '
|
|
'globally-installed packages.'),
|
|
)
|
|
self.cmd_opts.add_option(
|
|
'--user',
|
|
dest='user',
|
|
action='store_true',
|
|
default=False,
|
|
help='Only output packages installed in user-site.')
|
|
|
|
cmd_opts.add_option(
|
|
'--pre',
|
|
action='store_true',
|
|
default=False,
|
|
help=("Include pre-release and development versions. By default, "
|
|
"pip only finds stable versions."),
|
|
)
|
|
|
|
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, session):
|
|
"""
|
|
Create a package finder appropriate to this list command.
|
|
"""
|
|
return PackageFinder(
|
|
find_links=options.find_links,
|
|
index_urls=index_urls,
|
|
allow_external=options.allow_external,
|
|
allow_unverified=options.allow_unverified,
|
|
allow_all_external=options.allow_all_external,
|
|
allow_all_prereleases=options.pre,
|
|
trusted_hosts=options.trusted_hosts,
|
|
process_dependency_links=options.process_dependency_links,
|
|
session=session,
|
|
)
|
|
|
|
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, version, typ in self.find_packages_latest_versions(options):
|
|
if version > dist.parsed_version:
|
|
logger.info(
|
|
'%s (Current: %s Latest: %s [%s])',
|
|
dist.project_name, dist.version, version, typ,
|
|
)
|
|
|
|
def find_packages_latest_versions(self, options):
|
|
index_urls = [options.index_url] + options.extra_index_urls
|
|
if options.no_index:
|
|
logger.info('Ignoring indexes: %s', ','.join(index_urls))
|
|
index_urls = []
|
|
|
|
dependency_links = []
|
|
for dist in get_installed_distributions(local_only=options.local,
|
|
user_only=options.user):
|
|
if dist.has_metadata('dependency_links.txt'):
|
|
dependency_links.extend(
|
|
dist.get_metadata_lines('dependency_links.txt'),
|
|
)
|
|
|
|
with self._build_session(options) as session:
|
|
finder = self._build_package_finder(options, index_urls, session)
|
|
finder.add_dependency_links(dependency_links)
|
|
|
|
installed_packages = get_installed_distributions(
|
|
local_only=options.local,
|
|
user_only=options.user,
|
|
include_editables=False,
|
|
)
|
|
format_control = FormatControl(set(), set())
|
|
wheel_cache = WheelCache(options.cache_dir, format_control)
|
|
for dist in installed_packages:
|
|
req = InstallRequirement.from_line(
|
|
dist.key, None, isolated=options.isolated_mode,
|
|
wheel_cache=wheel_cache
|
|
)
|
|
typ = 'unknown'
|
|
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
|
|
else:
|
|
canonical_name = pkg_resources.safe_name(req.name).lower()
|
|
formats = fmt_ctl_formats(format_control, canonical_name)
|
|
search = Search(
|
|
req.name,
|
|
canonical_name,
|
|
formats)
|
|
remote_version = finder._link_package_versions(
|
|
link, search).version
|
|
if link.is_wheel:
|
|
typ = 'wheel'
|
|
else:
|
|
typ = 'sdist'
|
|
yield dist, remote_version, typ
|
|
|
|
def run_listing(self, options):
|
|
installed_packages = get_installed_distributions(
|
|
local_only=options.local,
|
|
user_only=options.user,
|
|
)
|
|
self.output_package_listing(installed_packages)
|
|
|
|
def run_editables(self, options):
|
|
installed_packages = get_installed_distributions(
|
|
local_only=options.local,
|
|
user_only=options.user,
|
|
editables_only=True,
|
|
)
|
|
self.output_package_listing(installed_packages)
|
|
|
|
def output_package_listing(self, installed_packages):
|
|
installed_packages = sorted(
|
|
installed_packages,
|
|
key=lambda dist: dist.project_name.lower(),
|
|
)
|
|
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.info(line)
|
|
|
|
def run_uptodate(self, options):
|
|
uptodate = []
|
|
for dist, version, typ in self.find_packages_latest_versions(options):
|
|
if dist.parsed_version == version:
|
|
uptodate.append(dist)
|
|
self.output_package_listing(uptodate)
|