diff options
author | Todd Leonhardt <todd.leonhardt@gmail.com> | 2018-12-13 23:10:51 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-13 23:10:51 -0500 |
commit | f5935889c98105538dbf2e4f640ad63c94f2b731 (patch) | |
tree | 3abd0c1dc367956a0ee2b58db445b58686137097 | |
parent | 3efb3f14630d007572a5cf1246bdb78ee63be089 (diff) | |
parent | 259ca0d04ac5c3a4bd28c2a971f3fd0d4d78513a (diff) | |
download | cmd2-git-f5935889c98105538dbf2e4f640ad63c94f2b731.tar.gz |
Merge pull request #612 from python-cmd2/select_zero
Fixed bug in cmd2.Cmd.select() when user enters 0 or negative number
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | cmd2/cmd2.py | 2 | ||||
-rw-r--r-- | tests/test_cmd2.py | 28 |
3 files changed, 30 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a7383541..22fd5046 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ ## 0.9.7 (TBD, 2018) +* Bug Fixes + * Fixed bug when user chooses a zero or negative index when calling ``Cmd.select()`` * Enhancements * **cmdloop** now only attempts to register a custom signal handler for SIGINT if running in the main thread * commands run as a result of ``default_to_shell`` being **True** now run via ``do_shell()`` and are saved diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index a513d0e7..56d74ec8 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -2780,6 +2780,8 @@ class Cmd(cmd.Cmd): try: choice = int(response) + if choice < 1: + raise IndexError result = fulloptions[choice - 1][0] break except (ValueError, IndexError): diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index 57e1e90f..630a8fa0 100644 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -1344,11 +1344,11 @@ def test_select_options(select_app): # And verify the expected output to stdout assert out == expected -def test_select_invalid_option(select_app): +def test_select_invalid_option_too_big(select_app): # Mock out the input call so we don't actually wait for a user's response on stdin m = mock.MagicMock(name='input') # If side_effect is an iterable then each call to the mock will return the next value from the iterable. - m.side_effect = ['3', '1'] # First pass and invalid selection, then pass a valid one + m.side_effect = ['3', '1'] # First pass an invalid selection, then pass a valid one builtins.input = m food = 'fish' @@ -1368,6 +1368,30 @@ def test_select_invalid_option(select_app): # And verify the expected output to stdout assert out == expected +def test_select_invalid_option_too_small(select_app): + # Mock out the input call so we don't actually wait for a user's response on stdin + m = mock.MagicMock(name='input') + # If side_effect is an iterable then each call to the mock will return the next value from the iterable. + m.side_effect = ['0', '1'] # First pass an invalid selection, then pass a valid one + builtins.input = m + + food = 'fish' + out = run_cmd(select_app, "eat {}".format(food)) + expected = normalize(""" + 1. sweet + 2. salty +'0' isn't a valid choice. Pick a number between 1 and 2: +{} with sweet sauce, yum! +""".format(food)) + + # Make sure our mock was called exactly twice with the expected arguments + arg = 'Sauce? ' + calls = [mock.call(arg), mock.call(arg)] + m.assert_has_calls(calls) + + # And verify the expected output to stdout + assert out == expected + def test_select_list_of_strings(select_app): # Mock out the input call so we don't actually wait for a user's response on stdin m = mock.MagicMock(name='input', return_value='2') |