diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_argparse_completer.py | 94 | ||||
-rwxr-xr-x | tests/test_cmd2.py | 6 | ||||
-rwxr-xr-x | tests/test_completion.py | 16 | ||||
-rw-r--r-- | tests/test_transcript.py | 4 |
4 files changed, 72 insertions, 48 deletions
diff --git a/tests/test_argparse_completer.py b/tests/test_argparse_completer.py index 68a2320c..788a7e59 100644 --- a/tests/test_argparse_completer.py +++ b/tests/test_argparse_completer.py @@ -41,6 +41,18 @@ def completer_function(text: str, line: str, begidx: int, endidx: int) -> List[s return basic_complete(text, line, begidx, endidx, completions_from_function) +def choices_takes_arg_tokens(arg_tokens: argparse.Namespace) -> List[str]: + """Choices function that receives arg_tokens from AutoCompleter""" + return [arg_tokens['parent_arg'][0], arg_tokens['subcommand'][0]] + + +def completer_takes_arg_tokens(text: str, line: str, begidx: int, endidx: int, + arg_tokens: argparse.Namespace) -> List[str]: + """Completer function that receives arg_tokens from AutoCompleter""" + match_against = [arg_tokens['parent_arg'][0], arg_tokens['subcommand'][0]] + return basic_complete(text, line, begidx, endidx, match_against) + + # noinspection PyMethodMayBeStatic,PyUnusedLocal class AutoCompleteTester(cmd2.Cmd): """Cmd2 app that exercises AutoCompleter class""" @@ -50,50 +62,21 @@ class AutoCompleteTester(cmd2.Cmd): ############################################################################################################ # Begin code related to help and command name completion ############################################################################################################ - def _music_create(self, args: argparse.Namespace) -> None: - """Implements the 'music create' command""" - self.poutput('music create') - - def _music_create_jazz(self, args: argparse.Namespace) -> None: - """Implements the 'music create jazz' command""" - self.poutput('music create jazz') - - def _music_create_rock(self, args: argparse.Namespace) -> None: - """Implements the 'music create rock' command""" - self.poutput('music create rock') - # Top level parser for music command music_parser = Cmd2ArgumentParser(description='Manage music', prog='music') # Add subcommands to music music_subparsers = music_parser.add_subparsers() - - # music -> create music_create_parser = music_subparsers.add_parser('create', help='Create music') - music_create_parser.set_defaults(func=_music_create) # Add subcommands to music -> create music_create_subparsers = music_create_parser.add_subparsers() - - # music -> create -> jazz music_create_jazz_parser = music_create_subparsers.add_parser('jazz', help='Create jazz') - music_create_jazz_parser.set_defaults(func=_music_create_jazz) - - # music -> create -> rock music_create_rock_parser = music_create_subparsers.add_parser('rock', help='Create rocks') - music_create_rock_parser.set_defaults(func=_music_create_rock) @with_argparser(music_parser) def do_music(self, args: argparse.Namespace) -> None: - """Music command""" - func = getattr(args, 'func', None) - if func is not None: - # Call whatever subcommand function was selected - func(self, args) - else: - # No subcommand was provided, so call help - # noinspection PyTypeChecker - self.do_help('music') + pass ############################################################################################################ # Begin code related to flag completion @@ -227,6 +210,26 @@ class AutoCompleteTester(cmd2.Cmd): def do_hint(self, args: argparse.Namespace) -> None: pass + ############################################################################################################ + # Begin code related to receiving arg_tokens + ############################################################################################################ + arg_tokens_parser = Cmd2ArgumentParser() + arg_tokens_parser.add_argument('parent_arg', help='arg from a parent parser') + + # Create a subcommand for to exercise receiving parent_tokens and subcommand name in arg_tokens + arg_tokens_subparser = arg_tokens_parser.add_subparsers(dest='subcommand') + arg_tokens_subcmd_parser = arg_tokens_subparser.add_parser('subcmd') + + arg_tokens_subcmd_parser.add_argument('choices_pos', choices_function=choices_takes_arg_tokens) + arg_tokens_subcmd_parser.add_argument('completer_pos', completer_function=completer_takes_arg_tokens) + + # Used to override parent_arg in arg_tokens_parser + arg_tokens_subcmd_parser.add_argument('--parent_arg') + + @with_argparser(arg_tokens_parser) + def do_arg_tokens(self, args: argparse.Namespace) -> None: + pass + @pytest.fixture def ac_app(): @@ -253,7 +256,9 @@ def test_help(ac_app, command): ('music', 'creab', []), ('music create', '', ['jazz', 'rock']), ('music crea', 'jazz', []), - ('music create', 'foo', []) + ('music create', 'foo', []), + ('fake create', '', []), + ('music fake', '', []) ]) def test_complete_help(ac_app, command, text, completions): line = 'help {} {}'.format(command, text) @@ -718,6 +723,31 @@ Hint: ''' +@pytest.mark.parametrize('command_and_args, completions', [ + # Exercise a choices function that receives arg_tokens dictionary + ('arg_tokens choice subcmd', ['choice', 'subcmd']), + + # Exercise a completer that receives arg_tokens dictionary + ('arg_tokens completer subcmd fake', ['completer', 'subcmd']), + + # Exercise overriding parent_arg from the subcommand + ('arg_tokens completer subcmd --parent_arg override fake', ['override', 'subcmd']) +]) +def test_arg_tokens(ac_app, command_and_args, completions): + text = '' + line = '{} {}'.format(command_and_args, text) + endidx = len(line) + begidx = endidx - len(text) + + first_match = complete_tester(text, line, begidx, endidx, ac_app) + if completions: + assert first_match is not None + else: + assert first_match is None + + assert ac_app.completion_matches == sorted(completions, key=ac_app.default_sort_key) + + def test_single_prefix_char(): from cmd2.argparse_completer import _single_prefix_char parser = Cmd2ArgumentParser(prefix_chars='-+') @@ -767,5 +797,5 @@ def test_complete_command_help_no_tokens(ac_app): parser = Cmd2ArgumentParser() ac = AutoCompleter(parser, ac_app) - completions = ac.complete_command_help(tokens=[], text='', line='', begidx=0, endidx=0) + completions = ac.complete_subcommand_help(tokens=[], text='', line='', begidx=0, endidx=0) assert not completions diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index fc8a1dae..94a49a95 100755 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -1620,7 +1620,8 @@ def test_get_settable_completion_items(base_app): def test_alias_no_subcommand(base_app): out, err = run_cmd(base_app, 'alias') - assert "Usage: alias [-h]" in out[0] + assert "Usage: alias [-h]" in err[0] + assert "Error: the following arguments are required: subcommand" in err[1] def test_alias_create(base_app): # Create the alias @@ -1713,7 +1714,8 @@ def test_multiple_aliases(base_app): def test_macro_no_subcommand(base_app): out, err = run_cmd(base_app, 'macro') - assert "Usage: macro [-h]" in out[0] + assert "Usage: macro [-h]" in err[0] + assert "Error: the following arguments are required: subcommand" in err[1] def test_macro_create(base_app): # Create the macro diff --git a/tests/test_completion.py b/tests/test_completion.py index cf5dcf75..c7d9bd21 100755 --- a/tests/test_completion.py +++ b/tests/test_completion.py @@ -1179,22 +1179,14 @@ def test_cmd2_help_subcommand_completion_with_flags_before_command(scu_app): first_match = complete_tester(text, line, begidx, endidx, scu_app) assert first_match is not None and scu_app.completion_matches == ['bar', 'foo', 'sport'] -def test_complete_help_subcommand_with_no_command(scu_app): - # No command because not enough tokens +def test_complete_help_subcommands_with_blank_command(scu_app): text = '' - line = 'help ' + line = 'help "" {}'.format(text) endidx = len(line) begidx = endidx - len(text) - assert not scu_app.complete_help_subcommand(text, line, begidx, endidx) - - # No command because everything is a flag - text = '-v' - line = 'help -f -v' - endidx = len(line) - begidx = endidx - len(text) - - assert not scu_app.complete_help_subcommand(text, line, begidx, endidx) + first_match = complete_tester(text, line, begidx, endidx, scu_app) + assert first_match is None and not scu_app.completion_matches def test_cmd2_help_subcommand_completion_nomatch_scu(scu_app): diff --git a/tests/test_transcript.py b/tests/test_transcript.py index 1d930c26..5739ad8e 100644 --- a/tests/test_transcript.py +++ b/tests/test_transcript.py @@ -224,13 +224,13 @@ def test_generate_transcript_stop(capsys): os.close(fd) # This should run all commands - commands = ['help', 'alias'] + commands = ['help', 'set'] app._generate_transcript(commands, transcript_fname) _, err = capsys.readouterr() assert err.startswith("2 commands") # Since quit returns True for stop, only the first 2 commands will run - commands = ['help', 'quit', 'alias'] + commands = ['help', 'quit', 'set'] app._generate_transcript(commands, transcript_fname) _, err = capsys.readouterr() assert err.startswith("Command 2 triggered a stop") |