Skip to content

Commit f2cb61d

Browse files
committed
Fixed remaining tests in test_argparse_completer.py.
1 parent 96477e2 commit f2cb61d

File tree

1 file changed

+122
-116
lines changed

1 file changed

+122
-116
lines changed

tests/test_argparse_completer.py

Lines changed: 122 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def __init__(self, *args, **kwargs) -> None:
5858
# Add subcommands to music -> create
5959
music_create_subparsers = music_create_parser.add_subparsers()
6060
music_create_jazz_parser = music_create_subparsers.add_parser('jazz', help='create jazz')
61-
music_create_rock_parser = music_create_subparsers.add_parser('rock', help='create rocks')
61+
music_create_rock_parser = music_create_subparsers.add_parser('rock', help='create rock')
6262

6363
@with_argparser(music_parser)
6464
def do_music(self, args: argparse.Namespace) -> None:
@@ -74,6 +74,7 @@ def do_music(self, args: argparse.Namespace) -> None:
7474
flag_parser.add_argument('-a', '--append_flag', help='append flag', action='append')
7575
flag_parser.add_argument('-o', '--append_const_flag', help='append const flag', action='append_const', const=True)
7676
flag_parser.add_argument('-c', '--count_flag', help='count flag', action='count')
77+
flag_parser.add_argument('-e', '--extend_flag', help='extend flag', action='extend')
7778
flag_parser.add_argument('-s', '--suppressed_flag', help=argparse.SUPPRESS, action='store_true')
7879
flag_parser.add_argument('-r', '--remainder_flag', nargs=argparse.REMAINDER, help='a remainder flag')
7980
flag_parser.add_argument('-q', '--required_flag', required=True, help='a required flag', action='store_true')
@@ -146,14 +147,14 @@ def completion_item_method(self) -> list[CompletionItem]:
146147
"-p", "--provider", help="a flag populated with a choices provider", choices_provider=choices_provider
147148
)
148149
choices_parser.add_argument(
149-
"--desc_header",
150-
help='this arg has a descriptive header',
150+
"--table_header",
151+
help='this arg has a table header',
151152
choices_provider=completion_item_method,
152153
table_header=CUSTOM_TABLE_HEADER,
153154
)
154155
choices_parser.add_argument(
155156
"--no_header",
156-
help='this arg has no descriptive header',
157+
help='this arg has no table header',
157158
choices_provider=completion_item_method,
158159
metavar=STR_METAVAR,
159160
)
@@ -299,7 +300,7 @@ def completer_takes_arg_tokens(
299300
arg_tokens_parser = Cmd2ArgumentParser()
300301
arg_tokens_parser.add_argument('parent_arg', help='arg from a parent parser')
301302

302-
# Create a subcommand for to exercise receiving parent_tokens and subcommand name in arg_tokens
303+
# Create a subcommand to exercise receiving parent_tokens and subcommand name in arg_tokens
303304
arg_tokens_subparser = arg_tokens_parser.add_subparsers(dest='subcommand')
304305
arg_tokens_subcmd_parser = arg_tokens_subparser.add_parser('subcmd')
305306

@@ -340,6 +341,26 @@ def do_mutex(self, args: argparse.Namespace) -> None:
340341
def do_standalone(self, args: argparse.Namespace) -> None:
341342
pass
342343

344+
############################################################################################################
345+
# Begin code related to display_meta data
346+
############################################################################################################
347+
meta_parser = Cmd2ArgumentParser()
348+
349+
# Add subcommands to meta
350+
meta_subparsers = meta_parser.add_subparsers()
351+
352+
# Create subcommands with and without help text
353+
meta_helpful_parser = meta_subparsers.add_parser('helpful', help='my helpful text')
354+
meta_helpless_parser = meta_subparsers.add_parser('helpless')
355+
356+
# Create flags with and without help text
357+
meta_helpful_parser.add_argument('--helpful_flag', help="a helpful flag")
358+
meta_helpless_parser.add_argument('--helpless_flag')
359+
360+
@with_argparser(meta_parser)
361+
def do_meta(self, args: argparse.Namespace) -> None:
362+
pass
363+
343364

344365
@pytest.fixture
345366
def ac_app() -> ArgparseCompleterTester:
@@ -402,142 +423,122 @@ def test_subcommand_completions(ac_app, subcommand, text, expected) -> None:
402423

403424

404425
@pytest.mark.parametrize(
405-
('command_and_args', 'text', 'expected_matches', 'expected_displays'),
426+
# expected_data is a list of tuples with completion text and display values
427+
('command_and_args', 'text', 'expected_data'),
406428
[
407429
# Complete all flags (suppressed will not show)
408430
(
409431
'flag',
410432
'-',
411433
[
412-
'-a',
413-
'-c',
414-
'-h',
415-
'-n',
416-
'-o',
417-
'-q',
418-
'-r',
419-
],
420-
[
421-
'-q, --required_flag',
422-
'[-o, --append_const_flag]',
423-
'[-a, --append_flag]',
424-
'[-c, --count_flag]',
425-
'[-h, --help]',
426-
'[-n, --normal_flag]',
427-
'[-r, --remainder_flag]',
434+
("-a", "[-a, --append_flag]"),
435+
("-c", "[-c, --count_flag]"),
436+
('-e', '[-e, --extend_flag]'),
437+
("-h", "[-h, --help]"),
438+
("-n", "[-n, --normal_flag]"),
439+
("-o", "[-o, --append_const_flag]"),
440+
("-q", "-q, --required_flag"),
441+
("-r", "[-r, --remainder_flag]"),
428442
],
429443
),
430444
(
431445
'flag',
432446
'--',
433447
[
434-
'--append_const_flag',
435-
'--append_flag',
436-
'--count_flag',
437-
'--help',
438-
'--normal_flag',
439-
'--remainder_flag',
440-
'--required_flag',
441-
],
442-
[
443-
'--required_flag',
444-
'[--append_const_flag]',
445-
'[--append_flag]',
446-
'[--count_flag]',
447-
'[--help]',
448-
'[--normal_flag]',
449-
'[--remainder_flag]',
448+
('--append_const_flag', '[--append_const_flag]'),
449+
('--append_flag', '[--append_flag]'),
450+
('--count_flag', '[--count_flag]'),
451+
('--extend_flag', '[--extend_flag]'),
452+
('--help', '[--help]'),
453+
('--normal_flag', '[--normal_flag]'),
454+
('--remainder_flag', '[--remainder_flag]'),
455+
('--required_flag', '--required_flag'),
450456
],
451457
),
452458
# Complete individual flag
453-
('flag', '-n', ['-n'], ['[-n]']),
454-
('flag', '--n', ['--normal_flag'], ['[--normal_flag]']),
459+
('flag', '-n', [('-n', '[-n]')]),
460+
('flag', '--n', [('--normal_flag', '[--normal_flag]')]),
455461
# No flags should complete until current flag has its args
456-
('flag --append_flag', '-', [], []),
462+
('flag --append_flag', '-', []),
457463
# Complete REMAINDER flag name
458-
('flag', '-r', ['-r'], ['[-r]']),
459-
('flag', '--rem', ['--remainder_flag'], ['[--remainder_flag]']),
464+
('flag', '-r', [('-r', '[-r]')]),
465+
('flag', '--rem', [('--remainder_flag', '[--remainder_flag]')]),
460466
# No flags after a REMAINDER should complete
461-
('flag -r value', '-', [], []),
462-
('flag --remainder_flag value', '--', [], []),
467+
('flag -r value', '-', []),
468+
('flag --remainder_flag value', '--', []),
463469
# Suppressed flag should not complete
464-
('flag', '-s', [], []),
465-
('flag', '--s', [], []),
470+
('flag', '-s', []),
471+
('flag', '--s', []),
466472
# A used flag should not show in completions
467473
(
468474
'flag -n',
469475
'--',
470-
['--append_const_flag', '--append_flag', '--count_flag', '--help', '--remainder_flag', '--required_flag'],
471476
[
472-
'--required_flag',
473-
'[--append_const_flag]',
474-
'[--append_flag]',
475-
'[--count_flag]',
476-
'[--help]',
477-
'[--remainder_flag]',
477+
('--append_const_flag', '[--append_const_flag]'),
478+
('--append_flag', '[--append_flag]'),
479+
('--count_flag', '[--count_flag]'),
480+
('--extend_flag', '[--extend_flag]'),
481+
('--help', '[--help]'),
482+
('--remainder_flag', '[--remainder_flag]'),
483+
('--required_flag', '--required_flag'),
478484
],
479485
),
480-
# Flags with actions set to append, append_const, and count will always show even if they've been used
486+
# Flags with actions set to append, append_const, extend, and count will always show even if they've been used
481487
(
482-
'flag --append_const_flag -c --append_flag value',
488+
'flag --append_flag value --append_const_flag --count_flag --extend_flag value',
483489
'--',
484490
[
485-
'--append_const_flag',
486-
'--append_flag',
487-
'--count_flag',
488-
'--help',
489-
'--normal_flag',
490-
'--remainder_flag',
491-
'--required_flag',
492-
],
493-
[
494-
'--required_flag',
495-
'[--append_const_flag]',
496-
'[--append_flag]',
497-
'[--count_flag]',
498-
'[--help]',
499-
'[--normal_flag]',
500-
'[--remainder_flag]',
491+
('--append_const_flag', '[--append_const_flag]'),
492+
('--append_flag', '[--append_flag]'),
493+
('--count_flag', '[--count_flag]'),
494+
('--extend_flag', '[--extend_flag]'),
495+
('--help', '[--help]'),
496+
('--normal_flag', '[--normal_flag]'),
497+
('--remainder_flag', '[--remainder_flag]'),
498+
('--required_flag', '--required_flag'),
501499
],
502500
),
503501
# Non-default flag prefix character (+)
504502
(
505503
'plus_flag',
506504
'+',
507-
['+h', '+n', '+q'],
508-
['+q, ++required_flag', '[+h, ++help]', '[+n, ++normal_flag]'],
505+
[
506+
('+h', '[+h, ++help]'),
507+
('+n', '[+n, ++normal_flag]'),
508+
('+q', '+q, ++required_flag'),
509+
],
509510
),
510511
(
511512
'plus_flag',
512513
'++',
513-
['++help', '++normal_flag', '++required_flag'],
514-
['++required_flag', '[++help]', '[++normal_flag]'],
514+
[
515+
('++help', '[++help]'),
516+
('++normal_flag', '[++normal_flag]'),
517+
('++required_flag', '++required_flag'),
518+
],
515519
),
516520
# Flag completion should not occur after '--' since that tells argparse all remaining arguments are non-flags
517-
('flag --', '--', [], []),
518-
('flag --help --', '--', [], []),
519-
('plus_flag --', '++', [], []),
520-
('plus_flag ++help --', '++', [], []),
521+
('flag --', '--', []),
522+
('flag --help --', '--', []),
523+
('plus_flag --', '++', []),
524+
('plus_flag ++help --', '++', []),
521525
# Test remaining flag names complete after all positionals are complete
522-
('pos_and_flag', '', ['a', 'choice'], ['a', 'choice']),
523-
('pos_and_flag choice ', '', ['-f', '-h'], ['[-f, --flag]', '[-h, --help]']),
524-
('pos_and_flag choice -f ', '', ['-h'], ['[-h, --help]']),
525-
('pos_and_flag choice -f -h ', '', [], []),
526+
('pos_and_flag', '', [('a', 'a'), ('choice', 'choice')]),
527+
('pos_and_flag choice ', '', [('-f', '[-f, --flag]'), ('-h', '[-h, --help]')]),
528+
('pos_and_flag choice -f ', '', [('-h', '[-h, --help]')]),
529+
('pos_and_flag choice -f -h ', '', []),
526530
],
527531
)
528-
def test_autcomp_flag_completion(ac_app, command_and_args, text, expected_matches, expected_displays) -> None:
532+
def test_autcomp_flag_completion(ac_app, command_and_args, text, expected_data) -> None:
529533
line = f'{command_and_args} {text}'
530534
endidx = len(line)
531535
begidx = endidx - len(text)
532536

533-
first_match = complete_tester(text, line, begidx, endidx, ac_app)
534-
if completion_matches:
535-
assert first_match is not None
536-
else:
537-
assert first_match is None
537+
expected_completions = Completions(items=[CompletionItem(value=v, display=d) for v, d in expected_data])
538+
completions = ac_app.complete(text, line, begidx, endidx)
538539

539-
assert ac_app.completion_matches == sorted(completion_matches, key=ac_app.default_sort_key)
540-
assert ac_app.display_matches == sorted(display_matches, key=ac_app.default_sort_key)
540+
assert completions.to_strings() == expected_completions.to_strings()
541+
assert [item.display for item in completions] == [item.display for item in expected_completions]
541542

542543

543544
@pytest.mark.parametrize(
@@ -576,7 +577,7 @@ def test_autocomp_flag_choices_completion(ac_app, flag, text, expected) -> None:
576577
],
577578
)
578579
def test_autocomp_positional_choices_completion(ac_app, pos, text, expected) -> None:
579-
# Generate line were preceding positionals are already filled
580+
# Generate line where preceding positionals are already filled
580581
line = 'choices {} {}'.format('foo ' * (pos - 1), text)
581582
endidx = len(line)
582583
begidx = endidx - len(text)
@@ -585,26 +586,6 @@ def test_autocomp_positional_choices_completion(ac_app, pos, text, expected) ->
585586
assert completions.to_strings() == Completions.from_values(expected).to_strings()
586587

