Example #1
0
def test_tool_exec_help_command_on_command_ok():
    """Execute charmcraft asking for help on a command ok."""
    dispatcher = Dispatcher(["help", "version"], COMMAND_GROUPS)

    with patch("charmcraft.helptexts.get_command_help") as mock:
        mock.return_value = "test help"
        with pytest.raises(CommandError) as cm:
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    args = mock.call_args[0]
    assert args[0] == COMMAND_GROUPS
    assert args[1].__class__ == VersionCommand
    assert sorted(x[0] for x in args[2]) == [
        "-h, --help",
        "-p, --project-dir",
        "-q, --quiet",
        "-v, --verbose",
    ]

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
    assert error.retcode == 0
Example #2
0
def test_tool_exec_command_dash_help_simple(help_option):
    """Execute a command (that needs no params) asking for help."""
    cmd = create_command('somecommand', 'This command does that.')
    command_groups = COMMAND_GROUPS + [('group', 'help text', [cmd])]

    dispatcher = Dispatcher(['somecommand', help_option], command_groups)

    with patch('charmcraft.helptexts.get_command_help') as mock:
        mock.return_value = 'test help'
        with pytest.raises(CommandError) as cm:
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    args = mock.call_args[0]
    assert args[0] == COMMAND_GROUPS
    assert args[1].__class__ == cmd
    assert sorted(x[0] for x in args[2]) == [
        '-h, --help', '-p, --project-dir', '-q, --quiet', '-v, --verbose'
    ]

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
    assert error.retcode == 0
Example #3
0
def test_tool_exec_command_dash_help_missing_params(help_option):
    """Execute a command (which needs params) asking for help."""
    def fill_parser(self, parser):
        parser.add_argument('mandatory')

    cmd = create_command('somecommand', 'This command does that.')
    cmd.fill_parser = fill_parser
    command_groups = COMMAND_GROUPS + [('group', 'help text', [cmd])]

    dispatcher = Dispatcher(['somecommand', help_option], command_groups)

    with patch('charmcraft.helptexts.get_command_help') as mock:
        mock.return_value = 'test help'
        with pytest.raises(CommandError) as cm:
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    args = mock.call_args[0]
    assert args[0] == COMMAND_GROUPS
    assert args[1].__class__ == cmd
    assert {x[0]
            for x in args[2]
            } == {'-h, --help', '-v, --verbose', '-q, --quiet', 'mandatory'}

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
Example #4
0
def test_dispatcher_commands_are_not_loaded_if_not_needed():
    class MyCommand1(BaseCommand):
        """Expected to be executed."""
        name = 'command1'
        help_msg = "some help"
        _executed = []

        def run(self, parsed_args):
            self._executed.append(parsed_args)

    class MyCommand2(BaseCommand):
        """Expected to not be instantiated, or parse args, or run."""
        name = 'command2'
        help_msg = "some help"

        def __init__(self, *args):
            raise AssertionError

        def fill_parser(self, parser):
            raise AssertionError

        def run(self, parsed_args):
            raise AssertionError

    groups = [('test-group', 'title', [MyCommand1, MyCommand2])]
    dispatcher = Dispatcher(['command1'], groups)
    dispatcher.run()
    assert isinstance(MyCommand1._executed[0], argparse.Namespace)
Example #5
0
def test_tool_exec_command_dash_help_missing_params(help_option):
    """Execute a command (which needs params) asking for help."""

    def fill_parser(self, parser):
        parser.add_argument("mandatory")

    cmd = create_command("somecommand", "This command does that.")
    cmd.fill_parser = fill_parser
    command_groups = COMMAND_GROUPS + [("group", "help text", [cmd])]

    dispatcher = Dispatcher(["somecommand", help_option], command_groups)

    with patch("charmcraft.helptexts.get_command_help") as mock:
        mock.return_value = "test help"
        with pytest.raises(CommandError) as cm:
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    args = mock.call_args[0]
    assert args[0] == COMMAND_GROUPS
    assert args[1].__class__ == cmd
    assert sorted(x[0] for x in args[2]) == [
        "-h, --help",
        "-p, --project-dir",
        "-q, --quiet",
        "-v, --verbose",
        "mandatory",
    ]

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
    assert error.retcode == 0
Example #6
0
def test_dispatcher_generic_setup_quiet(options):
    """Generic parameter handling for silent log setup, directly of after the command."""
    cmd = create_command('somecommand')
    groups = [('test-group', 'title', [cmd])]
    dispatcher = Dispatcher(options, groups)
    logsetup.message_handler.mode = None
    dispatcher.run()
    assert logsetup.message_handler.mode == logsetup.message_handler.QUIET
Example #7
0
def test_dispatcher_config_not_needed():
    """Command does not needs a config."""
    class MyCommand(BaseCommand):
        help_msg = "some help"
        name = 'cmdname'

        def run(self, parsed_args):
            pass

    groups = [('test-group', 'title', [MyCommand])]
    dispatcher = Dispatcher(['cmdname'], groups)
    dispatcher.run()
