def _pre_parse_args(self, sysargs): """Pre-parse sys args. Several steps: - extract the global options and detects the possible command and its args - validate global options and apply them - validate that command is correct (NOT loading and parsing its arguments) """ # get all flags (default to False) and those per options, to filter sysargs flags = {} flag_per_option = {} for flag, short_option, long_option, _ in GLOBAL_FLAGS: flag_per_option[short_option] = flag flag_per_option[long_option] = flag flags[flag] = False filtered_sysargs = [] for arg in sysargs: if arg in flag_per_option: flags[flag_per_option[arg]] = True else: filtered_sysargs.append(arg) # control and use quiet/verbose options if flags['quiet'] and flags['verbose']: raise CommandError( "The 'verbose' and 'quiet' options are mutually exclusive.") if flags['quiet']: message_handler.set_mode(message_handler.QUIET) elif flags['verbose']: message_handler.set_mode(message_handler.VERBOSE) logger.debug("Raw pre-parsed sysargs: flags=%s filtered=%s", flags, filtered_sysargs) # if help requested, transform the parameters to make that explicit if flags['help']: command = HelpCommand.name cmd_args = filtered_sysargs elif filtered_sysargs: command = filtered_sysargs[0] cmd_args = filtered_sysargs[1:] if command not in self.commands: msg = "no such command {!r}".format(command) help_text = helptexts.get_usage_message('charmcraft', msg) raise CommandError(help_text, argsparsing=True) else: # no command! help_text = get_general_help() raise CommandError(help_text, argsparsing=True) logger.debug("General parsed sysargs: command=%r args=%s", command, cmd_args) return command, cmd_args
def test_get_usage_message(): """Check the general "usage" text.""" text = get_usage_message("charmcraft build", "bad parameter for the build") expected = textwrap.dedent("""\ Usage: charmcraft [options] command [args]... Try 'charmcraft build -h' for help. Error: bad parameter for the build """) assert text == expected
def run(self, parsed_args, all_commands): """Present different help messages to the user. Unlike other commands, this one receives an extra parameter with all commands, to validate if the help requested is on a valid one, or even parse its data. """ if parsed_args.command_to_help is None or parsed_args.command_to_help == self.name: # help on no command in particular, get general text help_text = get_general_help(detailed=parsed_args.all) elif parsed_args.command_to_help not in all_commands: # asked help on a command that doesn't exist msg = "no such command {!r}".format(parsed_args.command_to_help) help_text = helptexts.get_usage_message('charmcraft', msg) else: cmd_class, group = all_commands[parsed_args.command_to_help] cmd = cmd_class(group) parser = CustomArgumentParser(prog=cmd.name) cmd.fill_parser(parser) help_text = get_command_help(parser, cmd) raise CommandError(help_text, argsparsing=True)
def _pre_parse_args(self, sysargs): """Pre-parse sys args. Several steps: - extract the global options and detects the possible command and its args - validate global options and apply them - validate that command is correct (NOT loading and parsing its arguments) """ # get all arguments (default to what's specified) and those per options, to filter sysargs global_args = {} arg_per_option = {} options_with_equal = [] for arg in GLOBAL_ARGS: arg_per_option[arg.short_option] = arg arg_per_option[arg.long_option] = arg if arg.type == 'flag': default = False elif arg.type == 'option': default = None options_with_equal.append(arg.long_option + '=') else: raise ValueError("Bad GLOBAL_ARGS structure.") global_args[arg.name] = default filtered_sysargs = [] sysargs = iter(sysargs) options_with_equal = tuple(options_with_equal) for sysarg in sysargs: if sysarg in arg_per_option: arg = arg_per_option[sysarg] if arg.type == 'flag': value = True else: try: value = next(sysargs) except StopIteration: raise CommandError( "The 'project-dir' option expects one argument.") global_args[arg.name] = value elif sysarg.startswith(options_with_equal): option, value = sysarg.split('=', 1) if not value: raise CommandError( "The 'project-dir' option expects one argument.") arg = arg_per_option[option] global_args[arg.name] = value else: filtered_sysargs.append(sysarg) # control and use quiet/verbose options if global_args['quiet'] and global_args['verbose']: raise CommandError( "The 'verbose' and 'quiet' options are mutually exclusive.") if global_args['quiet']: message_handler.set_mode(message_handler.QUIET) elif global_args['verbose']: message_handler.set_mode(message_handler.VERBOSE) logger.debug("Raw pre-parsed sysargs: args=%s filtered=%s", global_args, filtered_sysargs) # if help requested, transform the parameters to make that explicit if global_args['help']: command = HelpCommand.name cmd_args = filtered_sysargs elif filtered_sysargs: command = filtered_sysargs[0] cmd_args = filtered_sysargs[1:] if command not in self.commands: msg = "no such command {!r}".format(command) help_text = helptexts.get_usage_message('charmcraft', msg) raise CommandError(help_text, argsparsing=True) else: # no command! help_text = get_general_help() raise CommandError(help_text, argsparsing=True) # load the system's config charmcraft_config = config.load(global_args['project_dir']) logger.debug("General parsed sysargs: command=%r args=%s", command, cmd_args) return command, cmd_args, charmcraft_config
def error(self, message): """Show the usage, the error message, and no more.""" fullcommand = "charmcraft " + self.prog full_msg = helptexts.get_usage_message(fullcommand, message) raise CommandError(full_msg, argsparsing=True)