summaryrefslogtreecommitdiff
path: root/tests/test_argparse_completer.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_argparse_completer.py')
-rw-r--r--tests/test_argparse_completer.py797
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