Exemple #1
0
 def colorize(c, prefix):
     if isinstance(prefix, tuple):
         return "::".join(
             color.colorize("@%s{%s}" % (c, p))
             for p in prefix if p != "()"
         )
     return color.colorize("@%s{%s}" % (c, prefix))
Exemple #2
0
def display_targets(targets):
    """Prints a human readable list of the targets passed as argument."""
    by_vendor = collections.defaultdict(list)
    for _, target in targets.items():
        by_vendor[target.vendor].append(target)

    def display_target_group(header, target_group):
        print(header)
        colify.colify(target_group, indent=4)
        print('')

    generic_architectures = by_vendor.pop('generic', None)
    if generic_architectures:
        header = color.colorize(r'@*B{Generic architectures (families)}')
        group = sorted(generic_architectures, key=lambda x: str(x))
        display_target_group(header, group)

    for vendor, vendor_targets in by_vendor.items():
        by_family = collections.defaultdict(list)
        for t in vendor_targets:
            by_family[str(t.family)].append(t)

        for family, group in by_family.items():
            vendor = color.colorize(r'@*B{' + vendor + r'}')
            family = color.colorize(r'@*B{' + family + r'}')
            header = ' - '.join([vendor, family])
            group = sorted(group, key=lambda x: len(x.ancestors))
            display_target_group(header, group)
Exemple #3
0
 def avail_full(self, regex=None, long_format=False):
     sio = StringIO()
     sio.write("\n")
     _, width = tty.terminal_size()
     # head = lambda x: (" " + x + " ").center(width, "-")
     for path in self:
         directory = path.path
         modules = sorted([m for m in path.modules if m.is_enabled],
                          key=self.sort_key)
         modules = self.filter_modules_by_regex(modules, regex)
         if not os.path.isdir(directory):  # pragma: no cover
             s = colorize("@r{(Directory not readable)}".center(width))
         elif not modules:  # pragma: no cover
             if regex:
                 continue
             s = colorize("@r{(None)}".center(width))
         else:
             modules = [
                 self.colorize(m.format_dl_status()) for m in modules
             ]
             aliases = pymod.alias.get(directory)
             if aliases:  # pragma: no cover
                 for (alias, target) in aliases:
                     i = bisect.bisect_left(modules, alias)
                     insert_key = colorize("@M{%s}@@" % (alias))
                     if long_format:  # pragma: no cover
                         insert_key += " -> %s" % (target)
                     modules.insert(i, insert_key)
             s = colified(modules, width=width)
         directory = directory.replace(os.path.expanduser("~/"), "~/")
         # sio.write(head(directory) + '\n')
         sio.write(colorize("@G{%s}:\n" % (directory)))
         sio.write(s + "\n")
     return sio.getvalue()
Exemple #4
0
def style(parser, args):
    # ensure python version is new enough
    if sys.version_info < (3, 6):
        tty.die("spack style requires Python 3.6 or later.")

    # save initial working directory for relativizing paths later
    args.initial_working_dir = os.getcwd()

    # ensure that the config files we need actually exist in the spack prefix.
    # assertions b/c users should not ever see these errors -- they're checked in CI.
    assert os.path.isfile(os.path.join(spack.paths.prefix, "pyproject.toml"))
    assert os.path.isfile(os.path.join(spack.paths.prefix, ".flake8"))

    # validate spack root if the user provided one
    args.root = os.path.realpath(args.root) if args.root else spack.paths.prefix
    spack_script = os.path.join(args.root, "bin", "spack")
    if not os.path.exists(spack_script):
        tty.die(
            "This does not look like a valid spack root.",
            "No such file: '%s'" % spack_script
        )

    file_list = args.files
    if file_list:

        def prefix_relative(path):
            return os.path.relpath(os.path.abspath(os.path.realpath(path)), args.root)

        file_list = [prefix_relative(p) for p in file_list]

    return_code = 0
    with working_dir(args.root):
        if not file_list:
            file_list = changed_files(args.base, args.untracked, args.all)
        print_style_header(file_list, args)

        commands = {}
        with spack.bootstrap.ensure_bootstrap_configuration():
            for tool_name, bootstrap_fn in tool_order:
                # Skip the tool if it was not requested
                if not getattr(args, tool_name):
                    continue

                commands[tool_name] = bootstrap_fn()

            for tool_name, bootstrap_fn in tool_order:
                # Skip the tool if it was not requested
                if not getattr(args, tool_name):
                    continue

                run_function, required = tools[tool_name]
                print_tool_header(tool_name)
                return_code |= run_function(commands[tool_name], file_list, args)

    if return_code == 0:
        tty.msg(color.colorize("@*{spack style checks were clean}"))
    else:
        tty.error(color.colorize("@*{spack style found errors}"))

    return return_code
Exemple #5
0
 def decorator(spec, fmt):
     # add +/-/* to show added/removed/root specs
     if any(spec.dag_hash() == r.dag_hash() for r in roots):
         return color.colorize('@*{%s}' % fmt)
     elif spec in removed:
         return color.colorize('@K{%s}' % fmt)
     else:
         return '%s' % fmt
Exemple #6
0
 def decorator(spec, fmt):
     # add +/-/* to show added/removed/root specs
     if any(spec.dag_hash() == r.dag_hash() for r in roots):
         return color.colorize('@*{%s}' % fmt)
     elif spec in removed:
         return color.colorize('@K{%s}' % fmt)
     else:
         return '%s' % fmt
Exemple #7
0
 def colorize(self, string):
     """Colorize item for output to console"""
     D = "(%s)" % colorize("@R{D}")
     L = "(%s)" % colorize("@G{L}")
     DL = "(%s,%s)" % (colorize("@R{D}"), colorize("@G{L}"))
     colorized = string.replace("(D)", D)
     colorized = colorized.replace("(L)", L)
     colorized = colorized.replace("(D,L)", DL)
     return colorized
Exemple #8
0
    def print_status(self, *specs, **kwargs):
        if kwargs.get("with_dependencies", False):
            specs = set(get_dependencies(specs))

        specs = sorted(specs, key=lambda s: s.name)
        in_view = list(map(self.get_spec, specs))

        for s, v in zip(specs, in_view):
            if not v:
                tty.error(self._croot +
                          'Package not linked: %s' % s.name)
            elif s != v:
                self.print_conflict(v, s, level="warn")

        in_view = list(filter(None, in_view))

        if len(specs) > 0:
            tty.msg("Packages linked in %s:" % self._croot[:-1])

            # Make a dict with specs keyed by architecture and compiler.
            index = index_by(specs, ('architecture', 'compiler'))

            # Traverse the index and print out each package
            for i, (architecture, compiler) in enumerate(sorted(index)):
                if i > 0:
                    print()

                header = "%s{%s} / %s{%s}" % (spack.spec.architecture_color,
                                              architecture,
                                              spack.spec.compiler_color,
                                              compiler)
                tty.hline(colorize(header), char='-')

                specs = index[(architecture, compiler)]
                specs.sort()

                format_string = '{name}{@version}'
                format_string += '{%compiler}{compiler_flags}{variants}'
                abbreviated = [s.cformat(format_string) for s in specs]

                # Print one spec per line along with prefix path
                width = max(len(s) for s in abbreviated)
                width += 2
                format = "    %%-%ds%%s" % width

                for abbrv, s in zip(abbreviated, specs):
                    prefix = ''
                    if self.verbose:
                        prefix = colorize('@K{%s}' % s.dag_hash(7))
                    print(
                        prefix + (format % (abbrv,
                                            self.get_projection_for_spec(s)))
                    )
        else:
            tty.warn(self._croot + "No packages found.")
Exemple #9
0
def shell_init_instructions(cmd, equivalent):
    """Print out instructions for users to initialize shell support.

    Arguments:
        cmd (str): the command the user tried to run that requires
            shell support in order to work
        equivalent (str): a command they can run instead, without
            enabling shell support
    """

    shell_specific = "{sh_arg}" in equivalent

    msg = [
        "`%s` requires Spack's shell support." % cmd,
        "",
        "To set up shell support, run the command below for your shell.",
        "",
        color.colorize("@*c{For bash/zsh/sh:}"),
        "  . %s/setup-env.sh" % spack.paths.share_path,
        "",
        color.colorize("@*c{For csh/tcsh:}"),
        "  source %s/setup-env.csh" % spack.paths.share_path,
        "",
        color.colorize("@*c{For fish:}"),
        "  source %s/setup-env.fish" % spack.paths.share_path,
        "",
        color.colorize("@*c{For Windows batch:}"),
        "  source %s/spack_cmd.bat" % spack.paths.share_path,
        "",
        "Or, if you do not want to use shell support, run " +
        ("one of these" if shell_specific else "this") + " instead:",
        "",
    ]

    if shell_specific:
        msg += [
            equivalent.format(sh_arg="--sh  ") + "  # bash/zsh/sh",
            equivalent.format(sh_arg="--csh ") + "  # csh/tcsh",
            equivalent.format(sh_arg="--fish") + "  # fish",
            equivalent.format(sh_arg="--bat ") + "  # batch"
        ]
    else:
        msg += ["  " + equivalent]

    msg += [
        "",
        "If you have already set up Spack's shell support but still receive",
        "this message, please make sure to call Spack via the `spack` command",
        "without any path components (such as `bin/spack`).",
    ]

    msg += ['']
    tty.error(*msg)
Exemple #10
0
def _process_reports(reports):
    for check, errors in reports:
        if errors:
            msg = '{0}: {1} issue{2} found'.format(
                check, len(errors), '' if len(errors) == 1 else 's')
            header = '@*b{' + msg + '}'
            print(cl.colorize(header))
            for idx, error in enumerate(errors):
                print(str(idx + 1) + '. ' + str(error))
            raise SystemExit(1)
        else:
            msg = '{0}: 0 issues found.'.format(check)
            header = '@*b{' + msg + '}'
            print(cl.colorize(header))
Exemple #11
0
def iter_groups(specs, indent, all_headers):
    """Break a list of specs into groups indexed by arch/compiler."""
    # Make a dict with specs keyed by architecture and compiler.
    index = index_by(specs, ('architecture', 'compiler'))
    ispace = indent * ' '

    # Traverse the index and print out each package
    for i, (architecture, compiler) in enumerate(sorted(index)):
        if i > 0:
            print()

        header = "%s{%s} / %s{%s}" % (spack.spec.architecture_color,
                                      architecture if architecture else
                                      'no arch', spack.spec.compiler_color,
                                      compiler if compiler else 'no compiler')

        # Sometimes we want to display specs that are not yet concretized.
        # If they don't have a compiler / architecture attached to them,
        # then skip the header
        if all_headers or (architecture is not None or compiler is not None):
            sys.stdout.write(ispace)
            tty.hline(colorize(header), char='-')

        specs = index[(architecture, compiler)]
        specs.sort()
        yield specs
Exemple #12
0
def compiler_list(args):
    tty.msg("Available compilers")
    index = index_by(spack.compilers.all_compilers(scope=args.scope), lambda c:
                     (c.spec.name, c.operating_system, c.target))

    # For a container, take each element which does not evaluate to false and
    # convert it to a string. For elements which evaluate to False (e.g. None)
    # convert them to '' (in which case it still evaluates to False but is a
    # string type). Tuples produced by this are guaranteed to be comparable in
    # Python 3
    convert_str = (lambda tuple_container: tuple(
        str(x) if x else '' for x in tuple_container))

    index_str_keys = list((convert_str(x), y) for x, y in index.items())
    ordered_sections = sorted(index_str_keys, key=lambda item: item[0])
    for i, (key, compilers) in enumerate(ordered_sections):
        if i >= 1:
            print()
        name, os, target = key
        os_str = os
        if target:
            os_str += "-%s" % target
        cname = "%s{%s} %s" % (spack.spec.compiler_color, name, os_str)
        tty.hline(colorize(cname), char='-')
        colify(reversed(sorted(c.spec for c in compilers)))
