Changeset - cf5813628ae1
[Not reviewed]
0 4 0
Branko Majic (branko) - 6 years ago 2018-02-26 23:20:16
branko@majic.rs
GC-11: Updated CLI to display simple usage help:

- Added terse description to the CLI.
- Implemented small mechanism for invoking callback functions attached
to parser.
- Fixed some linting issues in setup script.
4 files changed with 65 insertions and 3 deletions:
0 comments (0 inline, 0 general)
functional_tests/test_help.py
Show inline comments
 
@@ -43,3 +43,17 @@ def test_cli_works():
 
    # be on the safe side.
 
    assert stderr == ''
 
    assert process.returncode == 0
 

	
 

	
 
def test_usage_help_shown():
 
    # Since John feels a bit lazy, he decides to skip reading the
 
    # documentation, and just run the tool to see if he gets any
 
    # useful help.
 
    process = subprocess.Popen(["gimmecert"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
    stdout, stderr = process.communicate()
 
    stdout, stderr = stdout.decode(), stderr.decode()
 

	
 
    # John is presented with short usage instructions.
 
    assert "usage: gimmecert [-h]" in stdout
 
    assert stderr == ''
 
    assert process.returncode == 0
gimmecert/cli.py
Show inline comments
 
@@ -22,6 +22,12 @@
 
import argparse
 

	
 

	
 
DESCRIPTION = """\
 
Issues server and client X.509 certificates using a local CA
 
hierarchy.
 
"""
 

	
 

	
 
def get_parser():
 
    """
 
    Sets-up and returns a CLI argument parser.
 
@@ -29,7 +35,9 @@ def get_parser():
 
    :returns: argparse.ArgumentParser -- argument parser for CLI.
 
    """
 

	
 
    parser = argparse.ArgumentParser()
 
    parser = argparse.ArgumentParser(description=DESCRIPTION)
 

	
 
    parser.set_defaults(func=lambda args: parser.print_usage())
 

	
 
    return parser
 

	
 
@@ -39,7 +47,13 @@ def main():
 
    This function is a CLI entry point for the tool. It is a thin
 
    wrapper around the argument parser, and underlying command
 
    implementation.
 

	
 
    In order for this to work, the parser needs to register the
 
    callback function as a default parameter for attribute
 
    'func'. This attribute is then invoked by the main function,
 
    passing-in all the parsed arguments while at it.
 
    """
 

	
 
    parser = get_parser()
 
    parser.parse_args()
 
    args = parser.parse_args()
 
    args.func(args)
setup.py
Show inline comments
 
@@ -73,7 +73,7 @@ setup(
 
    setup_requires=setup_requirements,
 
    tests_require=test_requirements,
 
    extras_require=extras_requirements,
 
    entry_points = {
 
    entry_points={
 
        'console_scripts': ['gimmecert=gimmecert.cli:main'],
 
    },
 
    classifiers=[
tests/test_cli.py
Show inline comments
 
@@ -48,3 +48,37 @@ def test_main_invokes_argument_parsing(mock_get_parser):
 
    gimmecert.cli.main()
 

	
 
    mock_parser.parse_args.assert_called_once_with()
 

	
 

	
 
def test_cli_parser_has_description():
 
    parser = gimmecert.cli.get_parser()
 

	
 
    assert parser.description
 

	
 

	
 
def test_parser_sets_up_default_callback_function():
 
    parser = gimmecert.cli.get_parser()
 

	
 
    assert callable(parser.get_default('func'))
 

	
 

	
 
@mock.patch('gimmecert.cli.argparse.ArgumentParser.print_usage')
 
def test_parser_default_callback_function_calls_print_usage(mock_print_usage):
 
    parser = gimmecert.cli.get_parser()
 
    func = parser.get_default('func')
 
    func(mock.Mock())
 

	
 
    assert mock_print_usage.called
 

	
 

	
 
@mock.patch('gimmecert.cli.get_parser')
 
def test_main_invokes_parser_function(mock_get_parser):
 
    mock_parser = mock.Mock()
 
    mock_args = mock.Mock()
 

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

	
 
    gimmecert.cli.main()
 

	
 
    mock_args.func.assert_called_once_with(mock_args)
0 comments (0 inline, 0 general)