##// END OF EJS Templates
Improve io.rprint* interface, unify usage in ipkernel....
Fernando Perez -
Show More
@@ -1,286 +1,294 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IO related utilities.
3 IO related utilities.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 from __future__ import print_function
12
13
13 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
14 # Imports
15 # Imports
15 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
16 import sys
17 import sys
17 import tempfile
18 import tempfile
18
19
19 from IPython.external.Itpl import itpl, printpl
20 from IPython.external.Itpl import itpl, printpl
20
21
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 # Code
23 # Code
23 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
24
25
25
26
26 class IOStream:
27 class IOStream:
27
28
28 def __init__(self,stream,fallback):
29 def __init__(self,stream,fallback):
29 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
30 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
30 stream = fallback
31 stream = fallback
31 self.stream = stream
32 self.stream = stream
32 self._swrite = stream.write
33 self._swrite = stream.write
33 self.flush = stream.flush
34 self.flush = stream.flush
34
35
35 def write(self,data):
36 def write(self,data):
36 try:
37 try:
37 self._swrite(data)
38 self._swrite(data)
38 except:
39 except:
39 try:
40 try:
40 # print handles some unicode issues which may trip a plain
41 # print handles some unicode issues which may trip a plain
41 # write() call. Attempt to emulate write() by using a
42 # write() call. Emulate write() by using an empty end
42 # trailing comma
43 # argument.
43 print >> self.stream, data,
44 print(data, end='', file=self.stream)
44 except:
45 except:
45 # if we get here, something is seriously broken.
46 # if we get here, something is seriously broken.
46 print >> sys.stderr, \
47 print('ERROR - failed to write data to stream:', self.stream,
47 'ERROR - failed to write data to stream:', self.stream
48 file=sys.stderr)
48
49
49 # This class used to have a writeln method, but regular files and streams
50 # This class used to have a writeln method, but regular files and streams
50 # in Python don't have this method. We need to keep this completely
51 # in Python don't have this method. We need to keep this completely
51 # compatible so we removed it.
52 # compatible so we removed it.
52
53
53 def close(self):
54 def close(self):
54 pass
55 pass
55
56
56
57
57 class IOTerm:
58 class IOTerm:
58 """ Term holds the file or file-like objects for handling I/O operations.
59 """ Term holds the file or file-like objects for handling I/O operations.
59
60
60 These are normally just sys.stdin, sys.stdout and sys.stderr but for
61 These are normally just sys.stdin, sys.stdout and sys.stderr but for
61 Windows they can can replaced to allow editing the strings before they are
62 Windows they can can replaced to allow editing the strings before they are
62 displayed."""
63 displayed."""
63
64
64 # In the future, having IPython channel all its I/O operations through
65 # In the future, having IPython channel all its I/O operations through
65 # this class will make it easier to embed it into other environments which
66 # this class will make it easier to embed it into other environments which
66 # are not a normal terminal (such as a GUI-based shell)
67 # are not a normal terminal (such as a GUI-based shell)
67 def __init__(self, cin=None, cout=None, cerr=None):
68 def __init__(self, cin=None, cout=None, cerr=None):
68 self.cin = IOStream(cin, sys.stdin)
69 self.cin = IOStream(cin, sys.stdin)
69 self.cout = IOStream(cout, sys.stdout)
70 self.cout = IOStream(cout, sys.stdout)
70 self.cerr = IOStream(cerr, sys.stderr)
71 self.cerr = IOStream(cerr, sys.stderr)
71
72
72
73
73 class Tee(object):
74 class Tee(object):
74 """A class to duplicate an output stream to stdout/err.
75 """A class to duplicate an output stream to stdout/err.
75
76
76 This works in a manner very similar to the Unix 'tee' command.
77 This works in a manner very similar to the Unix 'tee' command.
77
78
78 When the object is closed or deleted, it closes the original file given to
79 When the object is closed or deleted, it closes the original file given to
79 it for duplication.
80 it for duplication.
80 """
81 """
81 # Inspired by:
82 # Inspired by:
82 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
83 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
83
84
84 def __init__(self, file_or_name, mode=None, channel='stdout'):
85 def __init__(self, file_or_name, mode=None, channel='stdout'):
85 """Construct a new Tee object.
86 """Construct a new Tee object.
86
87
87 Parameters
88 Parameters
88 ----------
89 ----------
89 file_or_name : filename or open filehandle (writable)
90 file_or_name : filename or open filehandle (writable)
90 File that will be duplicated
91 File that will be duplicated
91
92
92 mode : optional, valid mode for open().
93 mode : optional, valid mode for open().
93 If a filename was give, open with this mode.
94 If a filename was give, open with this mode.
94
95
95 channel : str, one of ['stdout', 'stderr']
96 channel : str, one of ['stdout', 'stderr']
96 """
97 """
97 if channel not in ['stdout', 'stderr']:
98 if channel not in ['stdout', 'stderr']:
98 raise ValueError('Invalid channel spec %s' % channel)
99 raise ValueError('Invalid channel spec %s' % channel)
99
100
100 if hasattr(file, 'write') and hasattr(file, 'seek'):
101 if hasattr(file, 'write') and hasattr(file, 'seek'):
101 self.file = file_or_name
102 self.file = file_or_name
102 else:
103 else:
103 self.file = open(file_or_name, mode)
104 self.file = open(file_or_name, mode)
104 self.channel = channel
105 self.channel = channel
105 self.ostream = getattr(sys, channel)
106 self.ostream = getattr(sys, channel)
106 setattr(sys, channel, self)
107 setattr(sys, channel, self)
107 self._closed = False
108 self._closed = False
108
109
109 def close(self):
110 def close(self):
110 """Close the file and restore the channel."""
111 """Close the file and restore the channel."""
111 self.flush()
112 self.flush()
112 setattr(sys, self.channel, self.ostream)
113 setattr(sys, self.channel, self.ostream)
113 self.file.close()
114 self.file.close()
114 self._closed = True
115 self._closed = True
115
116
116 def write(self, data):
117 def write(self, data):
117 """Write data to both channels."""
118 """Write data to both channels."""
118 self.file.write(data)
119 self.file.write(data)
119 self.ostream.write(data)
120 self.ostream.write(data)
120 self.ostream.flush()
121 self.ostream.flush()
121
122
122 def flush(self):
123 def flush(self):
123 """Flush both channels."""
124 """Flush both channels."""
124 self.file.flush()
125 self.file.flush()
125 self.ostream.flush()
126 self.ostream.flush()
126
127
127 def __del__(self):
128 def __del__(self):
128 if not self._closed:
129 if not self._closed:
129 self.close()
130 self.close()
130
131
131
132
132 def file_read(filename):
133 def file_read(filename):
133 """Read a file and close it. Returns the file source."""
134 """Read a file and close it. Returns the file source."""
134 fobj = open(filename,'r');
135 fobj = open(filename,'r');
135 source = fobj.read();
136 source = fobj.read();
136 fobj.close()
137 fobj.close()
137 return source
138 return source
138
139
139
140
140 def file_readlines(filename):
141 def file_readlines(filename):
141 """Read a file and close it. Returns the file source using readlines()."""
142 """Read a file and close it. Returns the file source using readlines()."""
142 fobj = open(filename,'r');
143 fobj = open(filename,'r');
143 lines = fobj.readlines();
144 lines = fobj.readlines();
144 fobj.close()
145 fobj.close()
145 return lines
146 return lines
146
147
147
148
148 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
149 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
149 """Take multiple lines of input.
150 """Take multiple lines of input.
150
151
151 A list with each line of input as a separate element is returned when a
152 A list with each line of input as a separate element is returned when a
152 termination string is entered (defaults to a single '.'). Input can also
153 termination string is entered (defaults to a single '.'). Input can also
153 terminate via EOF (^D in Unix, ^Z-RET in Windows).
154 terminate via EOF (^D in Unix, ^Z-RET in Windows).
154
155
155 Lines of input which end in \\ are joined into single entries (and a
156 Lines of input which end in \\ are joined into single entries (and a
156 secondary continuation prompt is issued as long as the user terminates
157 secondary continuation prompt is issued as long as the user terminates
157 lines with \\). This allows entering very long strings which are still
158 lines with \\). This allows entering very long strings which are still
158 meant to be treated as single entities.
159 meant to be treated as single entities.
159 """
160 """
160
161
161 try:
162 try:
162 if header:
163 if header:
163 header += '\n'
164 header += '\n'
164 lines = [raw_input(header + ps1)]
165 lines = [raw_input(header + ps1)]
165 except EOFError:
166 except EOFError:
166 return []
167 return []
167 terminate = [terminate_str]
168 terminate = [terminate_str]
168 try:
169 try:
169 while lines[-1:] != terminate:
170 while lines[-1:] != terminate:
170 new_line = raw_input(ps1)
171 new_line = raw_input(ps1)
171 while new_line.endswith('\\'):
172 while new_line.endswith('\\'):
172 new_line = new_line[:-1] + raw_input(ps2)
173 new_line = new_line[:-1] + raw_input(ps2)
173 lines.append(new_line)
174 lines.append(new_line)
174
175
175 return lines[:-1] # don't return the termination command
176 return lines[:-1] # don't return the termination command
176 except EOFError:
177 except EOFError:
177 print
178 print
178 return lines
179 return lines
179
180
180
181
181 def raw_input_ext(prompt='', ps2='... '):
182 def raw_input_ext(prompt='', ps2='... '):
182 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
183 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
183
184
184 line = raw_input(prompt)
185 line = raw_input(prompt)
185 while line.endswith('\\'):
186 while line.endswith('\\'):
186 line = line[:-1] + raw_input(ps2)
187 line = line[:-1] + raw_input(ps2)
187 return line
188 return line
188
189
189
190
190 def ask_yes_no(prompt,default=None):
191 def ask_yes_no(prompt,default=None):
191 """Asks a question and returns a boolean (y/n) answer.
192 """Asks a question and returns a boolean (y/n) answer.
192
193
193 If default is given (one of 'y','n'), it is used if the user input is
194 If default is given (one of 'y','n'), it is used if the user input is
194 empty. Otherwise the question is repeated until an answer is given.
195 empty. Otherwise the question is repeated until an answer is given.
195
196
196 An EOF is treated as the default answer. If there is no default, an
197 An EOF is treated as the default answer. If there is no default, an
197 exception is raised to prevent infinite loops.
198 exception is raised to prevent infinite loops.
198
199
199 Valid answers are: y/yes/n/no (match is not case sensitive)."""
200 Valid answers are: y/yes/n/no (match is not case sensitive)."""
200
201
201 answers = {'y':True,'n':False,'yes':True,'no':False}
202 answers = {'y':True,'n':False,'yes':True,'no':False}
202 ans = None
203 ans = None
203 while ans not in answers.keys():
204 while ans not in answers.keys():
204 try:
205 try:
205 ans = raw_input(prompt+' ').lower()
206 ans = raw_input(prompt+' ').lower()
206 if not ans: # response was an empty string
207 if not ans: # response was an empty string
207 ans = default
208 ans = default
208 except KeyboardInterrupt:
209 except KeyboardInterrupt:
209 pass
210 pass
210 except EOFError:
211 except EOFError:
211 if default in answers.keys():
212 if default in answers.keys():
212 ans = default
213 ans = default
213 print
214 print
214 else:
215 else:
215 raise
216 raise
216
217
217 return answers[ans]
218 return answers[ans]
218
219
219
220
220 class NLprinter:
221 class NLprinter:
221 """Print an arbitrarily nested list, indicating index numbers.
222 """Print an arbitrarily nested list, indicating index numbers.
222
223
223 An instance of this class called nlprint is available and callable as a
224 An instance of this class called nlprint is available and callable as a
224 function.
225 function.
225
226
226 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
227 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
227 and using 'sep' to separate the index from the value. """
228 and using 'sep' to separate the index from the value. """
228
229
229 def __init__(self):
230 def __init__(self):
230 self.depth = 0
231 self.depth = 0
231
232
232 def __call__(self,lst,pos='',**kw):
233 def __call__(self,lst,pos='',**kw):
233 """Prints the nested list numbering levels."""
234 """Prints the nested list numbering levels."""
234 kw.setdefault('indent',' ')
235 kw.setdefault('indent',' ')
235 kw.setdefault('sep',': ')
236 kw.setdefault('sep',': ')
236 kw.setdefault('start',0)
237 kw.setdefault('start',0)
237 kw.setdefault('stop',len(lst))
238 kw.setdefault('stop',len(lst))
238 # we need to remove start and stop from kw so they don't propagate
239 # we need to remove start and stop from kw so they don't propagate
239 # into a recursive call for a nested list.
240 # into a recursive call for a nested list.
240 start = kw['start']; del kw['start']
241 start = kw['start']; del kw['start']
241 stop = kw['stop']; del kw['stop']
242 stop = kw['stop']; del kw['stop']
242 if self.depth == 0 and 'header' in kw.keys():
243 if self.depth == 0 and 'header' in kw.keys():
243 print kw['header']
244 print(kw['header'])
244
245
245 for idx in range(start,stop):
246 for idx in range(start,stop):
246 elem = lst[idx]
247 elem = lst[idx]
247 if type(elem)==type([]):
248 if type(elem)==type([]):
248 self.depth += 1
249 self.depth += 1
249 self.__call__(elem,itpl('$pos$idx,'),**kw)
250 self.__call__(elem,itpl('$pos$idx,'),**kw)
250 self.depth -= 1
251 self.depth -= 1
251 else:
252 else:
252 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
253 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
253
254
254 nlprint = NLprinter()
255 nlprint = NLprinter()
255
256
256
257
257 def temp_pyfile(src, ext='.py'):
258 def temp_pyfile(src, ext='.py'):
258 """Make a temporary python file, return filename and filehandle.
259 """Make a temporary python file, return filename and filehandle.
259
260
260 Parameters
261 Parameters
261 ----------
262 ----------
262 src : string or list of strings (no need for ending newlines if list)
263 src : string or list of strings (no need for ending newlines if list)
263 Source code to be written to the file.
264 Source code to be written to the file.
264
265
265 ext : optional, string
266 ext : optional, string
266 Extension for the generated file.
267 Extension for the generated file.
267
268
268 Returns
269 Returns
269 -------
270 -------
270 (filename, open filehandle)
271 (filename, open filehandle)
271 It is the caller's responsibility to close the open file and unlink it.
272 It is the caller's responsibility to close the open file and unlink it.
272 """
273 """
273 fname = tempfile.mkstemp(ext)[1]
274 fname = tempfile.mkstemp(ext)[1]
274 f = open(fname,'w')
275 f = open(fname,'w')
275 f.write(src)
276 f.write(src)
276 f.flush()
277 f.flush()
277 return fname, f
278 return fname, f
278
279
279
280
280 def rprint(*info):
281 def rprint(*args, **kw):
282 """Raw print to sys.__stdout__"""
283
284 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
285 file=sys.__stdout__)
286 sys.__stdout__.flush()
287
288
289 def rprinte(*args, **kw):
281 """Raw print to sys.__stderr__"""
290 """Raw print to sys.__stderr__"""
282
291
283 for item in info:
292 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
284 print >> sys.__stderr__, item,
293 file=sys.__stderr__)
285 print >> sys.__stderr__
286 sys.__stderr__.flush()
294 sys.__stderr__.flush()
@@ -1,399 +1,400 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """A simple interactive kernel that talks to a frontend over 0MQ.
2 """A simple interactive kernel that talks to a frontend over 0MQ.
3
3
4 Things to do:
4 Things to do:
5
5
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
7 call set_parent on all the PUB objects with the message about to be executed.
7 call set_parent on all the PUB objects with the message about to be executed.
8 * Implement random port and security key logic.
8 * Implement random port and security key logic.
9 * Implement control messages.
9 * Implement control messages.
10 * Implement event loop and poll version.
10 * Implement event loop and poll version.
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16
17
17 # Standard library imports.
18 # Standard library imports.
18 import __builtin__
19 import __builtin__
19 import sys
20 import sys
20 import time
21 import time
21 import traceback
22 import traceback
22
23
23 # System library imports.
24 # System library imports.
24 import zmq
25 import zmq
25
26
26 # Local imports.
27 # Local imports.
27 from IPython.config.configurable import Configurable
28 from IPython.config.configurable import Configurable
29 from IPython.utils import io
28 from IPython.utils.traitlets import Instance
30 from IPython.utils.traitlets import Instance
29 from completer import KernelCompleter
31 from completer import KernelCompleter
30 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, \
31 start_kernel
33 start_kernel
32 from iostream import OutStream
34 from iostream import OutStream
33 from session import Session, Message
35 from session import Session, Message
34 from zmqshell import ZMQInteractiveShell
36 from zmqshell import ZMQInteractiveShell
35
37
36 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
37 # Main kernel class
39 # Main kernel class
38 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
39
41
40 class Kernel(Configurable):
42 class Kernel(Configurable):
41
43
42 #---------------------------------------------------------------------------
44 #---------------------------------------------------------------------------
43 # Kernel interface
45 # Kernel interface
44 #---------------------------------------------------------------------------
46 #---------------------------------------------------------------------------
45
47
46 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
48 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
47 session = Instance(Session)
49 session = Instance(Session)
48 reply_socket = Instance('zmq.Socket')
50 reply_socket = Instance('zmq.Socket')
49 pub_socket = Instance('zmq.Socket')
51 pub_socket = Instance('zmq.Socket')
50 req_socket = Instance('zmq.Socket')
52 req_socket = Instance('zmq.Socket')
51
53
52 # Maps user-friendly backend names to matplotlib backend identifiers.
54 # Maps user-friendly backend names to matplotlib backend identifiers.
53 _pylab_map = { 'tk': 'TkAgg',
55 _pylab_map = { 'tk': 'TkAgg',
54 'gtk': 'GTKAgg',
56 'gtk': 'GTKAgg',
55 'wx': 'WXAgg',
57 'wx': 'WXAgg',
56 'qt': 'Qt4Agg', # qt3 not supported
58 'qt': 'Qt4Agg', # qt3 not supported
57 'qt4': 'Qt4Agg',
59 'qt4': 'Qt4Agg',
58 'payload-svg' : \
60 'payload-svg' : \
59 'module://IPython.zmq.pylab.backend_payload_svg' }
61 'module://IPython.zmq.pylab.backend_payload_svg' }
60
62
61 def __init__(self, **kwargs):
63 def __init__(self, **kwargs):
62 super(Kernel, self).__init__(**kwargs)
64 super(Kernel, self).__init__(**kwargs)
63
65
64 # Initialize the InteractiveShell subclass
66 # Initialize the InteractiveShell subclass
65 self.shell = ZMQInteractiveShell.instance()
67 self.shell = ZMQInteractiveShell.instance()
66 self.shell.displayhook.session = self.session
68 self.shell.displayhook.session = self.session
67 self.shell.displayhook.pub_socket = self.pub_socket
69 self.shell.displayhook.pub_socket = self.pub_socket
68
70
69 # TMP - hack while developing
71 # TMP - hack while developing
70 self.shell._reply_content = None
72 self.shell._reply_content = None
71
73
72 # Build dict of handlers for message types
74 # Build dict of handlers for message types
73 msg_types = [ 'execute_request', 'complete_request',
75 msg_types = [ 'execute_request', 'complete_request',
74 'object_info_request', 'prompt_request',
76 'object_info_request', 'prompt_request',
75 'history_request' ]
77 'history_request' ]
76 self.handlers = {}
78 self.handlers = {}
77 for msg_type in msg_types:
79 for msg_type in msg_types:
78 self.handlers[msg_type] = getattr(self, msg_type)
80 self.handlers[msg_type] = getattr(self, msg_type)
79
81
80 def activate_pylab(self, backend=None, import_all=True):
82 def activate_pylab(self, backend=None, import_all=True):
81 """ Activates pylab in this kernel's namespace.
83 """ Activates pylab in this kernel's namespace.
82
84
83 Parameters:
85 Parameters:
84 -----------
86 -----------
85 backend : str, optional
87 backend : str, optional
86 A valid backend name.
88 A valid backend name.
87
89
88 import_all : bool, optional
90 import_all : bool, optional
89 If true, an 'import *' is done from numpy and pylab.
91 If true, an 'import *' is done from numpy and pylab.
90 """
92 """
91 # FIXME: This is adapted from IPython.lib.pylabtools.pylab_activate.
93 # FIXME: This is adapted from IPython.lib.pylabtools.pylab_activate.
92 # Common functionality should be refactored.
94 # Common functionality should be refactored.
93
95
94 # We must set the desired backend before importing pylab.
96 # We must set the desired backend before importing pylab.
95 import matplotlib
97 import matplotlib
96 if backend:
98 if backend:
97 backend_id = self._pylab_map[backend]
99 backend_id = self._pylab_map[backend]
98 if backend_id.startswith('module://'):
100 if backend_id.startswith('module://'):
99 # Work around bug in matplotlib: matplotlib.use converts the
101 # Work around bug in matplotlib: matplotlib.use converts the
100 # backend_id to lowercase even if a module name is specified!
102 # backend_id to lowercase even if a module name is specified!
101 matplotlib.rcParams['backend'] = backend_id
103 matplotlib.rcParams['backend'] = backend_id
102 else:
104 else:
103 matplotlib.use(backend_id)
105 matplotlib.use(backend_id)
104
106
105 # Import numpy as np/pyplot as plt are conventions we're trying to
107 # Import numpy as np/pyplot as plt are conventions we're trying to
106 # somewhat standardize on. Making them available to users by default
108 # somewhat standardize on. Making them available to users by default
107 # will greatly help this.
109 # will greatly help this.
108 exec ("import numpy\n"
110 exec ("import numpy\n"
109 "import matplotlib\n"
111 "import matplotlib\n"
110 "from matplotlib import pylab, mlab, pyplot\n"
112 "from matplotlib import pylab, mlab, pyplot\n"
111 "np = numpy\n"
113 "np = numpy\n"
112 "plt = pyplot\n"
114 "plt = pyplot\n"
113 ) in self.shell.user_ns
115 ) in self.shell.user_ns
114
116
115 if import_all:
117 if import_all:
116 exec("from matplotlib.pylab import *\n"
118 exec("from matplotlib.pylab import *\n"
117 "from numpy import *\n") in self.shell.user_ns
119 "from numpy import *\n") in self.shell.user_ns
118
120
119 matplotlib.interactive(True)
121 matplotlib.interactive(True)
120
122
121 def start(self):
123 def start(self):
122 """ Start the kernel main loop.
124 """ Start the kernel main loop.
123 """
125 """
124 while True:
126 while True:
125 ident = self.reply_socket.recv()
127 ident = self.reply_socket.recv()
126 assert self.reply_socket.rcvmore(), "Missing message part."
128 assert self.reply_socket.rcvmore(), "Missing message part."
127 msg = self.reply_socket.recv_json()
129 msg = self.reply_socket.recv_json()
128 omsg = Message(msg)
130 omsg = Message(msg)
129 print>>sys.__stdout__
131 io.rprint('\n', omsg)
130 print>>sys.__stdout__, omsg
131 handler = self.handlers.get(omsg.msg_type, None)
132 handler = self.handlers.get(omsg.msg_type, None)
132 if handler is None:
133 if handler is None:
133 print >> sys.__stderr__, "UNKNOWN MESSAGE TYPE:", omsg
134 io.rprinte("UNKNOWN MESSAGE TYPE:", omsg)
134 else:
135 else:
135 handler(ident, omsg)
136 handler(ident, omsg)
136
137
137 #---------------------------------------------------------------------------
138 #---------------------------------------------------------------------------
138 # Kernel request handlers
139 # Kernel request handlers
139 #---------------------------------------------------------------------------
140 #---------------------------------------------------------------------------
140
141
141 def execute_request(self, ident, parent):
142 def execute_request(self, ident, parent):
142 try:
143 try:
143 code = parent[u'content'][u'code']
144 code = parent[u'content'][u'code']
144 except:
145 except:
145 print>>sys.__stderr__, "Got bad msg: "
146 io.rprinte("Got bad msg: ")
146 print>>sys.__stderr__, Message(parent)
147 io.rprinte(Message(parent))
147 return
148 return
148 pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent)
149 pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent)
149 self.pub_socket.send_json(pyin_msg)
150 self.pub_socket.send_json(pyin_msg)
150
151
151 try:
152 try:
152 # Replace raw_input. Note that is not sufficient to replace
153 # Replace raw_input. Note that is not sufficient to replace
153 # raw_input in the user namespace.
154 # raw_input in the user namespace.
154 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
155 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
155 __builtin__.raw_input = raw_input
156 __builtin__.raw_input = raw_input
156
157
157 # Set the parent message of the display hook and out streams.
158 # Set the parent message of the display hook and out streams.
158 self.shell.displayhook.set_parent(parent)
159 self.shell.displayhook.set_parent(parent)
159 sys.stdout.set_parent(parent)
160 sys.stdout.set_parent(parent)
160 sys.stderr.set_parent(parent)
161 sys.stderr.set_parent(parent)
161
162
162 # FIXME: runlines calls the exception handler itself. We should
163 # FIXME: runlines calls the exception handler itself. We should
163 # clean this up.
164 # clean this up.
164 self.shell._reply_content = None
165 self.shell._reply_content = None
165 self.shell.runlines(code)
166 self.shell.runlines(code)
166 except:
167 except:
167 # FIXME: this code right now isn't being used yet by default,
168 # FIXME: this code right now isn't being used yet by default,
168 # because the runlines() call above directly fires off exception
169 # because the runlines() call above directly fires off exception
169 # reporting. This code, therefore, is only active in the scenario
170 # reporting. This code, therefore, is only active in the scenario
170 # where runlines itself has an unhandled exception. We need to
171 # where runlines itself has an unhandled exception. We need to
171 # uniformize this, for all exception construction to come from a
172 # uniformize this, for all exception construction to come from a
172 # single location in the codbase.
173 # single location in the codbase.
173 etype, evalue, tb = sys.exc_info()
174 etype, evalue, tb = sys.exc_info()
174 tb_list = traceback.format_exception(etype, evalue, tb)
175 tb_list = traceback.format_exception(etype, evalue, tb)
175 reply_content = self.shell._showtraceback(etype, evalue, tb_list)
176 reply_content = self.shell._showtraceback(etype, evalue, tb_list)
176 else:
177 else:
177 payload = self.shell.payload_manager.read_payload()
178 payload = self.shell.payload_manager.read_payload()
178 # Be agressive about clearing the payload because we don't want
179 # Be agressive about clearing the payload because we don't want
179 # it to sit in memory until the next execute_request comes in.
180 # it to sit in memory until the next execute_request comes in.
180 self.shell.payload_manager.clear_payload()
181 self.shell.payload_manager.clear_payload()
181 reply_content = { 'status' : 'ok', 'payload' : payload }
182 reply_content = { 'status' : 'ok', 'payload' : payload }
182
183
183 # Compute the prompt information
184 # Compute the prompt information
184 prompt_number = self.shell.displayhook.prompt_count
185 prompt_number = self.shell.displayhook.prompt_count
185 reply_content['prompt_number'] = prompt_number
186 reply_content['prompt_number'] = prompt_number
186 prompt_string = self.shell.displayhook.prompt1.peek_next_prompt()
187 prompt_string = self.shell.displayhook.prompt1.peek_next_prompt()
187 next_prompt = {'prompt_string' : prompt_string,
188 next_prompt = {'prompt_string' : prompt_string,
188 'prompt_number' : prompt_number+1,
189 'prompt_number' : prompt_number+1,
189 'input_sep' : self.shell.displayhook.input_sep}
190 'input_sep' : self.shell.displayhook.input_sep}
190 reply_content['next_prompt'] = next_prompt
191 reply_content['next_prompt'] = next_prompt
191
192
192 # TMP - fish exception info out of shell, possibly left there by
193 # TMP - fish exception info out of shell, possibly left there by
193 # runlines
194 # runlines
194 if self.shell._reply_content is not None:
195 if self.shell._reply_content is not None:
195 reply_content.update(self.shell._reply_content)
196 reply_content.update(self.shell._reply_content)
196
197
197 # Flush output before sending the reply.
198 # Flush output before sending the reply.
198 sys.stderr.flush()
199 sys.stderr.flush()
199 sys.stdout.flush()
200 sys.stdout.flush()
200
201
201 # Send the reply.
202 # Send the reply.
202 reply_msg = self.session.msg(u'execute_reply', reply_content, parent)
203 reply_msg = self.session.msg(u'execute_reply', reply_content, parent)
203 print>>sys.__stdout__, Message(reply_msg)
204 io.rprint(Message(reply_msg))
204 self.reply_socket.send(ident, zmq.SNDMORE)
205 self.reply_socket.send(ident, zmq.SNDMORE)
205 self.reply_socket.send_json(reply_msg)
206 self.reply_socket.send_json(reply_msg)
206 if reply_msg['content']['status'] == u'error':
207 if reply_msg['content']['status'] == u'error':
207 self._abort_queue()
208 self._abort_queue()
208
209
209 def complete_request(self, ident, parent):
210 def complete_request(self, ident, parent):
210 matches = {'matches' : self._complete(parent),
211 txt, matches = self._complete(parent)
212 matches = {'matches' : matches,
213 'matched_text' : txt,
211 'status' : 'ok'}
214 'status' : 'ok'}
212 completion_msg = self.session.send(self.reply_socket, 'complete_reply',
215 completion_msg = self.session.send(self.reply_socket, 'complete_reply',
213 matches, parent, ident)
216 matches, parent, ident)
214 print >> sys.__stdout__, completion_msg
217 io.rprint(completion_msg)
215
218
216 def object_info_request(self, ident, parent):
219 def object_info_request(self, ident, parent):
217 context = parent['content']['oname'].split('.')
220 context = parent['content']['oname'].split('.')
218 object_info = self._object_info(context)
221 object_info = self._object_info(context)
219 msg = self.session.send(self.reply_socket, 'object_info_reply',
222 msg = self.session.send(self.reply_socket, 'object_info_reply',
220 object_info, parent, ident)
223 object_info, parent, ident)
221 print >> sys.__stdout__, msg
224 io.rprint(msg)
222
225
223 def prompt_request(self, ident, parent):
226 def prompt_request(self, ident, parent):
224 prompt_number = self.shell.displayhook.prompt_count
227 prompt_number = self.shell.displayhook.prompt_count
225 prompt_string = self.shell.displayhook.prompt1.peek_next_prompt()
228 prompt_string = self.shell.displayhook.prompt1.peek_next_prompt()
226 content = {'prompt_string' : prompt_string,
229 content = {'prompt_string' : prompt_string,
227 'prompt_number' : prompt_number+1,
230 'prompt_number' : prompt_number+1,
228 'input_sep' : self.shell.displayhook.input_sep}
231 'input_sep' : self.shell.displayhook.input_sep}
229 msg = self.session.send(self.reply_socket, 'prompt_reply',
232 msg = self.session.send(self.reply_socket, 'prompt_reply',
230 content, parent, ident)
233 content, parent, ident)
231 print >> sys.__stdout__, msg
234 io.rprint(msg)
232
235
233 def history_request(self, ident, parent):
236 def history_request(self, ident, parent):
234 output = parent['content']['output']
237 output = parent['content']['output']
235 index = parent['content']['index']
238 index = parent['content']['index']
236 raw = parent['content']['raw']
239 raw = parent['content']['raw']
237 hist = self.shell.get_history(index=index, raw=raw, output=output)
240 hist = self.shell.get_history(index=index, raw=raw, output=output)
238 content = {'history' : hist}
241 content = {'history' : hist}
239 msg = self.session.send(self.reply_socket, 'history_reply',
242 msg = self.session.send(self.reply_socket, 'history_reply',
240 content, parent, ident)
243 content, parent, ident)
241 print >> sys.__stdout__, msg
244 io.rprint(msg)
242
245
243 #---------------------------------------------------------------------------
246 #---------------------------------------------------------------------------
244 # Protected interface
247 # Protected interface
245 #---------------------------------------------------------------------------
248 #---------------------------------------------------------------------------
246
249
247 def _abort_queue(self):
250 def _abort_queue(self):
248 while True:
251 while True:
249 try:
252 try:
250 ident = self.reply_socket.recv(zmq.NOBLOCK)
253 ident = self.reply_socket.recv(zmq.NOBLOCK)
251 except zmq.ZMQError, e:
254 except zmq.ZMQError, e:
252 if e.errno == zmq.EAGAIN:
255 if e.errno == zmq.EAGAIN:
253 break
256 break
254 else:
257 else:
255 assert self.reply_socket.rcvmore(), "Unexpected missing message part."
258 assert self.reply_socket.rcvmore(), "Unexpected missing message part."
256 msg = self.reply_socket.recv_json()
259 msg = self.reply_socket.recv_json()
257 print>>sys.__stdout__, "Aborting:"
260 io.rprint("Aborting:\n", Message(msg))
258 print>>sys.__stdout__, Message(msg)
259 msg_type = msg['msg_type']
261 msg_type = msg['msg_type']
260 reply_type = msg_type.split('_')[0] + '_reply'
262 reply_type = msg_type.split('_')[0] + '_reply'
261 reply_msg = self.session.msg(reply_type, {'status' : 'aborted'}, msg)
263 reply_msg = self.session.msg(reply_type, {'status' : 'aborted'}, msg)
262 print>>sys.__stdout__, Message(reply_msg)
264 io.rprint(Message(reply_msg))
263 self.reply_socket.send(ident,zmq.SNDMORE)
265 self.reply_socket.send(ident,zmq.SNDMORE)
264 self.reply_socket.send_json(reply_msg)
266 self.reply_socket.send_json(reply_msg)
265 # We need to wait a bit for requests to come in. This can probably
267 # We need to wait a bit for requests to come in. This can probably
266 # be set shorter for true asynchronous clients.
268 # be set shorter for true asynchronous clients.
267 time.sleep(0.1)
269 time.sleep(0.1)
268
270
269 def _raw_input(self, prompt, ident, parent):
271 def _raw_input(self, prompt, ident, parent):
270 # Flush output before making the request.
272 # Flush output before making the request.
271 sys.stderr.flush()
273 sys.stderr.flush()
272 sys.stdout.flush()
274 sys.stdout.flush()
273
275
274 # Send the input request.
276 # Send the input request.
275 content = dict(prompt=prompt)
277 content = dict(prompt=prompt)
276 msg = self.session.msg(u'input_request', content, parent)
278 msg = self.session.msg(u'input_request', content, parent)
277 self.req_socket.send_json(msg)
279 self.req_socket.send_json(msg)
278
280
279 # Await a response.
281 # Await a response.
280 reply = self.req_socket.recv_json()
282 reply = self.req_socket.recv_json()
281 try:
283 try:
282 value = reply['content']['value']
284 value = reply['content']['value']
283 except:
285 except:
284 print>>sys.__stderr__, "Got bad raw_input reply: "
286 io.rprinte("Got bad raw_input reply: ")
285 print>>sys.__stderr__, Message(parent)
287 io.rprinte(Message(parent))
286 value = ''
288 value = ''
287 return value
289 return value
288
290
289 def _complete(self, msg):
291 def _complete(self, msg):
290 #from IPython.utils.io import rprint # dbg
291 #rprint('\n\n**MSG**\n\n', msg) # dbg
292 #import traceback; rprint(''.join(traceback.format_stack())) # dbg
293 c = msg['content']
292 c = msg['content']
294 try:
293 try:
295 cpos = int(c['cursor_pos'])
294 cpos = int(c['cursor_pos'])
296 except:
295 except:
297 # If we don't get something that we can convert to an integer, at
296 # If we don't get something that we can convert to an integer, at
298 # leasat attempt the completion guessing the cursor is at the end
297 # least attempt the completion guessing the cursor is at the end of
299 # of the text
298 # the text, if there's any, and otherwise of the line
300 cpos = len(c['text'])
299 cpos = len(c['text'])
300 if cpos==0:
301 cpos = len(c['line'])
301 return self.shell.complete(c['text'], c['line'], cpos)
302 return self.shell.complete(c['text'], c['line'], cpos)
302
303
303 def _object_info(self, context):
304 def _object_info(self, context):
304 symbol, leftover = self._symbol_from_context(context)
305 symbol, leftover = self._symbol_from_context(context)
305 if symbol is not None and not leftover:
306 if symbol is not None and not leftover:
306 doc = getattr(symbol, '__doc__', '')
307 doc = getattr(symbol, '__doc__', '')
307 else:
308 else:
308 doc = ''
309 doc = ''
309 object_info = dict(docstring = doc)
310 object_info = dict(docstring = doc)
310 return object_info
311 return object_info
311
312
312 def _symbol_from_context(self, context):
313 def _symbol_from_context(self, context):
313 if not context:
314 if not context:
314 return None, context
315 return None, context
315
316
316 base_symbol_string = context[0]
317 base_symbol_string = context[0]
317 symbol = self.shell.user_ns.get(base_symbol_string, None)
318 symbol = self.shell.user_ns.get(base_symbol_string, None)
318 if symbol is None:
319 if symbol is None:
319 symbol = __builtin__.__dict__.get(base_symbol_string, None)
320 symbol = __builtin__.__dict__.get(base_symbol_string, None)
320 if symbol is None:
321 if symbol is None:
321 return None, context
322 return None, context
322
323
323 context = context[1:]
324 context = context[1:]
324 for i, name in enumerate(context):
325 for i, name in enumerate(context):
325 new_symbol = getattr(symbol, name, None)
326 new_symbol = getattr(symbol, name, None)
326 if new_symbol is None:
327 if new_symbol is None:
327 return symbol, context[i:]
328 return symbol, context[i:]
328 else:
329 else:
329 symbol = new_symbol
330 symbol = new_symbol
330
331
331 return symbol, []
332 return symbol, []
332
333
333 #-----------------------------------------------------------------------------
334 #-----------------------------------------------------------------------------
334 # Kernel main and launch functions
335 # Kernel main and launch functions
335 #-----------------------------------------------------------------------------
336 #-----------------------------------------------------------------------------
336
337
337 def launch_kernel(xrep_port=0, pub_port=0, req_port=0, independent=False,
338 def launch_kernel(xrep_port=0, pub_port=0, req_port=0, independent=False,
338 pylab=False):
339 pylab=False):
339 """ Launches a localhost kernel, binding to the specified ports.
340 """ Launches a localhost kernel, binding to the specified ports.
340
341
341 Parameters
342 Parameters
342 ----------
343 ----------
343 xrep_port : int, optional
344 xrep_port : int, optional
344 The port to use for XREP channel.
345 The port to use for XREP channel.
345
346
346 pub_port : int, optional
347 pub_port : int, optional
347 The port to use for the SUB channel.
348 The port to use for the SUB channel.
348
349
349 req_port : int, optional
350 req_port : int, optional
350 The port to use for the REQ (raw input) channel.
351 The port to use for the REQ (raw input) channel.
351
352
352 independent : bool, optional (default False)
353 independent : bool, optional (default False)
353 If set, the kernel process is guaranteed to survive if this process
354 If set, the kernel process is guaranteed to survive if this process
354 dies. If not set, an effort is made to ensure that the kernel is killed
355 dies. If not set, an effort is made to ensure that the kernel is killed
355 when this process dies. Note that in this case it is still good practice
356 when this process dies. Note that in this case it is still good practice
356 to kill kernels manually before exiting.
357 to kill kernels manually before exiting.
357
358
358 pylab : bool or string, optional (default False)
359 pylab : bool or string, optional (default False)
359 If not False, the kernel will be launched with pylab enabled. If a
360 If not False, the kernel will be launched with pylab enabled. If a
360 string is passed, matplotlib will use the specified backend. Otherwise,
361 string is passed, matplotlib will use the specified backend. Otherwise,
361 matplotlib's default backend will be used.
362 matplotlib's default backend will be used.
362
363
363 Returns
364 Returns
364 -------
365 -------
365 A tuple of form:
366 A tuple of form:
366 (kernel_process, xrep_port, pub_port, req_port)
367 (kernel_process, xrep_port, pub_port, req_port)
367 where kernel_process is a Popen object and the ports are integers.
368 where kernel_process is a Popen object and the ports are integers.
368 """
369 """
369 extra_arguments = []
370 extra_arguments = []
370 if pylab:
371 if pylab:
371 extra_arguments.append('--pylab')
372 extra_arguments.append('--pylab')
372 if isinstance(pylab, basestring):
373 if isinstance(pylab, basestring):
373 extra_arguments.append(pylab)
374 extra_arguments.append(pylab)
374 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
375 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
375 xrep_port, pub_port, req_port, independent,
376 xrep_port, pub_port, req_port, independent,
376 extra_arguments)
377 extra_arguments)
377
378
378 def main():
379 def main():
379 """ The IPython kernel main entry point.
380 """ The IPython kernel main entry point.
380 """
381 """
381 parser = make_argument_parser()
382 parser = make_argument_parser()
382 parser.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
383 parser.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
383 const='auto', help = \
384 const='auto', help = \
384 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
385 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
385 given, the GUI backend is matplotlib's, otherwise use one of: \
386 given, the GUI backend is matplotlib's, otherwise use one of: \
386 ['tk', 'gtk', 'qt', 'wx', 'payload-svg'].")
387 ['tk', 'gtk', 'qt', 'wx', 'payload-svg'].")
387 namespace = parser.parse_args()
388 namespace = parser.parse_args()
388
389
389 kernel = make_kernel(namespace, Kernel, OutStream)
390 kernel = make_kernel(namespace, Kernel, OutStream)
390 if namespace.pylab:
391 if namespace.pylab:
391 if namespace.pylab == 'auto':
392 if namespace.pylab == 'auto':
392 kernel.activate_pylab()
393 kernel.activate_pylab()
393 else:
394 else:
394 kernel.activate_pylab(namespace.pylab)
395 kernel.activate_pylab(namespace.pylab)
395
396
396 start_kernel(namespace, kernel)
397 start_kernel(namespace, kernel)
397
398
398 if __name__ == '__main__':
399 if __name__ == '__main__':
399 main()
400 main()
General Comments 0
You need to be logged in to leave comments. Login now