Add help to shell (#2)

This commit is contained in:
ChristopherMSpencer
2016-07-06 09:18:58 -07:00
committed by Ian Cordasco
parent 2046c486e7
commit c123f0e35d
4 changed files with 114 additions and 3 deletions

View File

@@ -11,10 +11,55 @@
# under the License.
"""Main shell for parsing arguments directed toward Craton."""
from __future__ import print_function
import argparse
import six
import sys
from oslo_utils import encodeutils
class CratonShell(object):
"""Class used to handle shell definition and parsing."""
def get_base_parser(self):
"""Configure base craton arguments and parsing."""
parser = argparse.ArgumentParser(
prog='craton',
description=__doc__.strip(),
epilog='See "craton help COMMAND" '
'for help on a specific command.',
add_help=False,
formatter_class=argparse.HelpFormatter
)
parser.add_argument('-h', '--help',
action='store_true',
help=argparse.SUPPRESS)
return parser
def main(self, argv):
"""Main entry-point for cratonclient shell argument parsing."""
parser = self.get_base_parser()
(options, args) = parser.parse_known_args(argv)
if options.help or not argv:
parser.print_help()
return 0
def main():
"""Main entry-point for cratonclient's CLI."""
try:
CratonShell().main(map(encodeutils.safe_decode, sys.argv[1:]))
except Exception as e:
print("ERROR: %s" % encodeutils.safe_encode(six.text_type(e)),
file=sys.stderr)
sys.exit(1)
return 0
if __name__ == "__main__":
main()

View File

@@ -12,4 +12,5 @@
"""Command-line interface to the OpenStack Craton API V1."""
# TODO(cmspence): from cratonclient.v1 import client

View File

@@ -16,8 +16,31 @@
# under the License.
"""Base TestCase for all cratonclient tests."""
import mock
import six
import sys
from oslotest import base
from cratonclient.shell import main
class TestCase(base.BaseTestCase):
"""Test case base class for all unit tests."""
class ShellTestCase(base.BaseTestCase):
"""Test case base class for all shell unit tests."""
def shell(self, arg_str, exitcodes=(0,)):
"""Main function for exercising the craton shell."""
with mock.patch('sys.stdout', new=six.StringIO()) as mock_stdout, \
mock.patch('sys.stderr', new=six.StringIO()) as mock_stderr:
try:
main_shell = main.CratonShell()
main_shell.main(arg_str.split())
except SystemExit:
exc_type, exc_value, exc_traceback = sys.exc_info()
self.assertIn(exc_value.code, exitcodes)
return (mock_stdout.getvalue(), mock_stderr.getvalue())

View File

@@ -12,13 +12,55 @@
"""Tests for `cratonclient.shell.main` module."""
import mock
import re
from testtools import matchers
from cratonclient.shell import main
from cratonclient.tests import base
class TestMainShell(base.TestCase):
class TestMainShell(base.ShellTestCase):
"""Test our craton main shell."""
def test_main_returns_successfully(self):
"""Verify that cratonclient shell main returns as expected."""
re_options = re.DOTALL | re.MULTILINE
@mock.patch('cratonclient.shell.main.CratonShell.main')
def test_main_returns_successfully(self, cratonShellMainMock):
"""Verify that main returns as expected."""
cratonShellMainMock.return_value = 0
self.assertEqual(main.main(), 0)
def test_print_help_no_args(self):
"""Verify that no arguments prints out help by default."""
required_help_responses = [
'.*?^usage: craton',
'.*?^See "craton help COMMAND" '
'for help on a specific command.',
]
stdout, stderr = self.shell('')
for r in required_help_responses:
self.assertThat((stdout + stderr),
matchers.MatchesRegex(r, self.re_options))
def test_print_help_with_args(self):
"""Verify that help command(s) prints out help text correctly."""
required_help_responses = [
'.*?^usage: craton',
'.*?^See "craton help COMMAND" '
'for help on a specific command.',
]
for help_args in ['-h', '--help']:
stdout, stderr = self.shell(help_args)
for r in required_help_responses:
self.assertThat((stdout + stderr),
matchers.MatchesRegex(r, self.re_options))
@mock.patch('cratonclient.shell.main.CratonShell.main')
def test_main_catches_exception(self, cratonShellMainMock):
"""Verify exceptions will be caught and shell will exit properly."""
cratonShellMainMock.side_effect = Exception(mock.Mock(status=404),
'some error')
self.assertRaises(SystemExit, main.main)