Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.12.9"
rev: "v0.13.0"
hooks:
- id: ruff-format
args: [--config=pyproject.toml]
Expand Down
2 changes: 1 addition & 1 deletion cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -6024,7 +6024,7 @@ def _validate_prepostcmd_hook(
type_hints, ret_ann = get_types(func)
if not type_hints:
raise TypeError(f"{func.__name__} parameter is missing a type hint, expected: {data_type}")
param_name, par_ann = next(iter(type_hints.items()))
_param_name, par_ann = next(iter(type_hints.items()))
# validate the parameter has the right annotation
if par_ann != data_type:
raise TypeError(f'argument 1 of {func.__name__} has incompatible type {par_ann}, expected {data_type}')
Expand Down
64 changes: 32 additions & 32 deletions tests/test_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,17 @@ def argparse_app():


def test_invalid_syntax(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'speak "')
_out, err = run_cmd(argparse_app, 'speak "')
assert err[0] == "Invalid syntax: No closing quotation"


def test_argparse_basic_command(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'say hello')
out, _err = run_cmd(argparse_app, 'say hello')
assert out == ['hello']


def test_argparse_remove_quotes(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'say "hello there"')
out, _err = run_cmd(argparse_app, 'say "hello there"')
assert out == ['hello there']


Expand All @@ -150,64 +150,64 @@ def test_argparse_with_no_args(argparse_app) -> None:
def test_argparser_kwargs(argparse_app, capsys) -> None:
"""Test with_argparser wrapper passes through kwargs to command function"""
argparse_app.do_say('word', keyword_arg="foo")
out, err = capsys.readouterr()
out, _err = capsys.readouterr()
assert out == "foo\n"


def test_argparse_preserve_quotes(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'tag mytag "hello"')
out, _err = run_cmd(argparse_app, 'tag mytag "hello"')
assert out[0] == '<mytag>"hello"</mytag>'


def test_argparse_custom_namespace(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'test_argparse_ns')
out, _err = run_cmd(argparse_app, 'test_argparse_ns')
assert out[0] == 'custom'


def test_argparse_with_list(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'speak -s hello world!')
out, _err = run_cmd(argparse_app, 'speak -s hello world!')
assert out == ['HELLO WORLD!']


def test_argparse_with_list_remove_quotes(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'speak -s hello "world!"')
out, _err = run_cmd(argparse_app, 'speak -s hello "world!"')
assert out == ['HELLO WORLD!']


def test_argparse_with_list_preserve_quotes(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'test_argparse_with_list_quotes "hello" person')
out, _err = run_cmd(argparse_app, 'test_argparse_with_list_quotes "hello" person')
assert out[0] == '"hello" person'


def test_argparse_with_list_custom_namespace(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'test_argparse_with_list_ns')
out, _err = run_cmd(argparse_app, 'test_argparse_with_list_ns')
assert out[0] == 'custom'


def test_argparse_with_list_and_empty_doc(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'speak -s hello world!')
out, _err = run_cmd(argparse_app, 'speak -s hello world!')
assert out == ['HELLO WORLD!']


def test_argparser_correct_args_with_quotes_and_midline_options(argparse_app) -> None:
out, err = run_cmd(argparse_app, "speak 'This is a' -s test of the emergency broadcast system!")
out, _err = run_cmd(argparse_app, "speak 'This is a' -s test of the emergency broadcast system!")
assert out == ['THIS IS A TEST OF THE EMERGENCY BROADCAST SYSTEM!']


def test_argparser_and_unknown_args_kwargs(argparse_app, capsys) -> None:
"""Test with_argparser wrapper passing through kwargs to command function"""
argparse_app.do_speak('', keyword_arg="foo")
out, err = capsys.readouterr()
out, _err = capsys.readouterr()
assert out == "foo\n"


def test_argparse_quoted_arguments_multiple(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'say "hello there" "rick & morty"')
out, _err = run_cmd(argparse_app, 'say "hello there" "rick & morty"')
assert out == ['hello there rick & morty']


def test_argparse_help_docstring(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'help say')
out, _err = run_cmd(argparse_app, 'help say')
assert out[0].startswith('Usage: say')
assert out[1] == ''
assert out[2] == 'Repeat what you tell me to.'
Expand All @@ -216,32 +216,32 @@ def test_argparse_help_docstring(argparse_app) -> None:


def test_argparse_help_description(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'help tag')
out, _err = run_cmd(argparse_app, 'help tag')
assert out[0].startswith('Usage: tag')
assert out[1] == ''
assert out[2] == 'create a html tag'


def test_argparse_prog(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'help tag')
out, _err = run_cmd(argparse_app, 'help tag')
progname = out[0].split(' ')[1]
assert progname == 'tag'


def test_arglist(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'arglist "we should" get these')
out, _err = run_cmd(argparse_app, 'arglist "we should" get these')
assert out[0] == 'True'


def test_arglist_kwargs(argparse_app, capsys) -> None:
"""Test with_argument_list wrapper passes through kwargs to command function"""
argparse_app.do_arglist('arg', keyword_arg="foo")
out, err = capsys.readouterr()
out, _err = capsys.readouterr()
assert out == "foo\n"


def test_preservelist(argparse_app) -> None:
out, err = run_cmd(argparse_app, 'preservelist foo "bar baz"')
out, _err = run_cmd(argparse_app, 'preservelist foo "bar baz"')
assert out[0] == "['foo', '\"bar baz\"']"


Expand Down Expand Up @@ -332,70 +332,70 @@ def subcommand_app():


def test_subcommand_foo(subcommand_app) -> None:
out, err = run_cmd(subcommand_app, 'base foo -x2 5.0')
out, _err = run_cmd(subcommand_app, 'base foo -x2 5.0')
assert out == ['10.0']


def test_subcommand_bar(subcommand_app) -> None:
out, err = run_cmd(subcommand_app, 'base bar baz')
out, _err = run_cmd(subcommand_app, 'base bar baz')
assert out == ['((baz))']


def test_subcommand_invalid(subcommand_app) -> None:
out, err = run_cmd(subcommand_app, 'base baz')
_out, err = run_cmd(subcommand_app, 'base baz')
assert err[0].startswith('Usage: base')
assert err[1].startswith("Error: argument SUBCOMMAND: invalid choice: 'baz'")


def test_subcommand_base_help(subcommand_app) -> None:
out, err = run_cmd(subcommand_app, 'help base')
out, _err = run_cmd(subcommand_app, 'help base')
assert out[0].startswith('Usage: base')
assert out[1] == ''
assert out[2] == 'Base command help'


def test_subcommand_help(subcommand_app) -> None:
# foo has no aliases
out, err = run_cmd(subcommand_app, 'help base foo')
out, _err = run_cmd(subcommand_app, 'help base foo')
assert out[0].startswith('Usage: base foo')
assert out[1] == ''
assert out[2] == 'Positional Arguments:'

# bar has aliases (usage should never show alias name)
out, err = run_cmd(subcommand_app, 'help base bar')
out, _err = run_cmd(subcommand_app, 'help base bar')
assert out[0].startswith('Usage: base bar')
assert out[1] == ''
assert out[2] == 'Positional Arguments:'

out, err = run_cmd(subcommand_app, 'help base bar_1')
out, _err = run_cmd(subcommand_app, 'help base bar_1')
assert out[0].startswith('Usage: base bar')
assert out[1] == ''
assert out[2] == 'Positional Arguments:'

out, err = run_cmd(subcommand_app, 'help base bar_2')
out, _err = run_cmd(subcommand_app, 'help base bar_2')
assert out[0].startswith('Usage: base bar')
assert out[1] == ''
assert out[2] == 'Positional Arguments:'

# helpless has aliases and no help text (usage should never show alias name)
out, err = run_cmd(subcommand_app, 'help base helpless')
out, _err = run_cmd(subcommand_app, 'help base helpless')
assert out[0].startswith('Usage: base helpless')
assert out[1] == ''
assert out[2] == 'Positional Arguments:'

out, err = run_cmd(subcommand_app, 'help base helpless_1')
out, _err = run_cmd(subcommand_app, 'help base helpless_1')
assert out[0].startswith('Usage: base helpless')
assert out[1] == ''
assert out[2] == 'Positional Arguments:'

out, err = run_cmd(subcommand_app, 'help base helpless_2')
out, _err = run_cmd(subcommand_app, 'help base helpless_2')
assert out[0].startswith('Usage: base helpless')
assert out[1] == ''
assert out[2] == 'Positional Arguments:'


def test_subcommand_invalid_help(subcommand_app) -> None:
out, err = run_cmd(subcommand_app, 'help base baz')
out, _err = run_cmd(subcommand_app, 'help base baz')
assert out[0].startswith('Usage: base')


Expand Down
18 changes: 9 additions & 9 deletions tests/test_argparse_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,16 +348,16 @@ def ac_app():

@pytest.mark.parametrize('command', ['music', 'music create', 'music create rock', 'music create jazz'])
def test_help(ac_app, command) -> None:
out1, err1 = run_cmd(ac_app, f'{command} -h')
out2, err2 = run_cmd(ac_app, f'help {command}')
out1, _err1 = run_cmd(ac_app, f'{command} -h')
out2, _err2 = run_cmd(ac_app, f'help {command}')
assert out1 == out2


def test_bad_subcommand_help(ac_app) -> None:
# These should give the same output because the second one isn't using a
# real subcommand, so help will be called on the music command instead.
out1, err1 = run_cmd(ac_app, 'help music')
out2, err2 = run_cmd(ac_app, 'help music fake')
out1, _err1 = run_cmd(ac_app, 'help music')
out2, _err2 = run_cmd(ac_app, 'help music fake')
assert out1 == out2


Expand Down Expand Up @@ -907,7 +907,7 @@ def test_unfinished_flag_error(ac_app, command_and_args, text, is_error, capsys)

complete_tester(text, line, begidx, endidx, ac_app)

out, err = capsys.readouterr()
out, _err = capsys.readouterr()
assert is_error == all(x in out for x in ["Error: argument", "expected"])


Expand Down Expand Up @@ -1016,7 +1016,7 @@ def test_autocomp_hint(ac_app, command_and_args, text, has_hint, capsys) -> None
begidx = endidx - len(text)

complete_tester(text, line, begidx, endidx, ac_app)
out, err = capsys.readouterr()
out, _err = capsys.readouterr()
if has_hint:
assert "Hint:\n" in out
else:
Expand All @@ -1030,7 +1030,7 @@ def test_autocomp_hint_no_help_text(ac_app, capsys) -> None:
begidx = endidx - len(text)

first_match = complete_tester(text, line, begidx, endidx, ac_app)
out, err = capsys.readouterr()
out, _err = capsys.readouterr()

assert first_match is None
assert out != '''\nHint:\n NO_HELP_POS\n\n'''
Expand All @@ -1051,7 +1051,7 @@ def test_completion_error(ac_app, capsys, args, text) -> None:
begidx = endidx - len(text)

first_match = complete_tester(text, line, begidx, endidx, ac_app)
out, err = capsys.readouterr()
out, _err = capsys.readouterr()

assert first_match is None
assert f"{text} broke something" in out
Expand Down Expand Up @@ -1113,7 +1113,7 @@ def test_complete_mutex_group(ac_app, command_and_args, text, output_contains, f

assert first_match == complete_tester(text, line, begidx, endidx, ac_app)

out, err = capsys.readouterr()
out, _err = capsys.readouterr()
assert output_contains in out


Expand Down
18 changes: 9 additions & 9 deletions tests/test_argparse_custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,30 +87,30 @@ def test_apcustom_usage() -> None:


def test_apcustom_nargs_help_format(cust_app) -> None:
out, err = run_cmd(cust_app, 'help range')
out, _err = run_cmd(cust_app, 'help range')
assert 'Usage: range [-h] [--arg0 ARG0] [--arg1 ARG1{2}] [--arg2 ARG2{3+}]' in out[0]
assert ' [--arg3 ARG3{2..3}] [--arg4 [ARG4 [...]]] [--arg5 ARG5 [...]]' in out[1]


def test_apcustom_nargs_range_validation(cust_app) -> None:
# nargs = (3,) # noqa: ERA001
out, err = run_cmd(cust_app, 'range --arg2 one two')
_out, err = run_cmd(cust_app, 'range --arg2 one two')
assert 'Error: argument --arg2: expected at least 3 arguments' in err[2]

out, err = run_cmd(cust_app, 'range --arg2 one two three')
_out, err = run_cmd(cust_app, 'range --arg2 one two three')
assert not err

out, err = run_cmd(cust_app, 'range --arg2 one two three four')
_out, err = run_cmd(cust_app, 'range --arg2 one two three four')
assert not err

# nargs = (2,3) # noqa: ERA001
out, err = run_cmd(cust_app, 'range --arg3 one')
_out, err = run_cmd(cust_app, 'range --arg3 one')
assert 'Error: argument --arg3: expected 2 to 3 arguments' in err[2]

out, err = run_cmd(cust_app, 'range --arg3 one two')
_out, err = run_cmd(cust_app, 'range --arg3 one two')
assert not err

out, err = run_cmd(cust_app, 'range --arg2 one two three')
_out, err = run_cmd(cust_app, 'range --arg2 one two three')
assert not err


Expand Down Expand Up @@ -284,7 +284,7 @@ def test_completion_items_as_choices(capsys) -> None:
args = parser.parse_args(['3'])

# Confirm error text contains correct value type of str
out, err = capsys.readouterr()
_out, err = capsys.readouterr()
assert "invalid choice: '3' (choose from '1', '2')" in err

##############################################################
Expand All @@ -306,5 +306,5 @@ def test_completion_items_as_choices(capsys) -> None:
args = parser.parse_args(['3'])

# Confirm error text contains correct value type of int
out, err = capsys.readouterr()
_out, err = capsys.readouterr()
assert 'invalid choice: 3 (choose from 1, 2)' in err
Loading
Loading