""" 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. Authors: * Min RK * Paul Ivanov """ #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- import signal import sys import time from IPython.frontend.terminal.ipapp import TerminalIPythonApp, frontend_flags as term_flags from IPython.utils.traitlets import ( Dict, List, Unicode, Int, CaselessStrEnum, CBool, Any ) from IPython.utils.warn import warn,error from IPython.zmq.kernelapp import IPKernelApp from IPython.zmq.session import Session, default_secure from IPython.zmq.zmqshell import ZMQInteractiveShell from IPython.frontend.consoleapp import ( IPythonConsoleApp, app_aliases, app_flags, aliases, app_aliases, flags ) from IPython.frontend.terminal.console.interactiveshell import ZMQTerminalInteractiveShell #----------------------------------------------------------------------------- # Globals #----------------------------------------------------------------------------- _examples = """ ipython console # start the ZMQ-based console ipython console --existing # connect to an existing ipython session """ #----------------------------------------------------------------------------- # Flags and Aliases #----------------------------------------------------------------------------- # copy flags from mixin: flags = dict(flags) # start with mixin frontend flags: frontend_flags = dict(app_flags) # add TerminalIPApp flags: frontend_flags.update(term_flags) # disable quick startup, as it won't propagate to the kernel anyway frontend_flags.pop('quick') # update full dict with frontend flags: flags.update(frontend_flags) # copy flags from mixin aliases = dict(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(TerminalIPythonApp, IPythonConsoleApp): name = "ipython-console" """Start a terminal frontend to the IPython zmq kernel.""" description = """ The IPython 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: ipython 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] + IPythonConsoleApp.classes flags = Dict(flags) aliases = Dict(aliases) frontend_aliases = Any(frontend_aliases) frontend_flags = Any(frontend_flags) subcommands = Dict() def parse_command_line(self, argv=None): super(ZMQTerminalIPythonApp, self).parse_command_line(argv) self.build_kernel_argv(argv) def init_shell(self): IPythonConsoleApp.initialize(self) # relay sigint to kernel signal.signal(signal.SIGINT, self.handle_sigint) self.shell = ZMQTerminalInteractiveShell.instance(config=self.config, display_banner=False, profile_dir=self.profile_dir, ipython_dir=self.ipython_dir, kernel_manager=self.kernel_manager) 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.has_kernel: # interrupt already gets passed to subprocess by signal handler. # Only if we prevent that should we need to explicitly call # interrupt_kernel, until which time, this would result in a # double-interrupt: # self.kernel_manager.interrupt_kernel() pass else: self.shell.write_err('\n') error("Cannot interrupt kernels we didn't start.\n") else: # raise the KeyboardInterrupt if we aren't waiting for execution, # so that the interact loop advances, and prompt is redrawn, etc. raise KeyboardInterrupt def init_code(self): # no-op in the frontend, code gets run in the backend pass def launch_new_instance(): """Create and run a full blown IPython instance""" app = ZMQTerminalIPythonApp.instance() app.initialize() app.start() if __name__ == '__main__': launch_new_instance()