Exemple #13
0
def info(names):
    for name in names:
        modules = pymod.modulepath.candidates(name)
        if not modules:
            raise ModuleNotFoundError(name)

        for module in modules:
            s = "@B{Module:} @*{%s}\n" % module.fullname
            s += "  @C{Name:}         %s\n" % module.name

            if module.version:  # pragma: no cover
                s += "  @C{Version:}      %s\n" % module.version

            if module.family:  # pragma: no cover
                s += "  @C{Family:}      %s\n" % module.family

            s += "  @C{Loaded:}       %s\n" % module.is_loaded
            s += "  @C{Filename:}     %s\n" % module.filename
            s += "  @C{Modulepath:}   %s" % module.modulepath

            unlocked_by = module.unlocked_by()
            if unlocked_by:  # pragma: no cover
                s += "  @C{Unlocked by:}  %s\n"
                for m in unlocked_by:
                    s += "                    %s\n" % m.fullname

            unlocks = module.unlocks()
            if unlocks:  # pragma: no cover
                s += "  @C{Unlocks:}      %s\n"
                for dirname in unlocks:
                    s += "                    %s\n" % dirname

            sys.stderr.write(colorize(s) + "\n")
Exemple #14
0
def disambiguate_spec(spec, env, local=False, installed=True):
    """Given a spec, figure out which installed package it refers to.

    Arguments:
        spec (spack.spec.Spec): a spec to disambiguate
        env (spack.environment.Environment): a spack environment,
            if one is active, or None if no environment is active
        local (boolean, default False): do not search chained spack instances
        installed (boolean or any, or spack.database.InstallStatus or iterable
            of spack.database.InstallStatus): install status argument passed to
            database query. See ``spack.database.Database._query`` for details.
    """
    hashes = env.all_hashes() if env else None
    if local:
        matching_specs = spack.store.db.query_local(spec,
                                                    hashes=hashes,
                                                    installed=installed)
    else:
        matching_specs = spack.store.db.query(spec,
                                              hashes=hashes,
                                              installed=installed)
    if not matching_specs:
        tty.die("Spec '%s' matches no installed packages." % spec)

    elif len(matching_specs) > 1:
        format_string = '{name}{@version}{%compiler}{arch=architecture}'
        args = ["%s matches multiple packages." % spec, "Matching packages:"]
        args += [
            colorize("  @K{%s} " % s.dag_hash(7)) + s.cformat(format_string)
            for s in matching_specs
        ]
        args += ["Use a more specific spec."]
        tty.die(*args)

    return matching_specs[0]
Exemple #15
0
def disambiguate_spec_from_hashes(spec, hashes, local=False,
                                  installed=True, first=False):
    """Given a spec and a list of hashes, get concrete spec the spec refers to.

    Arguments:
        spec (spack.spec.Spec): a spec to disambiguate
        hashes (typing.Iterable): a set of hashes of specs among which to disambiguate
        local (bool): do not search chained spack instances
        installed (bool or spack.database.InstallStatus or typing.Iterable):
            install status argument passed to database query.
            See ``spack.database.Database._query`` for details.
    """
    if local:
        matching_specs = spack.store.db.query_local(spec, hashes=hashes,
                                                    installed=installed)
    else:
        matching_specs = spack.store.db.query(spec, hashes=hashes,
                                              installed=installed)
    if not matching_specs:
        tty.die("Spec '%s' matches no installed packages." % spec)

    elif first:
        return matching_specs[0]

    elif len(matching_specs) > 1:
        format_string = '{name}{@version}{%compiler}{arch=architecture}'
        args = ["%s matches multiple packages." % spec,
                "Matching packages:"]
        args += [colorize("  @K{%s} " % s.dag_hash(7)) +
                 s.cformat(format_string) for s in matching_specs]
        args += ["Use a more specific spec."]
        tty.die(*args)

    return matching_specs[0]
Exemple #16
0
def display_env(env, args, decorator):
    tty.msg('In environment %s' % env.name)

    if not env.user_specs:
        tty.msg('No root specs')
    else:
        tty.msg('Root specs')

        # Root specs cannot be displayed with prefixes, since those are not
        # set for abstract specs. Same for hashes
        root_args = copy.copy(args)
        root_args.paths = False

        # Roots are displayed with variants, etc. so that we can see
        # specifically what the user asked for.
        cmd.display_specs(
            env.user_specs,
            root_args,
            decorator=lambda s, f: color.colorize('@*{%s}' % f),
            namespace=True,
            show_flags=True,
            show_full_compiler=True,
            variants=True
        )
        print()

    if args.show_concretized:
        tty.msg('Concretized roots')
        cmd.display_specs(
            env.specs_by_hash.values(), args, decorator=decorator)
        print()
Exemple #17
0
def display_env(env, args, decorator):
    tty.msg('In environment %s' % env.name)

    if not env.user_specs:
        tty.msg('No root specs')
    else:
        tty.msg('Root specs')

        # Roots are displayed with variants, etc. so that we can see
        # specifically what the user asked for.
        cmd.display_specs(env.user_specs,
                          args,
                          decorator=lambda s, f: color.colorize('@*{%s}' % f),
                          namespace=True,
                          show_flags=True,
                          show_full_compiler=True,
                          variants=True)
        print()

    if args.show_concretized:
        tty.msg('Concretized roots')
        cmd.display_specs(env.specs_by_hash.values(),
                          args,
                          decorator=decorator)
        print()
