summaryrefslogtreecommitdiff
path: root/tests/test_argparse_custom.py
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2019-07-15 22:59:54 -0400
committerGitHub <noreply@github.com>2019-07-15 22:59:54 -0400
commit9bbebbd312dbe0331510f39cd6de70f4d9dcefa8 (patch)
treeef224bb15175be33c5fff45cf3b2dcfbb6b04471 /tests/test_argparse_custom.py
parentab3a01517a18582d1bcd35d728482e73ac707b20 (diff)
parent94b424e9c41f99c6eb268c6c97f09e99a8342de8 (diff)
downloadcmd2-git-9bbebbd312dbe0331510f39cd6de70f4d9dcefa8.tar.gz
Merge branch 'master' into migrating_docs
Diffstat (limited to 'tests/test_argparse_custom.py')
-rw-r--r--tests/test_argparse_custom.py219
1 files changed, 219 insertions, 0 deletions
diff --git a/tests/test_argparse_custom.py b/tests/test_argparse_custom.py
new file mode 100644
index 00000000..caf30080
--- /dev/null
+++ b/tests/test_argparse_custom.py
@@ -0,0 +1,219 @@
+# flake8: noqa E302
+"""
+Unit/functional testing for argparse customizations in cmd2
+"""
+import argparse
+
+import pytest
+
+import cmd2
+from cmd2.argparse_custom import generate_range_error, INFINITY
+from .conftest import run_cmd
+
+
+class ApCustomTestApp(cmd2.Cmd):
+ """Test app for cmd2's argparse customization"""
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ range_parser = cmd2.ArgParser()
+ range_parser.add_argument('--arg0', nargs=1)
+ range_parser.add_argument('--arg1', nargs=2)
+ range_parser.add_argument('--arg2', nargs=(3,))
+ range_parser.add_argument('--arg3', nargs=(2, 3))
+ range_parser.add_argument('--arg4', nargs=argparse.ZERO_OR_MORE)
+ range_parser.add_argument('--arg5', nargs=argparse.ONE_OR_MORE)
+
+ @cmd2.with_argparser(range_parser)
+ def do_range(self, _):
+ pass
+
+
+@pytest.fixture
+def cust_app():
+ return ApCustomTestApp()
+
+
+def fake_func():
+ pass
+
+
+@pytest.mark.parametrize('args, is_valid', [
+ ({'choices': []}, True),
+ ({'choices_function': fake_func}, True),
+ ({'choices_method': fake_func}, True),
+ ({'completer_function': fake_func}, True),
+ ({'completer_method': fake_func}, True),
+ ({'choices': [], 'choices_function': fake_func}, False),
+ ({'choices': [], 'choices_method': fake_func}, False),
+ ({'choices_method': fake_func, 'completer_function': fake_func}, False),
+ ({'choices_method': fake_func, 'completer_method': fake_func}, False),
+])
+def test_apcustom_invalid_args(args, is_valid):
+ parser = cmd2.ArgParser(prog='test')
+ try:
+ parser.add_argument('name', **args)
+ assert is_valid
+ except ValueError as ex:
+ assert not is_valid
+ assert 'Only one of the following may be used' in str(ex)
+
+
+def test_apcustom_usage():
+ usage = "A custom usage statement"
+ parser = cmd2.ArgParser(usage=usage)
+ assert usage in parser.format_help()
+
+
+def test_apcustom_nargs_help_format(cust_app):
+ 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):
+ # nargs = (3,)
+ 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')
+ assert not err
+
+ out, err = run_cmd(cust_app, 'range --arg2 one two three four')
+ assert not err
+
+ # nargs = (2,3)
+ 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')
+ assert not err
+
+ out, err = run_cmd(cust_app, 'range --arg2 one two three')
+ assert not err
+
+
+@pytest.mark.parametrize('nargs_tuple', [
+ (),
+ ('f', 5),
+ (5, 'f'),
+ (1, 2, 3),
+])
+def test_apcustom_narg_invalid_tuples(nargs_tuple):
+ with pytest.raises(ValueError) as excinfo:
+ parser = cmd2.ArgParser(prog='test')
+ parser.add_argument('invalid_tuple', nargs=nargs_tuple)
+ assert 'Ranged values for nargs must be a tuple of 1 or 2 integers' in str(excinfo.value)
+
+
+def test_apcustom_narg_tuple_order():
+ with pytest.raises(ValueError) as excinfo:
+ parser = cmd2.ArgParser(prog='test')
+ parser.add_argument('invalid_tuple', nargs=(2, 1))
+ assert 'Invalid nargs range. The first value must be less than the second' in str(excinfo.value)
+
+
+def test_apcustom_narg_tuple_negative():
+ with pytest.raises(ValueError) as excinfo:
+ parser = cmd2.ArgParser(prog='test')
+ parser.add_argument('invalid_tuple', nargs=(-1, 1))
+ assert 'Negative numbers are invalid for nargs range' in str(excinfo.value)
+
+
+# noinspection PyUnresolvedReferences
+def test_apcustom_narg_tuple_zero_base():
+ parser = cmd2.ArgParser(prog='test')
+ arg = parser.add_argument('arg', nargs=(0,))
+ assert arg.nargs == argparse.ZERO_OR_MORE
+ assert arg.nargs_range is None
+ assert "[arg [...]]" in parser.format_help()
+
+ parser = cmd2.ArgParser(prog='test')
+ arg = parser.add_argument('arg', nargs=(0, 1))
+ assert arg.nargs == argparse.OPTIONAL
+ assert arg.nargs_range is None
+ assert "[arg]" in parser.format_help()
+
+ parser = cmd2.ArgParser(prog='test')
+ arg = parser.add_argument('arg', nargs=(0, 3))
+ assert arg.nargs == argparse.ZERO_OR_MORE
+ assert arg.nargs_range == (0, 3)
+ assert "arg{0..3}" in parser.format_help()
+
+
+# noinspection PyUnresolvedReferences
+def test_apcustom_narg_tuple_one_base():
+ parser = cmd2.ArgParser(prog='test')
+ arg = parser.add_argument('arg', nargs=(1,))
+ assert arg.nargs == argparse.ONE_OR_MORE
+ assert arg.nargs_range is None
+ assert "arg [...]" in parser.format_help()
+
+ parser = cmd2.ArgParser(prog='test')
+ arg = parser.add_argument('arg', nargs=(1, 5))
+ assert arg.nargs == argparse.ONE_OR_MORE
+ assert arg.nargs_range == (1, 5)
+ assert "arg{1..5}" in parser.format_help()
+
+
+# noinspection PyUnresolvedReferences
+def test_apcustom_narg_tuple_other_ranges():
+
+ # Test range with no upper bound on max
+ parser = cmd2.ArgParser(prog='test')
+ arg = parser.add_argument('arg', nargs=(2,))
+ assert arg.nargs == argparse.ONE_OR_MORE
+ assert arg.nargs_range == (2, INFINITY)
+
+ # Test finite range
+ parser = cmd2.ArgParser(prog='test')
+ arg = parser.add_argument('arg', nargs=(2, 5))
+ assert arg.nargs == argparse.ONE_OR_MORE
+ assert arg.nargs_range == (2, 5)
+
+
+def test_apcustom_print_message(capsys):
+ import sys
+ test_message = 'The test message'
+
+ # Specify the file
+ parser = cmd2.ArgParser(prog='test')
+ parser._print_message(test_message, file=sys.stdout)
+ out, err = capsys.readouterr()
+ assert test_message in out
+
+ # Make sure file defaults to sys.stderr
+ parser = cmd2.ArgParser(prog='test')
+ parser._print_message(test_message)
+ out, err = capsys.readouterr()
+ assert test_message in err
+
+
+def test_generate_range_error():
+ # max is INFINITY
+ err_str = generate_range_error(1, INFINITY)
+ assert err_str == "expected at least 1 argument"
+
+ err_str = generate_range_error(2, INFINITY)
+ assert err_str == "expected at least 2 arguments"
+
+ # min and max are equal
+ err_str = generate_range_error(1, 1)
+ assert err_str == "expected 1 argument"
+
+ err_str = generate_range_error(2, 2)
+ assert err_str == "expected 2 arguments"
+
+ # min and max are not equal
+ err_str = generate_range_error(0, 1)
+ assert err_str == "expected 0 to 1 argument"
+
+ err_str = generate_range_error(0, 2)
+ assert err_str == "expected 0 to 2 arguments"
+
+
+def test_apcustom_required_options():
+ # Make sure a 'required arguments' section shows when a flag is marked required
+ parser = cmd2.ArgParser(prog='test')
+ parser.add_argument('--required_flag', required=True)
+ assert 'required arguments' in parser.format_help()