ipython_widget.py
158 lines
| 5.7 KiB
| text/x-python
|
PythonLexer
epatters
|
r2630 | # System library imports | ||
from PyQt4 import QtCore, QtGui | ||||
# Local imports | ||||
epatters
|
r2714 | from IPython.core.usage import default_banner | ||
epatters
|
r2627 | from frontend_widget import FrontendWidget | ||
class IPythonWidget(FrontendWidget): | ||||
""" A FrontendWidget for an IPython kernel. | ||||
""" | ||||
epatters
|
r2725 | # The default stylesheet: black text on a white background. | ||
epatters
|
r2715 | default_stylesheet = """ | ||
epatters
|
r2716 | .error { color: red; } | ||
epatters
|
r2715 | .in-prompt { color: navy; } | ||
.in-prompt-number { font-weight: bold; } | ||||
.out-prompt { color: darkred; } | ||||
.out-prompt-number { font-weight: bold; } | ||||
""" | ||||
epatters
|
r2725 | # A dark stylesheet: white text on a black background. | ||
dark_stylesheet = """ | ||||
QPlainTextEdit { background-color: black; color: white } | ||||
QFrame { border: 1px solid grey; } | ||||
.error { color: red; } | ||||
.in-prompt { color: lime; } | ||||
.in-prompt-number { color: lime; font-weight: bold; } | ||||
.out-prompt { color: red; } | ||||
.out-prompt-number { color: red; font-weight: bold; } | ||||
""" | ||||
epatters
|
r2627 | #--------------------------------------------------------------------------- | ||
epatters
|
r2669 | # 'QObject' interface | ||
epatters
|
r2627 | #--------------------------------------------------------------------------- | ||
epatters
|
r2643 | def __init__(self, parent=None): | ||
super(IPythonWidget, self).__init__(parent) | ||||
epatters
|
r2627 | |||
epatters
|
r2715 | # Initialize protected variables. | ||
self._prompt_count = 0 | ||||
# Set a default stylesheet. | ||||
epatters
|
r2728 | self.reset_styling() | ||
epatters
|
r2688 | |||
#--------------------------------------------------------------------------- | ||||
# 'FrontendWidget' interface | ||||
#--------------------------------------------------------------------------- | ||||
def execute_file(self, path, hidden=False): | ||||
""" Reimplemented to use the 'run' magic. | ||||
""" | ||||
self.execute('run %s' % path, hidden=hidden) | ||||
epatters
|
r2627 | |||
#--------------------------------------------------------------------------- | ||||
epatters
|
r2714 | # 'FrontendWidget' protected interface | ||
#--------------------------------------------------------------------------- | ||||
def _get_banner(self): | ||||
epatters
|
r2715 | """ Reimplemented to return IPython's default banner. | ||
epatters
|
r2714 | """ | ||
return default_banner | ||||
epatters
|
r2715 | def _show_interpreter_prompt(self): | ||
""" Reimplemented for IPython-style prompts. | ||||
""" | ||||
self._prompt_count += 1 | ||||
prompt_template = '<span class="in-prompt">%s</span>' | ||||
prompt_body = '<br/>In [<span class="in-prompt-number">%i</span>]: ' | ||||
prompt = (prompt_template % prompt_body) % self._prompt_count | ||||
self._show_prompt(prompt, html=True) | ||||
# Update continuation prompt to reflect (possibly) new prompt length. | ||||
cont_prompt_chars = '...: ' | ||||
space_count = len(self._prompt.lstrip()) - len(cont_prompt_chars) | ||||
cont_prompt_body = ' ' * space_count + cont_prompt_chars | ||||
self._continuation_prompt_html = prompt_template % cont_prompt_body | ||||
#------ Signal handlers ---------------------------------------------------- | ||||
epatters
|
r2716 | def _handle_execute_error(self, reply): | ||
""" Reimplemented for IPython-style traceback formatting. | ||||
""" | ||||
content = reply['content'] | ||||
traceback_lines = content['traceback'][:] | ||||
traceback = ''.join(traceback_lines) | ||||
traceback = traceback.replace(' ', ' ') | ||||
traceback = traceback.replace('\n', '<br/>') | ||||
ename = content['ename'] | ||||
ename_styled = '<span class="error">%s</span>' % ename | ||||
traceback = traceback.replace(ename, ename_styled) | ||||
self.appendHtml(traceback) | ||||
epatters
|
r2715 | def _handle_pyout(self, omsg): | ||
""" Reimplemented for IPython-style "display hook". | ||||
""" | ||||
prompt_template = '<span class="out-prompt">%s</span>' | ||||
prompt_body = 'Out[<span class="out-prompt-number">%i</span>]: ' | ||||
prompt = (prompt_template % prompt_body) % self._prompt_count | ||||
self.appendHtml(prompt) | ||||
self.appendPlainText(omsg['content']['data'] + '\n') | ||||
epatters
|
r2714 | #--------------------------------------------------------------------------- | ||
epatters
|
r2627 | # 'IPythonWidget' interface | ||
#--------------------------------------------------------------------------- | ||||
epatters
|
r2728 | def reset_styling(self): | ||
""" Restores the default IPythonWidget styling. | ||||
epatters
|
r2627 | """ | ||
epatters
|
r2728 | self.set_styling(self.default_stylesheet, syntax_style='default') | ||
#self.set_styling(self.dark_stylesheet, syntax_style='monokai') | ||||
def set_styling(self, stylesheet, syntax_style=None): | ||||
""" Sets the IPythonWidget styling. | ||||
Parameters: | ||||
----------- | ||||
stylesheet : str | ||||
A CSS stylesheet. The stylesheet can contain classes for: | ||||
1. Qt: QPlainTextEdit, QFrame, QWidget, etc | ||||
2. Pygments: .c, .k, .o, etc (see PygmentsHighlighter) | ||||
3. IPython: .error, .in-prompt, .out-prompt, etc. | ||||
syntax_style : str or None [default None] | ||||
If specified, use the Pygments style with given name. Otherwise, | ||||
the stylesheet is queried for Pygments style information. | ||||
epatters
|
r2715 | """ | ||
epatters
|
r2725 | self.setStyleSheet(stylesheet) | ||
epatters
|
r2715 | self.document().setDefaultStyleSheet(stylesheet) | ||
epatters
|
r2728 | if syntax_style is None: | ||
self._highlighter.set_style_sheet(stylesheet) | ||||
else: | ||||
self._highlighter.set_style(syntax_style) | ||||
epatters
|
r2627 | |||
if __name__ == '__main__': | ||||
epatters
|
r2667 | from IPython.frontend.qt.kernelmanager import QtKernelManager | ||
epatters
|
r2641 | |||
epatters
|
r2700 | # Don't let Qt or ZMQ swallow KeyboardInterupts. | ||
import signal | ||||
signal.signal(signal.SIGINT, signal.SIG_DFL) | ||||
epatters
|
r2667 | # Create a KernelManager. | ||
kernel_manager = QtKernelManager() | ||||
kernel_manager.start_kernel() | ||||
Brian Granger
|
r2699 | kernel_manager.start_channels() | ||
epatters
|
r2627 | |||
epatters
|
r2667 | # Launch the application. | ||
epatters
|
r2700 | app = QtGui.QApplication([]) | ||
epatters
|
r2643 | widget = IPythonWidget() | ||
widget.kernel_manager = kernel_manager | ||||
epatters
|
r2627 | widget.setWindowTitle('Python') | ||
widget.resize(640, 480) | ||||
widget.show() | ||||
epatters
|
r2641 | app.exec_() | ||