From 0f5582cefcfddf04cae2d345aa3d9d036e2feeda Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Thu, 17 Aug 2017 18:15:57 +0200 Subject: 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. --- lib/spack/spack/cmd/info.py | 110 +++++++++++++++++++++++++++------------ lib/spack/spack/test/cmd/info.py | 40 ++++++++++++++ 2 files changed, 117 insertions(+), 33 deletions(-) create mode 100644 lib/spack/spack/test/cmd/info.py (limited to 'lib') diff --git a/lib/spack/spack/cmd/info.py b/lib/spack/spack/cmd/info.py index 575b65f8b0..71ab5e3207 100644 --- a/lib/spack/spack/cmd/info.py +++ b/lib/spack/spack/cmd/info.py @@ -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 + +from llnl.util.tty.colify import * -description = "get detailed information on a particular package" -section = "basic" -level = "short" +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 padder(str_list, extra=0): 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 @@ class VariantFormatter(object): @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 @@ class VariantFormatter(object): 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") diff --git a/lib/spack/spack/test/cmd/info.py b/lib/spack/spack/test/cmd/info.py new file mode 100644 index 0000000000..9819f2cd84 --- /dev/null +++ b/lib/spack/spack/test/cmd/info.py @@ -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) -- cgit v1.2.3-60-g2f50