Example #8
0
def test_dispatcher_config_not_needed():
    """Command does not needs a config."""
    class MyCommand(BaseCommand):
        help_msg = "some help"
        name = "cmdname"

        def run(self, parsed_args):
            pass

    groups = [("test-group", "title", [MyCommand])]
    dispatcher = Dispatcher(["cmdname"], groups)
    dispatcher.run()
Example #9
0
def test_dispatcher_command_execution_crash():
    """Command crashing doesn't pass through, we inform nicely."""
    class MyCommand(BaseCommand):
        help_msg = "some help"
        name = "cmdname"

        def run(self, parsed_args):
            raise ValueError()

    groups = [("test-group", "title", [MyCommand])]
    dispatcher = Dispatcher(["cmdname"], groups)
    with pytest.raises(ValueError):
        dispatcher.run()
Example #10
0
def test_tool_exec_help_command_on_command_wrong():
    """Execute charmcraft asking for help on a command which does not exist."""
    dispatcher = Dispatcher(['help', 'wrongcommand'], COMMAND_GROUPS)

    with patch('charmcraft.helptexts.get_usage_message') as mock:
        mock.return_value = 'test help'
        with pytest.raises(CommandError) as cm:
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    assert mock.call_args[0] == ('charmcraft',
                                 "no such command 'wrongcommand'")

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
Example #11
0
def test_tool_exec_command_incorrect(sysargv):
    """Execute a command that doesn't exist."""
    command_groups = COMMAND_GROUPS + [('group', 'help text', [])]
    with pytest.raises(CommandError) as cm:
        dispatcher = Dispatcher(sysargv, command_groups)
        dispatcher.run()

    expected = textwrap.dedent("""\
        Usage: charmcraft [options] command [args]...
        Try 'charmcraft -h' for help.

        Error: no such command 'wrongcommand'
        """)

    error = cm.value
    assert error.argsparsing
    assert str(error) == expected
Example #12
0
def test_dispatcher_no_command():
    """When no command is given we should get the "usage" help."""
    groups = [('test-group', 'title', [create_command('cmd-name', 'cmd help')])]
    dispatcher = Dispatcher([], groups)
    fake_stdout = io.StringIO()
    with patch('sys.stdout', fake_stdout):
        retcode = dispatcher.run()
    assert retcode == 1
    assert "usage: charmcraft" in fake_stdout.getvalue()
Example #13
0
def test_dispatcher_config_needed_problem():
    """Command needs a config, which is not there."""
    class MyCommand(BaseCommand):
        help_msg = "some help"
        name = "cmdname"
        needs_config = True

        def run(self, parsed_args):
            pass

    groups = [("test-group", "title", [MyCommand])]
    dispatcher = Dispatcher(["cmdname"], groups)
    with pytest.raises(CommandError) as err:
        dispatcher.run()
    assert str(err.value) == (
        "The specified command needs a valid 'charmcraft.yaml' configuration file (in the "
        "current directory or where specified with --project-dir option); see the reference: "
        "https://discourse.charmhub.io/t/charmcraft-configuration/4138")
Example #14
0
def test_tool_exec_help_command_on_command_complex():
    """Execute charmcraft asking for help on a command with parameters and options."""
    def fill_parser(self, parser):
        parser.add_argument("param1", help="help on param1")
        parser.add_argument("param2", help="help on param2")
        parser.add_argument("param3",
                            metavar="transformed3",
                            help="help on param2")
        parser.add_argument("--option1", help="help on option1")
        parser.add_argument("-o2", "--option2", help="help on option2")

    cmd = create_command("somecommand", "This command does that.")
    cmd.fill_parser = fill_parser
    command_groups = COMMAND_GROUPS + [("group", "help text", [cmd])]

    dispatcher = Dispatcher(["help", "somecommand"], command_groups)

    with patch("charmcraft.helptexts.get_command_help") as mock:
        mock.return_value = "test help"
        with pytest.raises(CommandError) as cm:
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    args = mock.call_args[0]
    assert args[0] == COMMAND_GROUPS
    assert args[1].__class__ == cmd
    expected_options = [
        "--option1",
        "-h, --help",
        "-o2, --option2",
        "-p, --project-dir",
        "-q, --quiet",
        "-v, --verbose",
        "param1",
        "param2",
        "transformed3",
    ]
    assert sorted(x[0] for x in args[2]) == expected_options

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
    assert error.retcode == 0
Example #15
0
def test_dispatcher_config_needed_ok(tmp_path):
    """Command needs a config, which is provided ok."""
    class MyCommand(BaseCommand):
        help_msg = "some help"
        name = "cmdname"
        needs_config = True

        def run(self, parsed_args):
            pass

    # put the config in place
    test_file = tmp_path / "charmcraft.yaml"
    test_file.write_text("""
        type: charm
    """)

    groups = [("test-group", "title", [MyCommand])]
    dispatcher = Dispatcher(["cmdname", "--project-dir", tmp_path], groups)
    dispatcher.run()
Example #16
0
def test_tool_exec_full_help(sysargv):
    """Execute charmcraft without any option at all or explicitly asking for help."""
    with patch('charmcraft.helptexts.get_full_help') as mock:
        mock.return_value = 'test help'
        with pytest.raises(CommandError) as cm:
            dispatcher = Dispatcher(sysargv, COMMAND_GROUPS)
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    args = mock.call_args[0]
    assert args[0] == COMMAND_GROUPS
    assert sorted(x[0] for x in args[1]) == [
        '-h, --help', '-p, --project-dir', '-q, --quiet', '-v, --verbose'
    ]

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
Example #17
0
def test_tool_exec_help_command_all():
    """Execute charmcraft asking for detailed help."""
    dispatcher = Dispatcher(['help', '--all'], COMMAND_GROUPS)

    with patch('charmcraft.helptexts.get_detailed_help') as mock:
        mock.return_value = 'test help'
        with pytest.raises(CommandError) as cm:
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    args = mock.call_args[0]
    assert args[0] == COMMAND_GROUPS
    assert {x[0]
            for x in args[1]
            } == {'-h, --help', '-v, --verbose', '-q, --quiet'}

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
Example #18
0
def test_dispatcher_command_execution_ok():
    """Command execution depends of the indicated name in command line, return code ok."""
    class MyCommandControl(BaseCommand):
        help_msg = "some help"

        def run(self, parsed_args):
            self._executed.append(parsed_args)

    class MyCommand1(MyCommandControl):
        name = "name1"
        _executed = []

    class MyCommand2(MyCommandControl):
        name = "name2"
        _executed = []

    groups = [("test-group", "title", [MyCommand1, MyCommand2])]
    dispatcher = Dispatcher(["name2"], groups)
    dispatcher.run()
    assert MyCommand1._executed == []
    assert isinstance(MyCommand2._executed[0], argparse.Namespace)
Example #19
0
def test_tool_exec_help_command_on_command_complex():
    """Execute charmcraft asking for help on a command with parameters and options."""
    def fill_parser(self, parser):
        parser.add_argument('param1', help="help on param1")
        parser.add_argument('param2', help="help on param2")
        parser.add_argument('--option1', help="help on option1")
        parser.add_argument('-o2', '--option2', help="help on option2")

    cmd = create_command('somecommand', 'This command does that.')
    cmd.fill_parser = fill_parser
    command_groups = COMMAND_GROUPS + [('group', 'help text', [cmd])]

    dispatcher = Dispatcher(['help', 'somecommand'], command_groups)

    with patch('charmcraft.helptexts.get_command_help') as mock:
        mock.return_value = 'test help'
        with pytest.raises(CommandError) as cm:
            dispatcher.run()
    error = cm.value

    # check the given information to the builder
    args = mock.call_args[0]
    assert args[0] == COMMAND_GROUPS
    assert args[1].__class__ == cmd
    expected_options = [
        '--option1',
        '-h, --help',
        '-o2, --option2',
        '-p, --project-dir',
        '-q, --quiet',
        '-v, --verbose',
        'param1',
        'param2',
    ]
    assert sorted(x[0] for x in args[2]) == expected_options

    # check the result of the full help builder is what is shown
    assert error.argsparsing
    assert str(error) == "test help"
    assert error.retcode == 0
Example #20
0
def test_dispatcher_command_return_code():
    """Command ends indicating the return code to be used."""
    class MyCommand(BaseCommand):
        help_msg = "some help"
        name = "cmdname"

        def run(self, parsed_args):
            return 17

    groups = [("test-group", "title", [MyCommand])]
    dispatcher = Dispatcher(["cmdname"], groups)
    retcode = dispatcher.run()
    assert retcode == 17
Example #21
0
def test_dispatcher_command_execution_ok():
    """Command execution depends of the indicated name in command line, return code ok."""
    class MyCommandControl(BaseCommand):
        help_msg = "some help"

        def __init__(self, group):
            super().__init__(group)
            self.executed = None

        def run(self, parsed_args):
            self.executed = parsed_args

    class MyCommand1(MyCommandControl):
        name = 'name1'

    class MyCommand2(MyCommandControl):
        name = 'name2'

    groups = [('test-group', 'title', [MyCommand1, MyCommand2])]
    dispatcher = Dispatcher(['name2'], groups)
    dispatcher.run()
    assert dispatcher.commands['name1'].executed is None
    assert isinstance(dispatcher.commands['name2'].executed, argparse.Namespace)
Example #22
0
def test_dispatcher_command_return_code():
    """Command ends indicating the return code to be used."""

    class MyCommand(BaseCommand):
        help_msg = "some help"
        name = "cmdname"

        def run(self, parsed_args):
            return 17

    groups = [CommandGroup("title", [MyCommand])]
    dispatcher = Dispatcher(groups)
    dispatcher.pre_parse_args(["cmdname"])
    dispatcher.load_command("config")
    retcode = dispatcher.run()
    assert retcode == 17