##// END OF EJS Templates
traceback support added
Omar Andres Zapata Mesa -
Show More
@@ -1,281 +1,282 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Frontend of ipython working with python-zmq
3 3
4 4 Ipython's frontend, is a ipython interface that send request to kernel and proccess the kernel's outputs.
5 5
6 6 For more details, see the ipython-zmq design
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2010 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 import __builtin__
20 20 from contextlib import nested
21 21 import time
22 22 import sys
23 23 import os
24 24 import signal
25 25 import uuid
26 26 import cPickle as pickle
27 27 import code
28 28 import zmq
29 29 import readline
30 30 import rlcompleter
31 31 import time
32 32
33
34 33 #-----------------------------------------------------------------------------
35 34 # Imports from ipython
36 35 #-----------------------------------------------------------------------------
37 36 from IPython.external.argparse import ArgumentParser
38 37 from IPython.utils.traitlets import (
39 38 Int, Str, CBool, CaselessStrEnum, Enum, List, Unicode
40 39 )
41 40 from IPython.core.interactiveshell import get_default_colors
42 41 from IPython.core.excolors import exception_colors
43 42 from IPython.utils import PyColorize
44 43 from IPython.core.inputsplitter import InputSplitter
45 44 from IPython.frontend.terminal.kernelmanager import KernelManager2p as KernelManager
46 45 from IPython.zmq.session import Session
47 46 from IPython.frontend.terminal.completer import ClientCompleter2p
48 47
49 48 #-----------------------------------------------------------------------------
50 49 # Network Constants
51 50 #-----------------------------------------------------------------------------
52 51
53 52 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
54 53 class Frontend(object):
55 54 """ this class is a simple frontend to ipython-zmq
56 55
57 56 NOTE: this class use kernelmanager to manipulate sockets
58 57
59 58 Parameters:
60 59 -----------
61 60 kernelmanager : object
62 61 instantiated object from class KernelManager in module kernelmanager
63 62
64 63 """
65 64
66 65 def __init__(self,kernelmanager):
67 66 self.km = kernelmanager
68 67 self.session = kernelmanager.session
69 68 self.request_socket = self.km.xreq_channel.socket
70 69 self.sub_socket = self.km.sub_channel.socket
71 70 self.reply_socket = self.km.rep_channel.socket
72 71 self.msg_header = self.km.session.msg_header()
73 72 self.completer = ClientCompleter2p(self,self.km)
74 73 readline.parse_and_bind("tab: complete")
75 74 readline.parse_and_bind('set show-all-if-ambiguous on')
76 75 readline.set_completer(self.completer.complete)
77 76
78 77 history_path = os.path.expanduser('~/.ipython/history')
79 78 if os.path.isfile(history_path):
80 79 rlcompleter.readline.read_history_file(history_path)
81 80 else:
82 81 print("history file can not be readed.")
83 82
84 83 self.messages = {}
85 84
86 85 self._splitter = InputSplitter()
87 86 self.code = ""
88 87
89 88 self.prompt_count = 0
90 89 self._get_initail_promt()
91 90
92 91 def _get_initail_promt(self):
93 92 self._execute('', hidden=True)
94 93
95 94 def interact(self):
96 95 """ let you get input from console using inputsplitter, then
97 96 while you enter code it can indent and set index id to any input
98 97
99 98 """
100 99
101 100 try:
102 101 self._splitter.push(raw_input('In[%i]:'%self.prompt_count+self.code))
103 102 while self._splitter.push_accepts_more():
104 103 self.code = raw_input('.....:'+' '*self._splitter.indent_spaces)
105 104 self._splitter.push(' '*self._splitter.indent_spaces+self.code)
106 105 self._execute(self._splitter.source,False)
107 106 self._splitter.reset()
108 107 except KeyboardInterrupt:
109 108 print('\nKeyboardInterrupt\n')
110 109 pass
111 110
112 111
113 112 def start(self):
114 113 """ init a bucle that call interact method to get code.
115 114
116 115 """
117 116 while True:
118 117 try:
119 118 self.interact()
120 119 except KeyboardInterrupt:
121 120 print('\nKeyboardInterrupt\n')
122 121 pass
123 122 except EOFError:
124 123 answer = ''
125 124 while True:
126 125 answer = raw_input('\nDo you really want to exit ([y]/n)?')
127 126 if answer == 'y' or answer == '' :
128 127 self.km.shutdown_kernel()
129 128 sys.exit()
130 129 elif answer == 'n':
131 130 break
132 131
133 132 def _execute(self, source, hidden = True):
134 133 """ Execute 'source'. If 'hidden', do not show any output.
135 134
136 135 See parent class :meth:`execute` docstring for full details.
137 136 """
138 137 self.km.xreq_channel.execute(source, hidden)
139 138 self.handle_xreq_channel()
140 139 self.handle_rep_channel()
141 140
142 141 def handle_xreq_channel(self):
143 142 # Give the kernel up to 0.5s to respond
144 143 for i in range(5):
145 144 if self.km.xreq_channel.was_called():
146 145 self.msg_xreq = self.km.xreq_channel.get_msg()
147 146 if self.msg_header["session"] == self.msg_xreq["parent_header"]["session"] :
148 147 if self.msg_xreq["content"]["status"] == 'ok' :
149 148 if self.msg_xreq["msg_type"] == "execute_reply" :
150 149 self.handle_sub_channel()
151 150 self.prompt_count = self.msg_xreq["content"]["execution_count"]+1
152 151
153 152 else:
154 print >> sys.stderr, "Error executing: ",self.msg_xreq ##traceback no implemented yet here
155 print >> sys.stderr, "Status in the kernel: ", self.msg_xreq["content"]["status"]
153 etb = self.msg_xreq["content"]["traceback"]
154 print >> sys.stderr, etb[0]
155 print >> sys.stderr, etb[1]
156 print >> sys.stderr, etb[2]
156 157 break
157 158 time.sleep(0.1)
158 159
159 160
160 161
161 162 def handle_sub_channel(self):
162 163 """ Method to procces subscribe channel's messages
163 164
164 165 this method read a message and procces the content
165 166 in differents outputs like stdout, stderr, pyout
166 167 and status
167 168
168 169 Arguments:
169 170 sub_msg: message receive from kernel in the sub socket channel
170 171 capture by kernel manager.
171 172
172 173 """
173 174 while self.km.sub_channel.was_called():
174 175 sub_msg = self.km.sub_channel.get_msg()
175 176 if self.msg_header["username"] == sub_msg['parent_header']['username'] and self.km.session.session == sub_msg['parent_header']['session']:
176 177 if sub_msg['msg_type'] == 'status' :
177 178 if sub_msg["content"]["execution_state"] == "busy" :
178 179 pass
179 180
180 181 if sub_msg['msg_type'] == 'stream' :
181 182 if sub_msg["content"]["name"] == "stdout":
182 183 print >> sys.stdout,sub_msg["content"]["data"]
183 184 sys.stdout.flush()
184 185 if sub_msg["content"]["name"] == "stderr" :
185 186 print >> sys.stderr,sub_msg["content"]["data"]
186 187 sys.stderr.flush()
187 188
188 189 if sub_msg['msg_type'] == 'pyout' :
189 190 print >> sys.stdout,"Out[%i]:"%sub_msg["content"]["execution_count"], sub_msg["content"]["data"]["text/plain"]
190 191 sys.stdout.flush()
191 192
192 193 def handle_rep_channel(self):
193 194 """ Method to capture raw_input
194 195 """
195 196 if self.km.rep_channel.was_called() :
196 197 self.msg_rep = self.km.rep_channel.get_msg()
197 198 if self.msg_header["session"] == self.msg_rep["parent_header"]["session"] :
198 199 raw_data = raw_input(self.msg_rep["content"]["prompt"])
199 200 self.km.rep_channel.input(raw_data)
200 201
201 202
202 203
203 204
204 205 def start_frontend():
205 206 """ Entry point for application.
206 207
207 208 """
208 209 # Parse command line arguments.
209 210 parser = ArgumentParser()
210 211 kgroup = parser.add_argument_group('kernel options')
211 212 kgroup.add_argument('-e', '--existing', action='store_true',
212 213 help='connect to an existing kernel')
213 214 kgroup.add_argument('--ip', type=str, default=LOCALHOST,
214 215 help=\
215 216 "set the kernel\'s IP address [default localhost].\
216 217 If the IP address is something other than localhost, then \
217 218 Consoles on other machines will be able to connect\
218 219 to the Kernel, so be careful!")
219 220 kgroup.add_argument('--xreq', type=int, metavar='PORT', default=0,
220 221 help='set the XREQ channel port [default random]')
221 222 kgroup.add_argument('--sub', type=int, metavar='PORT', default=0,
222 223 help='set the SUB channel port [default random]')
223 224 kgroup.add_argument('--rep', type=int, metavar='PORT', default=0,
224 225 help='set the REP channel port [default random]')
225 226 kgroup.add_argument('--hb', type=int, metavar='PORT', default=0,
226 227 help='set the heartbeat port [default random]')
227 228
228 229 egroup = kgroup.add_mutually_exclusive_group()
229 230 egroup.add_argument('--pure', action='store_true', help = \
230 231 'use a pure Python kernel instead of an IPython kernel')
231 232 egroup.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
232 233 const='auto', help = \
233 234 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
234 235 given, the GUI backend is matplotlib's, otherwise use one of: \
235 236 ['tk', 'gtk', 'qt', 'wx', 'inline'].")
236 237 egroup.add_argument('--colors', type=str,
237 238 help="Set the color scheme (LightBG,Linux,NoColor). This is guessed\
238 239 based on the pygments style if not set.")
239 240
240 241 args = parser.parse_args()
241 242
242 243 # parse the colors arg down to current known labels
243 244 if args.colors:
244 245 colors=args.colors.lower()
245 246 if colors in ('lightbg', 'light'):
246 247 colors='lightbg'
247 248 elif colors in ('dark', 'linux'):
248 249 colors='linux'
249 250 else:
250 251 colors='nocolor'
251 252 else:
252 253 colors=None
253 254
254 255 # Create a KernelManager and start a kernel.
255 256 kernel_manager = KernelManager(xreq_address=(args.ip, args.xreq),
256 257 sub_address=(args.ip, args.sub),
257 258 rep_address=(args.ip, args.rep),
258 259 hb_address=(args.ip, args.hb))
259 260 if not args.existing:
260 261 # if not args.ip in LOCAL_IPS+ALL_ALIAS:
261 262 # raise ValueError("Must bind a local ip, such as: %s"%LOCAL_IPS)
262 263
263 264 kwargs = dict(ip=args.ip)
264 265 if args.pure:
265 266 kwargs['ipython']=False
266 267 else:
267 268 kwargs['colors']=colors
268 269 if args.pylab:
269 270 kwargs['pylab']=args.pylab
270 271 kernel_manager.start_kernel(**kwargs)
271 272
272 273
273 274 kernel_manager.start_channels()
274 275 time.sleep(4)
275 276
276 277 frontend=Frontend(kernel_manager)
277 278 return frontend
278 279
279 280 if __name__ == "__main__" :
280 281 frontend=start_frontend()
281 282 frontend.start() No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now