From 2cdadd69fc74fbc30b1beb83b7c3d2d1eadfae8a Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Fri, 10 Mar 2017 15:32:24 -0500 Subject: [PATCH] Improvements to py command. The following improvements have been made: 1) Can now use "cmd" to run cmd2 do_* commands within a python script before ever entering an interactive Python console 2) Issuing a cmd('quit') within a python script will now really quit the application. 3) Recursively entering an interactive Python session from within an existing one is no longer allowed. --- cmd2.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/cmd2.py b/cmd2.py index 74d44a8b7..e46266258 100755 --- a/cmd2.py +++ b/cmd2.py @@ -595,6 +595,9 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, use_ipython=False self._temp_filename = None self._transcript_files = transcript_files + self._should_quit = False + self._in_py = False + def poutput(self, msg): """Convenient shortcut for self.stdout.write(); adds newline if necessary.""" if msg: @@ -1001,6 +1004,7 @@ def do_eof(self, arg): def do_quit(self, arg): """Exits this application.""" + self._should_quit = True return self._STOP_AND_EXIT def select(self, options, prompt='Your choice? '): @@ -1131,13 +1135,18 @@ def help_shell(self): self.stdout.write("{}\n".format(help_str)) def do_py(self, arg): - ''' + """ py : Executes a Python command. py: Enters interactive Python mode. End with ``Ctrl-D`` (Unix) / ``Ctrl-Z`` (Windows), ``quit()``, '`exit()``. Non-python commands can be issued with ``cmd("your command")``. Run python code from external files with ``run("filename.py")`` - ''' + """ + if self._in_py: + self.perror("Recursively entering interactive Python consoles is not allowed.", traceback_war=False) + return + self._in_py = True + self.pystate['self'] = self arg = arg.parsed.raw[2:].strip() @@ -1148,7 +1157,12 @@ def run(arg): interp.runcode(f.read()) except IOError as e: self.perror(e) + + def onecmd_plus_hooks(arg): + return self.onecmd_plus_hooks(arg + '\n') + self.pystate['run'] = run + self.pystate['cmd'] = onecmd_plus_hooks localvars = (self.locals_in_py and self.pystate) or {} interp = InteractiveConsole(locals=localvars) @@ -1160,12 +1174,9 @@ def run(arg): def quit(): raise EmbeddedConsoleExit - def onecmd_plus_hooks(arg): - return self.onecmd_plus_hooks(arg + '\n') - self.pystate['quit'] = quit self.pystate['exit'] = quit - self.pystate['cmd'] = onecmd_plus_hooks + keepstate = None try: cprt = 'Type "help", "copyright", "credits" or "license" for more information.' @@ -1178,6 +1189,8 @@ def onecmd_plus_hooks(arg): pass if keepstate is not None: keepstate.restore() + self._in_py = False + return self._should_quit # Only include the do_ipy() method if IPython is available on the system if ipython_available: