Run an interactive IPython shell. :return: True if running of commands should stop
(self, _: argparse.Namespace)
| 5071 | |
| 5072 | @with_argparser(_build_ipython_parser) |
| 5073 | def do_ipy(self, _: argparse.Namespace) -> bool | None: # pragma: no cover |
| 5074 | """Run an interactive IPython shell. |
| 5075 | |
| 5076 | :return: True if running of commands should stop |
| 5077 | """ |
| 5078 | self.last_result = False |
| 5079 | |
| 5080 | # Detect whether IPython is installed |
| 5081 | try: |
| 5082 | import traitlets.config.loader as traitlets_loader |
| 5083 | |
| 5084 | # Allow users to install ipython from a cmd2 prompt when needed and still have ipy command work |
| 5085 | try: |
| 5086 | _dummy = start_ipython # noqa: F823 |
| 5087 | except NameError: |
| 5088 | from IPython import start_ipython |
| 5089 | |
| 5090 | from IPython.terminal.interactiveshell import TerminalInteractiveShell |
| 5091 | from IPython.terminal.ipapp import TerminalIPythonApp |
| 5092 | except ImportError: |
| 5093 | self.perror("IPython package is not installed") |
| 5094 | return None |
| 5095 | |
| 5096 | from .py_bridge import PyBridge |
| 5097 | |
| 5098 | if self.in_pyscript(): |
| 5099 | self.perror("Recursively entering interactive Python shells is not allowed") |
| 5100 | return None |
| 5101 | |
| 5102 | self.last_result = True |
| 5103 | |
| 5104 | try: |
| 5105 | self._in_py = True |
| 5106 | py_bridge = PyBridge(self) |
| 5107 | |
| 5108 | # Make a copy of self.py_locals for the locals dictionary in the IPython environment we are creating. |
| 5109 | # This is to prevent ipy from editing it. (e.g. locals().clear()). Only make a shallow copy since |
| 5110 | # it's OK for py_locals to contain objects which are editable in ipy. |
| 5111 | local_vars = self.py_locals.copy() |
| 5112 | local_vars[self.py_bridge_name] = py_bridge |
| 5113 | if self.self_in_py: |
| 5114 | local_vars["self"] = self |
| 5115 | |
| 5116 | # Configure IPython |
| 5117 | config = traitlets_loader.Config() |
| 5118 | config.InteractiveShell.banner2 = ( |
| 5119 | "Entering an IPython shell. Type exit, quit, or Ctrl-D to exit.\n" |
| 5120 | f'Run CLI commands with: {self.py_bridge_name}("command ...")\n' |
| 5121 | ) |
| 5122 | |
| 5123 | # Start IPython |
| 5124 | start_ipython(config=config, argv=[], user_ns=local_vars) # type: ignore[no-untyped-call] |
| 5125 | self.poutput("Now exiting IPython shell...") |
| 5126 | |
| 5127 | # The IPython application is a singleton and won't be recreated next time |
| 5128 | # this function runs. That's a problem since the contents of local_vars |
| 5129 | # may need to be changed. Therefore, we must destroy all instances of the |
| 5130 | # relevant classes. |
nothing calls this directly
no test coverage detected