Skip to content

Commit ab1ae68

Browse files
committed
Removed self._should_quit from cmd2 and add logic to PyscriptBridge to return whether a command returned True for stop.
Added stop to CommandResult so pyscripts can now know the return value of a command's do_* function.
1 parent ee699c3 commit ab1ae68

File tree

3 files changed

+19
-15
lines changed

3 files changed

+19
-15
lines changed

cmd2/cmd2.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,6 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, persistent
425425
shortcuts=shortcuts)
426426
self._transcript_files = transcript_files
427427

428-
# Used to enable the ability for a Python script to quit the application
429-
self._should_quit = False
430-
431428
# True if running inside a Python script or interactive console, False otherwise
432429
self._in_py = False
433430

@@ -2836,7 +2833,6 @@ def do_eof(self, _: argparse.Namespace) -> bool:
28362833
@with_argparser(ACArgumentParser())
28372834
def do_quit(self, _: argparse.Namespace) -> bool:
28382835
"""Exit this application"""
2839-
self._should_quit = True
28402836
# Return True to stop the command loop
28412837
return True
28422838

@@ -3053,6 +3049,8 @@ def do_py(self, args: argparse.Namespace) -> bool:
30533049
self.perror(err, traceback_war=False)
30543050
return False
30553051

3052+
bridge = PyscriptBridge(self)
3053+
30563054
try:
30573055
self._in_py = True
30583056

@@ -3078,7 +3076,6 @@ def py_quit():
30783076
raise EmbeddedConsoleExit
30793077

30803078
# Set up Python environment
3081-
bridge = PyscriptBridge(self)
30823079
self.pystate[self.pyscript_name] = bridge
30833080
self.pystate['run'] = py_run
30843081
self.pystate['quit'] = py_quit
@@ -3223,7 +3220,7 @@ def py_quit():
32233220
finally:
32243221
self._in_py = False
32253222

3226-
return self._should_quit
3223+
return bridge.stop
32273224

32283225
pyscript_parser = ACArgumentParser()
32293226
setattr(pyscript_parser.add_argument('script_path', help='path to the script file'),

cmd2/pyscript_bridge.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,18 @@
2020
from contextlib import redirect_stdout, redirect_stderr
2121

2222

23-
class CommandResult(namedtuple_with_defaults('CommandResult', ['stdout', 'stderr', 'data'])):
24-
"""Encapsulates the results from a command.
23+
class CommandResult(namedtuple_with_defaults('CommandResult', ['stdout', 'stderr', 'stop', 'data'])):
24+
"""Encapsulates the results from a cmd2 app command
2525
2626
Named tuple attributes
2727
----------------------
28-
stdout: str - Output captured from stdout while this command is executing
29-
stderr: str - Output captured from stderr while this command is executing. None if no error captured.
30-
data - Data returned by the command.
28+
stdout: str - output captured from stdout while this command is executing
29+
stderr: str - output captured from stderr while this command is executing. None if no error captured.
30+
stop: bool - return value of the command's corresponding do_* function
31+
data - possible data populated by the command.
3132
3233
Any combination of these fields can be used when developing a scripting API for a given command.
33-
By default stdout and stderr will be captured for you. If there is additional command specific data,
34+
By default stdout, stderr, and stop will be captured for you. If there is additional command specific data,
3435
then write that to cmd2's _last_result member. That becomes the data member of this tuple.
3536
3637
In some cases, the data member may contain everything needed for a command and storing stdout
@@ -67,6 +68,9 @@ def __init__(self, cmd2_app):
6768
self._cmd2_app = cmd2_app
6869
self.cmd_echo = False
6970

71+
# Tells if any of the commands run via __call__ returned True for stop
72+
self.stop = False
73+
7074
def __dir__(self):
7175
"""Return a custom set of attribute names"""
7276
attributes = []
@@ -95,16 +99,20 @@ def __call__(self, command: str, echo: Optional[bool] = None) -> CommandResult:
9599

96100
self._cmd2_app._last_result = None
97101

102+
stop = False
98103
try:
99104
self._cmd2_app.stdout = copy_cmd_stdout
100105
with redirect_stdout(copy_cmd_stdout):
101106
with redirect_stderr(copy_stderr):
102-
self._cmd2_app.onecmd_plus_hooks(command, pyscript_bridge_call=True)
107+
stop = self._cmd2_app.onecmd_plus_hooks(command, pyscript_bridge_call=True)
103108
finally:
104-
self._cmd2_app.stdout = copy_cmd_stdout.inner_stream
109+
with self._cmd2_app.sigint_protection:
110+
self._cmd2_app.stdout = copy_cmd_stdout.inner_stream
111+
self.stop = stop or self.stop
105112

106113
# Save the output. If stderr is empty, set it to None.
107114
result = CommandResult(stdout=copy_cmd_stdout.getvalue(),
108115
stderr=copy_stderr.getvalue() if copy_stderr.getvalue() else None,
116+
stop=stop,
109117
data=self._cmd2_app._last_result)
110118
return result

tests/test_cmd2.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1949,7 +1949,6 @@ def do_exit(self, arg_list) -> bool:
19491949
self.perror("{} isn't a valid integer exit code".format(arg_list[0]))
19501950
self.exit_code = -1
19511951

1952-
self._should_quit = True
19531952
# Return True to stop the command loop
19541953
return True
19551954

0 commit comments

Comments
 (0)