Colorize spack info. Adds prominence to preferred version. (#4994)

* Colorize spack info. Adds prominence to preferred version. fixes #2708

This uses 'llnl.util.tty.color' to colorize the output of 'spack info'.
It also displays versions in the order the concretizer would choose
them and shows the preferred in a line on its own and in bold.

* Modified output according to Adam and Denis reviews.

Section titles are not bold + black, but bold + blue. Added a new
section named "Preferred version", which prints the preferred version
in bold characters.

* Further modifications according to Adam and Denis reviews.

After "Homepage:" we now have a single space. Removed newline after each
variant. Preferred version is not in bold fonts anymore. Added a simple
test that just runs the command.
This commit is contained in:
Massimiliano Culpo 2017-08-17 18:15:57 +02:00 committed by becker33
parent aa21590099
commit 0f5582cefc
2 changed files with 117 additions and 33 deletions

View File

@ -25,14 +25,22 @@
from __future__ import print_function
import textwrap
from six.moves import zip_longest
from llnl.util.tty.colify import *
import llnl.util.tty.color as color
import spack
import spack.fetch_strategy as fs
import spack.spec
description = "get detailed information on a particular package"
section = "basic"
level = "short"
from llnl.util.tty.colify import *
from six.moves import zip_longest
description = 'get detailed information on a particular package'
section = 'basic'
level = 'short'
header_color = '@*b'
plain_format = '@.'
def padder(str_list, extra=0):
@ -48,11 +56,23 @@ def pad(string):
def setup_parser(subparser):
subparser.add_argument(
'name', metavar="PACKAGE", help="name of package to get info for")
'name', metavar='PACKAGE', help='name of package to get info for')
def section_title(s):
return header_color + s + plain_format
def version(s):
return spack.spec.version_color + s + plain_format
def variant(s):
return spack.spec.enabled_variant_color + s + plain_format
class VariantFormatter(object):
def __init__(self, variants, max_widths=(25, 20, 35)):
def __init__(self, variants, max_widths=(30, 20, 30)):
self.variants = variants
self.headers = ('Name [Default]', 'Allowed values', 'Description')
# Set max headers lengths
@ -102,9 +122,9 @@ def default(self, v):
@property
def lines(self):
if not self.variants:
yield " None"
yield ' None'
else:
yield " " + self.fmt % self.headers
yield ' ' + self.fmt % self.headers
yield '\n'
for k, v in sorted(self.variants.items()):
name = textwrap.wrap(
@ -123,61 +143,82 @@ def lines(self):
name, allowed, description, fillvalue=''
):
yield " " + self.fmt % t
yield '' # Trigger a new line
def print_text_info(pkg):
"""Print out a plain text description of a package."""
header = "{0}: ".format(pkg.build_system_class)
print(header, pkg.name)
header = section_title(
'{0}: '
).format(pkg.build_system_class) + pkg.name
color.cprint(header)
print()
print("Description:")
color.cprint('')
color.cprint(section_title('Description:'))
if pkg.__doc__:
print(pkg.format_doc(indent=4))
else:
print(" None")
whitespaces = ''.join([' '] * (len(header) - len("Homepage: ")))
print("Homepage:", whitespaces, pkg.homepage)
color.cprint(section_title('Homepage: ') + pkg.homepage)
print()
print("Safe versions: ")
color.cprint('')
color.cprint(section_title('Preferred version: '))
if not pkg.versions:
print(" None")
color.cprint(version(' None'))
color.cprint('')
color.cprint(section_title('Safe versions: '))
color.cprint(version(' None'))
else:
pad = padder(pkg.versions, 4)
# Here we sort first on the fact that a version is marked
# as preferred in the package, then on the fact that the
# version is not develop, then lexicographically
l = [
(value.get('preferred', False), not key.isdevelop(), key)
for key, value in pkg.versions.items()
]
l = sorted(l)
_, _, preferred = l.pop()
f = fs.for_package_version(pkg, preferred)
line = version(' {0}'.format(pad(preferred))) + str(f)
color.cprint(line)
color.cprint('')
color.cprint(section_title('Safe versions: '))
for v in reversed(sorted(pkg.versions)):
f = fs.for_package_version(pkg, v)
print(" %s%s" % (pad(v), str(f)))
line = version(' {0}'.format(pad(v))) + str(f)
color.cprint(line)
print()
print("Variants:")
color.cprint('')
color.cprint(section_title('Variants:'))
formatter = VariantFormatter(pkg.variants)
for line in formatter.lines:
print(line)
color.cprint(line)
print()
print("Installation Phases:")
color.cprint('')
color.cprint(section_title('Installation Phases:'))
phase_str = ''
for phase in pkg.phases:
phase_str += " {0}".format(phase)
print(phase_str)
color.cprint(phase_str)
for deptype in ('build', 'link', 'run'):
print()
print("%s Dependencies:" % deptype.capitalize())
color.cprint('')
color.cprint(section_title('%s Dependencies:' % deptype.capitalize()))
deps = sorted(pkg.dependencies_of_type(deptype))
if deps:
colify(deps, indent=4)
else:
print(" None")
print(' None')
print()
print("Virtual Packages: ")
color.cprint('')
color.cprint(section_title('Virtual Packages: '))
if pkg.provided:
inverse_map = {}
for spec, whens in pkg.provided.items():
@ -186,8 +227,11 @@ def print_text_info(pkg):
inverse_map[when] = set()
inverse_map[when].add(spec)
for when, specs in reversed(sorted(inverse_map.items())):
print(" %s provides %s" % (
when, ', '.join(str(s) for s in specs)))
line = " %s provides %s" % (
when.colorized(), ', '.join(s.colorized() for s in specs)
)
print(line)
else:
print(" None")

View File

@ -0,0 +1,40 @@
##############################################################################
# Copyright (c) 2013-2017, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the NOTICE and LICENSE files for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import pytest
from spack.main import SpackCommand
info = SpackCommand('info')
@pytest.mark.parametrize('pkg', [
'openmpi',
'trilinos',
'boost',
'python',
'dealii'
])
def test_it_just_runs(pkg):
info(pkg)