def commands(parser, args): formatter = formatters[args.format] # check header first so we don't open out files unnecessarily if args.header and not os.path.exists(args.header): tty.die("No such file: '%s'" % args.header) # if we're updating an existing file, only write output if a command # is newer than the file. if args.update: if os.path.exists(args.update): files = [ # pyc -> py get_command_module(command).__file__.rstrip('c') for command in all_commands() ] last_update = os.path.getmtime(args.update) if not any(os.path.getmtime(f) > last_update for f in files): tty.msg('File is up to date: %s' % args.update) return tty.msg('Updating file: %s' % args.update) with open(args.update, 'w') as f: prepend_header(args, f) formatter(args, f) else: prepend_header(args, sys.stdout) formatter(args, sys.stdout)
def index_commands(): """create an index of commands by section for this help level""" index = {} for command in all_commands(): cmd_module = get_command_module(command) # make sure command modules have required properties for p in required_command_properties: prop = getattr(cmd_module, p, None) if not prop: tty.die("Command doesn't define a property '%s': %s" % (p, command)) # add commands to lists for their level and higher levels for level in reversed(levels): level_sections = index.setdefault(level, {}) commands = level_sections.setdefault(cmd_module.section, []) commands.append(command) if level == cmd_module.level: break return index
def add_all_commands(parser): """Add all spack subcommands to the parser.""" for cmd in all_commands(): parser.add_command(cmd)
def format_help_sections(self, level): """Format help on sections for a particular verbosity level. Args: level (str): 'short' or 'long' (more commands shown for long) """ if level not in levels: raise ValueError("level must be one of: %s" % levels) # lazily add all commands to the parser when needed. add_all_commands(self) """Print help on subcommands in neatly formatted sections.""" formatter = self._get_formatter() # Create a list of subcommand actions. Argparse internals are nasty! # Note: you can only call _get_subactions() once. Even nastier! if not hasattr(self, 'actions'): self.actions = self._subparsers._actions[-1]._get_subactions() # make a set of commands not yet added. remaining = set(all_commands()) def add_group(group): formatter.start_section(group.title) formatter.add_text(group.description) formatter.add_arguments(group._group_actions) formatter.end_section() def add_subcommand_group(title, commands): """Add informational help group for a specific subcommand set.""" cmd_set = set(c for c in commands) # make a dict of commands of interest cmds = dict((a.dest, a) for a in self.actions if a.dest in cmd_set) # add commands to a group in order, and add the group group = argparse._ArgumentGroup(self, title=title) for name in commands: group._add_action(cmds[name]) if name in remaining: remaining.remove(name) add_group(group) # select only the options for the particular level we're showing. show_options = options_by_level[level] if show_options != 'all': opts = dict((opt.option_strings[0].strip('-'), opt) for opt in self._optionals._group_actions) new_actions = [opts[letter] for letter in show_options] self._optionals._group_actions = new_actions # custom, more concise usage for top level help_options = self._optionals._group_actions help_options = help_options + [self._positionals._group_actions[-1]] formatter.add_usage(self.usage, help_options, self._mutually_exclusive_groups) # description formatter.add_text(self.description) # start subcommands formatter.add_text(intro_by_level[level]) # add argument groups based on metadata in commands index = index_commands() sections = index[level] for section in sorted(sections): if section == 'help': continue # Cover help in the epilog. group_description = section_descriptions.get(section, section) to_display = sections[section] commands = [] # add commands whose order we care about first. if section in section_order: commands.extend(cmd for cmd in section_order[section] if cmd in to_display) # add rest in alphabetical order. commands.extend(cmd for cmd in sorted(sections[section]) if cmd not in commands) # add the group to the parser add_subcommand_group(group_description, commands) # optionals add_group(self._optionals) # epilog formatter.add_text("""\ {help}: spack help --all list all commands and options spack help <command> help on a specific command spack help --spec help on the package specification syntax spack docs open http://spack.rtfd.io/ in a browser """.format(help=section_descriptions['help'])) # determine help from format above return formatter.format_help()
def names(args, out): colify(all_commands(), output=out)
def test_commands_by_name(): """Test default output of spack commands.""" out = commands() assert out.strip().split('\n') == sorted(all_commands())