##// END OF EJS Templates
Fix 1px jumping of cells and menus in Notebook.
Fix 1px jumping of cells and menus in Notebook.

File last commit:

r7291:f4efbc04
r7300:7d83bc04
Show More
qtconsoleapp.py
372 lines | 12.7 KiB | text/x-python | PythonLexer
epatters
Created a proper IPython script from the console frontend demo.
r2801 """ A minimal application using the Qt console-style IPython frontend.
MinRK
code updates per review of PR #454
r4021
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:
* Evan Patterson
* Min RK
* Erik Tollerud
* Fernando Perez
MinRK
Split Qt MainWindow into its own file
r5136 * Bussonnier Matthias
* Thomas Kluyver
Paul Ivanov
refactoring common code out of qtconsole
r5603 * Paul Ivanov
MinRK
code updates per review of PR #454
r4021
epatters
* The SVG payload matplotlib backend now works....
r2758 """
epatters
* Moved shutdown_kernel method from FrontendWidget to KernelManager....
r2961 #-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
MinRK
QtConsole now uses newapp
r3971 # stdlib imports
MinRK
protect kernelapp/qtconsole from invalid connection files...
r4986 import json
MinRK
QtConsole now uses newapp
r3971 import os
import signal
import sys
MinRK
update tabbed qtconsole to use connection files
r5073 import uuid
MinRK
QtConsole now uses newapp
r3971
Mark Wiebe
Fix for issue #1437, unfriendly windows qtconsole error handling
r6168 # If run on Windows, install an exception hook which pops up a
# message box. Pythonw.exe hides the console, so without this
# the application silently fails to load.
#
# We always install this handler, because the expectation is for
# qtconsole to bring up a GUI even if called from the console.
# The old handler is called, so the exception is printed as well.
# If desired, check for pythonw with an additional condition
# (sys.executable.lower().find('pythonw.exe') >= 0).
if os.name == 'nt':
old_excepthook = sys.excepthook
def gui_excepthook(exctype, value, tb):
try:
import ctypes, traceback
MB_ICONERROR = 0x00000010L
title = u'Error starting IPython QtConsole'
msg = u''.join(traceback.format_exception(exctype, value, tb))
ctypes.windll.user32.MessageBoxW(0, msg, title, MB_ICONERROR)
finally:
# Also call the old exception hook to let it do
# its thing too.
old_excepthook(exctype, value, tb)
sys.excepthook = gui_excepthook
MinRK
QtConsole now uses newapp
r3971 # System library imports
MinRK
improve cleanup of connection files...
r5609 from IPython.external.qt import QtCore, QtGui
Evan Patterson
Paved the way for PySide support....
r3304
epatters
* The SVG payload matplotlib backend now works....
r2758 # Local imports
MinRK
catch_config -> catch_config_error
r5214 from IPython.config.application import boolean_flag, catch_config_error
MinRK
move ipcluster create|list to `ipython profile create|list`...
r4024 from IPython.core.application import BaseIPythonApplication
from IPython.core.profiledir import ProfileDir
MinRK
split qtconsole's connection-file search into lib.kernel...
r4972 from IPython.lib.kernel import tunnel_to_kernel, find_connection_file
epatters
Created a proper IPython script from the console frontend demo.
r2801 from IPython.frontend.qt.console.frontend_widget import FrontendWidget
from IPython.frontend.qt.console.ipython_widget import IPythonWidget
from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
MinRK
exposed pygments styles as ipythonqt options
r3170 from IPython.frontend.qt.console import styles
MinRK
Split Qt MainWindow into its own file
r5136 from IPython.frontend.qt.console.mainwindow import MainWindow
epatters
* The SVG payload matplotlib backend now works....
r2758 from IPython.frontend.qt.kernelmanager import QtKernelManager
MinRK
use connection files instead of ports to connect to kernels...
r4958 from IPython.utils.path import filefind
MinRK
py3compat pass on Session.key...
r4967 from IPython.utils.py3compat import str_to_bytes
MinRK
QtConsole now uses newapp
r3971 from IPython.utils.traitlets import (
MinRK
add Integer traitlet...
r5344 Dict, List, Unicode, Integer, CaselessStrEnum, CBool, Any
MinRK
QtConsole now uses newapp
r3971 )
Paul Ivanov
refactoring common code out of qtconsole
r5603 from IPython.zmq.ipkernel import IPKernelApp
MinRK
enable HMAC message signing by default in kernels...
r4962 from IPython.zmq.session import Session, default_secure
MinRK
QtConsole now uses newapp
r3971 from IPython.zmq.zmqshell import ZMQInteractiveShell
Paul Ivanov
zmqterminal now uses the zmq mixin app
r5604
MinRK
rename IPythonMixinConsoleApp to IPythonConsoleApp...
r5618 from IPython.frontend.consoleapp import (
IPythonConsoleApp, app_aliases, app_flags, flags, aliases
Paul Ivanov
refactoring common code out of qtconsole
r5603 )
MinRK
QtConsole now uses newapp
r3971
epatters
* Moved shutdown_kernel method from FrontendWidget to KernelManager....
r2961 #-----------------------------------------------------------------------------
MinRK
Possible fix for GH-169
r3144 # Network Constants
epatters
* Moved shutdown_kernel method from FrontendWidget to KernelManager....
r2961 #-----------------------------------------------------------------------------
MinRK
Possible fix for GH-169
r3144 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
epatters
Added arguments to the Qt console frontend script for connecting to an existing kernel and for specifying an IP and specific ports.
r2823
epatters
* Moved shutdown_kernel method from FrontendWidget to KernelManager....
r2961 #-----------------------------------------------------------------------------
Brian Granger
More work on adding examples to help strings.
r4216 # Globals
#-----------------------------------------------------------------------------
_examples = """
ipython qtconsole # start the qtconsole
ipython qtconsole --pylab=inline # start with pylab in inline plotting mode
"""
#-----------------------------------------------------------------------------
MinRK
QtConsole now uses newapp
r3971 # Aliases and Flags
epatters
* Moved shutdown_kernel method from FrontendWidget to KernelManager....
r2961 #-----------------------------------------------------------------------------
epatters
* The SVG payload matplotlib backend now works....
r2758
MinRK
update flags&aliases for two-process apps...
r5610 # start with copy of flags
flags = dict(flags)
MinRK
command-line pass...
r4247 qt_flags = {
MinRK
remove references to removed pykernel and associated pure flag
r6806 'plain' : ({'IPythonQtConsoleApp' : {'plain' : True}},
MinRK
QtConsole now uses newapp
r3971 "Disable rich text support."),
MinRK
command-line pass...
r4247 }
qt_flags.update(boolean_flag(
MinRK
add confirm_exit option to qtconsole to suppress exit dialog
r3983 'gui-completion', 'ConsoleWidget.gui_completion',
"use a GUI widget for tab completion",
"use plaintext output for completion"
))
MinRK
update flags&aliases for two-process apps...
r5610 # and app_flags from the Console Mixin
qt_flags.update(app_flags)
# add frontend flags to the full set
MinRK
command-line pass...
r4247 flags.update(qt_flags)
MinRK
QtConsole now uses newapp
r3971
MinRK
update flags&aliases for two-process apps...
r5610 # start with copy of front&backend aliases list
aliases = dict(aliases)
MinRK
command-line pass...
r4247 qt_aliases = dict(
MinRK
QtConsole now uses newapp
r3971
style = 'IPythonWidget.syntax_style',
stylesheet = 'IPythonQtConsoleApp.stylesheet',
colors = 'ZMQInteractiveShell.colors',
editor = 'IPythonWidget.editor',
MinRK
fix qtconsole description...
r4222 paging = 'ConsoleWidget.paging',
MinRK
command-line pass...
r4247 )
MinRK
update flags&aliases for two-process apps...
r5610 # and app_aliases from the Console Mixin
qt_aliases.update(app_aliases)
# add frontend aliases to the full set
MinRK
command-line pass...
r4247 aliases.update(qt_aliases)
MinRK
fix qtconsole description...
r4222
MinRK
update flags&aliases for two-process apps...
r5610 # get flags&aliases into sets, and remove a couple that
# shouldn't be scrubbed from backend flags:
qt_aliases = set(qt_aliases.keys())
qt_aliases.remove('colors')
qt_flags = set(qt_flags.keys())
MinRK
Split Qt MainWindow into its own file
r5136 #-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
MinRK
QtConsole now uses newapp
r3971
#-----------------------------------------------------------------------------
# IPythonQtConsole
#-----------------------------------------------------------------------------
Brian Granger
Command line examples added for non-parallel apps.
r4215
MinRK
rename IPythonMixinConsoleApp to IPythonConsoleApp...
r5618 class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):
MinRK
QtConsole now uses newapp
r3971 name = 'ipython-qtconsole'
Matthias BUSSONNIER
reorganise menu...
r5060
MinRK
code updates per review of PR #454
r4021 description = """
The IPython QtConsole.
This launches a Console-style application using Qt. It is not a full
MinRK
fix qtconsole description...
r4222 console, in that launched terminal subprocesses will not be able to accept
input.
The QtConsole supports various extra features beyond the Terminal IPython
shell, such as inline plotting with matplotlib, via:
ipython qtconsole --pylab=inline
MinRK
code updates per review of PR #454
r4021
MinRK
fix qtconsole description...
r4222 as well as saving your session as HTML, and printing the output.
MinRK
code updates per review of PR #454
r4021
"""
Brian Granger
More work on adding examples to help strings.
r4216 examples = _examples
Brian Granger
Command line examples added for non-parallel apps.
r4215
MinRK
add InlineBackend to ConsoleApp class list...
r7291 classes = [IPythonWidget] + IPythonConsoleApp.classes
MinRK
QtConsole now uses newapp
r3971 flags = Dict(flags)
aliases = Dict(aliases)
MinRK
Split swallow_argv into standalone function in lib.kernel...
r5620 frontend_flags = Any(qt_flags)
frontend_aliases = Any(qt_aliases)
Paul Ivanov
refactoring common code out of qtconsole
r5603 kernel_manager_class = QtKernelManager
MinRK
QtConsole now uses newapp
r3971
stylesheet = Unicode('', config=True,
help="path to a custom CSS stylesheet")
MinRK
add confirm_exit option to qtconsole to suppress exit dialog
r3983 plain = CBool(False, config=True,
MinRK
update docs/default config for qtconsole
r3976 help="Use a plaintext widget instead of rich text (plain can't print/save).")
MinRK
QtConsole now uses newapp
r3971
MinRK
remove references to removed pykernel and associated pure flag
r6806 def _plain_changed(self, name, old, new):
kind = 'plain' if new else 'rich'
MinRK
QtConsole now uses newapp
r3971 self.config.ConsoleWidget.kind = kind
MinRK
remove references to removed pykernel and associated pure flag
r6806 if new:
MinRK
QtConsole now uses newapp
r3971 self.widget_factory = IPythonWidget
MinRK
color settings from ipythonqt propagate down to the ZMQInteractiveShell in the Kernel
r3173 else:
MinRK
QtConsole now uses newapp
r3971 self.widget_factory = RichIPythonWidget
# the factory for creating a widget
widget_factory = Any(RichIPythonWidget)
def parse_command_line(self, argv=None):
super(IPythonQtConsoleApp, self).parse_command_line(argv)
MinRK
Split swallow_argv into standalone function in lib.kernel...
r5620 self.build_kernel_argv(argv)
Paul Ivanov
zmqterminal now uses the zmq mixin app
r5604
MinRK
QtConsole now uses newapp
r3971
MinRK
Work on QtConsole Menu...
r5135 def new_frontend_master(self):
""" Create and return new frontend attached to new kernel, launched on localhost.
Matthias BUSSONNIER
fx tab name and already existing kernel before application launch...
r5039 """
MinRK
update tabbed qtconsole to use connection files
r5073 ip = self.ip if self.ip in LOCAL_IPS else LOCALHOST
MinRK
use self.kernel_manager_class in qtconsoleapp
r5849 kernel_manager = self.kernel_manager_class(
MinRK
update tabbed qtconsole to use connection files
r5073 ip=ip,
connection_file=self._new_connection_file(),
config=self.config,
Matthias BUSSONNIER
tab management new/existing kernel....
r5035 )
# start the kernel
MinRK
remove references to removed pykernel and associated pure flag
r6806 kwargs = dict()
Matthias BUSSONNIER
fx tab name and already existing kernel before application launch...
r5039 kwargs['extra_arguments'] = self.kernel_argv
kernel_manager.start_kernel(**kwargs)
Matthias BUSSONNIER
tab management new/existing kernel....
r5035 kernel_manager.start_channels()
widget = self.widget_factory(config=self.config,
MinRK
update tabbed qtconsole to use connection files
r5073 local_kernel=True)
MinRK
adjust qtconsole color logic...
r6056 self.init_colors(widget)
Matthias BUSSONNIER
tab management new/existing kernel....
r5035 widget.kernel_manager = kernel_manager
MinRK
cleanup some closing logic...
r5138 widget._existing = False
widget._may_close = True
widget._confirm_exit = self.confirm_exit
MinRK
Work on QtConsole Menu...
r5135 return widget
def new_frontend_slave(self, current_widget):
"""Create and return a new frontend attached to an existing kernel.
Parameters
----------
current_widget : IPythonWidget
The IPythonWidget whose kernel this frontend is to share
"""
MinRK
use self.kernel_manager_class in qtconsoleapp
r5849 kernel_manager = self.kernel_manager_class(
MinRK
update tabbed qtconsole to use connection files
r5073 connection_file=current_widget.kernel_manager.connection_file,
config = self.config,
Matthias BUSSONNIER
tab management new/existing kernel....
r5035 )
MinRK
update tabbed qtconsole to use connection files
r5073 kernel_manager.load_connection_file()
Matthias BUSSONNIER
tab management new/existing kernel....
r5035 kernel_manager.start_channels()
widget = self.widget_factory(config=self.config,
MinRK
update tabbed qtconsole to use connection files
r5073 local_kernel=False)
MinRK
adjust qtconsole color logic...
r6056 self.init_colors(widget)
MinRK
cleanup some closing logic...
r5138 widget._existing = True
widget._may_close = False
widget._confirm_exit = False
Matthias BUSSONNIER
tab management new/existing kernel....
r5035 widget.kernel_manager = kernel_manager
MinRK
Work on QtConsole Menu...
r5135 return widget
MinRK
QtConsole now uses newapp
r3971
def init_qt_elements(self):
# Create the widget.
self.app = QtGui.QApplication([])
Matthias BUSSONNIER
remove all binary trace from Icons, use directly SVG
r5053
base_path = os.path.abspath(os.path.dirname(__file__))
icon_path = os.path.join(base_path, 'resources', 'icon', 'IPythonConsole.svg')
Matthias BUSSONNIER
use svg icon also for dialog box....
r5055 self.app.icon = QtGui.QIcon(icon_path)
QtGui.QApplication.setWindowIcon(self.app.icon)
Matthias BUSSONNIER
Add icon to qtconsole app...
r5028
MinRK
QtConsole now uses newapp
r3971 local_kernel = (not self.existing) or self.ip in LOCAL_IPS
self.widget = self.widget_factory(config=self.config,
local_kernel=local_kernel)
MinRK
adjust qtconsole color logic...
r6056 self.init_colors(self.widget)
MinRK
cleanup some closing logic...
r5138 self.widget._existing = self.existing
self.widget._may_close = not self.existing
self.widget._confirm_exit = self.confirm_exit
Matthias BUSSONNIER
Handle all the case of tab closing and clean the code
r5038
MinRK
QtConsole now uses newapp
r3971 self.widget.kernel_manager = self.kernel_manager
MinRK
cleanup some closing logic...
r5138 self.window = MainWindow(self.app,
MinRK
Work on QtConsole Menu...
r5135 confirm_exit=self.confirm_exit,
new_frontend_factory=self.new_frontend_master,
slave_frontend_factory=self.new_frontend_slave,
)
Matthias BUSSONNIER
Handle all the case of tab closing and clean the code
r5038 self.window.log = self.log
Matthias BUSSONNIER
decamelcasify: a few more
r5051 self.window.add_tab_with_frontend(self.widget)
Matthias BUSSONNIER
a few more deCamelCasification
r5052 self.window.init_menu_bar()
Matthias BUSSONNIER
triger menu update when kernel started...
r5393
MinRK
remove references to removed pykernel and associated pure flag
r6806 self.window.setWindowTitle('IPython')
MinRK
QtConsole now uses newapp
r3971
MinRK
adjust qtconsole color logic...
r6056 def init_colors(self, widget):
MinRK
QtConsole now uses newapp
r3971 """Configure the coloring of the widget"""
# Note: This will be dramatically simplified when colors
# are removed from the backend.
# parse the colors arg down to current known labels
try:
colors = self.config.ZMQInteractiveShell.colors
except AttributeError:
colors = None
try:
MinRK
fix typo preventing `ipython qtconsole --style` from having effect
r5127 style = self.config.IPythonWidget.syntax_style
MinRK
QtConsole now uses newapp
r3971 except AttributeError:
style = None
MinRK
adjust qtconsole color logic...
r6056 try:
sheet = self.config.IPythonWidget.style_sheet
except AttributeError:
sheet = None
MinRK
QtConsole now uses newapp
r3971
# find the value for colors:
if colors:
colors=colors.lower()
if colors in ('lightbg', 'light'):
colors='lightbg'
elif colors in ('dark', 'linux'):
colors='linux'
else:
colors='nocolor'
elif style:
if style=='bw':
colors='nocolor'
elif styles.dark_style(style):
colors='linux'
else:
colors='lightbg'
MinRK
color settings from ipythonqt propagate down to the ZMQInteractiveShell in the Kernel
r3173 else:
MinRK
QtConsole now uses newapp
r3971 colors=None
MinRK
adjust qtconsole color logic...
r6056 # Configure the style
MinRK
QtConsole now uses newapp
r3971 if style:
widget.style_sheet = styles.sheet_from_template(style, colors)
widget.syntax_style = style
MinRK
exposed pygments styles as ipythonqt options
r3170 widget._syntax_style_changed()
widget._style_sheet_changed()
MinRK
added --colors flag to ipythonqt
r3171 elif colors:
MinRK
adjust qtconsole color logic...
r6056 # use a default dark/light/bw style
MinRK
added --colors flag to ipythonqt
r3171 widget.set_default_style(colors=colors)
MinRK
exposed pygments styles as ipythonqt options
r3170
MinRK
QtConsole now uses newapp
r3971 if self.stylesheet:
MinRK
adjust qtconsole color logic...
r6056 # we got an explicit stylesheet
MinRK
QtConsole now uses newapp
r3971 if os.path.isfile(self.stylesheet):
with open(self.stylesheet) as f:
MinRK
exposed pygments styles as ipythonqt options
r3170 sheet = f.read()
else:
MinRK
adjust qtconsole color logic...
r6056 raise IOError("Stylesheet %r not found." % self.stylesheet)
if sheet:
widget.style_sheet = sheet
widget._style_sheet_changed()
MinRK
QtConsole now uses newapp
r3971
MinRK
improve cleanup of connection files...
r5609 def init_signal(self):
"""allow clean shutdown on sigint"""
signal.signal(signal.SIGINT, lambda sig, frame: self.exit(-2))
# need a timer, so that QApplication doesn't block until a real
# Qt event fires (can require mouse movement)
# timer trick from http://stackoverflow.com/q/4938723/938949
timer = QtCore.QTimer()
# Let the interpreter run each 200 ms:
timer.timeout.connect(lambda: None)
timer.start(200)
# hold onto ref, so the timer doesn't get cleaned up
self._sigint_timer = timer
MinRK
catch_config -> catch_config_error
r5214 @catch_config_error
MinRK
QtConsole now uses newapp
r3971 def initialize(self, argv=None):
super(IPythonQtConsoleApp, self).initialize(argv)
MinRK
rename IPythonMixinConsoleApp to IPythonConsoleApp...
r5618 IPythonConsoleApp.initialize(self,argv)
MinRK
QtConsole now uses newapp
r3971 self.init_qt_elements()
MinRK
improve cleanup of connection files...
r5609 self.init_signal()
MinRK
QtConsole now uses newapp
r3971
def start(self):
# draw the window
self.window.show()
Matthias BUSSONNIER
put qtconsole forground when launching
r5712 self.window.raise_()
MinRK
exposed pygments styles as ipythonqt options
r3170
MinRK
QtConsole now uses newapp
r3971 # Start the application main loop.
self.app.exec_()
epatters
* Tab completion now uses the correct cursor position....
r2841
MinRK
QtConsole now uses newapp
r3971 #-----------------------------------------------------------------------------
# Main entry point
#-----------------------------------------------------------------------------
def main():
app = IPythonQtConsoleApp()
app.initialize()
app.start()
epatters
* The SVG payload matplotlib backend now works....
r2758
if __name__ == '__main__':
main()