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