diff options
author | xNinjaKittyx <xNinjaKittyx@users.noreply.github.com> | 2020-12-15 17:21:33 -0800 |
---|---|---|
committer | xNinjaKittyx <xNinjaKittyx@users.noreply.github.com> | 2020-12-15 18:20:13 -0800 |
commit | 9aa54a5b27468d61337528cb1e1b5b9b11a80978 (patch) | |
tree | 567693115cc101efb9254a96d96d80e9f9ccd557 /tests/test_argparse_completer.py | |
parent | 03c65c60b39e369958b056c5c844d36d515c8a63 (diff) | |
download | cmd2-git-ci_improvements.tar.gz |
Adds pre-commit config to run various lintersci_improvements
This ads black, isort, pyupgrade, and flake8 to pre-commit-config.yaml
There are also some small changes to travis.yml and tasks.py to reduce
some repeated configurations that should be consolidated into
setup.cfg. Most other changes are automated by the linter scripts.
Diffstat (limited to 'tests/test_argparse_completer.py')
-rw-r--r-- | tests/test_argparse_completer.py | 797 |
1 files changed, 437 insertions, 360 deletions
diff --git a/tests/test_argparse_completer.py b/tests/test_argparse_completer.py index dd86163b..3898de85 100644 --- a/tests/test_argparse_completer.py +++ b/tests/test_argparse_completer.py @@ -12,6 +12,7 @@ import pytest import cmd2 from cmd2 import Cmd2ArgumentParser, CompletionItem, with_argparser from cmd2.utils import CompletionError, StdSim, basic_complete + from .conftest import complete_tester, run_cmd # Lists used in our tests (there is a mix of sorted and unsorted on purpose) @@ -48,8 +49,7 @@ def choices_takes_arg_tokens(arg_tokens: argparse.Namespace) -> List[str]: 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]: +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 ArgparseCompleter""" match_against = [arg_tokens['parent_arg'][0], arg_tokens['subcommand'][0]] return basic_complete(text, line, begidx, endidx, match_against) @@ -58,6 +58,7 @@ def completer_takes_arg_tokens(text: str, line: str, begidx: int, endidx: int, # noinspection PyMethodMayBeStatic,PyUnusedLocal,PyProtectedMember class ArgparseCompleterTester(cmd2.Cmd): """Cmd2 app that exercises ArgparseCompleter class""" + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -129,34 +130,47 @@ class ArgparseCompleterTester(cmd2.Cmd): choices_parser = Cmd2ArgumentParser() # Flag args for choices command. Include string and non-string arg types. - choices_parser.add_argument("-l", "--list", help="a flag populated with a choices list", - choices=static_choices_list) - choices_parser.add_argument("-f", "--function", help="a flag populated with a choices function", - choices_function=choices_function) - choices_parser.add_argument("-m", "--method", help="a flag populated with a choices method", - choices_method=choices_method) - choices_parser.add_argument('-d', "--desc_header", help='this arg has a descriptive header', - choices_method=completion_item_method, - descriptive_header=CUSTOM_DESC_HEADER) - choices_parser.add_argument('-n', "--no_header", help='this arg has no descriptive header', - choices_method=completion_item_method, metavar=STR_METAVAR) - choices_parser.add_argument('-t', "--tuple_metavar", help='this arg has tuple for a metavar', - choices_method=completion_item_method, metavar=TUPLE_METAVAR, - nargs=argparse.ONE_OR_MORE) - choices_parser.add_argument('-i', '--int', type=int, help='a flag with an int type', - choices=int_choices) + choices_parser.add_argument("-l", "--list", help="a flag populated with a choices list", choices=static_choices_list) + choices_parser.add_argument( + "-f", "--function", help="a flag populated with a choices function", choices_function=choices_function + ) + choices_parser.add_argument("-m", "--method", help="a flag populated with a choices method", choices_method=choices_method) + choices_parser.add_argument( + '-d', + "--desc_header", + help='this arg has a descriptive header', + choices_method=completion_item_method, + descriptive_header=CUSTOM_DESC_HEADER, + ) + choices_parser.add_argument( + '-n', + "--no_header", + help='this arg has no descriptive header', + choices_method=completion_item_method, + metavar=STR_METAVAR, + ) + choices_parser.add_argument( + '-t', + "--tuple_metavar", + help='this arg has tuple for a metavar', + choices_method=completion_item_method, + metavar=TUPLE_METAVAR, + nargs=argparse.ONE_OR_MORE, + ) + choices_parser.add_argument('-i', '--int', type=int, help='a flag with an int type', choices=int_choices) # Positional args for choices command - choices_parser.add_argument("list_pos", help="a positional populated with a choices list", - choices=static_choices_list) - choices_parser.add_argument("function_pos", help="a positional populated with a choices function", - choices_function=choices_function) - choices_parser.add_argument("method_pos", help="a positional populated with a choices method", - choices_method=choices_method) - choices_parser.add_argument('non_negative_int', type=int, help='a positional with non-negative int choices', - choices=non_negative_int_choices) - choices_parser.add_argument('empty_choices', help='a positional with empty choices', - choices=[]) + choices_parser.add_argument("list_pos", help="a positional populated with a choices list", choices=static_choices_list) + choices_parser.add_argument( + "function_pos", help="a positional populated with a choices function", choices_function=choices_function + ) + choices_parser.add_argument( + "method_pos", help="a positional populated with a choices method", choices_method=choices_method + ) + choices_parser.add_argument( + 'non_negative_int', type=int, help='a positional with non-negative int choices', choices=non_negative_int_choices + ) + choices_parser.add_argument('empty_choices', help='a positional with empty choices', choices=[]) @with_argparser(choices_parser) def do_choices(self, args: argparse.Namespace) -> None: @@ -172,16 +186,18 @@ class ArgparseCompleterTester(cmd2.Cmd): completer_parser = Cmd2ArgumentParser() # Flag args for completer command - completer_parser.add_argument("-f", "--function", help="a flag using a completer function", - completer_function=completer_function) - completer_parser.add_argument("-m", "--method", help="a flag using a completer method", - completer_method=completer_method) + completer_parser.add_argument( + "-f", "--function", help="a flag using a completer function", completer_function=completer_function + ) + completer_parser.add_argument("-m", "--method", help="a flag using a completer method", completer_method=completer_method) # Positional args for completer command - completer_parser.add_argument("function_pos", help="a positional using a completer function", - completer_function=completer_function) - completer_parser.add_argument("method_pos", help="a positional using a completer method", - completer_method=completer_method) + completer_parser.add_argument( + "function_pos", help="a positional using a completer function", completer_function=completer_function + ) + completer_parser.add_argument( + "method_pos", help="a positional using a completer method", completer_method=completer_method + ) @with_argparser(completer_parser) def do_completer(self, args: argparse.Namespace) -> None: @@ -193,22 +209,23 @@ class ArgparseCompleterTester(cmd2.Cmd): nargs_parser = Cmd2ArgumentParser() # Flag args for nargs command - nargs_parser.add_argument("--set_value", help="a flag with a set value for nargs", nargs=2, - choices=set_value_choices) - nargs_parser.add_argument("--one_or_more", help="a flag wanting one or more args", nargs=argparse.ONE_OR_MORE, - choices=one_or_more_choices) - nargs_parser.add_argument("--optional", help="a flag with an optional value", nargs=argparse.OPTIONAL, - choices=optional_choices) + nargs_parser.add_argument("--set_value", help="a flag with a set value for nargs", nargs=2, choices=set_value_choices) + nargs_parser.add_argument( + "--one_or_more", help="a flag wanting one or more args", nargs=argparse.ONE_OR_MORE, choices=one_or_more_choices + ) + nargs_parser.add_argument( + "--optional", help="a flag with an optional value", nargs=argparse.OPTIONAL, choices=optional_choices + ) # noinspection PyTypeChecker - nargs_parser.add_argument("--range", help="a flag with nargs range", nargs=(1, 2), - choices=range_choices) - nargs_parser.add_argument("--remainder", help="a flag wanting remaining", nargs=argparse.REMAINDER, - choices=remainder_choices) + nargs_parser.add_argument("--range", help="a flag with nargs range", nargs=(1, 2), choices=range_choices) + nargs_parser.add_argument( + "--remainder", help="a flag wanting remaining", nargs=argparse.REMAINDER, choices=remainder_choices + ) - nargs_parser.add_argument("normal_pos", help="a remainder positional", nargs=2, - choices=positional_choices) - nargs_parser.add_argument("remainder_pos", help="a remainder positional", nargs=argparse.REMAINDER, - choices=remainder_choices) + nargs_parser.add_argument("normal_pos", help="a remainder positional", nargs=2, choices=positional_choices) + nargs_parser.add_argument( + "remainder_pos", help="a remainder positional", nargs=argparse.REMAINDER, choices=remainder_choices + ) @with_argparser(nargs_parser) def do_nargs(self, args: argparse.Namespace) -> None: @@ -241,10 +258,8 @@ class ArgparseCompleterTester(cmd2.Cmd): raise CompletionError('choice broke something') comp_error_parser = Cmd2ArgumentParser() - comp_error_parser.add_argument('completer', help='positional arg', - completer_method=completer_raise_error) - comp_error_parser.add_argument('--choice', help='flag arg', - choices_method=choice_raise_error) + comp_error_parser.add_argument('completer', help='positional arg', completer_method=completer_raise_error) + comp_error_parser.add_argument('--choice', help='flag arg', choices_method=choice_raise_error) @with_argparser(comp_error_parser) def do_raise_completion_error(self, args: argparse.Namespace) -> None: @@ -294,12 +309,7 @@ def ac_app(): return app -@pytest.mark.parametrize('command', [ - 'music', - 'music create', - 'music create rock', - 'music create jazz' -]) +@pytest.mark.parametrize('command', ['music', 'music create', 'music create rock', 'music create jazz']) def test_help(ac_app, command): out1, err1 = run_cmd(ac_app, '{} -h'.format(command)) out2, err2 = run_cmd(ac_app, 'help {}'.format(command)) @@ -314,16 +324,19 @@ def test_bad_subcommand_help(ac_app): assert out1 == out2 -@pytest.mark.parametrize('command, text, completions', [ - ('', 'mus', ['music ']), - ('music', 'cre', ['create ']), - ('music', 'creab', []), - ('music create', '', ['jazz', 'rock']), - ('music crea', 'jazz', []), - ('music create', 'foo', []), - ('fake create', '', []), - ('music fake', '', []) -]) +@pytest.mark.parametrize( + 'command, text, completions', + [ + ('', 'mus', ['music ']), + ('music', 'cre', ['create ']), + ('music', 'creab', []), + ('music create', '', ['jazz', 'rock']), + ('music crea', 'jazz', []), + ('music create', 'foo', []), + ('fake create', '', []), + ('music fake', '', []), + ], +) def test_complete_help(ac_app, command, text, completions): line = 'help {} {}'.format(command, text) endidx = len(line) @@ -338,12 +351,10 @@ def test_complete_help(ac_app, command, text, completions): assert ac_app.completion_matches == sorted(completions, key=ac_app.default_sort_key) -@pytest.mark.parametrize('subcommand, text, completions', [ - ('create', '', ['jazz', 'rock']), - ('create', 'ja', ['jazz ']), - ('create', 'foo', []), - ('creab', 'ja', []) -]) +@pytest.mark.parametrize( + 'subcommand, text, completions', + [('create', '', ['jazz', 'rock']), ('create', 'ja', ['jazz ']), ('create', 'foo', []), ('creab', 'ja', [])], +) def test_subcommand_completions(ac_app, subcommand, text, completions): line = 'music {} {}'.format(subcommand, text) endidx = len(line) @@ -358,64 +369,132 @@ def test_subcommand_completions(ac_app, subcommand, text, completions): assert ac_app.completion_matches == sorted(completions, key=ac_app.default_sort_key) -@pytest.mark.parametrize('command_and_args, text, completion_matches, display_matches', [ - # Complete all flags (suppressed will not show) - ('flag', '-', - ['--append_const_flag', '--append_flag', '--count_flag', '--help', '--normal_flag', - '--remainder_flag', '--required_flag', '-a', '-c', '-h', '-n', '-o', '-q', '-r'], - ['-q, --required_flag', '[-o, --append_const_flag]', '[-a, --append_flag]', '[-c, --count_flag]', '[-h, --help]', - '[-n, --normal_flag]', '[-r, --remainder_flag]']), - ('flag', '--', - ['--append_const_flag', '--append_flag', '--count_flag', '--help', - '--normal_flag', '--remainder_flag', '--required_flag'], - ['--required_flag', '[--append_const_flag]', '[--append_flag]', '[--count_flag]', '[--help]', - '[--normal_flag]', '[--remainder_flag]']), - - # Complete individual flag - ('flag', '-n', ['-n '], ['[-n]']), - ('flag', '--n', ['--normal_flag '], ['[--normal_flag]']), - - # No flags should complete until current flag has its args - ('flag --append_flag', '-', [], []), - - # Complete REMAINDER flag name - ('flag', '-r', ['-r '], ['[-r]']), - ('flag', '--rem', ['--remainder_flag '], ['[--remainder_flag]']), - - # No flags after a REMAINDER should complete - ('flag -r value', '-', [], []), - ('flag --remainder_flag value', '--', [], []), - - # Suppressed flag should not complete - ('flag', '-s', [], []), - ('flag', '--s', [], []), - - # A used flag should not show in completions - ('flag -n', '--', - ['--append_const_flag', '--append_flag', '--count_flag', '--help', '--remainder_flag', '--required_flag'], - ['--required_flag', '[--append_const_flag]', '[--append_flag]', '[--count_flag]', '[--help]', '[--remainder_flag]']), - - # Flags with actions set to append, append_const, and count will always show even if they've been used - ('flag --append_const_flag -c --append_flag value', '--', - ['--append_const_flag', '--append_flag', '--count_flag', '--help', - '--normal_flag', '--remainder_flag', '--required_flag'], - ['--required_flag', '[--append_const_flag]', '[--append_flag]', '[--count_flag]', '[--help]', - '[--normal_flag]', '[--remainder_flag]']), - - # Non-default flag prefix character (+) - ('plus_flag', '+', - ['++help', '++normal_flag', '+h', '+n', '+q', '++required_flag'], - ['+q, ++required_flag', '[+h, ++help]', '[+n, ++normal_flag]']), - ('plus_flag', '++', - ['++help', '++normal_flag', '++required_flag'], - ['++required_flag', '[++help]', '[++normal_flag]']), - - # Flag completion should not occur after '--' since that tells argparse all remaining arguments are non-flags - ('flag --', '--', [], []), - ('flag --help --', '--', [], []), - ('plus_flag --', '++', [], []), - ('plus_flag ++help --', '++', [], []) -]) +@pytest.mark.parametrize( + 'command_and_args, text, completion_matches, display_matches', + [ + # Complete all flags (suppressed will not show) + ( + 'flag', + '-', + [ + '--append_const_flag', + '--append_flag', + '--count_flag', + '--help', + '--normal_flag', + '--remainder_flag', + '--required_flag', + '-a', + '-c', + '-h', + '-n', + '-o', + '-q', + '-r', + ], + [ + '-q, --required_flag', + '[-o, --append_const_flag]', + '[-a, --append_flag]', + '[-c, --count_flag]', + '[-h, --help]', + '[-n, --normal_flag]', + '[-r, --remainder_flag]', + ], + ), + ( + 'flag', + '--', + [ + '--append_const_flag', + '--append_flag', + '--count_flag', + '--help', + '--normal_flag', + '--remainder_flag', + '--required_flag', + ], + [ + '--required_flag', + '[--append_const_flag]', + '[--append_flag]', + '[--count_flag]', + '[--help]', + '[--normal_flag]', + '[--remainder_flag]', + ], + ), + # Complete individual flag + ('flag', '-n', ['-n '], ['[-n]']), + ('flag', '--n', ['--normal_flag '], ['[--normal_flag]']), + # No flags should complete until current flag has its args + ('flag --append_flag', '-', [], []), + # Complete REMAINDER flag name + ('flag', '-r', ['-r '], ['[-r]']), + ('flag', '--rem', ['--remainder_flag '], ['[--remainder_flag]']), + # No flags after a REMAINDER should complete + ('flag -r value', '-', [], []), + ('flag --remainder_flag value', '--', [], []), + # Suppressed flag should not complete + ('flag', '-s', [], []), + ('flag', '--s', [], []), + # A used flag should not show in completions + ( + 'flag -n', + '--', + ['--append_const_flag', '--append_flag', '--count_flag', '--help', '--remainder_flag', '--required_flag'], + [ + '--required_flag', + '[--append_const_flag]', + '[--append_flag]', + '[--count_flag]', + '[--help]', + '[--remainder_flag]', + ], + ), + # Flags with actions set to append, append_const, and count will always show even if they've been used + ( + 'flag --append_const_flag -c --append_flag value', + '--', + [ + '--append_const_flag', + '--append_flag', + '--count_flag', + '--help', + '--normal_flag', + '--remainder_flag', + '--required_flag', + ], + [ + '--required_flag', + '[--append_const_flag]', + '[--append_flag]', + '[--count_flag]', + '[--help]', + '[--normal_flag]', + '[--remainder_flag]', + ], + ), + # Non-default flag prefix character (+) + ( + 'plus_flag', + '+', + ['++help', '++normal_flag', '+h', '+n', '+q', '++required_flag'], + ['+q, ++required_flag', '[+h, ++help]', '[+n, ++normal_flag]'], + ), + ( + 'plus_flag', + '++', + ['++help', '++normal_flag', '++required_flag'], + ['++required_flag', '[++help]', '[++normal_flag]'], + ), + # Flag completion should not occur after '--' since that tells argparse all remaining arguments are non-flags + ('flag --', '--', [], []), + ('flag --help --', '--', [], []), + ('plus_flag --', '++', [], []), + ('plus_flag ++help --', '++', [], []), + ], +) def test_autcomp_flag_completion(ac_app, command_and_args, text, completion_matches, display_matches): line = '{} {}'.format(command_and_args, text) endidx = len(line) @@ -427,22 +506,26 @@ def test_autcomp_flag_completion(ac_app, command_and_args, text, completion_matc else: assert first_match is None - assert (ac_app.completion_matches == sorted(completion_matches, key=ac_app.default_sort_key) and - ac_app.display_matches == sorted(display_matches, key=ac_app.default_sort_key)) - - -@pytest.mark.parametrize('flag, text, completions', [ - ('-l', '', static_choices_list), - ('--list', 's', ['static', 'stop']), - ('-f', '', choices_from_function), - ('--function', 'ch', ['choices', 'chatty']), - ('-m', '', choices_from_method), - ('--method', 'm', ['method', 'most']), - ('-i', '', int_choices), - ('--int', '1', ['1 ']), - ('--int', '-', [-1, -2, -12]), - ('--int', '-1', [-1, -12]) -]) + assert ac_app.completion_matches == sorted( + completion_matches, key=ac_app.default_sort_key + ) and ac_app.display_matches == sorted(display_matches, key=ac_app.default_sort_key) + + +@pytest.mark.parametrize( + 'flag, text, completions', + [ + ('-l', '', static_choices_list), + ('--list', 's', ['static', 'stop']), + ('-f', '', choices_from_function), + ('--function', 'ch', ['choices', 'chatty']), + ('-m', '', choices_from_method), + ('--method', 'm', ['method', 'most']), + ('-i', '', int_choices), + ('--int', '1', ['1 ']), + ('--int', '-', [-1, -2, -12]), + ('--int', '-1', [-1, -12]), + ], +) def test_autocomp_flag_choices_completion(ac_app, flag, text, completions): line = 'choices {} {}'.format(flag, text) endidx = len(line) @@ -464,17 +547,20 @@ def test_autocomp_flag_choices_completion(ac_app, flag, text, completions): assert ac_app.completion_matches == completions -@pytest.mark.parametrize('pos, text, completions', [ - (1, '', static_choices_list), - (1, 's', ['static', 'stop']), - (2, '', choices_from_function), - (2, 'ch', ['choices', 'chatty']), - (3, '', choices_from_method), - (3, 'm', ['method', 'most']), - (4, '', non_negative_int_choices), - (4, '2', [2, 22]), - (5, '', []), -]) +@pytest.mark.parametrize( + 'pos, text, completions', + [ + (1, '', static_choices_list), + (1, 's', ['static', 'stop']), + (2, '', choices_from_function), + (2, 'ch', ['choices', 'chatty']), + (3, '', choices_from_method), + (3, 'm', ['method', 'most']), + (4, '', non_negative_int_choices), + (4, '2', [2, 22]), + (5, '', []), + ], +) def test_autocomp_positional_choices_completion(ac_app, pos, text, completions): # Generate line were preceding positionals are already filled line = 'choices {} {}'.format('foo ' * (pos - 1), text) @@ -518,12 +604,15 @@ def test_flag_sorting(ac_app): assert first_match is not None and ac_app.completion_matches == option_strings -@pytest.mark.parametrize('flag, text, completions', [ - ('-f', '', completions_from_function), - ('--function', 'f', ['function', 'fairly']), - ('-m', '', completions_from_method), - ('--method', 'm', ['method', 'missed']) -]) +@pytest.mark.parametrize( + 'flag, text, completions', + [ + ('-f', '', completions_from_function), + ('--function', 'f', ['function', 'fairly']), + ('-m', '', completions_from_method), + ('--method', 'm', ['method', 'missed']), + ], +) def test_autocomp_flag_completers(ac_app, flag, text, completions): line = 'completer {} {}'.format(flag, text) endidx = len(line) @@ -538,12 +627,15 @@ def test_autocomp_flag_completers(ac_app, flag, text, completions): assert ac_app.completion_matches == sorted(completions, key=ac_app.default_sort_key) -@pytest.mark.parametrize('pos, text, completions', [ - (1, '', completions_from_function), - (1, 'c', ['completions', 'complete']), - (2, '', completions_from_method), - (2, 'm', ['method', 'missed']) -]) +@pytest.mark.parametrize( + 'pos, text, completions', + [ + (1, '', completions_from_function), + (1, 'c', ['completions', 'complete']), + (2, '', completions_from_method), + (2, 'm', ['method', 'missed']), + ], +) def test_autocomp_positional_completers(ac_app, pos, text, completions): # Generate line were preceding positionals are already filled line = 'completer {} {}'.format('foo ' * (pos - 1), text) @@ -588,14 +680,17 @@ def test_autocomp_blank_token(ac_app): assert completions == completions_from_method -@pytest.mark.parametrize('num_aliases, show_description', [ - # The number of completion results determines if the description field of CompletionItems gets displayed - # in the tab completions. The count must be greater than 1 and less than ac_app.max_completion_items, - # which defaults to 50. - (1, False), - (5, True), - (100, False) -]) +@pytest.mark.parametrize( + 'num_aliases, show_description', + [ + # The number of completion results determines if the description field of CompletionItems gets displayed + # in the tab completions. The count must be greater than 1 and less than ac_app.max_completion_items, + # which defaults to 50. + (1, False), + (5, True), + (100, False), + ], +) def test_completion_items(ac_app, num_aliases, show_description): # Create aliases for i in range(0, num_aliases): @@ -617,71 +712,57 @@ def test_completion_items(ac_app, num_aliases, show_description): assert ('help' in ac_app.display_matches[0]) == show_description -@pytest.mark.parametrize('args, completions', [ - # Flag with nargs = 2 - ('--set_value', set_value_choices), - ('--set_value set', ['value', 'choices']), - - # Both args are filled. At positional arg now. - ('--set_value set value', positional_choices), - - # Using the flag again will reset the choices available - ('--set_value set value --set_value', set_value_choices), - - # Flag with nargs = ONE_OR_MORE - ('--one_or_more', one_or_more_choices), - ('--one_or_more one', ['or', 'more', 'choices']), - - # Flag with nargs = OPTIONAL - ('--optional', optional_choices), - - # Only one arg allowed for an OPTIONAL. At positional now. - ('--optional optional', positional_choices), - - # Flag with nargs range (1, 2) - ('--range', range_choices), - ('--range some', ['range', 'choices']), - - # Already used 2 args so at positional - ('--range some range', positional_choices), - - # Flag with nargs = REMAINDER - ('--remainder', remainder_choices), - ('--remainder remainder ', ['choices ']), - - # No more flags can appear after a REMAINDER flag) - ('--remainder choices --set_value', ['remainder ']), - - # Double dash ends the current flag - ('--range choice --', positional_choices), - - # Double dash ends a REMAINDER flag - ('--remainder remainder --', positional_choices), - - # No more flags after a double dash - ('-- --one_or_more ', positional_choices), - - # Consume positional - ('', positional_choices), - ('positional', ['the', 'choices']), - - # Intermixed flag and positional - ('positional --set_value', set_value_choices), - ('positional --set_value set', ['choices', 'value']), - - # Intermixed flag and positional with flag finishing - ('positional --set_value set value', ['the', 'choices']), - ('positional --range choice --', ['the', 'choices']), - - # REMAINDER positional - ('the positional', remainder_choices), - ('the positional remainder', ['choices ']), - ('the positional remainder choices', []), - - # REMAINDER positional. Flags don't work in REMAINDER - ('the positional --set_value', remainder_choices), - ('the positional remainder --set_value', ['choices ']) -]) +@pytest.mark.parametrize( + 'args, completions', + [ + # Flag with nargs = 2 + ('--set_value', set_value_choices), + ('--set_value set', ['value', 'choices']), + # Both args are filled. At positional arg now. + ('--set_value set value', positional_choices), + # Using the flag again will reset the choices available + ('--set_value set value --set_value', set_value_choices), + # Flag with nargs = ONE_OR_MORE + ('--one_or_more', one_or_more_choices), + ('--one_or_more one', ['or', 'more', 'choices']), + # Flag with nargs = OPTIONAL + ('--optional', optional_choices), + # Only one arg allowed for an OPTIONAL. At positional now. + ('--optional optional', positional_choices), + # Flag with nargs range (1, 2) + ('--range', range_choices), + ('--range some', ['range', 'choices']), + # Already used 2 args so at positional + ('--range some range', positional_choices), + # Flag with nargs = REMAINDER + ('--remainder', remainder_choices), + ('--remainder remainder ', ['choices ']), + # No more flags can appear after a REMAINDER flag) + ('--remainder choices --set_value', ['remainder ']), + # Double dash ends the current flag + ('--range choice --', positional_choices), + # Double dash ends a REMAINDER flag + ('--remainder remainder --', positional_choices), + # No more flags after a double dash + ('-- --one_or_more ', positional_choices), + # Consume positional + ('', positional_choices), + ('positional', ['the', 'choices']), + # Intermixed flag and positional + ('positional --set_value', set_value_choices), + ('positional --set_value set', ['choices', 'value']), + # Intermixed flag and positional with flag finishing + ('positional --set_value set value', ['the', 'choices']), + ('positional --range choice --', ['the', 'choices']), + # REMAINDER positional + ('the positional', remainder_choices), + ('the positional remainder', ['choices ']), + ('the positional remainder choices', []), + # REMAINDER positional. Flags don't work in REMAINDER + ('the positional --set_value', remainder_choices), + ('the positional remainder --set_value', ['choices ']), + ], +) def test_autcomp_nargs(ac_app, args, completions): text = '' line = 'nargs {} {}'.format(args, text) @@ -697,43 +778,39 @@ def test_autcomp_nargs(ac_app, args, completions): assert ac_app.completion_matches == sorted(completions, key=ac_app.default_sort_key) -@pytest.mark.parametrize('command_and_args, text, is_error', [ - # Flag is finished before moving on - ('hint --flag foo --', '', False), - ('hint --flag foo --help', '', False), - ('hint --flag foo', '--', False), - - ('nargs --one_or_more one --', '', False), - ('nargs --one_or_more one or --set_value', '', False), - ('nargs --one_or_more one or more', '--', False), - - ('nargs --set_value set value --', '', False), - ('nargs --set_value set value --one_or_more', '', False), - ('nargs --set_value set value', '--', False), - ('nargs --set_val set value', '--', False), # This exercises our abbreviated flag detection - - ('nargs --range choices --', '', False), - ('nargs --range choices range --set_value', '', False), - ('nargs --range range', '--', False), - - # Flag is not finished before moving on - ('hint --flag --', '', True), - ('hint --flag --help', '', True), - ('hint --flag', '--', True), - - ('nargs --one_or_more --', '', True), - ('nargs --one_or_more --set_value', '', True), - ('nargs --one_or_more', '--', True), - - ('nargs --set_value set --', '', True), - ('nargs --set_value set --one_or_more', '', True), - ('nargs --set_value set', '--', True), - ('nargs --set_val set', '--', True), # This exercises our abbreviated flag detection - - ('nargs --range --', '', True), - ('nargs --range --set_value', '', True), - ('nargs --range', '--', True), -]) +@pytest.mark.parametrize( + 'command_and_args, text, is_error', + [ + # Flag is finished before moving on + ('hint --flag foo --', '', False), + ('hint --flag foo --help', '', False), + ('hint --flag foo', '--', False), + ('nargs --one_or_more one --', '', False), + ('nargs --one_or_more one or --set_value', '', False), + ('nargs --one_or_more one or more', '--', False), + ('nargs --set_value set value --', '', False), + ('nargs --set_value set value --one_or_more', '', False), + ('nargs --set_value set value', '--', False), + ('nargs --set_val set value', '--', False), # This exercises our abbreviated flag detection + ('nargs --range choices --', '', False), + ('nargs --range choices range --set_value', '', False), + ('nargs --range range', '--', False), + # Flag is not finished before moving on + ('hint --flag --', '', True), + ('hint --flag --help', '', True), + ('hint --flag', '--', True), + ('nargs --one_or_more --', '', True), + ('nargs --one_or_more --set_value', '', True), + ('nargs --one_or_more', '--', True), + ('nargs --set_value set --', '', True), + ('nargs --set_value set --one_or_more', '', True), + ('nargs --set_value set', '--', True), + ('nargs --set_val set', '--', True), # This exercises our abbreviated flag detection + ('nargs --range --', '', True), + ('nargs --range --set_value', '', True), + ('nargs --range', '--', True), + ], +) def test_unfinished_flag_error(ac_app, command_and_args, text, is_error, capsys): line = '{} {}'.format(command_and_args, text) endidx = len(line) @@ -816,35 +893,32 @@ def test_completion_items_descriptive_header(ac_app): assert DEFAULT_DESCRIPTIVE_HEADER in ac_app.completion_header -@pytest.mark.parametrize('command_and_args, text, has_hint', [ - # Normal cases - ('hint', '', True), - ('hint --flag', '', True), - ('hint --suppressed_help', '', False), - ('hint --suppressed_hint', '', False), - - # Hint because flag does not have enough values to be considered finished - ('nargs --one_or_more', '-', True), - - # This flag has reached its minimum value count and therefore a new flag could start. - # However the flag can still consume values and the text is not a single prefix character. - # Therefor a hint will be shown. - ('nargs --one_or_more choices', 'bad_completion', True), - - # Like the previous case, but this time text is a single prefix character which will cause flag - # name completion to occur instead of a hint for the current flag. - ('nargs --one_or_more choices', '-', False), - - # Hint because this is a REMAINDER flag and therefore no more flag name completions occur. - ('nargs --remainder', '-', True), - - # No hint for the positional because text is a single prefix character which results in flag name completion - ('hint', '-', False), - - # Hint because this is a REMAINDER positional and therefore no more flag name completions occur. - ('nargs the choices', '-', True), - ('nargs the choices remainder', '-', True), -]) +@pytest.mark.parametrize( + 'command_and_args, text, has_hint', + [ + # Normal cases + ('hint', '', True), + ('hint --flag', '', True), + ('hint --suppressed_help', '', False), + ('hint --suppressed_hint', '', False), + # Hint because flag does not have enough values to be considered finished + ('nargs --one_or_more', '-', True), + # This flag has reached its minimum value count and therefore a new flag could start. + # However the flag can still consume values and the text is not a single prefix character. + # Therefor a hint will be shown. + ('nargs --one_or_more choices', 'bad_completion', True), + # Like the previous case, but this time text is a single prefix character which will cause flag + # name completion to occur instead of a hint for the current flag. + ('nargs --one_or_more choices', '-', False), + # Hint because this is a REMAINDER flag and therefore no more flag name completions occur. + ('nargs --remainder', '-', True), + # No hint for the positional because text is a single prefix character which results in flag name completion + ('hint', '-', False), + # Hint because this is a REMAINDER positional and therefore no more flag name completions occur. + ('nargs the choices', '-', True), + ('nargs the choices remainder', '-', True), + ], +) def test_autocomp_hint(ac_app, command_and_args, text, has_hint, capsys): line = '{} {}'.format(command_and_args, text) endidx = len(line) @@ -868,20 +942,25 @@ def test_autocomp_hint_no_help_text(ac_app, capsys): out, err = capsys.readouterr() assert first_match is None - assert not out == ''' + assert ( + not out + == ''' Hint: NO_HELP_POS ''' - - -@pytest.mark.parametrize('args, text', [ - # Exercise a flag arg and choices function that raises a CompletionError - ('--choice ', 'choice'), - - # Exercise a positional arg and completer that raises a CompletionError - ('', 'completer') -]) + ) + + +@pytest.mark.parametrize( + 'args, text', + [ + # Exercise a flag arg and choices function that raises a CompletionError + ('--choice ', 'choice'), + # Exercise a positional arg and completer that raises a CompletionError + ('', 'completer'), + ], +) def test_completion_error(ac_app, capsys, args, text): line = 'raise_completion_error {} {}'.format(args, text) endidx = len(line) @@ -894,16 +973,17 @@ def test_completion_error(ac_app, capsys, args, text): assert "{} broke something".format(text) in out -@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']) -]) +@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) @@ -919,34 +999,29 @@ def test_arg_tokens(ac_app, command_and_args, completions): assert ac_app.completion_matches == sorted(completions, key=ac_app.default_sort_key) -@pytest.mark.parametrize('command_and_args, text, output_contains, first_match', [ - # Group isn't done. Hint will show for optional positional and no completions returned - ('mutex', '', 'the optional positional', None), - - # Group isn't done. Flag name will still complete. - ('mutex', '--fl', '', '--flag '), - - # Group isn't done. Flag hint will show. - ('mutex --flag', '', 'the flag arg', None), - - # Group finished by optional positional. No flag name will complete. - ('mutex pos_val', '--fl', '', None), - - # Group finished by optional positional. Error will display trying to complete the flag's value. - ('mutex pos_val --flag', '', 'f/--flag: not allowed with argument optional_pos', None), - - # Group finished by --flag. Optional positional will be skipped and last_arg will show its hint. - ('mutex --flag flag_val', '', 'the last arg', None), - - # Group finished by --flag. Other flag name won't complete. - ('mutex --flag flag_val', '--oth', '', None), - - # Group finished by --flag. Error will display trying to complete other flag's value. - ('mutex --flag flag_val --other', '', '-o/--other_flag: not allowed with argument -f/--flag', None), - - # Group finished by --flag. That same flag can be used again so it's hint will show. - ('mutex --flag flag_val --flag', '', 'the flag arg', None) -]) +@pytest.mark.parametrize( + 'command_and_args, text, output_contains, first_match', + [ + # Group isn't done. Hint will show for optional positional and no completions returned + ('mutex', '', 'the optional positional', None), + # Group isn't done. Flag name will still complete. + ('mutex', '--fl', '', '--flag '), + # Group isn't done. Flag hint will show. + ('mutex --flag', '', 'the flag arg', None), + # Group finished by optional positional. No flag name will complete. + ('mutex pos_val', '--fl', '', None), + # Group finished by optional positional. Error will display trying to complete the flag's value. + ('mutex pos_val --flag', '', 'f/--flag: not allowed with argument optional_pos', None), + # Group finished by --flag. Optional positional will be skipped and last_arg will show its hint. + ('mutex --flag flag_val', '', 'the last arg', None), + # Group finished by --flag. Other flag name won't complete. + ('mutex --flag flag_val', '--oth', '', None), + # Group finished by --flag. Error will display trying to complete other flag's value. + ('mutex --flag flag_val --other', '', '-o/--other_flag: not allowed with argument -f/--flag', None), + # Group finished by --flag. That same flag can be used again so it's hint will show. + ('mutex --flag flag_val --flag', '', 'the flag arg', None), + ], +) def test_complete_mutex_group(ac_app, command_and_args, text, output_contains, first_match, capsys): line = '{} {}'.format(command_and_args, text) endidx = len(line) @@ -960,6 +1035,7 @@ def test_complete_mutex_group(ac_app, command_and_args, text, output_contains, f def test_single_prefix_char(): from cmd2.argparse_completer import _single_prefix_char + parser = Cmd2ArgumentParser(prefix_chars='-+') # Invalid @@ -976,6 +1052,7 @@ def test_single_prefix_char(): def test_looks_like_flag(): from cmd2.argparse_completer import _looks_like_flag + parser = Cmd2ArgumentParser() # Does not start like a flag |