587588

588-
def test_flag_sorting(ac_app) -> None:
589-
# This test exercises the case where a positional arg has non-negative integers for its choices.
590-
# ArgparseCompleter will sort these numerically before converting them to strings. As a result,
591-
# cmd2.matches_sorted gets set to True. If no completion matches are returned and the entered
592-
# text looks like the beginning of a flag (e.g -), then ArgparseCompleter will try to complete
593-
# flag names next. Before it does this, cmd2.matches_sorted is reset to make sure the flag names
594-
# get sorted correctly.
595-
option_strings = [action.option_strings[0] for action in ac_app.choices_parser._actions if action.option_strings]
596-
option_strings.sort(key=ac_app.default_sort_key)
597-
598-
text = '-'
599-
line = f'choices arg1 arg2 arg3 {text}'
600-
endidx = len(line)
601-
begidx = endidx - len(text)
602-
603-
first_match = complete_tester(text, line, begidx, endidx, ac_app)
604-
assert first_match is not None
605-
assert ac_app.completion_matches == option_strings
606-
607-
608589
@pytest.mark.parametrize(
609590
('flag', 'text', 'expected'),
610591
[
@@ -848,12 +829,12 @@ def test_unfinished_flag_error(ac_app, command_and_args, text, is_error) -> None
848829
def test_completion_table_arg_header(ac_app) -> None:
849830
# Test when metavar is None
850831
text = ''
851-
line = f'choices --desc_header {text}'
832+
line = f'choices --table_header {text}'
852833
endidx = len(line)
853834
begidx = endidx - len(text)
854835

855836
completions = ac_app.complete(text, line, begidx, endidx)
856-
assert "DESC_HEADER" in normalize(completions.completion_table)[0]
837+
assert "TABLE_HEADER" in normalize(completions.completion_table)[0]
857838

858839
# Test when metavar is a string
859840
text = ''
@@ -901,7 +882,7 @@ def test_completion_table_header(ac_app) -> None:
901882

902883
# This argument provided a table header
903884
text = ''
904-
line = f'choices --desc_header {text}'
885+
line = f'choices --table_header {text}'
905886
endidx = len(line)
906887
begidx = endidx - len(text)
907888

@@ -1124,6 +1105,31 @@ def test_complete_standalone(ac_app, flag, expected) -> None:
11241105
assert completions.to_strings() == Completions.from_values(expected).to_strings()
11251106

11261107

1108+
@pytest.mark.parametrize(
1109+
('subcommand', 'flag', 'display_meta'),
1110+
[
1111+
('helpful', '', 'my helpful text'),
1112+
('helpful', '--helpful_flag', "a helpful flag"),
1113+
('helpless', '', ''),
1114+
('helpless', '--helpless_flag', ''),
1115+
],
1116+
)
1117+
def test_display_meta(ac_app, subcommand, flag, display_meta) -> None:
1118+
"""Test that subcommands and flags can have display_meta data."""
1119+
if flag:
1120+
text = flag
1121+
line = line = f'meta {subcommand} {text}'
1122+
else:
1123+
text = subcommand
1124+
line = line = f'meta {text}'
1125+
1126+
endidx = len(line)
1127+
begidx = endidx - len(text)
1128+
1129+
completions = ac_app.complete(text, line, begidx, endidx)
1130+
assert completions[0].display_meta == display_meta
1131+
1132+
11271133
# Custom ArgparseCompleter-based class
11281134
class CustomCompleter(argparse_completer.ArgparseCompleter):
11291135
def _complete_flags(self, text: str, line: str, begidx: int, endidx: int, matched_flags: list[str]) -> list[str]:

0 commit comments

Comments
 (0)