Changeset - a3aeacfe4de8
[Not reviewed]
0 2 0
Branko Majic (branko) - 6 years ago 2018-03-09 22:35:01
branko@majic.rs
GC-17: Deduplicate exits in command wrapper functions:

- Move all calls to exit to the main function.
- Update signature of all wrapper functions to return status code.
- Update a couple of CLI tests to not fail due to systemexit being
thrown (instead of mocking away too much).
2 files changed with 64 insertions and 18 deletions:
0 comments (0 inline, 0 general)
gimmecert/cli.py
Show inline comments
 
@@ -61,9 +61,7 @@ def setup_init_subcommand_parser(parser, subparsers):
 
        if args.ca_base_name is None:
 
            args.ca_base_name = os.path.basename(project_directory)
 

	
 
        status_code = init(sys.stdout, sys.stderr, project_directory, args.ca_base_name, args.ca_hierarchy_depth)
 
        if status_code != ExitCode.SUCCESS:
 
            exit(status_code)
 
        return init(sys.stdout, sys.stderr, project_directory, args.ca_base_name, args.ca_hierarchy_depth)
 

	
 
    subparser.set_defaults(func=init_wrapper)
 

	
 
@@ -75,10 +73,7 @@ def setup_help_subcommand_parser(parser, subparsers):
 
    subparser = subparsers.add_parser('help', description='shows help')
 

	
 
    def help_wrapper(args):
 
        status_code = help_(sys.stdout, sys.stderr, parser)
 

	
 
        if status_code != ExitCode.SUCCESS:
 
            exit(status_code)
 
        return help_(sys.stdout, sys.stderr, parser)
 

	
 
    subparser.set_defaults(func=help_wrapper)
 

	
 
@@ -94,10 +89,7 @@ def setup_server_subcommand_parser(parser, subparsers):
 
    def server_wrapper(args):
 
        project_directory = os.getcwd()
 

	
 
        status_code = server(sys.stdout, sys.stderr, project_directory, args.entity_name, args.dns_name)
 

	
 
        if status_code != ExitCode.SUCCESS:
 
            exit(status_code)
 
        return server(sys.stdout, sys.stderr, project_directory, args.entity_name, args.dns_name)
 

	
 
    subparser.set_defaults(func=server_wrapper)
 

	
 
@@ -114,10 +106,7 @@ def get_parser():
 
    parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawDescriptionHelpFormatter)
 

	
 
    def usage_wrapper(args):
 
        status_code = usage(sys.stdout, sys.stderr, parser)
 

	
 
        if status_code != ExitCode.SUCCESS:
 
            exit(status_code)
 
        return usage(sys.stdout, sys.stderr, parser)
 

	
 
    parser.set_defaults(func=usage_wrapper)
 

	
 
@@ -143,4 +132,8 @@ def main():
 

	
 
    parser = get_parser()
 
    args = parser.parse_args()
 
    args.func(args)
 

	
 
    status_code = args.func(args)
 

	
 
    if status_code != ExitCode.SUCCESS:
 
        exit(status_code)
tests/test_cli.py
Show inline comments
 
@@ -39,7 +39,12 @@ def test_get_parser_returns_parser():
 
@mock.patch('gimmecert.cli.get_parser')
 
def test_main_invokes_get_parser(mock_get_parser):
 

	
 
    gimmecert.cli.main()
 
    # Ignore system exit. Dirty hack to avoid mocking the default
 
    # function. We care only about whether the get_parser is invoked.
 
    try:
 
        gimmecert.cli.main()
 
    except SystemExit:
 
        pass
 

	
 
    mock_get_parser.assert_called_once_with()
 

	
 
@@ -49,7 +54,13 @@ def test_main_invokes_argument_parsing(mock_get_parser):
 
    mock_parser = mock.Mock()
 
    mock_get_parser.return_value = mock_parser
 

	
 
    gimmecert.cli.main()
 
    # Ignore system exit. Dirty hack to avoid mocking the default
 
    # function. We care only about whether the parsing of arguments
 
    # got called.x
 
    try:
 
        gimmecert.cli.main()
 
    except SystemExit:
 
        pass
 

	
 
    mock_parser.parse_args.assert_called_once_with()
 

	
 
@@ -80,6 +91,9 @@ def test_main_invokes_parser_function(mock_get_parser):
 
    mock_parser = mock.Mock()
 
    mock_args = mock.Mock()
 

	
 
    # Avoid throws of SystemExit exception.
 
    mock_args.func.return_value = gimmecert.commands.ExitCode.SUCCESS
 

	
 
    mock_parser.parse_args.return_value = mock_args
 
    mock_get_parser.return_value = mock_parser
 

	
 
@@ -358,3 +372,42 @@ def test_usage_command_invoked_with_correct_parameters(mock_usage):
 
    # what-not.
 
    assert mock_usage.called
 
    assert mock_usage.call_count == 1
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'testcommand'])
 
def test_main_does_not_exit_if_it_calls_function_that_returns_success():
 

	
 
    @gimmecert.decorators.subcommand_parser
 
    def setup_testcommand_parser(parser, subparsers):
 
        subparser = subparsers.add_parser('testcommand', description='test command')
 

	
 
        def testcommand_wrapper(args):
 

	
 
            return gimmecert.commands.ExitCode.SUCCESS
 

	
 
        subparser.set_defaults(func=testcommand_wrapper)
 

	
 
        return subparser
 

	
 
    gimmecert.cli.main()  # Should not raise
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'testcommand'])
 
def test_main_exits_if_it_calls_function_that_returns_success():
 

	
 
    @gimmecert.decorators.subcommand_parser
 
    def setup_testcommand_parser(parser, subparsers):
 
        subparser = subparsers.add_parser('testcommand', description='test command')
 

	
 
        def testcommand_wrapper(args):
 

	
 
            return gimmecert.commands.ExitCode.ERROR_ALREADY_INITIALISED
 

	
 
        subparser.set_defaults(func=testcommand_wrapper)
 

	
 
        return subparser
 

	
 
    with pytest.raises(SystemExit) as e_info:
 
        gimmecert.cli.main()
 

	
 
    assert e_info.value.code == gimmecert.commands.ExitCode.ERROR_ALREADY_INITIALISED
0 comments (0 inline, 0 general)