summaryrefslogtreecommitdiff
path: root/cmd2/cmd2.py
diff options
context:
space:
mode:
Diffstat (limited to 'cmd2/cmd2.py')
-rw-r--r--cmd2/cmd2.py275
1 files changed, 138 insertions, 137 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index cbb79323..f4dd413d 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -2959,160 +2959,159 @@ class Cmd(cmd.Cmd):
return False
self._in_py = True
- # noinspection PyBroadException
- try:
- # Support the run command even if called prior to invoking an interactive interpreter
- def run(filename: str):
- """Run a Python script file in the interactive console.
-
- :param filename: filename of *.py script file to run
- """
- expanded_filename = os.path.expanduser(filename)
+ # Support the run command even if called prior to invoking an interactive interpreter
+ def py_run(filename: str):
+ """Run a Python script file in the interactive console.
+ :param filename: filename of *.py script file to run
+ """
+ expanded_filename = os.path.expanduser(filename)
- # cmd_echo defaults to False for scripts. The user can always toggle this value in their script.
- bridge.cmd_echo = False
+ # cmd_echo defaults to False for scripts. The user can always toggle this value in their script.
+ bridge.cmd_echo = False
- try:
- with open(expanded_filename) as f:
- interp.runcode(f.read())
- except OSError as ex:
- error_msg = "Error opening script file '{}': {}".format(expanded_filename, ex)
- self.perror(error_msg, traceback_war=False)
+ try:
+ with open(expanded_filename) as f:
+ interp.runcode(f.read())
+ except OSError as ex:
+ error_msg = "Error opening script file '{}': {}".format(expanded_filename, ex)
+ self.perror(error_msg, traceback_war=False)
+
+ def py_quit():
+ """Function callable from the interactive Python console to exit that environment"""
+ raise EmbeddedConsoleExit
+
+ # Set up Python environment
+ bridge = PyscriptBridge(self)
+ self.pystate[self.pyscript_name] = bridge
+ self.pystate['run'] = py_run
+ self.pystate['quit'] = py_quit
+ self.pystate['exit'] = py_quit
+
+ if self.locals_in_py:
+ self.pystate['self'] = self
+ elif 'self' in self.pystate:
+ del self.pystate['self']
+
+ localvars = self.pystate
+ from code import InteractiveConsole
+ interp = InteractiveConsole(locals=localvars)
+ interp.runcode('import sys, os;sys.path.insert(0, os.getcwd())')
+
+ # Check if the user is running a Python statement on the command line
+ if args.command:
+ full_command = args.command
+ if args.remainder:
+ full_command += ' ' + ' '.join(args.remainder)
+
+ # Set cmd_echo to True so PyscriptBridge statements like: py app('help')
+ # run at the command line will print their output.
+ bridge.cmd_echo = True
+
+ # noinspection PyBroadException
+ try:
+ interp.runcode(full_command)
+ except BaseException:
+ pass
- bridge = PyscriptBridge(self)
- self.pystate['run'] = run
- self.pystate[self.pyscript_name] = bridge
+ # If there are no args, then we will open an interactive Python console
+ else:
+ # Set up readline for Python console
+ if rl_type != RlType.NONE:
+ # Save cmd2 history
+ saved_cmd2_history = []
+ for i in range(1, readline.get_current_history_length() + 1):
+ saved_cmd2_history.append(readline.get_history_item(i))
- if self.locals_in_py:
- self.pystate['self'] = self
- elif 'self' in self.pystate:
- del self.pystate['self']
-
- localvars = self.pystate
- from code import InteractiveConsole
- interp = InteractiveConsole(locals=localvars)
- interp.runcode('import sys, os;sys.path.insert(0, os.getcwd())')
-
- # Check if the user is running a Python statement on the command line
- if args.command:
- full_command = args.command
- if args.remainder:
- full_command += ' ' + ' '.join(args.remainder)
-
- # Set cmd_echo to True so PyscriptBridge statements like: py app('help')
- # run at the command line will print their output.
- bridge.cmd_echo = True
- interp.runcode(full_command)
+ readline.clear_history()
- # If there are no args, then we will open an interactive Python console
- else:
- # noinspection PyShadowingBuiltins
- def quit():
- """Function callable from the interactive Python console to exit that environment"""
- raise EmbeddedConsoleExit
+ # Restore py's history
+ for item in self.py_history:
+ readline.add_history(item)
+
+ if self.use_rawinput and self.completekey:
+ # Set up tab completion for the Python console
+ # rlcompleter relies on the default settings of the Python readline module
+ if rl_type == RlType.GNU:
+ old_basic_quotes = ctypes.cast(rl_basic_quote_characters, ctypes.c_void_p).value
+ rl_basic_quote_characters.value = orig_rl_basic_quotes
+
+ if 'gnureadline' in sys.modules:
+ # rlcompleter imports readline by name, so it won't use gnureadline
+ # Force rlcompleter to use gnureadline instead so it has our settings and history
+ saved_readline = None
+ if 'readline' in sys.modules:
+ saved_readline = sys.modules['readline']
+
+ sys.modules['readline'] = sys.modules['gnureadline']
+
+ old_delims = readline.get_completer_delims()
+ readline.set_completer_delims(orig_rl_delims)
+
+ # rlcompleter will not need cmd2's custom display function
+ # This will be restored by cmd2 the next time complete() is called
+ if rl_type == RlType.GNU:
+ readline.set_completion_display_matches_hook(None)
+ elif rl_type == RlType.PYREADLINE:
+ readline.rl.mode._display_completions = self._display_matches_pyreadline
+
+ # Save off the current completer and set a new one in the Python console
+ # Make sure it tab completes from its locals() dictionary
+ old_completer = readline.get_completer()
+ interp.runcode("from rlcompleter import Completer")
+ interp.runcode("import readline")
+ interp.runcode("readline.set_completer(Completer(locals()).complete)")
+
+ # Set up sys module for the Python console
+ self._reset_py_display()
+ keepstate = Statekeeper(sys, ('stdin', 'stdout'))
+ sys.stdout = self.stdout
+ sys.stdin = self.stdin
+
+ cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
+ instructions = ('End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, `exit()`.\n'
+ 'Non-Python commands can be issued with: {}("your command")\n'
+ 'Run Python code from external script files with: run("script.py")'
+ .format(self.pyscript_name))
+
+ # noinspection PyBroadException
+ try:
+ interp.interact(banner="Python {} on {}\n{}\n\n{}\n".
+ format(sys.version, sys.platform, cprt, instructions))
+ except BaseException:
+ pass
- self.pystate['quit'] = quit
- self.pystate['exit'] = quit
+ finally:
+ keepstate.restore()
- # Set up readline for Python console
+ # Set up readline for cmd2
if rl_type != RlType.NONE:
- # Save cmd2 history
- saved_cmd2_history = []
+ # Save py's history
+ self.py_history.clear()
for i in range(1, readline.get_current_history_length() + 1):
- saved_cmd2_history.append(readline.get_history_item(i))
+ self.py_history.append(readline.get_history_item(i))
readline.clear_history()
- # Restore py's history
- for item in self.py_history:
+ # Restore cmd2's history
+ for item in saved_cmd2_history:
readline.add_history(item)
if self.use_rawinput and self.completekey:
- # Set up tab completion for the Python console
- # rlcompleter relies on the default settings of the Python readline module
- if rl_type == RlType.GNU:
- old_basic_quotes = ctypes.cast(rl_basic_quote_characters, ctypes.c_void_p).value
- rl_basic_quote_characters.value = orig_rl_basic_quotes
-
- if 'gnureadline' in sys.modules:
- # rlcompleter imports readline by name, so it won't use gnureadline
- # Force rlcompleter to use gnureadline instead so it has our settings and history
- saved_readline = None
- if 'readline' in sys.modules:
- saved_readline = sys.modules['readline']
-
- sys.modules['readline'] = sys.modules['gnureadline']
-
- old_delims = readline.get_completer_delims()
- readline.set_completer_delims(orig_rl_delims)
+ # Restore cmd2's tab completion settings
+ readline.set_completer(old_completer)
+ readline.set_completer_delims(old_delims)
- # rlcompleter will not need cmd2's custom display function
- # This will be restored by cmd2 the next time complete() is called
if rl_type == RlType.GNU:
- readline.set_completion_display_matches_hook(None)
- elif rl_type == RlType.PYREADLINE:
- readline.rl.mode._display_completions = self._display_matches_pyreadline
-
- # Save off the current completer and set a new one in the Python console
- # Make sure it tab completes from its locals() dictionary
- old_completer = readline.get_completer()
- interp.runcode("from rlcompleter import Completer")
- interp.runcode("import readline")
- interp.runcode("readline.set_completer(Completer(locals()).complete)")
-
- # Set up sys module for the Python console
- self._reset_py_display()
- keepstate = Statekeeper(sys, ('stdin', 'stdout'))
- sys.stdout = self.stdout
- sys.stdin = self.stdin
-
- cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
- instructions = ('End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, `exit()`.\n'
- 'Non-Python commands can be issued with: {}("your command")\n'
- 'Run Python code from external script files with: run("script.py")'
- .format(self.pyscript_name))
-
- try:
- interp.interact(banner="Python {} on {}\n{}\n\n{}\n".
- format(sys.version, sys.platform, cprt, instructions))
- except EmbeddedConsoleExit:
- pass
-
- finally:
- keepstate.restore()
-
- # Set up readline for cmd2
- if rl_type != RlType.NONE:
- # Save py's history
- self.py_history.clear()
- for i in range(1, readline.get_current_history_length() + 1):
- self.py_history.append(readline.get_history_item(i))
+ rl_basic_quote_characters.value = old_basic_quotes
- readline.clear_history()
-
- # Restore cmd2's history
- for item in saved_cmd2_history:
- readline.add_history(item)
-
- if self.use_rawinput and self.completekey:
- # Restore cmd2's tab completion settings
- readline.set_completer(old_completer)
- readline.set_completer_delims(old_delims)
-
- if rl_type == RlType.GNU:
- rl_basic_quote_characters.value = old_basic_quotes
-
- if 'gnureadline' in sys.modules:
- # Restore what the readline module pointed to
- if saved_readline is None:
- del(sys.modules['readline'])
- else:
- sys.modules['readline'] = saved_readline
+ if 'gnureadline' in sys.modules:
+ # Restore what the readline module pointed to
+ if saved_readline is None:
+ del(sys.modules['readline'])
+ else:
+ sys.modules['readline'] = saved_readline
- except Exception:
- pass
- finally:
- self._in_py = False
+ self._in_py = False
return self._should_quit
pyscript_parser = ACArgumentParser()
@@ -3123,7 +3122,7 @@ class Cmd(cmd.Cmd):
ACTION_ARG_CHOICES, ('path_complete',))
@with_argparser(pyscript_parser)
- def do_pyscript(self, args: argparse.Namespace) -> None:
+ def do_pyscript(self, args: argparse.Namespace) -> bool:
"""Run a Python script file inside the console"""
script_path = os.path.expanduser(args.script_path)
@@ -3134,11 +3133,13 @@ class Cmd(cmd.Cmd):
sys.argv = [script_path] + args.script_arguments
# Run the script - use repr formatting to escape things which need to be escaped to prevent issues on Windows
- self.do_py("run({!r})".format(script_path))
+ py_return = self.do_py("run({!r})".format(script_path))
# Restore command line arguments to original state
sys.argv = orig_args
+ return py_return
+
# Only include the do_ipy() method if IPython is available on the system
if ipython_available: # pragma: no cover
@with_argparser(ACArgumentParser())