Пример #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 {x[0]
            for x in args[2]
            } == {'-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"
Пример #2
0
def test_dispatcher_build_commands_ok():
    """Correct command loading."""
    cmd0, cmd1, cmd2 = [create_command("cmd-name-{}".format(n), "cmd help") for n in range(3)]
    groups = [
        CommandGroup("whatever title", [cmd0]),
        CommandGroup("other title", [cmd1, cmd2]),
    ]
    dispatcher = Dispatcher(groups)
    assert len(dispatcher.commands) == 3
    for cmd in [cmd0, cmd1, cmd2]:
        expected_class = dispatcher.commands[cmd.name]
        assert expected_class == cmd
Пример #3
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 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"
    assert error.retcode == 0
Пример #4
0
def test_tool_exec_help_command_all():
    """Execute charmcraft asking for detailed help."""
    command_groups = [CommandGroup("group", [])]
    dispatcher = Dispatcher(command_groups)

    with patch("charmcraft.helptexts.HelpBuilder.get_detailed_help") as mock:
        mock.return_value = "test help"
        with pytest.raises(ProvideHelpException) as cm:
            dispatcher.pre_parse_args(["help", "--all"])

    # check the result of the help builder is what is transmitted
    assert str(cm.value) == "test help"

    # check the given information to the help text builder
    args = mock.call_args[0]
    assert sorted(x[0] for x in args[0]) == [
        "-h, --help",
        "-q, --quiet",
        "-t, --trace",
        "-v, --verbose",
    ]
Пример #5
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)
Пример #6
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
Пример #7
0
def test_tool_exec_command_bad_option_type(help_builder):
    """Execute a correct command but giving the valid option a bad value."""
    def fill_parser(self, parser):
        parser.add_argument("--number", type=int)

    cmd = create_command("somecommand", "This command does that.")
    cmd.fill_parser = fill_parser

    command_groups = [CommandGroup("group", [cmd])]
    dispatcher = Dispatcher(command_groups)
    dispatcher.pre_parse_args(["somecommand", "--number=foo"])

    help_builder.init("testapp", "general summary", command_groups)
    with pytest.raises(ArgumentParsingError) as cm:
        dispatcher.load_command("config")

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

        Error: argument --number: invalid int value: 'foo'
        """)

    error = cm.value
    assert str(error) == expected
Пример #8
0
def test_dispatcher_build_commands_ok():
    """Correct command loading."""
    cmd0, cmd1, cmd2 = [create_command('cmd-name-{}'.format(n), 'cmd help') for n in range(3)]
    groups = [
        ('test-group-A', 'whatever title', [cmd0]),
        ('test-group-B', 'other title', [cmd1, cmd2]),
    ]
    dispatcher = Dispatcher([cmd0.name], groups)
    assert len(dispatcher.commands) == 3
    for cmd, group in [(cmd0, 'test-group-A'), (cmd1, 'test-group-B'), (cmd2, 'test-group-B')]:
        expected_class, expected_group = dispatcher.commands[cmd.name]
        assert expected_class == cmd
        assert expected_group == group
Пример #9
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"
Пример #10
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 = [CommandGroup("group", [cmd])]
    dispatcher = Dispatcher(command_groups)

    with patch("charmcraft.helptexts.HelpBuilder.get_command_help") as mock:
        mock.return_value = "test help"
        with pytest.raises(ProvideHelpException) as cm:
            dispatcher.pre_parse_args(["help", "somecommand"])

    # check the result of the help builder is what is transmitted
    assert str(cm.value) == "test help"

    # check the given information to the help text builder
    args = mock.call_args[0]
    assert args[0].__class__ == cmd
    expected_options = [
        "--option1",
        "-h, --help",
        "-o2, --option2",
        "-q, --quiet",
        "-t, --trace",
        "-v, --verbose",
        "param1",
        "param2",
        "transformed3",
    ]
    assert sorted(x[0] for x in args[1]) == expected_options
Пример #11
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)
Пример #12
0
def test_tool_exec_help_command_on_command_ok():
    """Execute charmcraft asking for help on a command ok."""
    cmd = create_command("somecommand", "This command does that.")
    command_groups = [CommandGroup("group", [cmd])]
    dispatcher = Dispatcher(command_groups)

    with patch("charmcraft.helptexts.HelpBuilder.get_command_help") as mock:
        mock.return_value = "test help"
        with pytest.raises(ProvideHelpException) as cm:
            dispatcher.pre_parse_args(["help", "somecommand"])

    # check the result of the help builder is what is transmitted
    assert str(cm.value) == "test help"

    # check the given information to the help text builder
    args = mock.call_args[0]
    assert isinstance(args[0], cmd)
    assert sorted(x[0] for x in args[1]) == [
        "-h, --help",
        "-q, --quiet",
        "-t, --trace",
        "-v, --verbose",
    ]
Пример #13
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 = [CommandGroup("title", [MyCommand])]
    dispatcher = Dispatcher(groups)
    dispatcher.pre_parse_args(["cmdname"])
    dispatcher.load_command("config")
    with pytest.raises(ValueError):
        dispatcher.run()
Пример #14
0
def test_tool_exec_command_dash_help_reverse(help_option):
    """Execute a command (that needs no params) asking for help."""
    cmd = create_command("somecommand", "This command does that.")
    command_groups = [CommandGroup("group", [cmd])]
    dispatcher = Dispatcher(command_groups)

    with patch("charmcraft.helptexts.HelpBuilder.get_command_help") as mock:
        mock.return_value = "test help"
        with pytest.raises(ProvideHelpException) as cm:
            dispatcher.pre_parse_args([help_option, "somecommand"])

    # check the result of the full help builder is what is transmitted
    assert str(cm.value) == "test help"

    # check the given information to the help text builder
    args = mock.call_args[0]
    assert args[0].__class__ == cmd
    assert sorted(x[0] for x in args[1]) == [
        "-h, --help",
        "-q, --quiet",
        "-t, --trace",
        "-v, --verbose",
    ]
Пример #15
0
def test_tool_exec_command_dash_help_reverse(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([help_option, '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
    assert {x[0]
            for x in args[2]
            } == {'-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"
Пример #16
0
def test_tool_exec_command_wrong_option():
    """Execute a correct command but with a wrong option."""
    cmd = create_command('somecommand', 'This command does that.')
    command_groups = [('group', 'help text', [cmd])]
    with pytest.raises(CommandError) as cm:
        Dispatcher(['somecommand', '--whatever'], command_groups)

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

        Error: unrecognized arguments: --whatever
        """)

    error = cm.value
    assert error.argsparsing
    assert str(error) == expected
