diff options
author | Rob Austein <sra@hactrn.net> | 2010-10-07 00:12:50 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2010-10-07 00:12:50 +0000 |
commit | 8ada594d05c4e79fc2e3a13b50489bb75bd90cae (patch) | |
tree | 96b1f0a63a0f75cfa49078f1768d13c772c5636a /rpkid.with_tls/rpki/cli.py | |
parent | fe3d8174f81370ca80d1d47158959ec3eb9d4eee (diff) |
Stash a copy of pre-conversion (with TLS) tree temporarily, in case of
problems during switchover. Will clean this up after testbed is back
up without TLS.
svn path=/rpkid.with_tls; revision=3464
Diffstat (limited to 'rpkid.with_tls/rpki/cli.py')
-rw-r--r-- | rpkid.with_tls/rpki/cli.py | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/rpkid.with_tls/rpki/cli.py b/rpkid.with_tls/rpki/cli.py new file mode 100644 index 00000000..d31f7204 --- /dev/null +++ b/rpkid.with_tls/rpki/cli.py @@ -0,0 +1,176 @@ +""" +Utilities for writing command line tools. + +$Id$ + +Copyright (C) 2010 Internet Systems Consortium ("ISC") + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +""" + +import cmd, glob, os.path, traceback + +try: + import readline + have_readline = True +except ImportError: + have_readline = False + +class Cmd(cmd.Cmd): + """ + Customized subclass of Python cmd module. + """ + + emptyline_repeats_last_command = False + + EOF_exits_command_loop = True + + identchars = cmd.IDENTCHARS + "/-." + + histfile = None + + def __init__(self, argv = None): + cmd.Cmd.__init__(self) + if argv: + self.onecmd(" ".join(argv)) + else: + self.cmdloop_with_history() + + def onecmd(self, line): + """ + Wrap error handling around cmd.Cmd.onecmd(). Might want to do + something kinder than showing a traceback, eventually. + """ + try: + return cmd.Cmd.onecmd(self, line) + except SystemExit: + raise + except: + traceback.print_exc() + + def do_EOF(self, arg): + """ + Exit program. + """ + if self.EOF_exits_command_loop and self.prompt: + print + return self.EOF_exits_command_loop + + def do_exit(self, arg): + """ + Exit program. + """ + return True + + do_quit = do_exit + + def emptyline(self): + """ + Handle an empty line. cmd module default is to repeat the last + command, which I find to be violation of the principal of least + astonishment, so my preference is that an empty line does nothing. + """ + if self.emptyline_repeats_last_command: + cmd.Cmd.emptyline(self) + + def filename_complete(self, text, line, begidx, endidx): + """ + Filename completion handler, with hack to restore what I consider + the normal (bash-like) behavior when one hits the completion key + and there's only one match. + """ + result = glob.glob(text + "*") + if len(result) == 1: + path = result.pop() + if os.path.isdir(path) or (os.path.islink(path) and os.path.isdir(os.path.join(path, "."))): + result.append(path + os.path.sep) + else: + result.append(path + " ") + return result + + def completenames(self, text, *ignored): + """ + Command name completion handler, with hack to restore what I + consider the normal (bash-like) behavior when one hits the + completion key and there's only one match. + """ + result = set(cmd.Cmd.completenames(self, text, *ignored)) + if len(result) == 1: + result.add(result.pop() + " ") + return list(result) + + def help_help(self): + """ + Type "help [topic]" for help on a command, + or just "help" for a list of commands. + """ + self.stdout.write(self.help_help.__doc__ + "\n") + + def complete_help(self, *args): + """ + Better completion function for help command arguments. + """ + text = args[0] + names = self.get_names() + result = [] + for prefix in ("do_", "help_"): + result.extend(s[len(prefix):] for s in names if s.startswith(prefix + text)) + return result + + if have_readline: + + def cmdloop_with_history(self): + """ + Better command loop, with history file and tweaked readline + completion delimiters. + """ + old_completer_delims = readline.get_completer_delims() + if self.histfile is not None: + try: + readline.read_history_file(self.histfile) + except IOError: + pass + try: + readline.set_completer_delims("".join(set(old_completer_delims) - set(self.identchars))) + self.cmdloop() + finally: + if self.histfile is not None and readline.get_current_history_length(): + readline.write_history_file(self.histfile) + readline.set_completer_delims(old_completer_delims) + + else: + + cmdloop_with_history = cmd.Cmd.cmdloop + + + +def yes_or_no(prompt, default = None, require_full_word = False): + """ + Ask a yes-or-no question. + """ + prompt = prompt.rstrip() + _yes_or_no_prompts[default] + while True: + answer = raw_input(prompt).strip().lower() + if not answer and default is not None: + return default + if answer == "yes" or (not require_full_word and answer.startswith("y")): + return True + if answer == "no" or (not require_full_word and answer.startswith("n")): + return False + print 'Please answer "yes" or "no"' + +_yes_or_no_prompts = { + True : ' ("yes" or "no" ["yes"]) ', + False : ' ("yes" or "no" ["no"]) ', + None : ' ("yes" or "no") ' } + |