##// END OF EJS Templates
* Updated FrontendWidget to use BlockBreaker for parsing input...
epatters -
Show More
@@ -1,303 +1,277 b''
1 # Standard library imports
2 from codeop import CommandCompiler
3 from threading import Thread
4 import time
5 import types
6
7 # System library imports
1 # System library imports
8 from pygments.lexers import PythonLexer
2 from pygments.lexers import PythonLexer
9 from PyQt4 import QtCore, QtGui
3 from PyQt4 import QtCore, QtGui
10 import zmq
4 import zmq
11
5
12 # Local imports
6 # Local imports
7 from IPython.core.blockbreaker import BlockBreaker
13 from call_tip_widget import CallTipWidget
8 from call_tip_widget import CallTipWidget
14 from completion_lexer import CompletionLexer
9 from completion_lexer import CompletionLexer
15 from console_widget import HistoryConsoleWidget
10 from console_widget import HistoryConsoleWidget
16 from pygments_highlighter import PygmentsHighlighter
11 from pygments_highlighter import PygmentsHighlighter
17
12
18
13
19 class FrontendHighlighter(PygmentsHighlighter):
14 class FrontendHighlighter(PygmentsHighlighter):
20 """ A Python PygmentsHighlighter that can be turned on and off and which
15 """ A Python PygmentsHighlighter that can be turned on and off and which
21 knows about continuation prompts.
16 knows about continuation prompts.
22 """
17 """
23
18
24 def __init__(self, frontend):
19 def __init__(self, frontend):
25 PygmentsHighlighter.__init__(self, frontend.document(), PythonLexer())
20 PygmentsHighlighter.__init__(self, frontend.document(), PythonLexer())
26 self._current_offset = 0
21 self._current_offset = 0
27 self._frontend = frontend
22 self._frontend = frontend
28 self.highlighting_on = False
23 self.highlighting_on = False
29
24
30 def highlightBlock(self, qstring):
25 def highlightBlock(self, qstring):
31 """ Highlight a block of text. Reimplemented to highlight selectively.
26 """ Highlight a block of text. Reimplemented to highlight selectively.
32 """
27 """
33 if self.highlighting_on:
28 if self.highlighting_on:
34 for prompt in (self._frontend._prompt,
29 for prompt in (self._frontend._prompt,
35 self._frontend.continuation_prompt):
30 self._frontend.continuation_prompt):
36 if qstring.startsWith(prompt):
31 if qstring.startsWith(prompt):
37 qstring.remove(0, len(prompt))
32 qstring.remove(0, len(prompt))
38 self._current_offset = len(prompt)
33 self._current_offset = len(prompt)
39 break
34 break
40 PygmentsHighlighter.highlightBlock(self, qstring)
35 PygmentsHighlighter.highlightBlock(self, qstring)
41
36
42 def setFormat(self, start, count, format):
37 def setFormat(self, start, count, format):
43 """ Reimplemented to avoid highlighting continuation prompts.
38 """ Reimplemented to avoid highlighting continuation prompts.
44 """
39 """
45 start += self._current_offset
40 start += self._current_offset
46 PygmentsHighlighter.setFormat(self, start, count, format)
41 PygmentsHighlighter.setFormat(self, start, count, format)
47
42
48
43
49 class FrontendWidget(HistoryConsoleWidget):
44 class FrontendWidget(HistoryConsoleWidget):
50 """ A Qt frontend for a generic Python kernel.
45 """ A Qt frontend for a generic Python kernel.
51 """
46 """
52
47
53 # Emitted when an 'execute_reply' is received from the kernel.
48 # Emitted when an 'execute_reply' is received from the kernel.
54 executed = QtCore.pyqtSignal(object)
49 executed = QtCore.pyqtSignal(object)
55
50
56 #---------------------------------------------------------------------------
51 #---------------------------------------------------------------------------
57 # 'QWidget' interface
52 # 'QWidget' interface
58 #---------------------------------------------------------------------------
53 #---------------------------------------------------------------------------
59
54
60 def __init__(self, kernel_manager, parent=None):
55 def __init__(self, kernel_manager, parent=None):
61 super(FrontendWidget, self).__init__(parent)
56 super(FrontendWidget, self).__init__(parent)
62
57
58 self._blockbreaker = BlockBreaker()
63 self._call_tip_widget = CallTipWidget(self)
59 self._call_tip_widget = CallTipWidget(self)
64 self._compile = CommandCompiler()
65 self._completion_lexer = CompletionLexer(PythonLexer())
60 self._completion_lexer = CompletionLexer(PythonLexer())
66 self._hidden = True
61 self._hidden = True
67 self._highlighter = FrontendHighlighter(self)
62 self._highlighter = FrontendHighlighter(self)
68 self._kernel_manager = None
63 self._kernel_manager = None
69
64
70 self.continuation_prompt = '... '
65 self.continuation_prompt = '... '
71 self.kernel_manager = kernel_manager
66 self.kernel_manager = kernel_manager
72
67
73 self.document().contentsChange.connect(self._document_contents_change)
68 self.document().contentsChange.connect(self._document_contents_change)
74
69
75 def focusOutEvent(self, event):
70 def focusOutEvent(self, event):
76 """ Reimplemented to hide calltips.
71 """ Reimplemented to hide calltips.
77 """
72 """
78 self._call_tip_widget.hide()
73 self._call_tip_widget.hide()
79 return super(FrontendWidget, self).focusOutEvent(event)
74 return super(FrontendWidget, self).focusOutEvent(event)
80
75
81 def keyPressEvent(self, event):
76 def keyPressEvent(self, event):
82 """ Reimplemented to hide calltips.
77 """ Reimplemented to hide calltips.
83 """
78 """
84 if event.key() == QtCore.Qt.Key_Escape:
79 if event.key() == QtCore.Qt.Key_Escape:
85 self._call_tip_widget.hide()
80 self._call_tip_widget.hide()
86 return super(FrontendWidget, self).keyPressEvent(event)
81 return super(FrontendWidget, self).keyPressEvent(event)
87
82
88 #---------------------------------------------------------------------------
83 #---------------------------------------------------------------------------
89 # 'ConsoleWidget' abstract interface
84 # 'ConsoleWidget' abstract interface
90 #---------------------------------------------------------------------------
85 #---------------------------------------------------------------------------
91
86
92 def _execute(self, interactive):
87 def _execute(self, interactive):
93 """ Called to execute the input buffer. When triggered by an the enter
88 """ Called to execute the input buffer. When triggered by an the enter
94 key press, 'interactive' is True; otherwise, it is False. Returns
89 key press, 'interactive' is True; otherwise, it is False. Returns
95 whether the input buffer was completely processed and a new prompt
90 whether the input buffer was completely processed and a new prompt
96 created.
91 created.
97 """
92 """
98 return self.execute_source(self.input_buffer, interactive=interactive)
93 return self.execute_source(self.input_buffer, interactive=interactive)
99
94
100 def _prompt_started_hook(self):
95 def _prompt_started_hook(self):
101 """ Called immediately after a new prompt is displayed.
96 """ Called immediately after a new prompt is displayed.
102 """
97 """
103 self._highlighter.highlighting_on = True
98 self._highlighter.highlighting_on = True
104
99
105 def _prompt_finished_hook(self):
100 def _prompt_finished_hook(self):
106 """ Called immediately after a prompt is finished, i.e. when some input
101 """ Called immediately after a prompt is finished, i.e. when some input
107 will be processed and a new prompt displayed.
102 will be processed and a new prompt displayed.
108 """
103 """
109 self._highlighter.highlighting_on = False
104 self._highlighter.highlighting_on = False
110
105
111 def _tab_pressed(self):
106 def _tab_pressed(self):
112 """ Called when the tab key is pressed. Returns whether to continue
107 """ Called when the tab key is pressed. Returns whether to continue
113 processing the event.
108 processing the event.
114 """
109 """
115 self._keep_cursor_in_buffer()
110 self._keep_cursor_in_buffer()
116 cursor = self.textCursor()
111 cursor = self.textCursor()
117 if not self._complete():
112 if not self._complete():
118 cursor.insertText(' ')
113 cursor.insertText(' ')
119 return False
114 return False
120
115
121 #---------------------------------------------------------------------------
116 #---------------------------------------------------------------------------
122 # 'FrontendWidget' interface
117 # 'FrontendWidget' interface
123 #---------------------------------------------------------------------------
118 #---------------------------------------------------------------------------
124
119
125 def execute_source(self, source, hidden=False, interactive=False):
120 def execute_source(self, source, hidden=False, interactive=False):
126 """ Execute a string containing Python code. If 'hidden', no output is
121 """ Execute a string containing Python code. If 'hidden', no output is
127 shown. Returns whether the source executed (i.e., returns True only
122 shown. Returns whether the source executed (i.e., returns True only
128 if no more input is necessary).
123 if no more input is necessary).
129 """
124 """
130 # Use CommandCompiler to determine if more input is needed.
125 self._blockbreaker.reset()
131 try:
126 self._blockbreaker.push(source)
132 code = self._compile(source, symbol='single')
127 executed = self._blockbreaker.interactive_block_ready()
133 except (OverflowError, SyntaxError, ValueError):
134 # Just let IPython deal with the syntax error.
135 code = Exception
136
137 # Only execute interactive multiline input if it ends with a blank line
138 lines = source.splitlines()
139 if interactive and len(lines) > 1 and lines[-1].strip() != '':
140 code = None
141
142 executed = code is not None
143 if executed:
128 if executed:
144 self.kernel_manager.xreq_channel.execute(source)
129 self.kernel_manager.xreq_channel.execute(source)
145 self._hidden = hidden
130 self._hidden = hidden
146 else:
131 else:
147 space = 0
148 for char in lines[-1]:
149 if char == '\t':
150 space += 4
151 elif char == ' ':
152 space += 1
153 else:
154 break
155 if source.endswith(':') or source.endswith(':\n'):
156 space += 4
157 self._show_continuation_prompt()
132 self._show_continuation_prompt()
158 self.appendPlainText(' ' * space)
133 self.appendPlainText(' ' * self._blockbreaker.indent_spaces)
159
160 return executed
134 return executed
161
135
162 def execute_file(self, path, hidden=False):
136 def execute_file(self, path, hidden=False):
163 """ Attempts to execute file with 'path'. If 'hidden', no output is
137 """ Attempts to execute file with 'path'. If 'hidden', no output is
164 shown.
138 shown.
165 """
139 """
166 self.execute_source('run %s' % path, hidden=hidden)
140 self.execute_source('run %s' % path, hidden=hidden)
167
141
168 def _get_kernel_manager(self):
142 def _get_kernel_manager(self):
169 """ Returns the current kernel manager.
143 """ Returns the current kernel manager.
170 """
144 """
171 return self._kernel_manager
145 return self._kernel_manager
172
146
173 def _set_kernel_manager(self, kernel_manager):
147 def _set_kernel_manager(self, kernel_manager):
174 """ Sets a new kernel manager, configuring its channels as necessary.
148 """ Sets a new kernel manager, configuring its channels as necessary.
175 """
149 """
176 # Disconnect the old kernel manager.
150 # Disconnect the old kernel manager.
177 if self._kernel_manager is not None:
151 if self._kernel_manager is not None:
178 sub = self._kernel_manager.sub_channel
152 sub = self._kernel_manager.sub_channel
179 xreq = self._kernel_manager.xreq_channel
153 xreq = self._kernel_manager.xreq_channel
180 sub.message_received.disconnect(self._handle_sub)
154 sub.message_received.disconnect(self._handle_sub)
181 xreq.execute_reply.disconnect(self._handle_execute_reply)
155 xreq.execute_reply.disconnect(self._handle_execute_reply)
182 xreq.complete_reply.disconnect(self._handle_complete_reply)
156 xreq.complete_reply.disconnect(self._handle_complete_reply)
183 xreq.object_info_reply.disconnect(self._handle_object_info_reply)
157 xreq.object_info_reply.disconnect(self._handle_object_info_reply)
184
158
185 # Connect the new kernel manager.
159 # Connect the new kernel manager.
186 self._kernel_manager = kernel_manager
160 self._kernel_manager = kernel_manager
187 sub = kernel_manager.sub_channel
161 sub = kernel_manager.sub_channel
188 xreq = kernel_manager.xreq_channel
162 xreq = kernel_manager.xreq_channel
189 sub.message_received.connect(self._handle_sub)
163 sub.message_received.connect(self._handle_sub)
190 xreq.execute_reply.connect(self._handle_execute_reply)
164 xreq.execute_reply.connect(self._handle_execute_reply)
191 xreq.complete_reply.connect(self._handle_complete_reply)
165 xreq.complete_reply.connect(self._handle_complete_reply)
192 xreq.object_info_reply.connect(self._handle_object_info_reply)
166 xreq.object_info_reply.connect(self._handle_object_info_reply)
193
167
194 self._show_prompt('>>> ')
168 self._show_prompt('>>> ')
195
169
196 kernel_manager = property(_get_kernel_manager, _set_kernel_manager)
170 kernel_manager = property(_get_kernel_manager, _set_kernel_manager)
197
171
198 #---------------------------------------------------------------------------
172 #---------------------------------------------------------------------------
199 # 'FrontendWidget' protected interface
173 # 'FrontendWidget' protected interface
200 #---------------------------------------------------------------------------
174 #---------------------------------------------------------------------------
201
175
202 def _call_tip(self):
176 def _call_tip(self):
203 """ Shows a call tip, if appropriate, at the current cursor location.
177 """ Shows a call tip, if appropriate, at the current cursor location.
204 """
178 """
205 # Decide if it makes sense to show a call tip
179 # Decide if it makes sense to show a call tip
206 cursor = self.textCursor()
180 cursor = self.textCursor()
207 cursor.movePosition(QtGui.QTextCursor.Left)
181 cursor.movePosition(QtGui.QTextCursor.Left)
208 document = self.document()
182 document = self.document()
209 if document.characterAt(cursor.position()).toAscii() != '(':
183 if document.characterAt(cursor.position()).toAscii() != '(':
210 return False
184 return False
211 context = self._get_context(cursor)
185 context = self._get_context(cursor)
212 if not context:
186 if not context:
213 return False
187 return False
214
188
215 # Send the metadata request to the kernel
189 # Send the metadata request to the kernel
216 name = '.'.join(context)
190 name = '.'.join(context)
217 self._calltip_id = self.kernel_manager.xreq_channel.object_info(name)
191 self._calltip_id = self.kernel_manager.xreq_channel.object_info(name)
218 self._calltip_pos = self.textCursor().position()
192 self._calltip_pos = self.textCursor().position()
219 return True
193 return True
220
194
221 def _complete(self):
195 def _complete(self):
222 """ Performs completion at the current cursor location.
196 """ Performs completion at the current cursor location.
223 """
197 """
224 # Decide if it makes sense to do completion
198 # Decide if it makes sense to do completion
225 context = self._get_context()
199 context = self._get_context()
226 if not context:
200 if not context:
227 return False
201 return False
228
202
229 # Send the completion request to the kernel
203 # Send the completion request to the kernel
230 text = '.'.join(context)
204 text = '.'.join(context)
231 self._complete_id = self.kernel_manager.xreq_channel.complete(
205 self._complete_id = self.kernel_manager.xreq_channel.complete(
232 text, self.input_buffer_cursor_line, self.input_buffer)
206 text, self.input_buffer_cursor_line, self.input_buffer)
233 self._complete_pos = self.textCursor().position()
207 self._complete_pos = self.textCursor().position()
234 return True
208 return True
235
209
236 def _get_context(self, cursor=None):
210 def _get_context(self, cursor=None):
237 """ Gets the context at the current cursor location.
211 """ Gets the context at the current cursor location.
238 """
212 """
239 if cursor is None:
213 if cursor is None:
240 cursor = self.textCursor()
214 cursor = self.textCursor()
241 cursor.movePosition(QtGui.QTextCursor.StartOfLine,
215 cursor.movePosition(QtGui.QTextCursor.StartOfLine,
242 QtGui.QTextCursor.KeepAnchor)
216 QtGui.QTextCursor.KeepAnchor)
243 text = unicode(cursor.selectedText())
217 text = unicode(cursor.selectedText())
244 return self._completion_lexer.get_context(text)
218 return self._completion_lexer.get_context(text)
245
219
246 #------ Signal handlers ----------------------------------------------------
220 #------ Signal handlers ----------------------------------------------------
247
221
248 def _document_contents_change(self, position, removed, added):
222 def _document_contents_change(self, position, removed, added):
249 """ Called whenever the document's content changes. Display a calltip
223 """ Called whenever the document's content changes. Display a calltip
250 if appropriate.
224 if appropriate.
251 """
225 """
252 # Calculate where the cursor should be *after* the change:
226 # Calculate where the cursor should be *after* the change:
253 position += added
227 position += added
254
228
255 document = self.document()
229 document = self.document()
256 if position == self.textCursor().position():
230 if position == self.textCursor().position():
257 self._call_tip()
231 self._call_tip()
258
232
259 def _handle_sub(self, omsg):
233 def _handle_sub(self, omsg):
260 if not self._hidden:
234 if not self._hidden:
261 handler = getattr(self, '_handle_%s' % omsg['msg_type'], None)
235 handler = getattr(self, '_handle_%s' % omsg['msg_type'], None)
262 if handler is not None:
236 if handler is not None:
263 handler(omsg)
237 handler(omsg)
264
238
265 def _handle_pyout(self, omsg):
239 def _handle_pyout(self, omsg):
266 session = omsg['parent_header']['session']
240 session = omsg['parent_header']['session']
267 if session == self.kernel_manager.session.session:
241 if session == self.kernel_manager.session.session:
268 self.appendPlainText(omsg['content']['data'] + '\n')
242 self.appendPlainText(omsg['content']['data'] + '\n')
269
243
270 def _handle_stream(self, omsg):
244 def _handle_stream(self, omsg):
271 self.appendPlainText(omsg['content']['data'])
245 self.appendPlainText(omsg['content']['data'])
272
246
273 def _handle_execute_reply(self, rep):
247 def _handle_execute_reply(self, rep):
274 # Make sure that all output from the SUB channel has been processed
248 # Make sure that all output from the SUB channel has been processed
275 # before writing a new prompt.
249 # before writing a new prompt.
276 self.kernel_manager.sub_channel.flush()
250 self.kernel_manager.sub_channel.flush()
277
251
278 content = rep['content']
252 content = rep['content']
279 status = content['status']
253 status = content['status']
280 if status == 'error':
254 if status == 'error':
281 self.appendPlainText(content['traceback'][-1])
255 self.appendPlainText(content['traceback'][-1])
282 elif status == 'aborted':
256 elif status == 'aborted':
283 text = "ERROR: ABORTED\n"
257 text = "ERROR: ABORTED\n"
284 self.appendPlainText(text)
258 self.appendPlainText(text)
285 self._hidden = True
259 self._hidden = True
286 self._show_prompt('>>> ')
260 self._show_prompt('>>> ')
287 self.executed.emit(rep)
261 self.executed.emit(rep)
288
262
289 def _handle_complete_reply(self, rep):
263 def _handle_complete_reply(self, rep):
290 cursor = self.textCursor()
264 cursor = self.textCursor()
291 if rep['parent_header']['msg_id'] == self._complete_id and \
265 if rep['parent_header']['msg_id'] == self._complete_id and \
292 cursor.position() == self._complete_pos:
266 cursor.position() == self._complete_pos:
293 text = '.'.join(self._get_context())
267 text = '.'.join(self._get_context())
294 cursor.movePosition(QtGui.QTextCursor.Left, n=len(text))
268 cursor.movePosition(QtGui.QTextCursor.Left, n=len(text))
295 self._complete_with_items(cursor, rep['content']['matches'])
269 self._complete_with_items(cursor, rep['content']['matches'])
296
270
297 def _handle_object_info_reply(self, rep):
271 def _handle_object_info_reply(self, rep):
298 cursor = self.textCursor()
272 cursor = self.textCursor()
299 if rep['parent_header']['msg_id'] == self._calltip_id and \
273 if rep['parent_header']['msg_id'] == self._calltip_id and \
300 cursor.position() == self._calltip_pos:
274 cursor.position() == self._calltip_pos:
301 doc = rep['content']['docstring']
275 doc = rep['content']['docstring']
302 if doc:
276 if doc:
303 self._call_tip_widget.show_tip(doc)
277 self._call_tip_widget.show_tip(doc)
@@ -1,80 +1,83 b''
1 # Local imports.
1 # System library imports
2 from PyQt4 import QtCore, QtGui
3
4 # Local imports
2 from frontend_widget import FrontendWidget
5 from frontend_widget import FrontendWidget
3
6
4
7
5 class IPythonWidget(FrontendWidget):
8 class IPythonWidget(FrontendWidget):
6 """ A FrontendWidget for an IPython kernel.
9 """ A FrontendWidget for an IPython kernel.
7 """
10 """
8
11
9 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
10 # 'FrontendWidget' interface
13 # 'FrontendWidget' interface
11 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
12
15
13 def __init__(self, kernel_manager, parent=None):
16 def __init__(self, kernel_manager, parent=None):
14 super(IPythonWidget, self).__init__(kernel_manager, parent)
17 super(IPythonWidget, self).__init__(kernel_manager, parent)
15
18
16 self._magic_overrides = {}
19 self._magic_overrides = {}
17
20
18 def execute_source(self, source, hidden=False, interactive=False):
21 def execute_source(self, source, hidden=False, interactive=False):
19 """ Reimplemented to override magic commands.
22 """ Reimplemented to override magic commands.
20 """
23 """
21 magic_source = source.strip()
24 magic_source = source.strip()
22 if magic_source.startswith('%'):
25 if magic_source.startswith('%'):
23 magic_source = magic_source[1:]
26 magic_source = magic_source[1:]
24 magic, sep, arguments = magic_source.partition(' ')
27 magic, sep, arguments = magic_source.partition(' ')
25 if not magic:
28 if not magic:
26 magic = magic_source
29 magic = magic_source
27
30
28 callback = self._magic_overrides.get(magic)
31 callback = self._magic_overrides.get(magic)
29 if callback:
32 if callback:
30 output = callback(arguments)
33 output = callback(arguments)
31 if output:
34 if output:
32 self.appendPlainText(output)
35 self.appendPlainText(output)
33 self._show_prompt('>>> ')
36 self._show_prompt('>>> ')
34 return True
37 return True
35 else:
38 else:
36 return super(IPythonWidget, self).execute_source(source, hidden,
39 return super(IPythonWidget, self).execute_source(source, hidden,
37 interactive)
40 interactive)
38
41
39 #---------------------------------------------------------------------------
42 #---------------------------------------------------------------------------
40 # 'IPythonWidget' interface
43 # 'IPythonWidget' interface
41 #---------------------------------------------------------------------------
44 #---------------------------------------------------------------------------
42
45
43 def set_magic_override(self, magic, callback):
46 def set_magic_override(self, magic, callback):
44 """ Overrides an IPython magic command. This magic will be intercepted
47 """ Overrides an IPython magic command. This magic will be intercepted
45 by the frontend rather than passed on to the kernel and 'callback'
48 by the frontend rather than passed on to the kernel and 'callback'
46 will be called with a single argument: a string of argument(s) for
49 will be called with a single argument: a string of argument(s) for
47 the magic. The callback can (optionally) return text to print to the
50 the magic. The callback can (optionally) return text to print to the
48 console.
51 console.
49 """
52 """
50 self._magic_overrides[magic] = callback
53 self._magic_overrides[magic] = callback
51
54
52 def remove_magic_override(self, magic):
55 def remove_magic_override(self, magic):
53 """ Removes the override for the specified magic, if there is one.
56 """ Removes the override for the specified magic, if there is one.
54 """
57 """
55 try:
58 try:
56 del self._magic_overrides[magic]
59 del self._magic_overrides[magic]
57 except KeyError:
60 except KeyError:
58 pass
61 pass
59
62
60
63
61 if __name__ == '__main__':
64 if __name__ == '__main__':
62 import sys
65 import sys
63 from IPython.frontend.qt.kernelmanager import QtKernelManager
66 from IPython.frontend.qt.kernelmanager import QtKernelManager
64
67
65 # Create KernelManager
68 # Create KernelManager
66 xreq_addr = ('127.0.0.1', 5575)
69 xreq_addr = ('127.0.0.1', 5575)
67 sub_addr = ('127.0.0.1', 5576)
70 sub_addr = ('127.0.0.1', 5576)
68 rep_addr = ('127.0.0.1', 5577)
71 rep_addr = ('127.0.0.1', 5577)
69 kernel_manager = QtKernelManager(xreq_addr, sub_addr, rep_addr)
72 kernel_manager = QtKernelManager(xreq_addr, sub_addr, rep_addr)
70 kernel_manager.sub_channel.start()
73 kernel_manager.sub_channel.start()
71 kernel_manager.xreq_channel.start()
74 kernel_manager.xreq_channel.start()
72
75
73 # Launch application
76 # Launch application
74 app = QtGui.QApplication(sys.argv)
77 app = QtGui.QApplication(sys.argv)
75 widget = IPythonWidget(kernel_manager)
78 widget = IPythonWidget(kernel_manager)
76 widget.setWindowTitle('Python')
79 widget.setWindowTitle('Python')
77 widget.resize(640, 480)
80 widget.resize(640, 480)
78 widget.show()
81 widget.show()
79 sys.exit(app.exec_())
82 sys.exit(app.exec_())
80
83
General Comments 0
You need to be logged in to leave comments. Login now