##// END OF EJS Templates
rebased and updated to master
MinRK -
Show More
@@ -1,259 +1,253 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 from __future__ import print_function
19 19
20 20 import __builtin__
21 21 import sys
22 22 import os
23 23 from Queue import Empty
24 24 import readline
25 25 import rlcompleter
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Imports from ipython
29 29 #-----------------------------------------------------------------------------
30 30 from IPython.external.argparse import ArgumentParser
31 31 from IPython.core.inputsplitter import IPythonInputSplitter
32 32 from IPython.zmq.blockingkernelmanager import BlockingKernelManager as KernelManager
33 33 from IPython.frontend.zmqterminal.completer import ClientCompleter2p
34 34
35 35 #-----------------------------------------------------------------------------
36 36 # Network Constants
37 37 #-----------------------------------------------------------------------------
38 38
39 39 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
40 40 class Frontend(object):
41 41 """This class is a simple frontend to ipython-zmq
42 42
43 43 NOTE: this class uses kernelmanager to manipulate sockets
44 44
45 45 Parameters:
46 46 -----------
47 47 kernelmanager : object
48 48 instantiated object from class KernelManager in module kernelmanager
49 49
50 50 """
51 51
52 52 def __init__(self, kernelmanager):
53 53 self.km = kernelmanager
54 54 self.session_id = self.km.session.session
55 55 self.completer = ClientCompleter2p(self, self.km)
56 56 readline.parse_and_bind("tab: complete")
57 57 readline.parse_and_bind('set show-all-if-ambiguous on')
58 58 readline.set_completer(self.completer.complete)
59 59
60 60 history_path = os.path.expanduser('~/.ipython/history')
61 61 if os.path.isfile(history_path):
62 62 rlcompleter.readline.read_history_file(history_path)
63 63 else:
64 64 print("history file cannot be read.")
65 65
66 66 self.messages = {}
67 67
68 68 self._splitter = IPythonInputSplitter()
69 69 self.code = ""
70 70
71 71 self.prompt_count = 0
72 72 self._get_initial_prompt()
73 73
74 74 def _get_initial_prompt(self):
75 75 self._execute('', hidden=True)
76 76
77 77 def interact(self):
78 78 """Gets input from console using inputsplitter, then
79 79 while you enter code it can indent and set index id to any input
80 80 """
81 81
82 82 try:
83 83 print()
84 self._splitter.push(raw_input(' In[%i]: '%self.prompt_count+self.code))
84 self._splitter.push(raw_input('In [%i]: '%self.prompt_count+self.code))
85 85 while self._splitter.push_accepts_more():
86 self.code = raw_input(' .....: '+' '*self._splitter.indent_spaces)
86 self.code = raw_input('.....: '+' '*self._splitter.indent_spaces)
87 87 self._splitter.push(' '*self._splitter.indent_spaces+self.code)
88 88 self._execute(self._splitter.source,False)
89 89 self._splitter.reset()
90 90 except KeyboardInterrupt:
91 91 print('\nKeyboardInterrupt\n')
92 92 pass
93 93
94 94
95 95 def start(self):
96 96 """Start the interaction loop, calling the .interact() method for each
97 97 input cell.
98 98 """
99 99 while True:
100 100 try:
101 101 self.interact()
102 102 except KeyboardInterrupt:
103 103 print('\nKeyboardInterrupt\n')
104 104 pass
105 105 except EOFError:
106 106 answer = ''
107 107 while True:
108 108 answer = raw_input('\nDo you really want to exit ([y]/n)?')
109 109 if answer == 'y' or answer == '' :
110 110 self.km.shutdown_kernel()
111 111 sys.exit()
112 112 elif answer == 'n':
113 113 break
114 114
115 115 def _execute(self, source, hidden = True):
116 116 """ Execute 'source'. If 'hidden', do not show any output.
117 117
118 118 See parent class :meth:`execute` docstring for full details.
119 119 """
120 msg_id = self.km.xreq_channel.execute(source, hidden)
121 while not self.km.xreq_channel.msg_ready():
120 msg_id = self.km.shell_channel.execute(source, hidden)
121 while not self.km.shell_channel.msg_ready():
122 122 try:
123 self.handle_rep_channel(timeout=0.1)
123 self.handle_stdin_channel(timeout=0.1)
124 124 except Empty:
125 125 pass
126 126 self.handle_execute_reply(msg_id)
127 127
128 128 def handle_execute_reply(self, msg_id):
129 msg_xreq = self.km.xreq_channel.get_msg()
130 if msg_xreq["parent_header"]["msg_id"] == msg_id:
131 if msg_xreq["content"]["status"] == 'ok' :
129 msg = self.km.shell_channel.get_msg()
130 if msg["parent_header"]["msg_id"] == msg_id:
131 if msg["content"]["status"] == 'ok' :
132 132 self.handle_sub_channel()
133 133
134 elif msg_xreq["content"]["status"] == 'error':
135 for frame in msg_xreq["content"]["traceback"]:
134 elif msg["content"]["status"] == 'error':
135 for frame in msg["content"]["traceback"]:
136 136 print(frame, file=sys.stderr)
137 137
138 self.prompt_count = msg_xreq["content"]["execution_count"] + 1
138 self.prompt_count = msg["content"]["execution_count"] + 1
139 139
140 140
141 141 def handle_sub_channel(self):
142 142 """ Method to procces subscribe channel's messages
143 143
144 144 This method reads a message and processes the content in different
145 145 outputs like stdout, stderr, pyout and status
146 146
147 147 Arguments:
148 148 sub_msg: message receive from kernel in the sub socket channel
149 149 capture by kernel manager.
150 150 """
151 151 while self.km.sub_channel.msg_ready():
152 152 sub_msg = self.km.sub_channel.get_msg()
153 153 if self.session_id == sub_msg['parent_header']['session']:
154 154 if sub_msg['msg_type'] == 'status' :
155 155 if sub_msg["content"]["execution_state"] == "busy" :
156 156 pass
157 157
158 158 elif sub_msg['msg_type'] == 'stream' :
159 159 if sub_msg["content"]["name"] == "stdout":
160 160 print(sub_msg["content"]["data"], file=sys.stdout, end="")
161 161 sys.stdout.flush()
162 162 elif sub_msg["content"]["name"] == "stderr" :
163 163 print(sub_msg["content"]["data"], file=sys.stderr, end="")
164 164 sys.stderr.flush()
165 165
166 166 elif sub_msg['msg_type'] == 'pyout' :
167 167 print("Out[%i]:"%sub_msg["content"]["execution_count"],
168 168 sub_msg["content"]["data"]["text/plain"],
169 169 file=sys.stdout)
170 170 sys.stdout.flush()
171 171
172 def handle_rep_channel(self, timeout=0.1):
172 def handle_stdin_channel(self, timeout=0.1):
173 173 """ Method to capture raw_input
174 174 """
175 msg_rep = self.km.rep_channel.get_msg(timeout=timeout)
175 msg_rep = self.km.stdin_channel.get_msg(timeout=timeout)
176 176 if self.session_id == msg_rep["parent_header"]["session"] :
177 177 raw_data = raw_input(msg_rep["content"]["prompt"])
178 self.km.rep_channel.input(raw_data)
178 self.km.stdin_channel.input(raw_data)
179 179
180 180
181 181
182 182
183 183 def start_frontend():
184 184 """ Entry point for application.
185 185
186 186 """
187 187 # Parse command line arguments.
188 188 parser = ArgumentParser()
189 189 kgroup = parser.add_argument_group('kernel options')
190 190 kgroup.add_argument('-e', '--existing', action='store_true',
191 191 help='connect to an existing kernel')
192 192 kgroup.add_argument('--ip', type=str, default=LOCALHOST,
193 193 help=\
194 194 "set the kernel\'s IP address [default localhost].\
195 195 If the IP address is something other than localhost, then \
196 196 Consoles on other machines will be able to connect\
197 197 to the Kernel, so be careful!")
198 kgroup.add_argument('--xreq', type=int, metavar='PORT', default=0,
198 kgroup.add_argument('--shell', type=int, metavar='PORT', default=0,
199 199 help='set the XREQ channel port [default random]')
200 kgroup.add_argument('--sub', type=int, metavar='PORT', default=0,
200 kgroup.add_argument('--iopub', type=int, metavar='PORT', default=0,
201 201 help='set the SUB channel port [default random]')
202 kgroup.add_argument('--rep', type=int, metavar='PORT', default=0,
202 kgroup.add_argument('--stdin', type=int, metavar='PORT', default=0,
203 203 help='set the REP channel port [default random]')
204 204 kgroup.add_argument('--hb', type=int, metavar='PORT', default=0,
205 205 help='set the heartbeat port [default random]')
206 206
207 207 egroup = kgroup.add_mutually_exclusive_group()
208 208 egroup.add_argument('--pure', action='store_true', help = \
209 209 'use a pure Python kernel instead of an IPython kernel')
210 210 egroup.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
211 211 const='auto', help = \
212 212 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
213 213 given, the GUI backend is matplotlib's, otherwise use one of: \
214 214 ['tk', 'gtk', 'qt', 'wx', 'inline'].")
215 215 egroup.add_argument('--colors', type=str,
216 216 help="Set the color scheme (LightBG,Linux,NoColor). This is guessed\
217 217 based on the pygments style if not set.")
218 218
219 219 args = parser.parse_args()
220 220
221 221 # parse the colors arg down to current known labels
222 222 if args.colors:
223 223 colors=args.colors.lower()
224 224 if colors in ('lightbg', 'light'):
225 225 colors='lightbg'
226 226 elif colors in ('dark', 'linux'):
227 227 colors='linux'
228 228 else:
229 229 colors='nocolor'
230 230 else:
231 231 colors=None
232 232
233 233 # Create a KernelManager and start a kernel.
234 kernel_manager = KernelManager(xreq_address=(args.ip, args.xreq),
235 sub_address=(args.ip, args.sub),
236 rep_address=(args.ip, args.rep),
234 kernel_manager = KernelManager(shell_address=(args.ip, args.shell),
235 sub_address=(args.ip, args.iopub),
236 stdin_address=(args.ip, args.stdin),
237 237 hb_address=(args.ip, args.hb))
238 238 if not args.existing:
239 239 # if not args.ip in LOCAL_IPS+ALL_ALIAS:
240 240 # raise ValueError("Must bind a local ip, such as: %s"%LOCAL_IPS)
241 241
242 kwargs = dict(ip=args.ip)
243 if args.pure:
244 kwargs['ipython']=False
245 else:
246 kwargs['colors']=colors
247 if args.pylab:
248 kwargs['pylab']=args.pylab
242 kwargs = dict(ip=args.ip, ipython=True)
249 243 kernel_manager.start_kernel(**kwargs)
250 244
251 245
252 246 kernel_manager.start_channels()
253 247
254 248 frontend=Frontend(kernel_manager)
255 249 return frontend
256 250
257 251 if __name__ == "__main__" :
258 252 frontend=start_frontend()
259 253 frontend.start()
@@ -1,152 +1,152 b''
1 1 """Implement a fully blocking kernel manager.
2 2
3 3 Useful for test suites and blocking terminal interfaces.
4 4 """
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2010-2011 The IPython Development Team
7 7 #
8 8 # Distributed under the terms of the BSD License. The full license is in
9 9 # the file COPYING.txt, distributed as part of this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15 from __future__ import print_function
16 16
17 17 # Stdlib
18 18 from Queue import Queue, Empty
19 19 from threading import Event
20 20
21 21 # Our own
22 22 from IPython.utils import io
23 23 from IPython.utils.traitlets import Type
24 24
25 25 from .kernelmanager import (KernelManager, SubSocketChannel, HBSocketChannel,
26 26 ShellSocketChannel, StdInSocketChannel)
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Functions and classes
30 30 #-----------------------------------------------------------------------------
31 31
32 32 class BlockingSubSocketChannel(SubSocketChannel):
33 33
34 34 def __init__(self, context, session, address=None):
35 35 super(BlockingSubSocketChannel, self).__init__(context, session,
36 36 address)
37 37 self._in_queue = Queue()
38 38
39 39 def call_handlers(self, msg):
40 40 #io.rprint('[[Sub]]', msg) # dbg
41 41 self._in_queue.put(msg)
42 42
43 43 def msg_ready(self):
44 44 """Is there a message that has been received?"""
45 45 if self._in_queue.qsize() == 0:
46 46 return False
47 47 else:
48 48 return True
49 49
50 50 def get_msg(self, block=True, timeout=None):
51 51 """Get a message if there is one that is ready."""
52 52 if block and timeout is None:
53 53 # never use timeout=None, because get
54 54 # becomes uninterruptible
55 55 timeout = 1e6
56 56 return self._in_queue.get(block, timeout)
57 57
58 58 def get_msgs(self):
59 59 """Get all messages that are currently ready."""
60 60 msgs = []
61 61 while True:
62 62 try:
63 63 msgs.append(self.get_msg(block=False))
64 64 except Empty:
65 65 break
66 66 return msgs
67 67
68 68
69 69 class BlockingShellSocketChannel(ShellSocketChannel):
70 70
71 71 def __init__(self, context, session, address=None):
72 72 super(BlockingShellSocketChannel, self).__init__(context, session,
73 73 address)
74 74 self._in_queue = Queue()
75 75
76 76 def call_handlers(self, msg):
77 77 #io.rprint('[[Shell]]', msg) # dbg
78 78 self._in_queue.put(msg)
79 79
80 80 def msg_ready(self):
81 81 """Is there a message that has been received?"""
82 82 if self._in_queue.qsize() == 0:
83 83 return False
84 84 else:
85 85 return True
86 86
87 87 def get_msg(self, block=True, timeout=None):
88 88 """Get a message if there is one that is ready."""
89 89 if block and timeout is None:
90 90 # never use timeout=None, because get
91 91 # becomes uninterruptible
92 92 timeout = 1e6
93 93 return self._in_queue.get(block, timeout)
94 94
95 95 def get_msgs(self):
96 96 """Get all messages that are currently ready."""
97 97 msgs = []
98 98 while True:
99 99 try:
100 100 msgs.append(self.get_msg(block=False))
101 101 except Empty:
102 102 break
103 103 return msgs
104 104
105 105
106 106 class BlockingStdInSocketChannel(StdInSocketChannel):
107 107
108 108 def __init__(self, context, session, address=None):
109 super(BlockingRepSocketChannel, self).__init__(context, session, address)
109 super(BlockingStdInSocketChannel, self).__init__(context, session, address)
110 110 self._in_queue = Queue()
111 111
112 112 def call_handlers(self, msg):
113 113 #io.rprint('[[Rep]]', msg) # dbg
114 114 self._in_queue.put(msg)
115 115
116 116 def get_msg(self, block=True, timeout=None):
117 117 "Gets a message if there is one that is ready."
118 118 return self._in_queue.get(block, timeout)
119 119
120 120 def get_msgs(self):
121 121 """Get all messages that are currently ready."""
122 122 msgs = []
123 123 while True:
124 124 try:
125 125 msgs.append(self.get_msg(block=False))
126 126 except Empty:
127 127 break
128 128 return msgs
129 129
130 130 def msg_ready(self):
131 131 "Is there a message that has been received?"
132 132 return not self._in_queue.empty()
133 133
134 134
135 135 class BlockingHBSocketChannel(HBSocketChannel):
136 136
137 137 # This kernel needs rapid monitoring capabilities
138 138 time_to_dead = 0.2
139 139
140 140 def call_handlers(self, since_last_heartbeat):
141 141 #io.rprint('[[Heart]]', since_last_heartbeat) # dbg
142 142 pass
143 143
144 144
145 145 class BlockingKernelManager(KernelManager):
146 146
147 147 # The classes to use for the various channels.
148 148 shell_channel_class = Type(BlockingShellSocketChannel)
149 149 sub_channel_class = Type(BlockingSubSocketChannel)
150 150 stdin_channel_class = Type(BlockingStdInSocketChannel)
151 151 hb_channel_class = Type(BlockingHBSocketChannel)
152 152
General Comments 0
You need to be logged in to leave comments. Login now