def test_dispatcher_generic_setup_default(): """Generic parameter handling for default values.""" cmd = create_command("somecommand") groups = [CommandGroup("title", [cmd])] emit.set_mode(EmitterMode.NORMAL) # this is how `main` will init the Emitter dispatcher = Dispatcher(groups) dispatcher.pre_parse_args(["somecommand"]) assert emit.get_mode() == EmitterMode.NORMAL
def test_dispatcher_generic_setup_trace(options): """Generic parameter handling for trace log setup, directly or after the command.""" cmd = create_command("somecommand") groups = [CommandGroup("title", [cmd])] emit.set_mode(EmitterMode.NORMAL) # this is how `main` will init the Emitter dispatcher = Dispatcher(groups) dispatcher.pre_parse_args(options) assert emit.get_mode() == EmitterMode.TRACE
def _run_dispatcher(dispatcher: craft_cli.Dispatcher) -> None: global_args = dispatcher.pre_parse_args(sys.argv[1:]) if global_args.get("version"): emit.message(f"snapcraft {__version__}") else: if global_args.get("trace"): emit.message( "Options -t and --trace are deprecated, use --verbosity=debug instead." ) emit.set_mode(EmitterMode.DEBUG) dispatcher.load_command(None) dispatcher.run() emit.ended_ok()
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 self.global_arguments: 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 ArgumentParsingError( f"The {arg.name!r} option expects one argument.") global_args[arg.name] = value elif sysarg.startswith(options_with_equal): option, value = sysarg.split("=", 1) if not value: raise ArgumentParsingError( f"The {arg.name!r} 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 sum([global_args[key] for key in ("quiet", "verbose", "trace")]) > 1: raise ArgumentParsingError( "The 'verbose', 'trace' and 'quiet' options are mutually exclusive." ) if global_args["quiet"]: emit.set_mode(EmitterMode.QUIET) elif global_args["verbose"]: emit.set_mode(EmitterMode.VERBOSE) elif global_args["trace"]: emit.set_mode(EmitterMode.TRACE) emit.trace( f"Raw pre-parsed sysargs: args={global_args} filtered={filtered_sysargs}" ) # handle requested help through -h/--help options if global_args["help"]: help_text = self._get_requested_help(filtered_sysargs) raise ProvideHelpException(help_text) if filtered_sysargs: command = filtered_sysargs[0] cmd_args = filtered_sysargs[1:] # handle requested help through implicit "help" command if command == "help": help_text = self._get_requested_help(cmd_args) raise ProvideHelpException(help_text) self.command_args = cmd_args try: self.command_class = self.commands[command] except KeyError: msg = "no such command {!r}".format(command) help_text = help_builder.get_usage_message(msg) raise ArgumentParsingError(help_text) else: # no command passed! help_text = self._get_general_help(detailed=False) raise ArgumentParsingError(help_text) emit.trace( f"General parsed sysargs: command={ command!r} args={cmd_args}") return global_args