Repository :
http://git.fedorahosted.org/cgit/cura-tools.git
On branch : master
---------------------------------------------------------------
commit 2a732ce26b022840e52dac58a806e33433ae6a90
Author: Peter Hatina <phatina(a)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)