Skip to content

Commit

Permalink
Fixed #36016 -- Prevented traceback when quitting makemigrations with…
Browse files Browse the repository at this point in the history
… Ctrl-C.
  • Loading branch information
Aman Sharma authored and sarahboyce committed Dec 19, 2024
1 parent 3ee4c6a commit f05edb2
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 4 deletions.
12 changes: 9 additions & 3 deletions django/db/migrations/questioner.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,19 @@ def _choice_input(self, question, choices):
for i, choice in enumerate(choices):
self.prompt_output.write(" %s) %s" % (i + 1, choice))
self.prompt_output.write("Select an option: ", ending="")
result = input()
while True:
try:
result = input()
value = int(result)
except ValueError:
pass
except KeyboardInterrupt:
self.prompt_output.write("\nCancelled.")
sys.exit(1)
else:
if 0 < value <= len(choices):
return value
self.prompt_output.write("Please select a valid option: ", ending="")
result = input()

def _ask_default(self, default=""):
"""
Expand All @@ -148,7 +150,11 @@ def _ask_default(self, default=""):
else:
prompt = ">>> "
self.prompt_output.write(prompt, ending="")
code = input()
try:
code = input()
except KeyboardInterrupt:
self.prompt_output.write("\nCancelled.")
sys.exit(1)
if not code and default:
code = default
if not code:
Expand Down
18 changes: 17 additions & 1 deletion tests/migrations/test_questioner.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ def test_questioner_no_default_attribute_error(self, mock_input):

@mock.patch("builtins.input", side_effect=[KeyboardInterrupt()])
def test_questioner_no_default_keyboard_interrupt(self, mock_input):
with self.assertRaises(KeyboardInterrupt):
with self.assertRaises(SystemExit):
self.questioner._ask_default()
self.assertIn("Cancelled.\n", self.prompt.getvalue())

@mock.patch("builtins.input", side_effect=["", "n"])
def test_questioner_no_default_no_user_entry_boolean(self, mock_input):
Expand All @@ -105,3 +106,18 @@ def test_questioner_bad_user_choice(self, mock_input):
expected_msg = f"{question}\n" f" 1) a\n" f" 2) b\n" f" 3) c\n"
self.assertIn(expected_msg, self.prompt.getvalue())
self.assertEqual(value, 1)

@mock.patch("builtins.input", side_effect=[KeyboardInterrupt()])
def test_questioner_no_choice_keyboard_interrupt(self, mock_input):
question = "Make a choice:"
with self.assertRaises(SystemExit):
self.questioner._choice_input(question, choices="abc")
expected_msg = (
f"{question}\n"
f" 1) a\n"
f" 2) b\n"
f" 3) c\n"
f"Select an option: \n"
f"Cancelled.\n"
)
self.assertIn(expected_msg, self.prompt.getvalue())

0 comments on commit f05edb2

Please sign in to comment.