Source code for spack.cmd.info

# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from __future__ import print_function

import inspect
import textwrap

from six.moves import zip_longest

import llnl.util.tty as tty
import llnl.util.tty.color as color
from llnl.util.tty.colify import colify

import spack.cmd.common.arguments as arguments
import spack.fetch_strategy as fs
import spack.repo
import spack.spec
from spack.package import has_test_method, preferred_version

description = 'get detailed information on a particular package'
section = 'basic'
level = 'short'

header_color = '@*b'
plain_format = '@.'


[docs]def padder(str_list, extra=0): """Return a function to pad elements of a list.""" length = max(len(str(s)) for s in str_list) + extra def pad(string): string = str(string) padding = max(0, length - len(string)) return string + (padding * ' ') return pad
[docs]def setup_parser(subparser): subparser.add_argument( '-a', '--all', action='store_true', default=False, help="output all package information" ) options = [ ('--detectable', print_detectable.__doc__), ('--maintainers', print_maintainers.__doc__), ('--no-dependencies', 'do not ' + print_dependencies.__doc__), ('--no-variants', 'do not ' + print_variants.__doc__), ('--no-versions', 'do not ' + print_versions.__doc__), ('--phases', print_phases.__doc__), ('--tags', print_tags.__doc__), ('--tests', print_tests.__doc__), ('--virtuals', print_virtuals.__doc__), ] for opt, help_comment in options: subparser.add_argument(opt, action='store_true', help=help_comment) arguments.add_common_arguments(subparser, ['package'])
[docs]def section_title(s): return header_color + s + plain_format
[docs]def version(s): return spack.spec.version_color + s + plain_format
[docs]def variant(s): return spack.spec.enabled_variant_color + s + plain_format
[docs]class VariantFormatter(object): def __init__(self, variants): self.variants = variants self.headers = ('Name [Default]', 'When', 'Allowed values', 'Description') # Formats fmt_name = '{0} [{1}]' # Initialize column widths with the length of the # corresponding headers, as they cannot be shorter # than that self.column_widths = [len(x) for x in self.headers] # Expand columns based on max line lengths for k, e in variants.items(): v, w = e candidate_max_widths = ( len(fmt_name.format(k, self.default(v))), # Name [Default] len(str(w)), len(v.allowed_values), # Allowed values len(v.description) # Description ) self.column_widths = ( max(self.column_widths[0], candidate_max_widths[0]), max(self.column_widths[1], candidate_max_widths[1]), max(self.column_widths[2], candidate_max_widths[2]), max(self.column_widths[3], candidate_max_widths[3]) ) # Don't let name or possible values be less than max widths _, cols = tty.terminal_size() max_name = min(self.column_widths[0], 30) max_when = min(self.column_widths[1], 30) max_vals = min(self.column_widths[2], 20) # allow the description column to extend as wide as the terminal. max_description = min( self.column_widths[3], # min width 70 cols, 14 cols of margins and column spacing max(cols, 70) - max_name - max_vals - 14, ) self.column_widths = (max_name, max_when, max_vals, max_description) # Compute the format self.fmt = "%%-%ss%%-%ss%%-%ss%%s" % ( self.column_widths[0] + 4, self.column_widths[1] + 4, self.column_widths[2] + 4 )
[docs] def default(self, v): s = 'on' if v.default is True else 'off' if not isinstance(v.default, bool): s = v.default return s
@property def lines(self): if not self.variants: yield ' None' else: yield ' ' + self.fmt % self.headers underline = tuple([w * "=" for w in self.column_widths]) yield ' ' + self.fmt % underline yield '' for k, e in sorted(self.variants.items()): v, w = e name = textwrap.wrap( '{0} [{1}]'.format(k, self.default(v)), width=self.column_widths[0] ) if len(w) == 1: w = w[0] if w == spack.spec.Spec(): w = '--' when = textwrap.wrap(str(w), width=self.column_widths[1]) allowed = v.allowed_values.replace('True, False', 'on, off') allowed = textwrap.wrap(allowed, width=self.column_widths[2]) description = [] for d_line in v.description.split('\n'): description += textwrap.wrap( d_line, width=self.column_widths[3] ) for t in zip_longest( name, when, allowed, description, fillvalue='' ): yield " " + self.fmt % t
[docs]def info(parser, args): pkg = spack.repo.get(args.package) # Output core package information header = section_title( '{0}: ' ).format(pkg.build_system_class) + pkg.name color.cprint(header) color.cprint('') color.cprint(section_title('Description:')) if pkg.__doc__: color.cprint(color.cescape(pkg.format_doc(indent=4))) else: color.cprint(" None") color.cprint(section_title('Homepage: ') + pkg.homepage) # Now output optional information in expected order sections = [ (args.all or args.maintainers, print_maintainers), (args.all or args.detectable, print_detectable), (args.all or args.tags, print_tags), (args.all or not args.no_versions, print_versions), (args.all or not args.no_variants, print_variants), (args.all or args.phases, print_phases), (args.all or not args.no_dependencies, print_dependencies), (args.all or args.virtuals, print_virtuals), (args.all or args.tests, print_tests), ] for print_it, func in sections: if print_it: func(pkg) color.cprint('')