Skip to content

Commit 1cd0a38

Browse files
committed
Added a default signal handler for SIGINT (Ctrl-C)
Added a default signal handler for SIGINT that does the following: - Terminates a pipe process if one exists - Raises a KeyboardInterrupt for other parts othe code to catch Also: - Changed the default value for quit_on_sigint to False - Modified the way the subcommand functions are called in subcommand.py (unrelated to rest of commit)
1 parent 627360c commit 1cd0a38

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-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 within a Python script")
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(signalnum=signal.SIGINT, handler=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

0 commit comments

Comments
 (0)