Repository: python-cmd2/cmd2
Pull request #743 (2019-07-29 22:07:55)

Added more validation to add_argument wrapper
Raising `TypeError` if trying to set choices/completions on argparse action that accepts no arguments


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bf02d7f7..37999bbf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.9.16 (TBD, 2019)
+* Enhancements
+    * Raise `TypeError` if trying to set choices/completions on argparse action that accepts no arguments
+
 ## 0.9.15 (July 24, 2019)
 * Bug Fixes
     * Fixed exception caused by tab completing after an invalid subcommand was entered
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py
index da5410d0..5432314b 100644
--- a/cmd2/argparse_custom.py
+++ b/cmd2/argparse_custom.py
@@ -346,13 +346,17 @@ def _add_argument_wrapper(self, *args,
     new_arg = orig_actions_container_add_argument(self, *args, **kwargs)
 
     # Verify consistent use of arguments
-    choice_params = [new_arg.choices, choices_function, choices_method, completer_function, completer_method]
-    num_set = len(choice_params) - choice_params.count(None)
+    choices_params = [new_arg.choices, choices_function, choices_method, completer_function, completer_method]
+    num_params_set = len(choices_params) - choices_params.count(None)
 
-    if num_set > 1:
-        err_msg = ("Only one of the following may be used in an argparser argument at a time:\n"
+    if num_params_set > 1:
+        err_msg = ("Only one of the following parameters may be used at a time:\n"
                    "choices, choices_function, choices_method, completer_function, completer_method")
         raise (ValueError(err_msg))
+    elif num_params_set > 0 and new_arg.nargs == 0:
+        err_msg = ("None of the following parameters can be used for this type of action:\n"
+                   "choices, choices_function, choices_method, completer_function, completer_method")
+        raise (TypeError(err_msg))
 
     # Set the custom attributes
     setattr(new_arg, ATTR_NARGS_RANGE, nargs_range)


Test patch:
diff --git a/tests/test_argparse_custom.py b/tests/test_argparse_custom.py
index 6c6879c8..f5d45fd1 100644
--- a/tests/test_argparse_custom.py
+++ b/tests/test_argparse_custom.py
@@ -39,7 +39,7 @@ def fake_func():
     pass
 
 
-@pytest.mark.parametrize('args, is_valid', [
+@pytest.mark.parametrize('kwargs, is_valid', [
     ({'choices': []}, True),
     ({'choices_function': fake_func}, True),
     ({'choices_method': fake_func}, True),
@@ -50,14 +50,27 @@ def fake_func():
     ({'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):
+def test_apcustom_choices_params_count(kwargs, is_valid):
     parser = Cmd2ArgumentParser(prog='test')
     try:
-        parser.add_argument('name', **args)
+        parser.add_argument('name', **kwargs)
         assert is_valid
     except ValueError as ex:
         assert not is_valid
-        assert 'Only one of the following may be used' in str(ex)
+        assert 'Only one of the following parameters' in str(ex)
+
+
+@pytest.mark.parametrize('kwargs', [
+    ({'choices_function': fake_func}),
+    ({'choices_method': fake_func}),
+    ({'completer_function': fake_func}),
+    ({'completer_method': fake_func})
+])
+def test_apcustom_no_choices_when_nargs_is_0(kwargs):
+    with pytest.raises(TypeError) as excinfo:
+        parser = Cmd2ArgumentParser(prog='test')
+        parser.add_argument('name', action='store_true', **kwargs)
+    assert 'None of the following parameters can be used' in str(excinfo.value)
 
 
 def test_apcustom_usage():