def test_split_input(self): from kamaki.cli.utils import split_input for line, expected in ( ('set key="v1"', ['set', 'key=v1']), ('unparsable', ['unparsable']), ('"parsable"', ['parsable']), ('"parse" out', ['parse', 'out']), ('"one', ['"one']), ('two" or" more"', ['two or', 'more"']), ('Go "down \'deep " deeper \'bottom \' up" go\' up" !', [ 'Go', "down 'deep ", 'deeper', 'bottom ', 'up go\' up', '!']), ('Is "this" a \'parsed\' string?', [ 'Is', 'this', 'a', 'parsed', 'string?'])): self.assertEqual(split_input(line), expected)
def complete_method(self, text, line, begidx, endidx): subcmd, cmd_args = cmd.parse_out(split_input(line)[1:]) if subcmd.is_command: cls = subcmd.cmd_class instance = cls(dict(arguments)) empty, sep, subname = subcmd.path.partition(cmd.path) cmd_name = '%s %s' % (cmd.name, subname.replace('_', ' ')) print('\n%s\nSyntax:\t%s %s' % ( cls.help, cmd_name, cls.syntax)) cmd_args = {} for arg in instance.arguments.values(): cmd_args[','.join(arg.parsed_name)] = arg.help print_dict(cmd_args, indent=2) stdout.write('%s %s' % (self.prompt, line)) return subcmd.subnames()
def complete_method(self, text, line, begidx, endidx): subcmd, cmd_args = cmd.parse_out(split_input(line)[1:]) if subcmd.is_command: cls = subcmd.cmd_class instance = cls(dict(arguments)) empty, sep, subname = subcmd.path.partition(cmd.path) cmd_name = '%s %s' % (cmd.name, subname.replace('_', ' ')) print('\n%s\nSyntax:\t%s %s' % (cls.help, cmd_name, cls.syntax)) cmd_args = {} for arg in instance.arguments.values(): cmd_args[','.join(arg.parsed_name)] = arg.help print_dict(cmd_args, indent=2) stdout.write('%s %s' % (self.prompt, line)) return subcmd.subnames()
def parse(self, new_args=None): """Parse user input""" try: pkargs = (new_args,) if new_args else () self._parsed, unparsed = self.parser.parse_known_args(*pkargs) parsed_args = [ k for k, v in vars(self._parsed).items() if v not in (None, )] if not self._parse_required_arguments(self.required, parsed_args): self.print_help() raise CLISyntaxError('Missing required arguments') except SystemExit: raiseCLIError(CLISyntaxError('Argument Syntax Error')) for name, arg in self.arguments.items(): arg.value = getattr(self._parsed, name, arg.default) self._unparsed = [] for term in unparsed: self._unparsed += split_input(' \'%s\' ' % term) self._parser_modified = False
def _run_from_line(self, line): terms = split_input(line) cmd, args = self._cmd_tree.find_best_match(terms) if cmd.is_command: try: instance = cmd.cmd_class( self.arguments, auth_base=getattr(self, 'auth_base', None)) instance.config = self.config prs = ArgumentParseManager( cmd.path.split(), dict(instance.arguments)) prs.syntax = '%s %s' % ( cmd.path.replace('_', ' '), cmd.cmd_class.syntax) prs.parse(args) exec_cmd(instance, prs.unparsed, prs.parser.print_help) except (CLIError, ClientError) as err: print_error_message(err, self._err) except Exception as e: self.error('Execution of [ %s ] failed\n\t%s' % (line, e))
def parse(self, new_args=None): """Parse user input""" try: pkargs = (new_args,) if new_args else () self._parsed, unparsed = self.parser.parse_known_args(*pkargs) parsed_args = [ k for k, v in vars(self._parsed).items() if v not in (None, )] if not self._parse_required_arguments(self.required, parsed_args): self.print_help() raise CLISyntaxError('Missing required arguments') except SystemExit: raiseCLIError(CLISyntaxError('Argument Syntax Error')) for name, arg in self.arguments.items(): arg.value = getattr(self._parsed, name, arg.default) self._unparsed = [] for term in unparsed: self._unparsed += split_input(' \'%s\' ' % term) self._parser_modified = False
def do_method(new_context, line): """ Template for all cmd.Cmd methods of the form do_<cmd name> Parse cmd + args and decide to execute or change context <cmd> <term> <term> <args> is always parsed to most specific even if cmd_term_term is not a terminal path """ line = line.decode(pref_enc) subcmd, cmd_args = cmd.parse_out(split_input(line)) self._history.add(' '.join([cmd.path.replace('_', ' '), line])) cmd_parser = ArgumentParseManager( cmd.name, dict(self._parser.arguments)) cmd_parser.parser.description = subcmd.help # exec command or change context if subcmd.is_command: # exec command try: cls = subcmd.cmd_class cmd_parser.required = getattr(cls, 'required', None) ldescr = getattr(cls, 'long_description', '') if subcmd.path == 'history_run': instance = cls( dict(cmd_parser.arguments), self.astakos, cmd_tree=self.cmd_tree) else: instance = cls( dict(cmd_parser.arguments), self.astakos, self.cloud) cmd_parser.update_arguments(instance.arguments) cmd_parser.arguments = instance.arguments subpath = subcmd.path.split('_')[ (len(cmd.path.split('_')) - 1):] cmd_parser.syntax = '%s %s' % ( ' '.join(subpath), instance.syntax) help_method = self._create_help_method( cmd.name, cmd_parser.arguments, cmd_parser.required, subcmd.help, cmd_parser.syntax) if '-h' in cmd_args or '--help' in cmd_args: help_method() if ldescr.strip(): print('\nDetails:') print('%s' % ldescr) return cmd_parser.parse(cmd_args) for name, arg in instance.arguments.items(): arg.value = getattr( cmd_parser.parsed, name, arg.default) exec_cmd(instance, cmd_parser.unparsed, help_method) except (ClientError, CLIError) as err: print_error_message(err) elif ('-h' in cmd_args or '--help' in cmd_args) or len(cmd_args): # print options print('%s' % cmd.help) print_subcommands_help(cmd) else: # change context backup_context = self._backup() old_prompt = self.prompt new_context._roll_command(cmd.parent_path) new_context.set_prompt(subcmd.path.replace('_', ' ')) newcmds = [scmd for scmd in subcmd.subcommands.values()] for scmd in newcmds: new_context._register_command(scmd.path) new_context.cmdloop() self.prompt = old_prompt # when new context is over, roll back to the old one self._restore(backup_context)
def do_method(new_context, line): """ Template for all cmd.Cmd methods of the form do_<cmd name> Parse cmd + args and decide to execute or change context <cmd> <term> <term> <args> is always parsed to most specific even if cmd_term_term is not a terminal path """ line = line.decode(pref_enc) subcmd, cmd_args = cmd.parse_out(split_input(line)) self._history.add(' '.join([cmd.path.replace('_', ' '), line])) cmd_parser = ArgumentParseManager(cmd.name, dict(self._parser.arguments)) cmd_parser.parser.description = subcmd.help # exec command or change context if subcmd.is_command: # exec command try: cls = subcmd.cmd_class cmd_parser.required = getattr(cls, 'required', None) ldescr = getattr(cls, 'long_description', '') if subcmd.path == 'history_run': instance = cls(dict(cmd_parser.arguments), self.astakos, cmd_tree=self.cmd_tree) else: instance = cls(dict(cmd_parser.arguments), self.astakos, self.cloud) cmd_parser.update_arguments(instance.arguments) cmd_parser.arguments = instance.arguments subpath = subcmd.path.split('_')[( len(cmd.path.split('_')) - 1):] cmd_parser.syntax = '%s %s' % (' '.join(subpath), instance.syntax) help_method = self._create_help_method( cmd.name, cmd_parser.arguments, cmd_parser.required, subcmd.help, cmd_parser.syntax) if '-h' in cmd_args or '--help' in cmd_args: help_method() if ldescr.strip(): print('\nDetails:') print('%s' % ldescr) return cmd_parser.parse(cmd_args) for name, arg in instance.arguments.items(): arg.value = getattr(cmd_parser.parsed, name, arg.default) exec_cmd(instance, cmd_parser.unparsed, help_method) except (ClientError, CLIError) as err: print_error_message(err) elif ('-h' in cmd_args or '--help' in cmd_args) or len(cmd_args): # print options print('%s' % cmd.help) print_subcommands_help(cmd) else: # change context backup_context = self._backup() old_prompt = self.prompt new_context._roll_command(cmd.parent_path) new_context.set_prompt(subcmd.path.replace('_', ' ')) newcmds = [scmd for scmd in subcmd.subcommands.values()] for scmd in newcmds: new_context._register_command(scmd.path) new_context.cmdloop() self.prompt = old_prompt # when new context is over, roll back to the old one self._restore(backup_context)