123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- """ A minimal application using the ZMQ-based terminal IPython frontend.
- This is not a complete console app, as subprocess will not be able to receive
- input, there is no real readline support, among other limitations.
- """
- # Copyright (c) IPython Development Team.
- # Distributed under the terms of the Modified BSD License.
- from __future__ import print_function
- import logging
- import signal
- import sys
- from traitlets import (
- Dict, Any
- )
- from traitlets.config import catch_config_error, boolean_flag
- from jupyter_core.application import JupyterApp, base_aliases, base_flags, NoStart
- from jupyter_client.consoleapp import (
- JupyterConsoleApp, app_aliases, app_flags,
- )
- from jupyter_console.ptshell import ZMQTerminalInteractiveShell
- from jupyter_console import __version__
- #-----------------------------------------------------------------------------
- # Globals
- #-----------------------------------------------------------------------------
- _examples = """
- jupyter console # start the ZMQ-based console
- jupyter console --existing # connect to an existing ipython session
- """
- #-----------------------------------------------------------------------------
- # Flags and Aliases
- #-----------------------------------------------------------------------------
- # copy flags from mixin:
- flags = dict(base_flags)
- # start with mixin frontend flags:
- frontend_flags = dict(app_flags)
- # update full dict with frontend flags:
- flags.update(frontend_flags)
- flags.update(boolean_flag(
- 'simple-prompt', 'ZMQTerminalInteractiveShell.simple_prompt',
- "Force simple minimal prompt using `raw_input`",
- "Use a rich interactive prompt with prompt_toolkit"
- ))
- # copy flags from mixin
- aliases = dict(base_aliases)
- # start with mixin frontend flags
- frontend_aliases = dict(app_aliases)
- # load updated frontend flags into full dict
- aliases.update(frontend_aliases)
- # get flags&aliases into sets, and remove a couple that
- # shouldn't be scrubbed from backend flags:
- frontend_aliases = set(frontend_aliases.keys())
- frontend_flags = set(frontend_flags.keys())
- #-----------------------------------------------------------------------------
- # Classes
- #-----------------------------------------------------------------------------
- class ZMQTerminalIPythonApp(JupyterApp, JupyterConsoleApp):
- name = "jupyter-console"
- version = __version__
- """Start a terminal frontend to the IPython zmq kernel."""
- description = """
- The Jupyter terminal-based Console.
- This launches a Console application inside a terminal.
- The Console supports various extra features beyond the traditional
- single-process Terminal IPython shell, such as connecting to an
- existing ipython session, via:
- jupyter console --existing
- where the previous session could have been created by another ipython
- console, an ipython qtconsole, or by opening an ipython notebook.
- """
- examples = _examples
- classes = [ZMQTerminalInteractiveShell] + JupyterConsoleApp.classes
- flags = Dict(flags)
- aliases = Dict(aliases)
- frontend_aliases = Any(frontend_aliases)
- frontend_flags = Any(frontend_flags)
- subcommands = Dict()
- force_interact = True
- def parse_command_line(self, argv=None):
- super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
- self.build_kernel_argv(self.extra_args)
- def init_shell(self):
- JupyterConsoleApp.initialize(self)
- # relay sigint to kernel
- signal.signal(signal.SIGINT, self.handle_sigint)
- self.shell = ZMQTerminalInteractiveShell.instance(parent=self,
- manager=self.kernel_manager,
- client=self.kernel_client,
- )
- self.shell.own_kernel = not self.existing
- def init_gui_pylab(self):
- # no-op, because we don't want to import matplotlib in the frontend.
- pass
- def handle_sigint(self, *args):
- if self.shell._executing:
- if self.kernel_manager:
- self.kernel_manager.interrupt_kernel()
- else:
- print("ERROR: Cannot interrupt kernels we didn't start.",
- file = sys.stderr)
- else:
- # raise the KeyboardInterrupt if we aren't waiting for execution,
- # so that the interact loop advances, and prompt is redrawn, etc.
- raise KeyboardInterrupt
- @catch_config_error
- def initialize(self, argv=None):
- """Do actions after construct, but before starting the app."""
- super(ZMQTerminalIPythonApp, self).initialize(argv)
- if self._dispatching:
- return
- # create the shell
- self.init_shell()
- # and draw the banner
- self.init_banner()
- def init_banner(self):
- """optionally display the banner"""
- self.shell.show_banner()
- # Make sure there is a space below the banner.
- if self.log_level <= logging.INFO: print()
- def start(self):
- # JupyterApp.start dispatches on NoStart
- super(ZMQTerminalIPythonApp, self).start()
- self.log.debug("Starting the jupyter console mainloop...")
- self.shell.mainloop()
- main = launch_new_instance = ZMQTerminalIPythonApp.launch_instance
- if __name__ == '__main__':
- main()
|