##// END OF EJS Templates
Merge branch 'newkernel' into upstream-newkernel...
Brian Granger -
r2873:087388fb merge
parent child Browse files
Show More
@@ -194,8 +194,8 b' class InteractiveShell(Configurable, Magic):'
194 # TODO: this part of prompt management should be moved to the frontends.
194 # TODO: this part of prompt management should be moved to the frontends.
195 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
195 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
196 separate_in = SeparateStr('\n', config=True)
196 separate_in = SeparateStr('\n', config=True)
197 separate_out = SeparateStr('\n', config=True)
197 separate_out = SeparateStr('', config=True)
198 separate_out2 = SeparateStr('\n', config=True)
198 separate_out2 = SeparateStr('', config=True)
199 system_header = Str('IPython system call: ', config=True)
199 system_header = Str('IPython system call: ', config=True)
200 system_verbose = CBool(False, config=True)
200 system_verbose = CBool(False, config=True)
201 wildcards_case_sensitive = CBool(True, config=True)
201 wildcards_case_sensitive = CBool(True, config=True)
@@ -604,7 +604,7 b' class ListTB(TBTools):'
604 return ListTB.structured_traceback(self, etype, value, [])
604 return ListTB.structured_traceback(self, etype, value, [])
605
605
606
606
607 def show_exception_only(self, etype, value):
607 def show_exception_only(self, etype, evalue):
608 """Only print the exception type and message, without a traceback.
608 """Only print the exception type and message, without a traceback.
609
609
610 Parameters
610 Parameters
@@ -5,7 +5,6 b' import sys'
5 # System library imports
5 # System library imports
6 from pygments.lexers import PythonLexer
6 from pygments.lexers import PythonLexer
7 from PyQt4 import QtCore, QtGui
7 from PyQt4 import QtCore, QtGui
8 import zmq
9
8
10 # Local imports
9 # Local imports
11 from IPython.core.inputsplitter import InputSplitter
10 from IPython.core.inputsplitter import InputSplitter
@@ -4,7 +4,7 b''
4 """
4 """
5
5
6 # Systemm library imports
6 # Systemm library imports
7 from PyQt4 import QtCore, QtGui
7 from PyQt4 import QtGui
8
8
9 # Local imports
9 # Local imports
10 from IPython.external.argparse import ArgumentParser
10 from IPython.external.argparse import ArgumentParser
@@ -37,8 +37,11 b' def main():'
37 egroup = kgroup.add_mutually_exclusive_group()
37 egroup = kgroup.add_mutually_exclusive_group()
38 egroup.add_argument('--pure', action='store_true', help = \
38 egroup.add_argument('--pure', action='store_true', help = \
39 'use a pure Python kernel instead of an IPython kernel')
39 'use a pure Python kernel instead of an IPython kernel')
40 egroup.add_argument('--pylab', action='store_true',
40 egroup.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
41 help='use a kernel with PyLab enabled')
41 const='auto', help = \
42 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
43 given, the GUI backend is matplotlib's, otherwise use one of: \
44 ['tk', 'gtk', 'qt', 'wx', 'payload-svg'].")
42
45
43 wgroup = parser.add_argument_group('widget options')
46 wgroup = parser.add_argument_group('widget options')
44 wgroup.add_argument('--paging', type=str, default='inside',
47 wgroup.add_argument('--paging', type=str, default='inside',
@@ -48,9 +51,9 b' def main():'
48 help='enable rich text support')
51 help='enable rich text support')
49 wgroup.add_argument('--tab-simple', action='store_true',
52 wgroup.add_argument('--tab-simple', action='store_true',
50 help='do tab completion ala a Unix terminal')
53 help='do tab completion ala a Unix terminal')
51
54
52 args = parser.parse_args()
55 args = parser.parse_args()
53
56
54 # Don't let Qt or ZMQ swallow KeyboardInterupts.
57 # Don't let Qt or ZMQ swallow KeyboardInterupts.
55 import signal
58 import signal
56 signal.signal(signal.SIGINT, signal.SIG_DFL)
59 signal.signal(signal.SIGINT, signal.SIG_DFL)
@@ -66,7 +69,10 b' def main():'
66 if args.rich:
69 if args.rich:
67 kernel_manager.start_kernel(pylab='payload-svg')
70 kernel_manager.start_kernel(pylab='payload-svg')
68 else:
71 else:
69 kernel_manager.start_kernel(pylab='qt4')
72 if args.pylab == 'auto':
73 kernel_manager.start_kernel(pylab='qt4')
74 else:
75 kernel_manager.start_kernel(pylab=args.pylab)
70 else:
76 else:
71 kernel_manager.start_kernel()
77 kernel_manager.start_kernel()
72 kernel_manager.start_channels()
78 kernel_manager.start_channels()
@@ -76,7 +76,7 b' def appstart_qt4(app):'
76 except ImportError:
76 except ImportError:
77 app.exec_()
77 app.exec_()
78 """
78 """
79 from PyQt4 import QtCore, QtGui
79 from PyQt4 import QtCore
80
80
81 assert isinstance(app, QtCore.QCoreApplication)
81 assert isinstance(app, QtCore.QCoreApplication)
82 if app is not None:
82 if app is not None:
@@ -241,6 +241,7 b' class InputHookManager(object):'
241 mainloop at anytime but startup.
241 mainloop at anytime but startup.
242 """
242 """
243 import Tkinter
243 import Tkinter
244 # FIXME: gtk is not imported here and we shouldn't be using gtk.main!
244 orig_mainloop = gtk.main
245 orig_mainloop = gtk.main
245 dumb_ml = _DummyMainloop(orig_mainloop, self, GUI_TK)
246 dumb_ml = _DummyMainloop(orig_mainloop, self, GUI_TK)
246 Tkinter.Misc.mainloop = dumb_ml
247 Tkinter.Misc.mainloop = dumb_ml
@@ -252,7 +253,7 b' class InputHookManager(object):'
252 This is for internal IPython use only and user code should not call this.
253 This is for internal IPython use only and user code should not call this.
253 Instead, they should issue the raw GUI calls themselves.
254 Instead, they should issue the raw GUI calls themselves.
254 """
255 """
255 from PyQt4 import QtCore, QtGui
256 from PyQt4 import QtCore
256
257
257 app = QtCore.QCoreApplication.instance()
258 app = QtCore.QCoreApplication.instance()
258 if app is not None:
259 if app is not None:
@@ -23,29 +23,21 b' from IPython.utils.decorators import flag_calls'
23 # Main classes and functions
23 # Main classes and functions
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 def pylab_activate(user_ns, gui=None, import_all=True):
27 """Activate pylab mode in the user's namespace.
28
26
29 Loads and initializes numpy, matplotlib and friends for interactive use.
27 def find_gui_and_backend(gui=None):
28 """Given a gui string return the gui and mpl backend.
30
29
31 Parameters
30 Parameters
32 ----------
31 ----------
33 user_ns : dict
32 gui : str
34 Namespace where the imports will occur.
33 Can be one of ('tk','gtk','wx','qt','qt4','payload-svg').
35
36 gui : optional, string
37 A valid gui name following the conventions of the %gui magic.
38
39 import_all : optional, boolean
40 If true, an 'import *' is done from numpy and pylab.
41
34
42 Returns
35 Returns
43 -------
36 -------
44 The actual gui used (if not given as input, it was obtained from matplotlib
37 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
45 itself, and will be needed next to configure IPython's gui integration.
38 'WXAgg','Qt4Agg','module://IPython.zmq.pylab.backend_payload_svg').
46 """
39 """
47
40
48 # Initialize matplotlib to interactive mode always
49 import matplotlib
41 import matplotlib
50
42
51 # If user specifies a GUI, that dictates the backend, otherwise we read the
43 # If user specifies a GUI, that dictates the backend, otherwise we read the
@@ -54,7 +46,9 b' def pylab_activate(user_ns, gui=None, import_all=True):'
54 'gtk': 'GTKAgg',
46 'gtk': 'GTKAgg',
55 'wx': 'WXAgg',
47 'wx': 'WXAgg',
56 'qt': 'Qt4Agg', # qt3 not supported
48 'qt': 'Qt4Agg', # qt3 not supported
57 'qt4': 'Qt4Agg' }
49 'qt4': 'Qt4Agg',
50 'payload-svg' : \
51 'module://IPython.zmq.pylab.backend_payload_svg'}
58
52
59 if gui:
53 if gui:
60 # select backend based on requested gui
54 # select backend based on requested gui
@@ -65,10 +59,21 b' def pylab_activate(user_ns, gui=None, import_all=True):'
65 # should be for IPython, so we can activate inputhook accordingly
59 # should be for IPython, so we can activate inputhook accordingly
66 b2g = dict(zip(g2b.values(),g2b.keys()))
60 b2g = dict(zip(g2b.values(),g2b.keys()))
67 gui = b2g.get(backend, None)
61 gui = b2g.get(backend, None)
62 return gui, backend
63
64
65 def activate_matplotlib(backend):
66 """Activate the given backend and set interactive to True."""
67
68 import matplotlib
69 if backend.startswith('module://'):
70 # Work around bug in matplotlib: matplotlib.use converts the
71 # backend_id to lowercase even if a module name is specified!
72 matplotlib.rcParams['backend'] = backend
73 else:
74 matplotlib.use(backend)
75 matplotlib.interactive(True)
68
76
69 # We must set the desired backend before importing pylab
70 matplotlib.use(backend)
71
72 # This must be imported last in the matplotlib series, after
77 # This must be imported last in the matplotlib series, after
73 # backend/interactivity choices have been made
78 # backend/interactivity choices have been made
74 import matplotlib.pylab as pylab
79 import matplotlib.pylab as pylab
@@ -83,6 +88,9 b' def pylab_activate(user_ns, gui=None, import_all=True):'
83 # For this, we wrap it into a decorator which adds a 'called' flag.
88 # For this, we wrap it into a decorator which adds a 'called' flag.
84 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
89 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
85
90
91 def import_pylab(user_ns, import_all=True):
92 """Import the standard pylab symbols into user_ns."""
93
86 # Import numpy as np/pyplot as plt are conventions we're trying to
94 # Import numpy as np/pyplot as plt are conventions we're trying to
87 # somewhat standardize on. Making them available to users by default
95 # somewhat standardize on. Making them available to users by default
88 # will greatly help this.
96 # will greatly help this.
@@ -97,7 +105,31 b' def pylab_activate(user_ns, gui=None, import_all=True):'
97 exec("from matplotlib.pylab import *\n"
105 exec("from matplotlib.pylab import *\n"
98 "from numpy import *\n") in user_ns
106 "from numpy import *\n") in user_ns
99
107
100 matplotlib.interactive(True)
108
109 def pylab_activate(user_ns, gui=None, import_all=True):
110 """Activate pylab mode in the user's namespace.
111
112 Loads and initializes numpy, matplotlib and friends for interactive use.
113
114 Parameters
115 ----------
116 user_ns : dict
117 Namespace where the imports will occur.
118
119 gui : optional, string
120 A valid gui name following the conventions of the %gui magic.
121
122 import_all : optional, boolean
123 If true, an 'import *' is done from numpy and pylab.
124
125 Returns
126 -------
127 The actual gui used (if not given as input, it was obtained from matplotlib
128 itself, and will be needed next to configure IPython's gui integration.
129 """
130 gui, backend = find_gui_and_backend(gui)
131 activate_matplotlib(backend)
132 import_pylab(user_ns)
101
133
102 print """
134 print """
103 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
135 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
@@ -3,6 +3,7 b' launchers.'
3 """
3 """
4
4
5 # Standard library imports.
5 # Standard library imports.
6 import os
6 import socket
7 import socket
7 from subprocess import Popen
8 from subprocess import Popen
8 import sys
9 import sys
@@ -63,7 +64,10 b' def make_kernel(namespace, kernel_factory,'
63 """ Creates a kernel.
64 """ Creates a kernel.
64 """
65 """
65 # Install minimal exception handling
66 # Install minimal exception handling
66 sys.excepthook = FormattedTB(mode='Verbose', ostream=sys.__stdout__)
67 color_scheme = 'LightBG' if sys.platform == 'darwin' else 'Linux'
68 sys.excepthook = FormattedTB(
69 mode='Verbose', color_scheme=color_scheme, ostream=sys.__stdout__
70 )
67
71
68 # Create a context, a session, and the kernel sockets.
72 # Create a context, a session, and the kernel sockets.
69 io.rprint("Starting the kernel...")
73 io.rprint("Starting the kernel...")
@@ -84,6 +88,7 b' def make_kernel(namespace, kernel_factory,'
84
88
85 # Redirect input streams and set a display hook.
89 # Redirect input streams and set a display hook.
86 if out_stream_factory:
90 if out_stream_factory:
91 pass
87 sys.stdout = out_stream_factory(session, pub_socket, u'stdout')
92 sys.stdout = out_stream_factory(session, pub_socket, u'stdout')
88 sys.stderr = out_stream_factory(session, pub_socket, u'stderr')
93 sys.stderr = out_stream_factory(session, pub_socket, u'stderr')
89 if display_hook_factory:
94 if display_hook_factory:
@@ -27,8 +27,8 b' import zmq'
27 # Local imports.
27 # Local imports.
28 from IPython.config.configurable import Configurable
28 from IPython.config.configurable import Configurable
29 from IPython.utils import io
29 from IPython.utils import io
30 from IPython.lib import pylabtools
30 from IPython.utils.traitlets import Instance
31 from IPython.utils.traitlets import Instance
31 from completer import KernelCompleter
32 from entry_point import base_launch_kernel, make_argument_parser, make_kernel, \
32 from entry_point import base_launch_kernel, make_argument_parser, make_kernel, \
33 start_kernel
33 start_kernel
34 from iostream import OutStream
34 from iostream import OutStream
@@ -51,15 +51,6 b' class Kernel(Configurable):'
51 pub_socket = Instance('zmq.Socket')
51 pub_socket = Instance('zmq.Socket')
52 req_socket = Instance('zmq.Socket')
52 req_socket = Instance('zmq.Socket')
53
53
54 # Maps user-friendly backend names to matplotlib backend identifiers.
55 _pylab_map = { 'tk': 'TkAgg',
56 'gtk': 'GTKAgg',
57 'wx': 'WXAgg',
58 'qt': 'Qt4Agg', # qt3 not supported
59 'qt4': 'Qt4Agg',
60 'payload-svg' : \
61 'module://IPython.zmq.pylab.backend_payload_svg' }
62
63 def __init__(self, **kwargs):
54 def __init__(self, **kwargs):
64 super(Kernel, self).__init__(**kwargs)
55 super(Kernel, self).__init__(**kwargs)
65
56
@@ -79,61 +70,33 b' class Kernel(Configurable):'
79 for msg_type in msg_types:
70 for msg_type in msg_types:
80 self.handlers[msg_type] = getattr(self, msg_type)
71 self.handlers[msg_type] = getattr(self, msg_type)
81
72
82 def activate_pylab(self, backend=None, import_all=True):
73 def do_one_iteration(self):
83 """ Activates pylab in this kernel's namespace.
74 try:
84
75 ident = self.reply_socket.recv(zmq.NOBLOCK)
85 Parameters:
76 except zmq.ZMQError, e:
86 -----------
77 if e.errno == zmq.EAGAIN:
87 backend : str, optional
78 return
88 A valid backend name.
89
90 import_all : bool, optional
91 If true, an 'import *' is done from numpy and pylab.
92 """
93 # FIXME: This is adapted from IPython.lib.pylabtools.pylab_activate.
94 # Common functionality should be refactored.
95
96 # We must set the desired backend before importing pylab.
97 import matplotlib
98 if backend:
99 backend_id = self._pylab_map[backend]
100 if backend_id.startswith('module://'):
101 # Work around bug in matplotlib: matplotlib.use converts the
102 # backend_id to lowercase even if a module name is specified!
103 matplotlib.rcParams['backend'] = backend_id
104 else:
79 else:
105 matplotlib.use(backend_id)
80 raise
106
81 # FIXME: Bug in pyzmq/zmq?
107 # Import numpy as np/pyplot as plt are conventions we're trying to
82 # assert self.reply_socket.rcvmore(), "Missing message part."
108 # somewhat standardize on. Making them available to users by default
83 msg = self.reply_socket.recv_json()
109 # will greatly help this.
84 omsg = Message(msg)
110 exec ("import numpy\n"
85 io.rprint('\n')
111 "import matplotlib\n"
86 io.rprint(omsg)
112 "from matplotlib import pylab, mlab, pyplot\n"
87 handler = self.handlers.get(omsg.msg_type, None)
113 "np = numpy\n"
88 if handler is None:
114 "plt = pyplot\n"
89 io.rprinte("UNKNOWN MESSAGE TYPE:", omsg)
115 ) in self.shell.user_ns
90 else:
116
91 handler(ident, omsg)
117 if import_all:
118 exec("from matplotlib.pylab import *\n"
119 "from numpy import *\n") in self.shell.user_ns
120
121 matplotlib.interactive(True)
122
92
123 def start(self):
93 def start(self):
124 """ Start the kernel main loop.
94 """ Start the kernel main loop.
125 """
95 """
126 while True:
96 while True:
127 ident = self.reply_socket.recv()
97 time.sleep(0.05)
128 assert self.reply_socket.rcvmore(), "Missing message part."
98 self.do_one_iteration()
129 msg = self.reply_socket.recv_json()
99
130 omsg = Message(msg)
131 io.rprint('\n', omsg)
132 handler = self.handlers.get(omsg.msg_type, None)
133 if handler is None:
134 io.rprinte("UNKNOWN MESSAGE TYPE:", omsg)
135 else:
136 handler(ident, omsg)
137
100
138 #---------------------------------------------------------------------------
101 #---------------------------------------------------------------------------
139 # Kernel request handlers
102 # Kernel request handlers
@@ -331,6 +294,82 b' class Kernel(Configurable):'
331
294
332 return symbol, []
295 return symbol, []
333
296
297
298 class QtKernel(Kernel):
299 """A Kernel subclass with Qt support."""
300
301 def start(self):
302 """Start a kernel with QtPy4 event loop integration."""
303
304 from PyQt4 import QtGui, QtCore
305 self.app = QtGui.QApplication([])
306 self.app.setQuitOnLastWindowClosed (False)
307 self.timer = QtCore.QTimer()
308 self.timer.timeout.connect(self.do_one_iteration)
309 self.timer.start(50)
310 self.app.exec_()
311
312
313 class WxKernel(Kernel):
314 """A Kernel subclass with Wx support."""
315
316 def start(self):
317 """Start a kernel with wx event loop support."""
318
319 import wx
320 doi = self.do_one_iteration
321
322 # We have to put the wx.Timer in a wx.Frame for it to fire properly.
323 # We make the Frame hidden when we create it in the main app below.
324 class TimerFrame(wx.Frame):
325 def __init__(self, func):
326 wx.Frame.__init__(self, None, -1)
327 self.timer = wx.Timer(self)
328 self.timer.Start(50)
329 self.Bind(wx.EVT_TIMER, self.on_timer)
330 self.func = func
331 def on_timer(self, event):
332 self.func()
333
334 # We need a custom wx.App to create our Frame subclass that has the
335 # wx.Timer to drive the ZMQ event loop.
336 class IPWxApp(wx.App):
337 def OnInit(self):
338 self.frame = TimerFrame(doi)
339 self.frame.Show(False)
340 return True
341
342 # The redirect=False here makes sure that wx doesn't replace
343 # sys.stdout/stderr with its own classes.
344 self.app = IPWxApp(redirect=False)
345 self.app.MainLoop()
346
347
348 class TkKernel(Kernel):
349 """A Kernel subclass with Tk support."""
350
351 def start(self):
352 """Start a Tk enabled event loop."""
353
354 import Tkinter
355 doi = self.do_one_iteration
356
357 # For Tkinter, we create a Tk object and call its withdraw method.
358 class Timer(object):
359 def __init__(self, func):
360 self.app = Tkinter.Tk()
361 self.app.withdraw()
362 self.func = func
363 def on_timer(self):
364 self.func()
365 self.app.after(50, self.on_timer)
366 def start(self):
367 self.on_timer() # Call it once to get things going.
368 self.app.mainloop()
369
370 self.timer = Timer(doi)
371 self.timer.start()
372
334 #-----------------------------------------------------------------------------
373 #-----------------------------------------------------------------------------
335 # Kernel main and launch functions
374 # Kernel main and launch functions
336 #-----------------------------------------------------------------------------
375 #-----------------------------------------------------------------------------
@@ -387,13 +426,30 b" given, the GUI backend is matplotlib's, otherwise use one of: \\"
387 ['tk', 'gtk', 'qt', 'wx', 'payload-svg'].")
426 ['tk', 'gtk', 'qt', 'wx', 'payload-svg'].")
388 namespace = parser.parse_args()
427 namespace = parser.parse_args()
389
428
390 kernel = make_kernel(namespace, Kernel, OutStream)
429 kernel_class = Kernel
430
431 _kernel_classes = {
432 'qt' : QtKernel,
433 'qt4' : QtKernel,
434 'payload-svg':Kernel,
435 'wx' : WxKernel,
436 'tk' : TkKernel
437 }
391 if namespace.pylab:
438 if namespace.pylab:
392 if namespace.pylab == 'auto':
439 if namespace.pylab == 'auto':
393 kernel.activate_pylab()
440 gui, backend = pylabtools.find_gui_and_backend()
394 else:
441 else:
395 kernel.activate_pylab(namespace.pylab)
442 gui, backend = pylabtools.find_gui_and_backend(namespace.pylab)
396
443 kernel_class = _kernel_classes.get(gui)
444 if kernel_class is None:
445 raise ValueError('GUI is not supported: %r' % gui)
446 pylabtools.activate_matplotlib(backend)
447
448 kernel = make_kernel(namespace, kernel_class, OutStream)
449
450 if namespace.pylab:
451 pylabtools.import_pylab(kernel.shell.user_ns)
452
397 start_kernel(namespace, kernel)
453 start_kernel(namespace, kernel)
398
454
399 if __name__ == '__main__':
455 if __name__ == '__main__':
@@ -15,7 +15,7 b' from IPython.utils.traitlets import Instance, Type, Dict'
15 from IPython.utils.warn import warn
15 from IPython.utils.warn import warn
16 from IPython.zmq.session import extract_header
16 from IPython.zmq.session import extract_header
17 from IPython.core.payloadpage import install_payload_page
17 from IPython.core.payloadpage import install_payload_page
18
18 from session import Session
19
19
20 # Install the payload version of page.
20 # Install the payload version of page.
21 install_payload_page()
21 install_payload_page()
@@ -23,7 +23,7 b' install_payload_page()'
23
23
24 class ZMQDisplayHook(DisplayHook):
24 class ZMQDisplayHook(DisplayHook):
25
25
26 session = Instance('IPython.zmq.session.Session')
26 session = Instance(Session)
27 pub_socket = Instance('zmq.Socket')
27 pub_socket = Instance('zmq.Socket')
28 parent_header = Dict({})
28 parent_header = Dict({})
29
29
General Comments 0
You need to be logged in to leave comments. Login now