##// 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 194 # TODO: this part of prompt management should be moved to the frontends.
195 195 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
196 196 separate_in = SeparateStr('\n', config=True)
197 separate_out = SeparateStr('\n', config=True)
198 separate_out2 = SeparateStr('\n', config=True)
197 separate_out = SeparateStr('', config=True)
198 separate_out2 = SeparateStr('', config=True)
199 199 system_header = Str('IPython system call: ', config=True)
200 200 system_verbose = CBool(False, config=True)
201 201 wildcards_case_sensitive = CBool(True, config=True)
@@ -604,7 +604,7 b' class ListTB(TBTools):'
604 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 608 """Only print the exception type and message, without a traceback.
609 609
610 610 Parameters
@@ -5,7 +5,6 b' import sys'
5 5 # System library imports
6 6 from pygments.lexers import PythonLexer
7 7 from PyQt4 import QtCore, QtGui
8 import zmq
9 8
10 9 # Local imports
11 10 from IPython.core.inputsplitter import InputSplitter
@@ -4,7 +4,7 b''
4 4 """
5 5
6 6 # Systemm library imports
7 from PyQt4 import QtCore, QtGui
7 from PyQt4 import QtGui
8 8
9 9 # Local imports
10 10 from IPython.external.argparse import ArgumentParser
@@ -37,8 +37,11 b' def main():'
37 37 egroup = kgroup.add_mutually_exclusive_group()
38 38 egroup.add_argument('--pure', action='store_true', help = \
39 39 'use a pure Python kernel instead of an IPython kernel')
40 egroup.add_argument('--pylab', action='store_true',
41 help='use a kernel with PyLab enabled')
40 egroup.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
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 46 wgroup = parser.add_argument_group('widget options')
44 47 wgroup.add_argument('--paging', type=str, default='inside',
@@ -48,9 +51,9 b' def main():'
48 51 help='enable rich text support')
49 52 wgroup.add_argument('--tab-simple', action='store_true',
50 53 help='do tab completion ala a Unix terminal')
51
54
52 55 args = parser.parse_args()
53
56
54 57 # Don't let Qt or ZMQ swallow KeyboardInterupts.
55 58 import signal
56 59 signal.signal(signal.SIGINT, signal.SIG_DFL)
@@ -66,7 +69,10 b' def main():'
66 69 if args.rich:
67 70 kernel_manager.start_kernel(pylab='payload-svg')
68 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 76 else:
71 77 kernel_manager.start_kernel()
72 78 kernel_manager.start_channels()
@@ -76,7 +76,7 b' def appstart_qt4(app):'
76 76 except ImportError:
77 77 app.exec_()
78 78 """
79 from PyQt4 import QtCore, QtGui
79 from PyQt4 import QtCore
80 80
81 81 assert isinstance(app, QtCore.QCoreApplication)
82 82 if app is not None:
@@ -241,6 +241,7 b' class InputHookManager(object):'
241 241 mainloop at anytime but startup.
242 242 """
243 243 import Tkinter
244 # FIXME: gtk is not imported here and we shouldn't be using gtk.main!
244 245 orig_mainloop = gtk.main
245 246 dumb_ml = _DummyMainloop(orig_mainloop, self, GUI_TK)
246 247 Tkinter.Misc.mainloop = dumb_ml
@@ -252,7 +253,7 b' class InputHookManager(object):'
252 253 This is for internal IPython use only and user code should not call this.
253 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 258 app = QtCore.QCoreApplication.instance()
258 259 if app is not None:
@@ -23,29 +23,21 b' from IPython.utils.decorators import flag_calls'
23 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 30 Parameters
32 31 ----------
33 user_ns : dict
34 Namespace where the imports will occur.
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.
32 gui : str
33 Can be one of ('tk','gtk','wx','qt','qt4','payload-svg').
41 34
42 35 Returns
43 36 -------
44 The actual gui used (if not given as input, it was obtained from matplotlib
45 itself, and will be needed next to configure IPython's gui integration.
37 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
38 'WXAgg','Qt4Agg','module://IPython.zmq.pylab.backend_payload_svg').
46 39 """
47 40
48 # Initialize matplotlib to interactive mode always
49 41 import matplotlib
50 42
51 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 46 'gtk': 'GTKAgg',
55 47 'wx': 'WXAgg',
56 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 53 if gui:
60 54 # select backend based on requested gui
@@ -65,10 +59,21 b' def pylab_activate(user_ns, gui=None, import_all=True):'
65 59 # should be for IPython, so we can activate inputhook accordingly
66 60 b2g = dict(zip(g2b.values(),g2b.keys()))
67 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 77 # This must be imported last in the matplotlib series, after
73 78 # backend/interactivity choices have been made
74 79 import matplotlib.pylab as pylab
@@ -83,6 +88,9 b' def pylab_activate(user_ns, gui=None, import_all=True):'
83 88 # For this, we wrap it into a decorator which adds a 'called' flag.
84 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 94 # Import numpy as np/pyplot as plt are conventions we're trying to
87 95 # somewhat standardize on. Making them available to users by default
88 96 # will greatly help this.
@@ -97,7 +105,31 b' def pylab_activate(user_ns, gui=None, import_all=True):'
97 105 exec("from matplotlib.pylab import *\n"
98 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 134 print """
103 135 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
@@ -3,6 +3,7 b' launchers.'
3 3 """
4 4
5 5 # Standard library imports.
6 import os
6 7 import socket
7 8 from subprocess import Popen
8 9 import sys
@@ -63,7 +64,10 b' def make_kernel(namespace, kernel_factory,'
63 64 """ Creates a kernel.
64 65 """
65 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 72 # Create a context, a session, and the kernel sockets.
69 73 io.rprint("Starting the kernel...")
@@ -84,6 +88,7 b' def make_kernel(namespace, kernel_factory,'
84 88
85 89 # Redirect input streams and set a display hook.
86 90 if out_stream_factory:
91 pass
87 92 sys.stdout = out_stream_factory(session, pub_socket, u'stdout')
88 93 sys.stderr = out_stream_factory(session, pub_socket, u'stderr')
89 94 if display_hook_factory:
@@ -27,8 +27,8 b' import zmq'
27 27 # Local imports.
28 28 from IPython.config.configurable import Configurable
29 29 from IPython.utils import io
30 from IPython.lib import pylabtools
30 31 from IPython.utils.traitlets import Instance
31 from completer import KernelCompleter
32 32 from entry_point import base_launch_kernel, make_argument_parser, make_kernel, \
33 33 start_kernel
34 34 from iostream import OutStream
@@ -51,15 +51,6 b' class Kernel(Configurable):'
51 51 pub_socket = Instance('zmq.Socket')
52 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 54 def __init__(self, **kwargs):
64 55 super(Kernel, self).__init__(**kwargs)
65 56
@@ -79,61 +70,33 b' class Kernel(Configurable):'
79 70 for msg_type in msg_types:
80 71 self.handlers[msg_type] = getattr(self, msg_type)
81 72
82 def activate_pylab(self, backend=None, import_all=True):
83 """ Activates pylab in this kernel's namespace.
84
85 Parameters:
86 -----------
87 backend : str, optional
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
73 def do_one_iteration(self):
74 try:
75 ident = self.reply_socket.recv(zmq.NOBLOCK)
76 except zmq.ZMQError, e:
77 if e.errno == zmq.EAGAIN:
78 return
104 79 else:
105 matplotlib.use(backend_id)
106
107 # Import numpy as np/pyplot as plt are conventions we're trying to
108 # somewhat standardize on. Making them available to users by default
109 # will greatly help this.
110 exec ("import numpy\n"
111 "import matplotlib\n"
112 "from matplotlib import pylab, mlab, pyplot\n"
113 "np = numpy\n"
114 "plt = pyplot\n"
115 ) in self.shell.user_ns
116
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)
80 raise
81 # FIXME: Bug in pyzmq/zmq?
82 # assert self.reply_socket.rcvmore(), "Missing message part."
83 msg = self.reply_socket.recv_json()
84 omsg = Message(msg)
85 io.rprint('\n')
86 io.rprint(omsg)
87 handler = self.handlers.get(omsg.msg_type, None)
88 if handler is None:
89 io.rprinte("UNKNOWN MESSAGE TYPE:", omsg)
90 else:
91 handler(ident, omsg)
122 92
123 93 def start(self):
124 94 """ Start the kernel main loop.
125 95 """
126 96 while True:
127 ident = self.reply_socket.recv()
128 assert self.reply_socket.rcvmore(), "Missing message part."
129 msg = self.reply_socket.recv_json()
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)
97 time.sleep(0.05)
98 self.do_one_iteration()
99
137 100
138 101 #---------------------------------------------------------------------------
139 102 # Kernel request handlers
@@ -331,6 +294,82 b' class Kernel(Configurable):'
331 294
332 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 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 426 ['tk', 'gtk', 'qt', 'wx', 'payload-svg'].")
388 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 438 if namespace.pylab:
392 439 if namespace.pylab == 'auto':
393 kernel.activate_pylab()
440 gui, backend = pylabtools.find_gui_and_backend()
394 441 else:
395 kernel.activate_pylab(namespace.pylab)
396
442 gui, backend = pylabtools.find_gui_and_backend(namespace.pylab)
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 453 start_kernel(namespace, kernel)
398 454
399 455 if __name__ == '__main__':
@@ -15,7 +15,7 b' from IPython.utils.traitlets import Instance, Type, Dict'
15 15 from IPython.utils.warn import warn
16 16 from IPython.zmq.session import extract_header
17 17 from IPython.core.payloadpage import install_payload_page
18
18 from session import Session
19 19
20 20 # Install the payload version of page.
21 21 install_payload_page()
@@ -23,7 +23,7 b' install_payload_page()'
23 23
24 24 class ZMQDisplayHook(DisplayHook):
25 25
26 session = Instance('IPython.zmq.session.Session')
26 session = Instance(Session)
27 27 pub_socket = Instance('zmq.Socket')
28 28 parent_header = Dict({})
29 29
General Comments 0
You need to be logged in to leave comments. Login now