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 _create_help_method(cmd_name, args, required, descr, syntax): tmp_args = dict(args) tmp_args.pop('cloud', None) tmp_args.pop('debug', None) tmp_args.pop('verbose', None) tmp_args.pop('config', None) tmp_args.pop('ignore_ssl', None) tmp_args.pop('ca_file', None) help_parser = ArgumentParseManager(cmd_name, tmp_args, required, syntax=syntax, description=descr, check_required=False) return help_parser.print_help
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 wrap(): try: exe = basename(argv[0]) internal_argv = [] for i, a in enumerate(argv): try: internal_argv.append(a.decode(pref_enc)) except UnicodeDecodeError as ude: raise CLIError( 'Invalid encoding in command', importance=3, details=[ 'The invalid term is #%s (with "%s" being 0)' % (i, exe), 'Encoding is invalid with current locale settings ' '(%s)' % pref_enc, '( %s )' % ude ]) for i, a in enumerate(internal_argv): argv[i] = a logger.add_stream_logger( __name__, logging.WARNING, fmt='%(levelname)s (%(name)s): %(message)s') _config_arg = ConfigArgument('Path to a custom config file') parser = ArgumentParseManager( exe, arguments=dict( config=_config_arg, cloud=ValueArgument('Chose a cloud to connect to', ('--cloud')), help=Argument(0, 'Show help message', ('-h', '--help')), debug=FlagArgument('Include debug output', ('-d', '--debug')), verbose=FlagArgument( 'Show HTTP requests and responses, without HTTP body', ('-v', '--verbose')), verbose_with_data=FlagArgument( 'Show HTTP requests and responses, including HTTP body', ('-vv', '--verbose-with-data')), version=VersionArgument('Print current version', ('-V', '--version')), options=RuntimeConfigArgument( _config_arg, 'Override a config option (not persistent)', ('-o', '--options')), ignore_ssl=FlagArgument( 'Allow connections to SSL sites without certs', ('-k', '--ignore-ssl', '--insecure')), ca_file=ValueArgument( 'CA certificates for SSL authentication', '--ca-certs'), )) if parser.arguments['version'].value: exit(0) _cnf = parser.arguments['config'] log_file = _cnf.get('global', 'log_file') if log_file: logger.set_log_filename(log_file) filelog = logger.add_file_logger(__name__.split('.')[0]) filelog.info('%s\n- - -' % ' '.join(argv)) _colors = _cnf.value.get('global', 'colors') exclude = ['ansicolors'] if not _colors == 'on' else [] suggest_missing(exclude=exclude) func(exe, parser) except CLIError as err: print_error_message(err) if _debug: raise err exit(1) except KamakiSSLError as err: ca_arg = parser.arguments.get('ca_file') ca = ca_arg.value if ca_arg and ca_arg.value else _cnf.get( 'global', 'ca_certs') stderr.write(red('SSL Authentication failed\n')) if ca: stderr.write('Path used for CA certifications file: %s\n' % (escape_ctrl_chars(ca))) stderr.write('Please make sure the path is correct\n') if not (ca_arg and ca_arg.value): stderr.write('| To set the correct path:\n') stderr.write('| kamaki config set ca_certs CA_FILE\n') else: stderr.write('| To use a CA certifications file:\n') stderr.write('| kamaki config set ca_certs CA_FILE\n') stderr.write('| OR run with --ca-certs=FILE_LOCATION\n') stderr.write('| To ignore SSL errors and move on (%s):\n' % (red('insecure'))) stderr.write('| kamaki config set ignore_ssl on\n') stderr.write('| OR run with --ignore-ssl\n') stderr.flush() if _debug: raise stderr.write('| %s: %s\n' % (type(err), escape_ctrl_chars('%s' % err))) stderr.flush() exit(1) except KeyboardInterrupt: print('Canceled by user') exit(1) except Exception as er: print('Unknown Error: %s' % er) if _debug: raise exit(1)
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)