Exemple #18
0
def activate(
    env, use_env_repo=False, add_view=True, shell='sh', prompt=None
):
    """Activate an environment.

    To activate an environment, we add its configuration scope to the
    existing Spack configuration, and we set active to the current
    environment.

    Arguments:
        env (Environment): the environment to activate
        use_env_repo (bool): use the packages exactly as they appear in the
            environment's repository
        add_view (bool): generate commands to add view to path variables
        shell (string): One of `sh`, `csh`.
        prompt (string): string to add to the users prompt, or None

    Returns:
        cmds: Shell commands to activate environment.
    TODO: environment to use the activated spack environment.
    """
    global _active_environment

    _active_environment = env
    prepare_config_scope(_active_environment)
    if use_env_repo:
        spack.repo.path.put_first(_active_environment.repo)

    tty.debug("Using environmennt '%s'" % _active_environment.name)

    # Construct the commands to run
    cmds = ''
    if shell == 'csh':
        # TODO: figure out how to make color work for csh
        cmds += 'setenv SPACK_ENV %s;\n' % env.path
        cmds += 'alias despacktivate "spack env deactivate";\n'
        if prompt:
            cmds += 'if (! $?SPACK_OLD_PROMPT ) '
            cmds += 'setenv SPACK_OLD_PROMPT "${prompt}";\n'
            cmds += 'set prompt="%s ${prompt}";\n' % prompt
    else:
        if os.getenv('TERM') and 'color' in os.getenv('TERM') and prompt:
            prompt = colorize('@G{%s} ' % prompt, color=True)

        cmds += 'export SPACK_ENV=%s;\n' % env.path
        cmds += "alias despacktivate='spack env deactivate';\n"
        if prompt:
            cmds += 'if [ -z ${SPACK_OLD_PS1+x} ]; then\n'
            cmds += '    if [ -z ${PS1+x} ]; then\n'
            cmds += "        PS1='$$$$';\n"
            cmds += '    fi;\n'
            cmds += '    export SPACK_OLD_PS1="${PS1}";\n'
            cmds += 'fi;\n'
            cmds += 'export PS1="%s ${PS1}";\n' % prompt

    if add_view and default_view_name in env.views:
        cmds += env.add_default_view_to_shell(shell)

    return cmds
Exemple #19
0
def activate_header(env, shell, prompt=None):
    # Construct the commands to run
    cmds = ''
    if shell == 'csh':
        # TODO: figure out how to make color work for csh
        cmds += 'setenv SPACK_ENV %s;\n' % env.path
        cmds += 'alias despacktivate "spack env deactivate";\n'
        if prompt:
            cmds += 'if (! $?SPACK_OLD_PROMPT ) '
            cmds += 'setenv SPACK_OLD_PROMPT "${prompt}";\n'
            cmds += 'set prompt="%s ${prompt}";\n' % prompt
    elif shell == 'fish':
        if 'color' in os.getenv('TERM', '') and prompt:
            prompt = colorize('@G{%s} ' % prompt, color=True)

        cmds += 'set -gx SPACK_ENV %s;\n' % env.path
        cmds += 'function despacktivate;\n'
        cmds += '   spack env deactivate;\n'
        cmds += 'end;\n'
        #
        # NOTE: We're not changing the fish_prompt function (which is fish's
        # solution to the PS1 variable) here. This is a bit fiddly, and easy to
        # screw up => spend time reasearching a solution. Feedback welcome.
        #
    elif shell == 'bat':
        # TODO: Color
        cmds += 'set "SPACK_ENV=%s"\n' % env.path
        # TODO: despacktivate
        # TODO: prompt
    else:
        if 'color' in os.getenv('TERM', '') and prompt:
            prompt = colorize('@G{%s}' % prompt, color=True)

        cmds += 'export SPACK_ENV=%s;\n' % env.path
        cmds += "alias despacktivate='spack env deactivate';\n"
        if prompt:
            cmds += 'if [ -z ${SPACK_OLD_PS1+x} ]; then\n'
            cmds += '    if [ -z ${PS1+x} ]; then\n'
            cmds += "        PS1='$$$$';\n"
            cmds += '    fi;\n'
            cmds += '    export SPACK_OLD_PS1="${PS1}";\n'
            cmds += 'fi;\n'
            cmds += 'export PS1="%s ${PS1}";\n' % prompt

    return cmds
Exemple #20
0
def compiler_list(args):
    tty.msg("Available compilers")
    index = index_by(spack.compilers.all_compilers(scope=args.scope), 'name')
    for i, (name, compilers) in enumerate(index.items()):
        if i >= 1: print

        cname = "%s{%s}" % (spack.spec.compiler_color, name)
        tty.hline(colorize(cname), char='-')
        colify(reversed(sorted(compilers)))
Exemple #21
0
def dump(stream=None):  # pragma: no cover
    """Dump the final results to the shell to be evaluated"""
    output = format_output()
    stream = sys.stderr if pymod.config.get("dryrun") else stream or sys.stdout
    stream.write(output)

    output = pymod.mc._mc.format_changed_module_state()
    if output.split():
        sys.stderr.write(colorize(output))
Exemple #22
0
def compiler_list(args):
    tty.msg("Available compilers")
    index = index_by(spack.compilers.all_compilers(), 'name')
    for i, (name, compilers) in enumerate(index.items()):
        if i >= 1: print

        cname = "%s{%s}" % (spack.spec.compiler_color, name)
        tty.hline(colorize(cname), char='-')
        colify(reversed(sorted(compilers)))
Exemple #23
0
def find(names):
    for name in names:
        s = None
        candidates = pymod.modulepath.candidates(name)
        if not candidates:
            raise ModuleNotFoundError(name)
        for module in candidates:
            s = "@*{%s}\n  @C{%s}" % (module.fullname, module.filename)
            sys.stderr.write(colorize(s) + "\n")
