Repository : http://git.fedorahosted.org/cgit/cura-tools.git
On branch : master
commit 2a732ce26b022840e52dac58a806e33433ae6a90 Author: Peter Hatina phatina@redhat.com Date: Tue Jul 30 21:58:23 2013 +0200
introduce argparse for cli option parsing
cli/lmi/shell/LMIShellOptions.py | 133 ++++++++++++++++++++------------------ cli/lmishell | 12 +--- 2 files changed, 73 insertions(+), 72 deletions(-)
diff --git a/cli/lmi/shell/LMIShellOptions.py b/cli/lmi/shell/LMIShellOptions.py index e9a6d5f..3e182a7 100644 --- a/cli/lmi/shell/LMIShellOptions.py +++ b/cli/lmi/shell/LMIShellOptions.py @@ -15,8 +15,33 @@
import os import sys +import argparse + from . import __version__
+class LMIShellOptionsHelpWithVersionFormatter(argparse.HelpFormatter): + """ + Helper class used for help message formatting. + """ + def _format_usage(self, usage, actions, groups, prefix): + """ + Returns a string with preformatted LMIShell usage. This method prepends + LMIShell version to the usage message. + """ + return argparse.HelpFormatter._format_usage(self, usage, actions, groups, + "OpenLMI Shell v%s\n\n" % __version__) + +class LMIShellOptionParser(argparse.ArgumentParser): + """ + Helper class for CLI option parsing. + """ + def error(self, msg): + """ + Prints help message, error message and exits with erro code 2. + """ + self.print_help() + self.exit(2, "\n%s: error: %s\n" % (self.prog, msg)) + class LMIShellOptions(object): """ Class representing a LMIShell command line options. @@ -36,51 +61,50 @@ class LMIShellOptions(object): Arguments: argv -- list of strings of all the provided arguments """ - self._argv = argv - self._script_name = "" - self._script_argv = [] - self._good = True - self._inspect = False - self._help = False - self._log = LMIShellOptions._LOG_DEFAULT - for a in self._argv[1:]: - if not self._script_name and a in ("-h", "--help"): - self._help = True - return - elif not self._script_name and a in ("-i", "--inspect"): - self._inspect = True - elif not self._script_name and a in ("-v", "--verbose"): - if self._log == LMIShellOptions._LOG_VERBOSE: - self._log = LMIShellOptions._LOG_MORE_VERBOSE - else: - self._log = LMIShellOptions._LOG_VERBOSE - elif not self._script_name and a in ("-vv", "--more-verbose"): - self._log = LMIShellOptions._LOG_MORE_VERBOSE - elif not self._script_name and a in ("-q", "--quiet"): - self._log = LMIShellOptions._LOG_QUIET - elif not self._script_name and not a.startswith("-"): - self._script_name = a - elif self._script_name: - self._script_argv.append(a) - else: - self._good = False - break + # Create a option parser + parser = LMIShellOptionParser( + usage="%(prog)s [options] script [script-options]", + formatter_class=LMIShellOptionsHelpWithVersionFormatter) + parser.add_argument("-i", "--interact", dest="interact", + action="store_true", default=False, + help="inspect interactively after running a script") + parser.add_argument("-v", "--verbose", dest="verbose", + action="store_true", default=False, + help="print log messages to stderr") + parser.add_argument("-m", "--more-verbose", dest="more_verbose", + action="store_true", default=False, + help="print all log messages to stderr") + parser.add_argument("-q", "--quiet", dest="quiet", + action="store_true", default=False, + help="do not print any log messages to stderr")
- @property - def good(self): - """ - Property returning a bool flag, if all the provided options on the command line - are good; if the LMIShell can continue after parsing the options. - """ - return self._good + # Split CLI arguments into LMIShell ones and script ones. LMIShell arguments + # are those, which are before the first positional argument. Other CLI arguments + # are passed to the interpreted script. + try: + delimiter = 1 + map(lambda arg: not arg.startswith("-"), argv[1:]).index(True) + except ValueError, e: + delimiter = len(argv) + self._script_argv = argv[delimiter:] + self._script_name = self._script_argv[0] if self._script_argv else ""
- @property - def help(self): - """ - Property returning a bool flag, if the help message option was seen and the help - message should be printed out. - """ - return self._help + # Parse CLI options + shell_argv = argv[1:delimiter] + options = parser.parse_args(shell_argv) + + # Store CLI options + self._interact = options.interact + self._log = LMIShellOptions._LOG_DEFAULT + if options.verbose: + self._log = LMIShellOptions._LOG_VERBOSE + if options.more_verbose: + self._log = LMIShellOptions._LOG_MORE_VERBOSE + if options.quiet: + self._log = LMIShellOptions._LOG_QUIET + + # Check for errors + if (options.verbose, options.more_verbose, options.quiet).count(True) > 1: + parser.error("Options -v, -m and -q are mutually exclusive")
@property def interactive(self): @@ -88,16 +112,16 @@ class LMIShellOptions(object): Property returning a bool flag, which indicates, if the LMIShell should be intially run in the interactive mode. """ - return not self._script_name + return not self._script_argv
@property - def inspect(self): + def interact(self): """ Property returning a bool flag, which indicates, if the LMIShell should enter an interactive mode, after executing a provided script. The behavior is similar to python interpreter. """ - return self._inspect + return self._interact
@property def script_name(self): @@ -112,7 +136,7 @@ class LMIShellOptions(object): """ Property returning a list of command line arguments of the interpreted script. """ - return [self._script_name] + self._script_argv + return self._script_argv
@property def log(self): @@ -125,18 +149,3 @@ class LMIShellOptions(object): _LOG_QUIET """ return self._log - - def print_usage(self): - """ - Prints out a help message. - """ - sys.stdout.write("OpenLMI Shell v%s\n" % __version__) - sys.stdout.write("\nUsage: %s [options] [script] [script-options]\n" % os.path.basename(self._argv[0])) - sys.stdout.write("\nOptions:\n") - sys.stdout.write(" -h, --help print this message\n") - sys.stdout.write(" -i, --interact inspect interactively after running a script\n\n") - sys.stdout.write(" -v, --verbose print log messages to stderr; if provided twice,\n") - sys.stdout.write(" all the log messages will be printed to stderr\n") - sys.stdout.write(" -vv, --more-verbose print all log messages to stderr\n") - sys.stderr.write(" -q, --quiet do not print any log messages to stderr\n") - sys.stderr.write("\n By default, error messages are print to stderr stream.\n") diff --git a/cli/lmishell b/cli/lmishell index 7f7c263..9bc10ff 100755 --- a/cli/lmishell +++ b/cli/lmishell @@ -22,15 +22,7 @@ from lmi.shell import LMIShellOptions
if __name__ == "__main__": options = LMIShellOptions(sys.argv) - if not options.good: - sys.stderr.write("Wrong tool usage!\n\n") - options.print_usage() - sys.exit(1) - - if options.help: - options.print_usage() - sys.exit(0) - elif options.log == LMIShellOptions._LOG_MORE_VERBOSE: + if options.log == LMIShellOptions._LOG_MORE_VERBOSE: # Print out all the log messages to stderr stream logger = logging.getLogger("") logger.setLevel(logging.DEBUG) @@ -56,7 +48,7 @@ if __name__ == "__main__": script_name = options.script_name script_argv = options.script_argv exit_code = console.interpret(script_name, script_argv) - if options.inspect: + if options.interact: console.interact() else: sys.exit(exit_code)
cura-tools-devel@lists.fedorahosted.org