summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2018-12-13 23:10:51 -0500
committerGitHub <noreply@github.com>2018-12-13 23:10:51 -0500
commitf5935889c98105538dbf2e4f640ad63c94f2b731 (patch)
tree3abd0c1dc367956a0ee2b58db445b58686137097
parent3efb3f14630d007572a5cf1246bdb78ee63be089 (diff)
parent259ca0d04ac5c3a4bd28c2a971f3fd0d4d78513a (diff)
downloadcmd2-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.md2
-rw-r--r--cmd2/cmd2.py2
-rw-r--r--tests/test_cmd2.py28
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')