Exemple #24
0
def get_package_context(traceback, context=3):
    """Return some context for an error message when the build fails.

    Args:
        traceback (traceback): A traceback from some exception raised during
            install
        context (int): Lines of context to show before and after the line
            where the error happened

    This function inspects the stack to find where we failed in the
    package file, and it adds detailed context to the long_message
    from there.

    """
    def make_stack(tb, stack=None):
        """Tracebacks come out of the system in caller -> callee order.  Return
        an array in callee -> caller order so we can traverse it."""
        if stack is None:
            stack = []
        if tb is not None:
            make_stack(tb.tb_next, stack)
            stack.append(tb)
        return stack

    stack = make_stack(traceback)

    for tb in stack:
        frame = tb.tb_frame
        if 'self' in frame.f_locals:
            # Find the first proper subclass of PackageBase.
            obj = frame.f_locals['self']
            if isinstance(obj, spack.package.PackageBase):
                break

    # we found obj, the Package implementation we care about.
    # point out the location in the install method where we failed.
    lines = []
    lines.append("%s:%d, in %s:" % (
        inspect.getfile(frame.f_code), frame.f_lineno, frame.f_code.co_name
    ))

    # Build a message showing context in the install method.
    sourcelines, start = inspect.getsourcelines(frame)

    fl = frame.f_lineno - start
    start_ctx = max(0, fl - context)
    sourcelines = sourcelines[start_ctx:fl + context + 1]
    for i, line in enumerate(sourcelines):
        is_error = start_ctx + i == fl
        mark = ">> " if is_error else "   "
        marked = "  %s%-6d%s" % (mark, start_ctx + i, line.rstrip())
        if is_error:
            marked = colorize('@R{%s}' % marked)
        lines.append(marked)

    return lines
Exemple #25
0
def help(parser, args):
    if args.guide:
        print(colorize(guides[args.guide]))
        return 0

    if args.help_command:
        parser.add_command(args.help_command)
        parser.parse_args([args.help_command, '-h'])
    else:
        sys.stdout.write(parser.format_help(level=args.all))
Exemple #26
0
def help(parser, args):
    if args.guide:
        print(colorize(guides[args.guide]))
        return 0

    if args.help_command:
        parser.add_command(args.help_command)
        parser.parse_args([args.help_command, '-h'])
    else:
        sys.stdout.write(parser.format_help(level=args.all))
Exemple #27
0
def shell_init_instructions(cmd, equivalent):
    """Print out instructions for users to initialize shell support.

    Arguments:
        cmd (str): the command the user tried to run that requires
            shell support in order to work
        equivalent (str): a command they can run instead, without
            enabling shell support
    """

    shell_specific = "{sh_arg}" in equivalent

    msg = [
        "`%s` requires spack's shell support." % cmd,
        "",
        "To set up shell support, run the command below for your shell.",
        "",
        color.colorize("@*c{For bash/zsh/sh:}"),
        "  . %s/setup-env.sh" % spack.paths.share_path,
        "",
        color.colorize("@*c{For csh/tcsh:}"),
        "  source %s/setup-env.csh" % spack.paths.share_path,
        "",
        color.colorize("@*c{For fish:}"),
        "  source %s/setup-env.fish" % spack.paths.share_path,
        "",
        "Or, if you do not want to use shell support, run " +
        ("one of these" if shell_specific else "this") + " instead:",
        "",
    ]

    if shell_specific:
        msg += [
            equivalent.format(sh_arg="--sh  ") + "  # bash/zsh/sh",
            equivalent.format(sh_arg="--csh ") + "  # csh/tcsh",
            equivalent.format(sh_arg="--fish") + "  # fish",
        ]
    else:
        msg += ["  " + equivalent]

    msg += ['']
    tty.error(*msg)
Exemple #28
0
def list(parser, args):
    for subcommand, check_tags in spack.audit.GROUPS.items():
        print(cl.colorize('@*b{' + subcommand + '}:'))
        for tag in check_tags:
            audit_obj = spack.audit.CALLBACKS[tag]
            print('  ' + audit_obj.description)
            if args.verbose:
                for idx, fn in enumerate(audit_obj.callbacks):
                    print('    {0}. '.format(idx + 1) + fn.__doc__)
                print()
        print()
Exemple #29
0
def style(parser, args):
    # save initial working directory for relativizing paths later
    global initial_working_dir
    initial_working_dir = os.getcwd()

    file_list = args.files
    if file_list:

        def prefix_relative(path):
            return os.path.relpath(os.path.abspath(os.path.realpath(path)),
                                   spack.paths.prefix)

        file_list = [prefix_relative(p) for p in file_list]

    returncode = 0
    with working_dir(spack.paths.prefix):
        if not file_list:
            file_list = changed_files(args.base, args.untracked, args.all)
        print_style_header(file_list, args)

        # run tools in order defined in tool_order
        returncode = 0
        for tool_name in tool_order:
            if getattr(args, tool_name):
                run_function, required = tools[tool_name]
                print_tool_header(tool_name)

                cmd = which(tool_name, required=required)
                if not cmd:
                    color.cprint("  @y{%s not in PATH, skipped}" % tool_name)
                    continue

                returncode |= run_function(cmd, file_list, args)

    if returncode == 0:
        tty.msg(color.colorize("@*{spack style checks were clean}"))
    else:
        tty.error(color.colorize("@*{spack style found errors}"))

    return returncode
