##// END OF EJS Templates
Merge branch 'newkernel' into qtnewkernel
epatters -
r2895:01ca9ced merge
parent child Browse files
Show More
@@ -0,0 +1,140 b''
1 #!/usr/bin/env python
2 # coding: utf-8
3 """
4 Support for creating GUI apps and starting event loops.
5
6 IPython's GUI integration allows interative plotting and GUI usage in IPython
7 session. IPython has two different types of GUI integration:
8
9 1. The terminal based IPython supports GUI event loops through Python's
10 PyOS_InputHook. PyOS_InputHook is a hook that Python calls periodically
11 whenever raw_input is waiting for a user to type code. We implement GUI
12 support in the terminal by setting PyOS_InputHook to a function that
13 iterates the event loop for a short while. It is important to note that
14 in this situation, the real GUI event loop is NOT run in the normal
15 manner, so you can't use the normal means to detect that it is running.
16 2. In the two process IPython kernel/frontend, the GUI event loop is run in
17 the kernel. In this case, the event loop is run in the normal manner by
18 calling the function or method of the GUI toolkit that starts the event
19 loop.
20
21 In addition to starting the GUI event loops in one of these two ways, IPython
22 will *always* create an appropriate GUI application object when GUi
23 integration is enabled.
24
25 If you want your GUI apps to run in IPython you need to do two things:
26
27 1. Test to see if there is already an existing main application object. If
28 there is, you should use it. If there is not an existing application object
29 you should create one.
30 2. Test to see if the GUI event loop is running. If it is, you should not
31 start it. If the event loop is not running you may start it.
32
33 This module contains functions for each toolkit that perform these things
34 in a consistent manner. Because of how PyOS_InputHook runs the event loop
35 you cannot detect if the event loop is running using the traditional calls
36 (such as ``wx.GetApp.IsMainLoopRunning()`` in wxPython). If PyOS_InputHook is
37 set These methods will return a false negative. That is, they will say the
38 event loop is not running, when is actually is. To work around this limitation
39 we proposed the following informal protocol:
40
41 * Whenever someone starts the event loop, they *must* set the ``_in_event_loop``
42 attribute of the main application object to ``True``. This should be done
43 regardless of how the event loop is actually run.
44 * Whenever someone stops the event loop, they *must* set the ``_in_event_loop``
45 attribute of the main application object to ``False``.
46 * If you want to see if the event loop is running, you *must* use ``hasattr``
47 to see if ``_in_event_loop`` attribute has been set. If it is set, you
48 *must* use its value. If it has not been set, you can query the toolkit
49 in the normal manner.
50
51 The functions below implement this logic for each GUI toolkit. If you need
52 to create custom application subclasses, you will likely have to modify this
53 code for your own purposes. This code can be copied into your own project
54 so you don't have to depend on IPython.
55
56 """
57
58 #-----------------------------------------------------------------------------
59 # Copyright (C) 2008-2010 The IPython Development Team
60 #
61 # Distributed under the terms of the BSD License. The full license is in
62 # the file COPYING, distributed as part of this software.
63 #-----------------------------------------------------------------------------
64
65 #-----------------------------------------------------------------------------
66 # Imports
67 #-----------------------------------------------------------------------------
68
69 #-----------------------------------------------------------------------------
70 # wx
71 #-----------------------------------------------------------------------------
72
73 def get_app_wx(*args, **kwargs):
74 """Create a new wx app or return an exiting one."""
75 import wx
76 app = wx.GetApp()
77 if app is None:
78 app = wx.PySimpleApp(*args, **kwargs)
79 return app
80
81 def is_event_loop_running_wx(app=None):
82 """Is the wx event loop running."""
83 if app is None:
84 app = get_app_wx()
85 if hasattr(app, '_in_event_loop'):
86 return app._in_event_loop
87 else:
88 return app.IsMainLoopRunning()
89
90 def start_event_loop_wx(app=None):
91 """Start the wx event loop in a consistent manner."""
92 if app is None:
93 app = get_app_wx()
94 if not is_event_loop_running_wx(app):
95 app._in_event_loop = True
96 app.MainLoop()
97 app._in_event_loop = False
98 else:
99 app._in_event_loop = True
100
101 #-----------------------------------------------------------------------------
102 # qt4
103 #-----------------------------------------------------------------------------
104
105 def get_app_qt4(*args, **kwargs):
106 """Create a new qt4 app or return an existing one."""
107 from PyQt4 import QtGui
108 app = QtGui.QApplication.instance()
109 if app is None:
110 app = QtGui.QApplication(*args, **kwargs)
111 return app
112
113 def is_event_loop_running_qt4(app=None):
114 """Is the qt4 event loop running."""
115 if app is None:
116 app = get_app_qt4()
117 if hasattr(app, '_in_event_loop'):
118 return app._in_event_loop
119 else:
120 # Does qt4 provide a other way to detect this?
121 return False
122
123 def start_event_loop_qt4(app=None):
124 """Start the qt4 event loop in a consistent manner."""
125 if app is None:
126 app = get_app_qt4()
127 if not is_event_loop_running_qt4(app):
128 app._in_event_loop = True
129 app.exec_()
130 app._in_event_loop = False
131 else:
132 app._in_event_loop = True
133
134 #-----------------------------------------------------------------------------
135 # Tk
136 #-----------------------------------------------------------------------------
137
138 #-----------------------------------------------------------------------------
139 # gtk
140 #-----------------------------------------------------------------------------
@@ -1,3 +1,9 b''
1 """Produce SVG versions of active plots for display by the rich Qt frontend.
2 """
3 #-----------------------------------------------------------------------------
4 # Imports
5 #-----------------------------------------------------------------------------
6
1 # Standard library imports
7 # Standard library imports
2 from cStringIO import StringIO
8 from cStringIO import StringIO
3
9
@@ -8,12 +14,14 b' from matplotlib._pylab_helpers import Gcf'
8 # Local imports.
14 # Local imports.
9 from backend_payload import add_plot_payload
15 from backend_payload import add_plot_payload
10
16
17 #-----------------------------------------------------------------------------
18 # Functions
19 #-----------------------------------------------------------------------------
11
20
12 def show():
21 def show():
13 """ Deliver a SVG payload.
22 """ Deliver a SVG payload.
14 """
23 """
15 figure_manager = Gcf.get_active()
24 for figure_manager in Gcf.get_all_fig_managers():
16 if figure_manager is not None:
17 # Make the background transparent.
25 # Make the background transparent.
18 # figure_manager.canvas.figure.patch.set_alpha(0.0)
26 # figure_manager.canvas.figure.patch.set_alpha(0.0)
19 # Set the background to white instead so it looks good on black.
27 # Set the background to white instead so it looks good on black.
@@ -22,6 +30,7 b' def show():'
22 data = svg_from_canvas(figure_manager.canvas)
30 data = svg_from_canvas(figure_manager.canvas)
23 add_plot_payload('svg', data)
31 add_plot_payload('svg', data)
24
32
33
25 def svg_from_canvas(canvas):
34 def svg_from_canvas(canvas):
26 """ Return a string containing the SVG representation of a FigureCanvasSvg.
35 """ Return a string containing the SVG representation of a FigureCanvasSvg.
27 """
36 """
@@ -1,8 +1,29 b''
1 """A ZMQ-based subclass of InteractiveShell.
2
3 This code is meant to ease the refactoring of the base InteractiveShell into
4 something with a cleaner architecture for 2-process use, without actually
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 we subclass and override what we want to fix. Once this is working well, we
7 can go back to the base class and refactor the code for a cleaner inheritance
8 implementation that doesn't rely on so much monkeypatching.
9
10 But this lets us maintain a fully working IPython as we develop the new
11 machinery. This should thus be thought of as scaffolding.
12 """
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
17
18 # Stdlib
1 import inspect
19 import inspect
20 import os
2 import re
21 import re
3 import sys
22 import sys
23
4 from subprocess import Popen, PIPE
24 from subprocess import Popen, PIPE
5
25
26 # Our own
6 from IPython.core.interactiveshell import (
27 from IPython.core.interactiveshell import (
7 InteractiveShell, InteractiveShellABC
28 InteractiveShell, InteractiveShellABC
8 )
29 )
@@ -16,9 +37,16 b' from IPython.zmq.session import extract_header'
16 from IPython.core.payloadpage import install_payload_page
37 from IPython.core.payloadpage import install_payload_page
17 from session import Session
38 from session import Session
18
39
40 #-----------------------------------------------------------------------------
41 # Globals and side-effects
42 #-----------------------------------------------------------------------------
43
19 # Install the payload version of page.
44 # Install the payload version of page.
20 install_payload_page()
45 install_payload_page()
21
46
47 #-----------------------------------------------------------------------------
48 # Functions and classes
49 #-----------------------------------------------------------------------------
22
50
23 class ZMQDisplayHook(DisplayHook):
51 class ZMQDisplayHook(DisplayHook):
24
52
@@ -56,16 +84,23 b' class ZMQInteractiveShell(InteractiveShell):'
56 displayhook_class = Type(ZMQDisplayHook)
84 displayhook_class = Type(ZMQDisplayHook)
57
85
58 def system(self, cmd):
86 def system(self, cmd):
59 cmd = self.var_expand(cmd, depth=2)
87 cmd = self.var_expand(cmd, depth=2).strip()
88
89 # Runnning a bacgkrounded process from within the gui isn't supported
90 # because we do p.wait() at the end. So instead of silently blocking
91 # we simply refuse to run in this mode, to avoid surprising the user.
92 if cmd.endswith('&'):
93 raise OSError("Background processes not supported.")
94
60 sys.stdout.flush()
95 sys.stdout.flush()
61 sys.stderr.flush()
96 sys.stderr.flush()
62 p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
97 p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
63 for line in p.stdout.read().split('\n'):
98 for line in p.stdout.read().split('\n'):
64 if len(line) > 0:
99 if len(line) > 0:
65 print line
100 print(line)
66 for line in p.stderr.read().split('\n'):
101 for line in p.stderr.read().split('\n'):
67 if len(line) > 0:
102 if len(line) > 0:
68 print line
103 print(line, file=sys.stderr)
69 p.wait()
104 p.wait()
70
105
71 def init_io(self):
106 def init_io(self):
@@ -349,7 +384,11 b' class ZMQInteractiveShell(InteractiveShell):'
349
384
350 if use_temp:
385 if use_temp:
351 filename = self.shell.mktempfile(data)
386 filename = self.shell.mktempfile(data)
352 print 'IPython will make a temporary file named:',filename
387 print('IPython will make a temporary file named:', filename)
388
389 # Make sure we send to the client an absolute path, in case the working
390 # directory of client and kernel don't match
391 filename = os.path.abspath(filename)
353
392
354 payload = {
393 payload = {
355 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
394 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
@@ -101,4 +101,4 b' gitwash-update:'
101 cd source/development/gitwash && rename 's/.rst/.txt/' *.rst
101 cd source/development/gitwash && rename 's/.rst/.txt/' *.rst
102
102
103 nightly: dist
103 nightly: dist
104 rsync -avH --delete dist/ ipython:www/doc/nightly No newline at end of file
104 rsync -avH --delete dist/ ipython:www/doc/nightly
@@ -130,15 +130,9 b' Messages on the XREP/XREQ socket'
130 Execute
130 Execute
131 -------
131 -------
132
132
133 The execution request contains a single string, but this may be a multiline
133 This message type is used by frontends to ask the kernel to execute code on
134 string. The kernel is responsible for splitting this into possibly more than
134 behalf of the user, in a namespace reserved to the user's variables (and thus
135 one block and deciding whether to compile these in 'single' or 'exec' mode.
135 separate from the kernel's own internal code and variables).
136 We're still sorting out this policy. The current inputsplitter is capable of
137 splitting the input for blocks that can all be run as 'single', but in the long
138 run it may prove cleaner to only use 'single' mode for truly single-line
139 inputs, and run all multiline input in 'exec' mode. This would preserve the
140 natural behavior of single-line inputs while allowing long cells to behave more
141 likea a script. This design will be refined as we complete the implementation.
142
136
143 Message type: ``execute_request``::
137 Message type: ``execute_request``::
144
138
@@ -148,17 +142,94 b' Message type: ``execute_request``::'
148
142
149 # A boolean flag which, if True, signals the kernel to execute this
143 # A boolean flag which, if True, signals the kernel to execute this
150 # code as quietly as possible. This means that the kernel will compile
144 # code as quietly as possible. This means that the kernel will compile
151 # the code with 'exec' instead of 'single' (so sys.displayhook will not
145 # the code witIPython/core/tests/h 'exec' instead of 'single' (so
152 # fire), and will *not*:
146 # sys.displayhook will not fire), and will *not*:
153 # - broadcast exceptions on the PUB socket
147 # - broadcast exceptions on the PUB socket
154 # - do any logging
148 # - do any logging
155 # - populate any history
149 # - populate any history
150 #
156 # The default is False.
151 # The default is False.
157 'silent' : bool,
152 'silent' : bool,
153
154 # A list of variable names from the user's namespace to be retrieved. What
155 # returns is a JSON string of the variable's repr(), not a python object.
156 'user_variables' : list,
157
158 # Similarly, a dict mapping names to expressions to be evaluated in the
159 # user's dict.
160 'user_expressions' : dict,
158 }
161 }
159
162
160 Upon execution, the kernel *always* sends a reply, with a status code
163 The ``code`` field contains a single string, but this may be a multiline
161 indicating what happened and additional data depending on the outcome.
164 string. The kernel is responsible for splitting this into possibly more than
165 one block and deciding whether to compile these in 'single' or 'exec' mode.
166 We're still sorting out this policy. The current inputsplitter is capable of
167 splitting the input for blocks that can all be run as 'single', but in the long
168 run it may prove cleaner to only use 'single' mode for truly single-line
169 inputs, and run all multiline input in 'exec' mode. This would preserve the
170 natural behavior of single-line inputs while allowing long cells to behave more
171 likea a script. This design will be refined as we complete the implementation.
172
173 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
174 the notion of a prompt string that allowed arbitrary code to be evaluated, and
175 this was put to good use by many in creating prompts that displayed system
176 status, path information, and even more esoteric uses like remote instrument
177 status aqcuired over the network. But now that IPython has a clean separation
178 between the kernel and the clients, the notion of embedding 'prompt'
179 maninpulations into the kernel itself feels awkward. Prompts should be a
180 frontend-side feature, and it should be even possible for different frontends
181 to display different prompts while interacting with the same kernel.
182
183 We have therefore abandoned the idea of a 'prompt string' to be evaluated by
184 the kernel, and instead provide the ability to retrieve from the user's
185 namespace information after the execution of the main ``code``, with two fields
186 of the execution request:
187
188 - ``user_variables``: If only variables from the user's namespace are needed, a
189 list of variable names can be passed and a dict with these names as keys and
190 their :func:`repr()` as values will be returned.
191
192 - ``user_expressions``: For more complex expressions that require function
193 evaluations, a dict can be provided with string keys and arbitrary python
194 expressions as values. The return message will contain also a dict with the
195 same keys and the :func:`repr()` of the evaluated expressions as value.
196
197 With this information, frontends can display any status information they wish
198 in the form that best suits each frontend (a status line, a popup, inline for a
199 terminal, etc).
200
201 .. Note::
202
203 In order to obtain the current execution counter for the purposes of
204 displaying input prompts, frontends simply make an execution request with an
205 empty code string and ``silent=True``.
206
207 Execution semantics
208 Upon completion of the execution request, the kernel *always* sends a
209 reply, with a status code indicating what happened and additional data
210 depending on the outcome.
211
212 The ``code`` field is executed first, and then the ``user_variables`` and
213 ``user_expressions`` are computed. This ensures that any error in the
214 latter don't harm the main code execution.
215
216 Any error in retrieving the ``user_variables`` or evaluating the
217 ``user_expressions`` will result in a simple error message in the return
218 fields of the form::
219
220 [ERROR] ExceptionType: Exception message
221
222 The user can simply send the same variable name or expression for
223 evaluation to see a regular traceback.
224
225 Execution counter (old prompt number)
226 The kernel has a single, monotonically increasing counter of all execution
227 requests that are made with ``silent=False``. This counter is used to
228 populate the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will
229 likely want to display it in some form to the user, which will typically
230 (but not necessarily) be done in the prompts. The value of this counter
231 will be returned as the ``execution_count`` field of all ``execute_reply```
232 messages.
162
233
163 Message type: ``execute_reply``::
234 Message type: ``execute_reply``::
164
235
@@ -166,30 +237,25 b' Message type: ``execute_reply``::'
166 # One of: 'ok' OR 'error' OR 'abort'
237 # One of: 'ok' OR 'error' OR 'abort'
167 'status' : str,
238 'status' : str,
168
239
169 # This has the same structure as the output of a prompt request, but is
240 # The global kernel counter that increases by one with each non-silent
170 # for the client to set up the *next* prompt (with identical limitations
241 # executed request. This will typically be used by clients to display
171 # to a prompt request)
242 # prompt numbers to the user. If the request was a silent one, this will
172 'next_prompt' : {
243 # be the current value of the counter in the kernel.
173 'prompt_string' : str,
244 'execution_count' : int,
174 'prompt_number' : int,
245
175 'input_sep' : str
246 # If the state_template was provided, this will contain the evaluated
176 },
247 # form of the template.
177
248 'state' : str,
178 # The prompt number of the actual execution for this code, which may be
179 # different from the one used when the code was typed, which was the
180 # 'next_prompt' field of the *previous* request. They will differ in the
181 # case where there is more than one client talking simultaneously to a
182 # kernel, since the numbers can go out of sync. GUI clients can use this
183 # to correct the previously written number in-place, terminal ones may
184 # re-print a corrected one if desired.
185 'prompt_number' : int,
186 }
249 }
187
250
188 When status is 'ok', the following extra fields are present::
251 When status is 'ok', the following extra fields are present::
189
252
190 {
253 {
191 # The kernel will often transform the input provided to it. This
254 # The kernel will often transform the input provided to it. If the
192 # contains the transformed code, which is what was actually executed.
255 # '---->' transform had been applied, this is filled, otherwise it's the
256 # empty string. So transformations like magics don't appear here, only
257 # autocall ones.
258
193 'transformed_code' : str,
259 'transformed_code' : str,
194
260
195 # The execution payload is a dict with string keys that may have been
261 # The execution payload is a dict with string keys that may have been
@@ -235,31 +301,65 b" When status is 'error', the following extra fields are present::"
235 When status is 'abort', there are for now no additional data fields. This
301 When status is 'abort', there are for now no additional data fields. This
236 happens when the kernel was interrupted by a signal.
302 happens when the kernel was interrupted by a signal.
237
303
304 Kernel attribute access
305 -----------------------
238
306
239 Prompt
307 While this protocol does not specify full RPC access to arbitrary methods of
240 ------
308 the kernel object, the kernel does allow read (and in some cases write) access
309 to certain attributes.
241
310
242 A simple request for a current prompt string.
311 The policy for which attributes can be read is: any attribute of the kernel, or
312 its sub-objects, that belongs to a :class:`Configurable` object and has been
313 declared at the class-level with Traits validation, is in principle accessible
314 as long as its name does not begin with a leading underscore. The attribute
315 itself will have metadata indicating whether it allows remote read and/or write
316 access. The message spec follows for attribute read and write requests.
243
317
244 Message type: ``prompt_request``::
318 Message type: ``getattr_request``::
245
319
246 content = {}
320 content = {
321 # The (possibly dotted) name of the attribute
322 'name' : str,
323 }
324
325 When a ``getattr_request`` fails, there are two possible error types:
326
327 - AttributeError: this type of error was raised when trying to access the
328 given name by the kernel itself. This means that the attribute likely
329 doesn't exist.
330
331 - AccessError: the attribute exists but its value is not readable remotely.
247
332
248 In the reply, the prompt string comes back with the prompt number placeholder
333
249 *unevaluated*. The message format is:
334 Message type: ``getattr_reply``::
250
335
251 Message type: ``prompt_reply``::
336 content = {
337 # One of ['ok', 'AttributeError', 'AccessError'].
338 'status' : str,
339 # If status is 'ok', a JSON object.
340 'value' : object,
341 }
342
343 Message type: ``setattr_request``::
252
344
253 content = {
345 content = {
254 'prompt_string' : str,
346 # The (possibly dotted) name of the attribute
255 'prompt_number' : int,
347 'name' : str,
256 'input_sep' : str
348
349 # A JSON-encoded object, that will be validated by the Traits
350 # information in the kernel
351 'value' : object,
257 }
352 }
258
353
259 Clients can produce a prompt with ``prompt_string.format(prompt_number)``, but
354 When a ``setattr_request`` fails, there are also two possible error types with
260 they should be aware that the actual prompt number for that input could change
355 similar meanings as those of the ``getattr_request`` case, but for writing.
261 later, in the case where multiple clients are interacting with a single
356
262 kernel.
357 Message type: ``setattr_reply``::
358
359 content = {
360 # One of ['ok', 'AttributeError', 'AccessError'].
361 'status' : str,
362 }
263
363
264
364
265 Object information
365 Object information
@@ -276,12 +376,12 b' Message type: ``object_info_request``::'
276
376
277 content = {
377 content = {
278 # The (possibly dotted) name of the object to be searched in all
378 # The (possibly dotted) name of the object to be searched in all
279 # relevant namespaces
379 # relevant namespaces
280 'name' : str,
380 'name' : str,
281
381
282 # The level of detail desired. The default (0) is equivalent to typing
382 # The level of detail desired. The default (0) is equivalent to typing
283 # 'x?' at the prompt, 1 is equivalent to 'x??'.
383 # 'x?' at the prompt, 1 is equivalent to 'x??'.
284 'detail_level' : int,
384 'detail_level' : int,
285 }
385 }
286
386
287 The returned information will be a dictionary with keys very similar to the
387 The returned information will be a dictionary with keys very similar to the
@@ -315,9 +415,29 b' Message type: ``object_info_reply``::'
315 'file' : str,
415 'file' : str,
316
416
317 # For pure Python callable objects, we can reconstruct the object
417 # For pure Python callable objects, we can reconstruct the object
318 # definition line which provides its call signature
418 # definition line which provides its call signature. For convenience this
419 # is returned as a single 'definition' field, but below the raw parts that
420 # compose it are also returned as the argspec field.
319 'definition' : str,
421 'definition' : str,
320
422
423 # The individual parts that together form the definition string. Clients
424 # with rich display capabilities may use this to provide a richer and more
425 # precise representation of the definition line (e.g. by highlighting
426 # arguments based on the user's cursor position). For non-callable
427 # objects, this field is empty.
428 'argspec' : { # The names of all the arguments
429 args : list,
430 # The name of the varargs (*args), if any
431 varargs : str,
432 # The name of the varkw (**kw), if any
433 varkw : str,
434 # The values (as strings) of all default arguments. Note
435 # that these must be matched *in reverse* with the 'args'
436 # list above, since the first positional args have no default
437 # value at all.
438 func_defaults : list,
439 },
440
321 # For instances, provide the constructor signature (the definition of
441 # For instances, provide the constructor signature (the definition of
322 # the __init__ method):
442 # the __init__ method):
323 'init_definition' : str,
443 'init_definition' : str,
@@ -406,6 +526,7 b' Message type: ``history_reply``::'
406 # respectively.
526 # respectively.
407 'history' : dict,
527 'history' : dict,
408 }
528 }
529
409 Messages on the PUB/SUB socket
530 Messages on the PUB/SUB socket
410 ==============================
531 ==============================
411
532
@@ -458,10 +579,10 b' Message type: ``pyout``::'
458 # The data is typically the repr() of the object.
579 # The data is typically the repr() of the object.
459 'data' : str,
580 'data' : str,
460
581
461 # The prompt number for this execution is also provided so that clients
582 # The counter for this execution is also provided so that clients can
462 # can display it, since IPython automatically creates variables called
583 # display it, since IPython automatically creates variables called _N (for
463 # _N (for prompt N).
584 # prompt N).
464 'prompt_number' : int,
585 'execution_count' : int,
465 }
586 }
466
587
467 Python errors
588 Python errors
General Comments 0
You need to be logged in to leave comments. Login now