Skip to content

Commit 328b408

Browse files
authored
Merge pull request #323 from python-cmd2/sigint_handler
Added default sigint handler
2 parents 627360c + 0075c6d commit 328b408

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

cmd2.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import platform
3737
import re
3838
import shlex
39+
import signal
3940
import six
4041
import sys
4142
import tempfile
@@ -1051,7 +1052,7 @@ class Cmd(cmd.Cmd):
10511052
allow_cli_args = True # Should arguments passed on the command-line be processed as commands?
10521053
allow_redirection = True # Should output redirection and pipes be allowed
10531054
default_to_shell = False # Attempt to run unrecognized commands as shell commands
1054-
quit_on_sigint = True # Quit the loop on interrupt instead of just resetting prompt
1055+
quit_on_sigint = False # Quit the loop on interrupt instead of just resetting prompt
10551056
reserved_words = []
10561057

10571058
# Attributes which ARE dynamically settable at runtime
@@ -1480,6 +1481,28 @@ def complete_help(self, text, line, begidx, endidx):
14801481
completions.sort()
14811482
return completions
14821483

1484+
# noinspection PyUnusedLocal
1485+
def sigint_handler(self, signum, frame):
1486+
"""Signal handler for SIGINTs which typically come from Ctrl-C events.
1487+
1488+
If you need custom SIGINT behavior, then override this function.
1489+
1490+
:param signum: int - signal number
1491+
:param frame
1492+
"""
1493+
# Save copy of pipe_proc since it could theoretically change while this is running
1494+
pipe_proc = self.pipe_proc
1495+
if pipe_proc is not None:
1496+
pipe_proc.terminate()
1497+
1498+
# Re-raise a KeyboardInterrupt so other parts of the code can catch it
1499+
raise KeyboardInterrupt("Got a keyboard interrupt")
1500+
1501+
def preloop(self):
1502+
"""Hook method executed once when the cmdloop() method is called."""
1503+
# Register a default SIGINT signal handler for Ctrl+C
1504+
signal.signal(signal.SIGINT, self.sigint_handler)
1505+
14831506
def precmd(self, statement):
14841507
"""Hook method executed just before the command is processed by ``onecmd()`` and after adding it to the history.
14851508

examples/subcommands.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ def complete_base_sport(self, text, line, begidx, endidx):
6363
@with_argparser(base_parser)
6464
def do_base(self, args):
6565
"""Base command help"""
66-
try:
66+
if args.func is not None:
6767
# Call whatever subcommand function was selected
6868
args.func(self, args)
69-
except AttributeError:
70-
# No subcommand was provided, so as called
69+
else:
70+
# No subcommand was provided, so call help
7171
self.do_help('base')
7272

7373
# functools.partialmethod was added in Python 3.4

tests/test_cmd2.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,8 @@ def say_app():
915915
return app
916916

917917
def test_interrupt_quit(say_app):
918+
say_app.quit_on_sigint = True
919+
918920
# Mock out the input call so we don't actually wait for a user's response on stdin
919921
m = mock.MagicMock(name='input')
920922
m.side_effect = ['say hello', KeyboardInterrupt(), 'say goodbye', 'eof']

0 commit comments

Comments
 (0)