Exemple #30
0
def env_activate(args):
    env = args.activate_env
    if not args.shell:
        msg = [
            "This command works best with Spack's shell support",
            ""
        ] + spack.cmd.common.shell_init_instructions + [
            'Or, if you want to use `spack env activate` without initializing',
            'shell support, you can run one of these:',
            '',
            '    eval `spack env activate --sh %s`   # for bash/sh' % env,
            '    eval `spack env activate --csh %s`  # for csh/tcsh' % env,
        ]
        tty.msg(*msg)
        return 1

    if ev.exists(env) and not args.dir:
        spack_env = ev.root(env)
        short_name = env
        env_prompt = '[%s]' % env

    elif ev.is_env_dir(env):
        spack_env = os.path.abspath(env)
        short_name = os.path.basename(os.path.abspath(env))
        env_prompt = '[%s]' % short_name

    else:
        tty.die("No such environment: '%s'" % env)

    if spack_env == os.environ.get('SPACK_ENV'):
        tty.die("Environment %s is already active" % args.activate_env)

    if args.shell == 'csh':
        # TODO: figure out how to make color work for csh
        sys.stdout.write('setenv SPACK_ENV %s;\n' % spack_env)
        sys.stdout.write('alias despacktivate "spack env deactivate";\n')
        if args.prompt:
            sys.stdout.write('if (! $?SPACK_OLD_PROMPT ) '
                             'setenv SPACK_OLD_PROMPT "${prompt}";\n')
            sys.stdout.write('set prompt="%s ${prompt}";\n' % env_prompt)

    else:
        if 'color' in os.environ['TERM']:
            env_prompt = colorize('@G{%s} ' % env_prompt, color=True)

        sys.stdout.write('export SPACK_ENV=%s;\n' % spack_env)
        sys.stdout.write("alias despacktivate='spack env deactivate';\n")
        if args.prompt:
            sys.stdout.write('if [ -z "${SPACK_OLD_PS1}" ]; then\n')
            sys.stdout.write('export SPACK_OLD_PS1="${PS1}"; fi;\n')
            sys.stdout.write('export PS1="%s ${PS1}";\n' % env_prompt)
Exemple #31
0
def env_activate(args):
    env = args.activate_env
    if not args.shell:
        msg = [
            "This command works best with Spack's shell support",
            ""
        ] + spack.cmd.common.shell_init_instructions + [
            'Or, if you want to use `spack env activate` without initializing',
            'shell support, you can run one of these:',
            '',
            '    eval `spack env activate --sh %s`   # for bash/sh' % env,
            '    eval `spack env activate --csh %s`  # for csh/tcsh' % env,
        ]
        tty.msg(*msg)
        return 1

    if ev.exists(env) and not args.dir:
        spack_env = ev.root(env)
        short_name = env
        env_prompt = '[%s]' % env

    elif ev.is_env_dir(env):
        spack_env = os.path.abspath(env)
        short_name = os.path.basename(os.path.abspath(env))
        env_prompt = '[%s]' % short_name

    else:
        tty.die("No such environment: '%s'" % env)

    if spack_env == os.environ.get('SPACK_ENV'):
        tty.die("Environment %s is already active" % args.activate_env)

    if args.shell == 'csh':
        # TODO: figure out how to make color work for csh
        sys.stdout.write('setenv SPACK_ENV %s;\n' % spack_env)
        sys.stdout.write('alias despacktivate "spack env deactivate";\n')
        if args.prompt:
            sys.stdout.write('if (! $?SPACK_OLD_PROMPT ) '
                             'setenv SPACK_OLD_PROMPT "${prompt}";\n')
            sys.stdout.write('set prompt="%s ${prompt}";\n' % env_prompt)

    else:
        if 'color' in os.environ['TERM']:
            env_prompt = colorize('@G{%s} ' % env_prompt, color=True)

        sys.stdout.write('export SPACK_ENV=%s;\n' % spack_env)
        sys.stdout.write("alias despacktivate='spack env deactivate';\n")
        if args.prompt:
            sys.stdout.write('if [ -z "${SPACK_OLD_PS1}" ]; then\n')
            sys.stdout.write('export SPACK_OLD_PS1="${PS1}"; fi;\n')
            sys.stdout.write('export PS1="%s ${PS1}";\n' % env_prompt)
Exemple #32
0
    def write_line_break(self):
        super(LineAnnotationDumper, self).write_line_break()
        if self.saved is None:
            _annotations.append(colorize('@K{---}'))
            return

        # append annotations at the end of each line
        if self.saved:
            mark = self.saved._start_mark

            color = self.filename_colors.get(mark.name)
            if not color:
                ncolors = len(self.colors)
                color = self.colors[len(self.filename_colors) % ncolors]
                self.filename_colors[mark.name] = color

            fmt = '@%s{%%s}' % color
            ann = fmt % mark.name
            if mark.line is not None:
                ann += ':@c{%s}' % (mark.line + 1)
            _annotations.append(colorize(ann))
        else:
            _annotations.append('')
Exemple #33
0
    def write_line_break(self):
        super(LineAnnotationDumper, self).write_line_break()
        if not self.saved:
            return

        # append annotations at the end of each line
        if self.saved:
            mark = self.saved._start_mark
            ann = '@K{%s}' % mark.name
            if mark.line is not None:
                ann += ':@c{%s}' % (mark.line + 1)
            _annotations.append(colorize(ann))
        else:
            _annotations.append('')
Exemple #34
0
def disambiguate_spec(spec):
    matching_specs = spack.store.db.query(spec)
    if not matching_specs:
        tty.die("Spec '%s' matches no installed packages." % spec)

    elif len(matching_specs) > 1:
        args = ["%s matches multiple packages." % spec,
                "Matching packages:"]
        args += [colorize("  @K{%s} " % s.dag_hash(7)) +
                 s.cformat('$_$@$%@$=') for s in matching_specs]
        args += ["Use a more specific spec."]
        tty.die(*args)

    return matching_specs[0]
Exemple #35
0
def disambiguate_spec(spec):
    matching_specs = spack.store.db.query(spec)
    if not matching_specs:
        tty.die("Spec '%s' matches no installed packages." % spec)

    elif len(matching_specs) > 1:
        args = ["%s matches multiple packages." % spec,
                "Matching packages:"]
        args += [colorize("  @K{%s} " % s.dag_hash(7)) +
                 s.cformat('$_$@$%@$=') for s in matching_specs]
        args += ["Use a more specific spec."]
        tty.die(*args)

    return matching_specs[0]