Пример #17
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
Пример #18
0
def test_dispatcher_build_commands_ok():
    """Correct command loading."""
    cmd0, cmd1, cmd2 = [
        create_command("cmd-name-{}".format(n), "cmd help") for n in range(3)
    ]
    groups = [
        ("test-group-A", "whatever title", [cmd0]),
        ("test-group-B", "other title", [cmd1, cmd2]),
    ]
    dispatcher = Dispatcher([cmd0.name], groups)
    assert len(dispatcher.commands) == 3
    for cmd, group in [
        (cmd0, "test-group-A"),
        (cmd1, "test-group-B"),
        (cmd2, "test-group-B"),
    ]:
        expected_class, expected_group = dispatcher.commands[cmd.name]
        assert expected_class == cmd
        assert expected_group == group
Пример #19
0
def test_dispatcher_build_commands_repeated():
    """Error while loading commands with repeated name."""
    class Foo(BaseCommand):
        help_msg = "some help"
        name = "repeated"

    class Bar(BaseCommand):
        help_msg = "some help"
        name = "cool"

    class Baz(BaseCommand):
        help_msg = "some help"
        name = "repeated"

    groups = [
        ("test-group-1", "whatever title", [Foo, Bar]),
        ("test-group-2", "other title", [Baz]),
    ]
    expected_msg = "Multiple commands with same name: (Foo|Baz) and (Baz|Foo)"
    with pytest.raises(RuntimeError, match=expected_msg):
        Dispatcher([], groups)
Пример #20
0
def test_dispatcher_load_commands_repeated():
    """Error while loading commands with repeated name."""
    class Foo(BaseCommand):
        help_msg = "some help"
        name = 'repeated'

    class Bar(BaseCommand):
        help_msg = "some help"
        name = 'cool'

    class Baz(BaseCommand):
        help_msg = "some help"
        name = 'repeated'

    groups = [
        ('test-group-1', 'whatever title', [Foo, Bar]),
        ('test-group-2', 'other title', [Baz]),
    ]
    expected_msg = "Multiple commands with same name: (Foo|Baz) and (Baz|Foo)"
    with pytest.raises(RuntimeError, match=expected_msg):
        Dispatcher([], groups)
Пример #21
0
def test_tool_exec_command_bad_option_type():
    """Execute a correct command but giving the valid option a bad value."""
    def fill_parser(self, parser):
        parser.add_argument('--number', type=int)

    cmd = create_command('somecommand', 'This command does that.')
    cmd.fill_parser = fill_parser

    command_groups = [('group', 'help text', [cmd])]
    with pytest.raises(CommandError) as cm:
        Dispatcher(['somecommand', '--number=foo'], command_groups)

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

        Error: argument --number: invalid int value: 'foo'
        """)

    error = cm.value
    assert error.argsparsing
    assert str(error) == expected
Пример #22
0
def test_tool_exec_command_wrong_option(help_builder):
    """Execute a correct command but with a wrong option."""
    cmd = create_command("somecommand", "This command does that.")
    command_groups = [CommandGroup("group", [cmd])]
    dispatcher = Dispatcher(command_groups)
    dispatcher.pre_parse_args(["somecommand", "--whatever"])

    help_builder.init("testapp", "general summary", command_groups)
    with pytest.raises(ArgumentParsingError) as cm:
        dispatcher.load_command("config")

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

        Error: unrecognized arguments: --whatever
        """)

    error = cm.value
    assert str(error) == expected
Пример #23
0
def get_generated_help(groups):
    """Helper to use the dispatcher to make the custom arg parser to generate special help."""
    dispatcher = Dispatcher([], groups)
    with patch.object(argparse.ArgumentParser, 'format_help', str):
        generated_help = dispatcher.main_parser.format_help()
    return generated_help
Пример #24
0
def test_dispatcher_pre_parsing():
    """Parses and return global arguments."""
    groups = [CommandGroup("title", [create_command("somecommand")])]
    dispatcher = Dispatcher(groups)
    global_args = dispatcher.pre_parse_args(["-q", "somecommand"])
    assert global_args == {"help": False, "verbose": False, "quiet": True, "trace": False}