Add help to shell (#2)
This commit is contained in:
		
				
					committed by
					
						
						Ian Cordasco
					
				
			
			
				
	
			
			
			
						parent
						
							2046c486e7
						
					
				
				
					commit
					c123f0e35d
				
			@@ -11,10 +11,55 @@
 | 
				
			|||||||
# under the License.
 | 
					# under the License.
 | 
				
			||||||
"""Main shell for parsing arguments directed toward Craton."""
 | 
					"""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():
 | 
					def main():
 | 
				
			||||||
    """Main entry-point for cratonclient's CLI."""
 | 
					    """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
 | 
					    return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == "__main__":
 | 
					if __name__ == "__main__":
 | 
				
			||||||
    main()
 | 
					    main()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,4 +12,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
"""Command-line interface to the OpenStack Craton API V1."""
 | 
					"""Command-line interface to the OpenStack Craton API V1."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO(cmspence): from cratonclient.v1 import client
 | 
					# TODO(cmspence): from cratonclient.v1 import client
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,8 +16,31 @@
 | 
				
			|||||||
# under the License.
 | 
					# under the License.
 | 
				
			||||||
"""Base TestCase for all cratonclient tests."""
 | 
					"""Base TestCase for all cratonclient tests."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import mock
 | 
				
			||||||
 | 
					import six
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from oslotest import base
 | 
					from oslotest import base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from cratonclient.shell import main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestCase(base.BaseTestCase):
 | 
					class TestCase(base.BaseTestCase):
 | 
				
			||||||
    """Test case base class for all unit tests."""
 | 
					    """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())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,13 +12,55 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
"""Tests for `cratonclient.shell.main` module."""
 | 
					"""Tests for `cratonclient.shell.main` module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import mock
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from testtools import matchers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from cratonclient.shell import main
 | 
					from cratonclient.shell import main
 | 
				
			||||||
from cratonclient.tests import base
 | 
					from cratonclient.tests import base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestMainShell(base.TestCase):
 | 
					class TestMainShell(base.ShellTestCase):
 | 
				
			||||||
    """Test our craton main shell."""
 | 
					    """Test our craton main shell."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_main_returns_successfully(self):
 | 
					    re_options = re.DOTALL | re.MULTILINE
 | 
				
			||||||
        """Verify that cratonclient shell main returns as expected."""
 | 
					
 | 
				
			||||||
 | 
					    @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)
 | 
					        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)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user