Exemple #36
0
def compiler_list(args):
    tty.msg("Available compilers")
    index = index_by(spack.compilers.all_compilers(scope=args.scope),
                     lambda c: (c.spec.name, c.operating_system, c.target))
    ordered_sections = sorted(index.items(), key=lambda item: item[0])
    for i, (key, compilers) in enumerate(ordered_sections):
        if i >= 1:
            print()
        name, os, target = key
        os_str = os
        if target:
            os_str += "-%s" % target
        cname = "%s{%s} %s" % (spack.spec.compiler_color, name, os_str)
        tty.hline(colorize(cname), char='-')
        colify(reversed(sorted(c.spec for c in compilers)))
Exemple #37
0
def env_list(args):
    names = ev.all_environment_names()

    color_names = []
    for name in names:
        if ev.active(name):
            name = colorize('@*g{%s}' % name)
        color_names.append(name)

    # say how many there are if writing to a tty
    if sys.stdout.isatty():
        if not names:
            tty.msg('No environments')
        else:
            tty.msg('%d environments' % len(names))

    colify(color_names, indent=4)
Exemple #38
0
def find(parser, args):
    q_args = query_arguments(args)
    results = args.specs(**q_args)

    decorator = lambda s, f: f
    added = set()
    removed = set()

    env = ev.get_env(args, 'find', required=False)
    if env:
        decorator, added, roots, removed = setup_env(env)

    # Exit early if no package matches the constraint
    if not results and args.constraint:
        msg = "No package matches the query: {0}"
        msg = msg.format(' '.join(args.constraint))
        tty.msg(msg)
        return

    # If tags have been specified on the command line, filter by tags
    if args.tags:
        packages_with_tags = spack.repo.path.packages_with_tags(*args.tags)
        results = [x for x in results if x.name in packages_with_tags]

    # Display the result
    if env:
        tty.msg('In environment %s' % env.name)

        if not env.user_specs:
            tty.msg('No root specs')
        else:
            tty.msg('Root specs')
            display_specs(
                env.user_specs, args,
                decorator=lambda s, f: color.colorize('@*{%s}' % f))
        print()

        if args.show_concretized:
            tty.msg('Concretized roots')
            display_specs(
                env.specs_by_hash.values(), args, decorator=decorator)
            print()

    tty.msg("%s" % plural(len(results), 'installed package'))

    display_specs(results, args, decorator=decorator, all_headers=True)
Exemple #39
0
    def write_line_break(self):
        super(LineAnnotationDumper, self).write_line_break()
        if not self.saved:
            return

        # append annotations at the end of each line
        if self.saved:
            mark = self.saved._start_mark

            color = self.filename_colors.get(mark.name)
            if not color:
                ncolors = len(self.colors)
                color = self.colors[len(self.filename_colors) % ncolors]
                self.filename_colors[mark.name] = color

            fmt = '@%s{%%s}' % color
            ann = fmt % mark.name
            if mark.line is not None:
                ann += ':@c{%s}' % (mark.line + 1)
            _annotations.append(colorize(ann))
        else:
            _annotations.append('')
