def display_specs()

in lib/ramble/spack/cmd/__init__.py [0:0]


def display_specs(specs, args=None, **kwargs):
    """Display human readable specs with customizable formatting.

    Prints the supplied specs to the screen, formatted according to the
    arguments provided.

    Specs are grouped by architecture and compiler, and columnized if
    possible.

    Options can add more information to the default display. Options can
    be provided either as keyword arguments or as an argparse namespace.
    Keyword arguments take precedence over settings in the argparse
    namespace.

    Args:
        specs (list): the specs to display
        args (argparse.Namespace or None): namespace containing formatting arguments

    Keyword Args:
        paths (bool): Show paths with each displayed spec
        deps (bool): Display dependencies with specs
        long (bool): Display short hashes with specs
        very_long (bool): Display full hashes with specs (supersedes ``long``)
        namespace (bool): Print namespaces along with names
        show_flags (bool): Show compiler flags with specs
        variants (bool): Show variants with specs
        indent (int): indent each line this much
        groups (bool): display specs grouped by arch/compiler (default True)
        decorators (dict): dictionary mappng specs to decorators
        header_callback (typing.Callable): called at start of arch/compiler groups
        all_headers (bool): show headers even when arch/compiler aren't defined
        output (typing.IO): A file object to write to. Default is ``sys.stdout``

    """
    def get_arg(name, default=None):
        """Prefer kwargs, then args, then default."""
        if name in kwargs:
            return kwargs.get(name)
        elif args is not None:
            return getattr(args, name, default)
        else:
            return default

    paths         = get_arg('paths', False)
    deps          = get_arg('deps', False)
    hashes        = get_arg('long', False)
    namespace     = get_arg('namespace', False)
    flags         = get_arg('show_flags', False)
    full_compiler = get_arg('show_full_compiler', False)
    variants      = get_arg('variants', False)
    groups        = get_arg('groups', True)
    all_headers   = get_arg('all_headers', False)
    output        = get_arg('output', sys.stdout)

    decorator     = get_arg('decorator', None)
    if decorator is None:
        decorator = lambda s, f: f

    indent = get_arg('indent', 0)

    hlen = 7
    if get_arg('very_long', False):
        hashes = True
        hlen = None

    format_string = get_arg('format', None)
    if format_string is None:
        nfmt = '{fullname}' if namespace else '{name}'
        ffmt = ''
        if full_compiler or flags:
            ffmt += '{%compiler.name}'
            if full_compiler:
                ffmt += '{@compiler.version}'
            ffmt += ' {compiler_flags}'
        vfmt = '{variants}' if variants else ''
        format_string = nfmt + '{@version}' + ffmt + vfmt

    transform = {'package': decorator, 'fullpackage': decorator}

    def fmt(s, depth=0):
        """Formatter function for all output specs"""
        string = ""
        if hashes:
            string += gray_hash(s, hlen) + ' '
        string += depth * "    "
        string += s.cformat(format_string, transform=transform)
        return string

    def format_list(specs):
        """Display a single list of specs, with no groups"""
        # create the final, formatted versions of all specs
        formatted = []
        for spec in specs:
            formatted.append((fmt(spec), spec))
            if deps:
                for depth, dep in spec.traverse(root=False, depth=True):
                    formatted.append((fmt(dep, depth), dep))
                formatted.append(('', None))  # mark newlines

        # unless any of these are set, we can just colify and be done.
        if not any((deps, paths)):
            colify((f[0] for f in formatted), indent=indent, output=output)
            return ''

        # otherwise, we'll print specs one by one
        max_width = max(len(f[0]) for f in formatted)
        path_fmt = "%%-%ds%%s" % (max_width + 2)

        out = ''
        # getting lots of prefixes requires DB lookups. Ensure
        # all spec.prefix calls are in one transaction.
        with spack.store.db.read_transaction():
            for string, spec in formatted:
                if not string:
                    # print newline from above
                    out += '\n'
                    continue

                if paths:
                    out += path_fmt % (string, spec.prefix) + '\n'
                else:
                    out += string + '\n'

        return out

    out = ''
    if groups:
        for specs in iter_groups(specs, indent, all_headers):
            output.write(format_list(specs))
    else:
        out = format_list(sorted(specs))

    output.write(out)
    output.flush()