aboutsummaryrefslogtreecommitdiff
path: root/rpki/cli.py
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-10-26 06:29:00 +0000
committerRob Austein <sra@hactrn.net>2015-10-26 06:29:00 +0000
commitb46deb1417dc3596e9ac9fe2fe8cc0b7f42457e7 (patch)
treeca0dc0276d1adc168bc3337ce0564c4ec4957c1b /rpki/cli.py
parent397beaf6d9900dc3b3cb612c89ebf1d57b1d16f6 (diff)
"Any programmer who fails to comply with the standard naming, formatting,
or commenting conventions should be shot. If it so happens that it is inconvenient to shoot him, then he is to be politely requested to recode his program in adherence to the above standard." -- Michael Spier, Digital Equipment Corporation svn path=/branches/tk705/; revision=6152
Diffstat (limited to 'rpki/cli.py')
-rw-r--r--rpki/cli.py402
1 files changed, 201 insertions, 201 deletions
diff --git a/rpki/cli.py b/rpki/cli.py
index 35999cb0..51ac0367 100644
--- a/rpki/cli.py
+++ b/rpki/cli.py
@@ -28,244 +28,244 @@ import argparse
import traceback
try:
- import readline
- have_readline = True
+ import readline
+ have_readline = True
except ImportError:
- have_readline = False
+ have_readline = False
class BadCommandSyntax(Exception):
- "Bad command line syntax."
+ "Bad command line syntax."
class ExitArgparse(Exception):
- "Exit method from ArgumentParser."
+ "Exit method from ArgumentParser."
- def __init__(self, message = None, status = 0):
- super(ExitArgparse, self).__init__()
- self.message = message
- self.status = status
+ def __init__(self, message = None, status = 0):
+ super(ExitArgparse, self).__init__()
+ self.message = message
+ self.status = status
class Cmd(cmd.Cmd):
- """
- Customized subclass of Python cmd module.
- """
+ """
+ Customized subclass of Python cmd module.
+ """
- emptyline_repeats_last_command = False
+ emptyline_repeats_last_command = False
- EOF_exits_command_loop = True
+ EOF_exits_command_loop = True
- identchars = cmd.IDENTCHARS + "/-."
+ identchars = cmd.IDENTCHARS + "/-."
- histfile = None
+ histfile = None
- last_command_failed = False
+ last_command_failed = False
- def onecmd(self, line):
- """
- Wrap error handling around cmd.Cmd.onecmd(). Might want to do
- something kinder than showing a traceback, eventually.
- """
+ def onecmd(self, line):
+ """
+ Wrap error handling around cmd.Cmd.onecmd(). Might want to do
+ something kinder than showing a traceback, eventually.
+ """
- self.last_command_failed = False
- try:
- return cmd.Cmd.onecmd(self, line)
- except SystemExit:
- raise
- except ExitArgparse, e:
- if e.message is not None:
- print e.message
- self.last_command_failed = e.status != 0
- return False
- except BadCommandSyntax, e:
- print e
- except:
- traceback.print_exc()
- self.last_command_failed = True
- return False
-
- def do_EOF(self, arg):
- if self.EOF_exits_command_loop and self.prompt:
- print
- return self.EOF_exits_command_loop
-
- def do_exit(self, arg):
- """
- Exit program.
- """
+ self.last_command_failed = False
+ try:
+ return cmd.Cmd.onecmd(self, line)
+ except SystemExit:
+ raise
+ except ExitArgparse, e:
+ if e.message is not None:
+ print e.message
+ self.last_command_failed = e.status != 0
+ return False
+ except BadCommandSyntax, e:
+ print e
+ except:
+ traceback.print_exc()
+ self.last_command_failed = True
+ return False
+
+ def do_EOF(self, arg):
+ 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 = cmd.Cmd.completenames(self, text, *ignored)
+ if len(result) == 1:
+ result[0] += " "
+ return 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) and s != "do_EOF")
+ 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
- return True
- do_quit = do_exit
- def emptyline(self):
+def yes_or_no(prompt, default = None, require_full_word = False):
"""
- 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.
+ Ask a yes-or-no question.
"""
- if self.emptyline_repeats_last_command:
- cmd.Cmd.emptyline(self)
+ 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"'
- 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.
- """
+_yes_or_no_prompts = {
+ True : ' ("yes" or "no" ["yes"]) ',
+ False : ' ("yes" or "no" ["no"]) ',
+ None : ' ("yes" or "no") ' }
- 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):
+class NonExitingArgumentParser(argparse.ArgumentParser):
"""
- 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.
+ ArgumentParser tweaked to throw ExitArgparse exception
+ rather than using sys.exit(), for use with command loop.
"""
- result = cmd.Cmd.completenames(self, text, *ignored)
- if len(result) == 1:
- result[0] += " "
- return result
+ def exit(self, status = 0, message = None):
+ raise ExitArgparse(status = status, message = message)
- 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.
+def parsecmd(subparsers, *arg_clauses):
"""
+ Decorator to combine the argparse and cmd modules.
- 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) and s != "do_EOF")
- return result
+ subparsers is an instance of argparse.ArgumentParser (or subclass) which was
+ returned by calling the .add_subparsers() method on an ArgumentParser instance
+ intended to handle parsing for the entire program on the command line.
- 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
+ arg_clauses is a series of defarg() invocations defining arguments to be parsed
+ by the argparse code.
+ The decorator will use arg_clauses to construct two separate argparse parser
+ instances: one will be attached to the global parser as a subparser, the
+ other will be used to parse arguments for this command when invoked by cmd.
+ The decorator will replace the original do_whatever method with a wrapped version
+ which uses the local argparse instance to parse the single string supplied by
+ the cmd module.
-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") ' }
-
-
-class NonExitingArgumentParser(argparse.ArgumentParser):
- """
- ArgumentParser tweaked to throw ExitArgparse exception
- rather than using sys.exit(), for use with command loop.
- """
-
- def exit(self, status = 0, message = None):
- raise ExitArgparse(status = status, message = message)
+ The intent is that, from the command's point of view, all of this should work
+ pretty much the same way regardless of whether the command was invoked from
+ the global command line or from within the cmd command loop. Either way,
+ the command method should get an argparse.Namespace object.
+ In theory, we could generate a completion handler from the argparse definitions,
+ much as the separate argcomplete package does. In practice this is a lot of
+ work and I'm not ready to get into that just yet.
+ """
-def parsecmd(subparsers, *arg_clauses):
- """
- Decorator to combine the argparse and cmd modules.
-
- subparsers is an instance of argparse.ArgumentParser (or subclass) which was
- returned by calling the .add_subparsers() method on an ArgumentParser instance
- intended to handle parsing for the entire program on the command line.
-
- arg_clauses is a series of defarg() invocations defining arguments to be parsed
- by the argparse code.
-
- The decorator will use arg_clauses to construct two separate argparse parser
- instances: one will be attached to the global parser as a subparser, the
- other will be used to parse arguments for this command when invoked by cmd.
-
- The decorator will replace the original do_whatever method with a wrapped version
- which uses the local argparse instance to parse the single string supplied by
- the cmd module.
-
- The intent is that, from the command's point of view, all of this should work
- pretty much the same way regardless of whether the command was invoked from
- the global command line or from within the cmd command loop. Either way,
- the command method should get an argparse.Namespace object.
-
- In theory, we could generate a completion handler from the argparse definitions,
- much as the separate argcomplete package does. In practice this is a lot of
- work and I'm not ready to get into that just yet.
- """
-
- def decorate(func):
- assert func.__name__.startswith("do_")
- parser = NonExitingArgumentParser(description = func.__doc__,
- prog = func.__name__[3:],
- add_help = False)
- subparser = subparsers.add_parser(func.__name__[3:],
- description = func.__doc__,
- help = func.__doc__.lstrip().partition("\n")[0])
- for positional, keywords in arg_clauses:
- parser.add_argument(*positional, **keywords)
- subparser.add_argument(*positional, **keywords)
- subparser.set_defaults(func = func)
- def wrapped(self, arg):
- return func(self, parser.parse_args(shlex.split(arg)))
- wrapped.argparser = parser
- wrapped.__doc__ = func.__doc__
- return wrapped
- return decorate
+ def decorate(func):
+ assert func.__name__.startswith("do_")
+ parser = NonExitingArgumentParser(description = func.__doc__,
+ prog = func.__name__[3:],
+ add_help = False)
+ subparser = subparsers.add_parser(func.__name__[3:],
+ description = func.__doc__,
+ help = func.__doc__.lstrip().partition("\n")[0])
+ for positional, keywords in arg_clauses:
+ parser.add_argument(*positional, **keywords)
+ subparser.add_argument(*positional, **keywords)
+ subparser.set_defaults(func = func)
+ def wrapped(self, arg):
+ return func(self, parser.parse_args(shlex.split(arg)))
+ wrapped.argparser = parser
+ wrapped.__doc__ = func.__doc__
+ return wrapped
+ return decorate
def cmdarg(*positional, **keywords):
- """
- Syntactic sugar to let us use keyword arguments normally when constructing
- arguments for deferred calls to argparse.ArgumentParser.add_argument().
- """
+ """
+ Syntactic sugar to let us use keyword arguments normally when constructing
+ arguments for deferred calls to argparse.ArgumentParser.add_argument().
+ """
- return positional, keywords
+ return positional, keywords