Exemple #40
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.  There are three possible "modes":

      * ``short`` (default): short specs with name and version, columnized
      * ``paths``: Two columns: one for specs, one for paths
      * ``deps``: Dependency-tree style, like ``spack spec``; can get long

    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 of spack.spec.Spec): the specs to display
        args (optional argparse.Namespace): namespace containing
            formatting arguments

    Keyword Args:
        mode (str): Either 'short', 'paths', or 'deps'
        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

    """
    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

    mode      = get_arg('mode', 'short')
    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)

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

    nfmt = '.' if namespace else '_'
    ffmt = ''
    if full_compiler or flags:
        ffmt += '$%'
        if full_compiler:
            ffmt += '@'
        ffmt += '+'
    vfmt = '$+' if variants else ''
    format_string = '$%s$@%s%s' % (nfmt, ffmt, vfmt)

    # Make a dict with specs keyed by architecture and compiler.
    index = index_by(specs, ('architecture', 'compiler'))

    # Traverse the index and print out each package
    for i, (architecture, compiler) in enumerate(sorted(index)):
        if i > 0:
            print()

        header = "%s{%s} / %s{%s}" % (spack.spec.architecture_color,
                                      architecture, spack.spec.compiler_color,
                                      compiler)
        # Sometimes we want to display specs that are not yet concretized.
        # If they don't have a compiler / architecture attached to them,
        # then skip the header
        if architecture is not None or compiler is not None:
            tty.hline(colorize(header), char='-')

        specs = index[(architecture, compiler)]
        specs.sort()

        abbreviated = [s.cformat(format_string) for s in specs]
        if mode == 'paths':
            # Print one spec per line along with prefix path
            width = max(len(s) for s in abbreviated)
            width += 2
            format = "    %%-%ds%%s" % width

            for abbrv, spec in zip(abbreviated, specs):
                prefix = gray_hash(spec, hlen) if hashes else ''
                print(prefix + (format % (abbrv, spec.prefix)))

        elif mode == 'deps':
            for spec in specs:
                print(spec.tree(
                    format=format_string,
                    indent=4,
                    prefix=(lambda s: gray_hash(s, hlen)) if hashes else None))

        elif mode == 'short':
            # Print columns of output if not printing flags
            if not flags and not full_compiler:

                def fmt(s):
                    string = ""
                    if hashes:
                        string += gray_hash(s, hlen) + ' '
                    string += s.cformat('$-%s$@%s' % (nfmt, vfmt))

                    return string

                colify(fmt(s) for s in specs)
            # Print one entry per line if including flags
            else:
                for spec in specs:
                    # Print the hash if necessary
                    hsh = gray_hash(spec, hlen) + ' ' if hashes else ''
                    print(hsh + spec.cformat(format_string) + '\n')

        else:
            raise ValueError(
                "Invalid mode for display_specs: %s. Must be one of (paths,"
                "deps, short)." % mode)
Exemple #41
0
 def write_stream_start(self):
     super(LineAnnotationDumper, self).write_stream_start()
     _annotations.append(colorize('@K{---}'))
Exemple #42
0
def gray_hash(spec, length):
    return colorize('@K{%s}' % spec.dag_hash(length))
Exemple #43
0
def make_log_context(log_events, width=None):
    """Get error context from a log file.

    Args:
        log_events (list of LogEvent): list of events created by
            ``ctest_log_parser.parse()``
        width (int or None): wrap width; ``0`` for no limit; ``None`` to
            auto-size for terminal
    Returns:
        str: context from the build log with errors highlighted

    Parses the log file for lines containing errors, and prints them out
    with line numbers and context.  Errors are highlighted with '>>' and
    with red highlighting (if color is enabled).

    Events are sorted by line number before they are displayed.
    """
    error_lines = set(e.line_no for e in log_events)
    log_events = sorted(log_events, key=lambda e: e.line_no)

    num_width = len(str(max(error_lines))) + 4
    line_fmt = '%%-%dd%%s' % num_width
    indent = ' ' * (5 + num_width)

    if width is None:
        _, width = tty.terminal_size()
    if width <= 0:
        width = sys.maxsize
    wrap_width = width - num_width - 6

    out = StringIO()
    next_line = 1
    for event in log_events:
        start = event.start

        if isinstance(event, BuildError):
            color = 'R'
        elif isinstance(event, BuildWarning):
            color = 'Y'
        else:
            color = 'W'

        if next_line != 1 and start > next_line:
            out.write('\n     ...\n\n')

        if start < next_line:
            start = next_line

        for i in range(start, event.end):
            # wrap to width
            lines = _wrap(event[i], wrap_width)
            lines[1:] = [indent + l for l in lines[1:]]
            wrapped_line = line_fmt % (i, '\n'.join(lines))

            if i in error_lines:
                out.write(colorize(
                    '  @%s{>> %s}\n' % (color, cescape(wrapped_line))))
            else:
                out.write('     %s\n' % wrapped_line)

        next_line = event.end

    return out.getvalue()
Exemple #44
0
def get_package_context(traceback, context=3):
    """Return some context for an error message when the build fails.

    Args:
        traceback (traceback): A traceback from some exception raised during
            install
        context (int): Lines of context to show before and after the line
            where the error happened

    This function inspects the stack to find where we failed in the
    package file, and it adds detailed context to the long_message
    from there.

    """
    def make_stack(tb, stack=None):
        """Tracebacks come out of the system in caller -> callee order.  Return
        an array in callee -> caller order so we can traverse it."""
        if stack is None:
            stack = []
        if tb is not None:
            make_stack(tb.tb_next, stack)
            stack.append(tb)
        return stack

    stack = make_stack(traceback)

    for tb in stack:
        frame = tb.tb_frame
        if 'self' in frame.f_locals:
            # Find the first proper subclass of PackageBase.
            obj = frame.f_locals['self']
            if isinstance(obj, spack.package.PackageBase):
                break

    # We found obj, the Package implementation we care about.
    # Point out the location in the install method where we failed.
    lines = [
        '{0}:{1:d}, in {2}:'.format(
            inspect.getfile(frame.f_code),
            frame.f_lineno - 1,  # subtract 1 because f_lineno is 0-indexed
            frame.f_code.co_name
        )
    ]

    # Build a message showing context in the install method.
    sourcelines, start = inspect.getsourcelines(frame)

    # Calculate lineno of the error relative to the start of the function.
    # Subtract 1 because f_lineno is 0-indexed.
    fun_lineno = frame.f_lineno - start - 1
    start_ctx = max(0, fun_lineno - context)
    sourcelines = sourcelines[start_ctx:fun_lineno + context + 1]

    for i, line in enumerate(sourcelines):
        is_error = start_ctx + i == fun_lineno
        mark = '>> ' if is_error else '   '
        # Add start to get lineno relative to start of file, not function.
        marked = '  {0}{1:-6d}{2}'.format(
            mark, start + start_ctx + i, line.rstrip())
        if is_error:
            marked = colorize('@R{%s}' % cescape(marked))
        lines.append(marked)

    return lines
Exemple #45
0
def color_url(path, **kwargs):
    """Color the parts of the url according to Spack's parsing.

    Colors are:
       | Cyan: The version found by :func:`parse_version_offset`.
       | Red:  The name found by :func:`parse_name_offset`.

       | Green:   Instances of version string from :func:`substitute_version`.
       | Magenta: Instances of the name (protected from substitution).

    Args:
        path (str): The filename or URL for the package
        errors (bool): Append parse errors at end of string.
        subs (bool): Color substitutions as well as parsed name/version.
    """
    errors = kwargs.get('errors', False)
    subs   = kwargs.get('subs', False)

    (name, ns, nl, noffs,
     ver,  vs, vl, voffs) = substitution_offsets(path)

    nends = [no + nl - 1 for no in noffs]
    vends = [vo + vl - 1 for vo in voffs]

    nerr = verr = 0
    out = StringIO()
    for i in range(len(path)):
        if i == vs:
            out.write('@c')
            verr += 1
        elif i == ns:
            out.write('@r')
            nerr += 1
        elif subs:
            if i in voffs:
                out.write('@g')
            elif i in noffs:
                out.write('@m')

        out.write(path[i])

        if i == vs + vl - 1:
            out.write('@.')
            verr += 1
        elif i == ns + nl - 1:
            out.write('@.')
            nerr += 1
        elif subs:
            if i in vends or i in nends:
                out.write('@.')

    if errors:
        if nerr == 0:
            out.write(" @r{[no name]}")
        if verr == 0:
            out.write(" @r{[no version]}")
        if nerr == 1:
            out.write(" @r{[incomplete name]}")
        if verr == 1:
            out.write(" @r{[incomplete version]}")

    return colorize(out.getvalue())
Exemple #46
0
def gray_hash(spec, length):
    h = spec.dag_hash(length) if spec.concrete else '-' * length
    return colorize('@K{%s}' % h)