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
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
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"
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)
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
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
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()
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()
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()
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"
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
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()
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")
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
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()
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"
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"
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)
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
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
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)
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