##// END OF EJS Templates
Refactor and simplification of zmqterminal.
Thomas Kluyver -
Show More
@@ -1,11 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2 import readline
3 import time
4 import sys
5 stdout = sys.stdout
6
7 class TimeoutError(Exception):
8 pass
3 from Queue import Empty
9 4
10 5 class ClientCompleter2p(object):
11 6 """Client-side completion machinery.
@@ -27,22 +22,18 b' class ClientCompleter2p(object):'
27 22 dict(text=text, line=line))
28 23 # send completion request to kernel
29 24 # Give the kernel up to 0.5s to respond
30 for i in range(5):
31 if self.km.xreq_channel.was_called():
32 msg_xreq = self.km.xreq_channel.get_msg()
33 if msg["header"]['session'] == msg_xreq["parent_header"]['session'] and \
34 msg_xreq["content"]["status"] == 'ok' and \
35 msg_xreq["msg_type"] == "complete_reply" :
36 return msg_xreq["content"]["matches"]
37
38 time.sleep(0.1)
39 raise TimeoutError
25 msg_xreq = self.km.xreq_channel.get_msg(timeout=0.5)
26 if msg["header"]['session'] == msg_xreq["parent_header"]['session'] and \
27 msg_xreq["content"]["status"] == 'ok' and \
28 msg_xreq["msg_type"] == "complete_reply" :
29 return msg_xreq["content"]["matches"]
30 return []
40 31
41 32 def complete(self, text, state):
42 33 if state == 0:
43 34 try:
44 35 self.matches = self.complete_request(text)
45 except TimeoutError:
36 except Empty:
46 37 print('WARNING: Kernel timeout on tab completion.')
47 38
48 39 try:
@@ -17,32 +17,18 b' For more details, see the ipython-zmq design'
17 17 #-----------------------------------------------------------------------------
18 18
19 19 import __builtin__
20 from contextlib import nested
21 import time
22 20 import sys
23 21 import os
24 import signal
25 import uuid
26 import cPickle as pickle
27 import code
28 import zmq
22 from Queue import Empty
29 23 import readline
30 24 import rlcompleter
31 import time
32 25
33 26 #-----------------------------------------------------------------------------
34 27 # Imports from ipython
35 28 #-----------------------------------------------------------------------------
36 29 from IPython.external.argparse import ArgumentParser
37 from IPython.utils.traitlets import (
38 Int, Str, CBool, CaselessStrEnum, Enum, List, Unicode
39 )
40 from IPython.core.interactiveshell import get_default_colors
41 from IPython.core.excolors import exception_colors
42 from IPython.utils import PyColorize
43 30 from IPython.core.inputsplitter import IPythonInputSplitter
44 from IPython.frontend.zmqterminal.kernelmanager import KernelManager2p as KernelManager
45 from IPython.zmq.session import Session
31 from IPython.zmq.blockingkernelmanager import BlockingKernelManager as KernelManager
46 32 from IPython.frontend.zmqterminal.completer import ClientCompleter2p
47 33
48 34 #-----------------------------------------------------------------------------
@@ -51,7 +37,7 b' from IPython.frontend.zmqterminal.completer import ClientCompleter2p'
51 37
52 38 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
53 39 class Frontend(object):
54 """This class is a simple frontend to ipython-zmq
40 """This class is a simple frontend to ipython-zmq
55 41
56 42 NOTE: this class uses kernelmanager to manipulate sockets
57 43
@@ -60,16 +46,16 b' class Frontend(object):'
60 46 kernelmanager : object
61 47 instantiated object from class KernelManager in module kernelmanager
62 48
63 """
49 """
64 50
65 def __init__(self, kernelmanager):
51 def __init__(self, kernelmanager):
66 52 self.km = kernelmanager
67 53 self.session = kernelmanager.session
68 54 self.request_socket = self.km.xreq_channel.socket
69 55 self.sub_socket = self.km.sub_channel.socket
70 56 self.reply_socket = self.km.rep_channel.socket
71 57 self.msg_header = self.km.session.msg_header()
72 self.completer = ClientCompleter2p(self,self.km)
58 self.completer = ClientCompleter2p(self, self.km)
73 59 readline.parse_and_bind("tab: complete")
74 60 readline.parse_and_bind('set show-all-if-ambiguous on')
75 61 readline.set_completer(self.completer.complete)
@@ -88,10 +74,10 b' class Frontend(object):'
88 74 self.prompt_count = 0
89 75 self._get_initial_prompt()
90 76
91 def _get_initial_prompt(self):
77 def _get_initial_prompt(self):
92 78 self._execute('', hidden=True)
93 79
94 def interact(self):
80 def interact(self):
95 81 """Gets input from console using inputsplitter, then
96 82 while you enter code it can indent and set index id to any input
97 83 """
@@ -108,7 +94,7 b' class Frontend(object):'
108 94 pass
109 95
110 96
111 def start(self):
97 def start(self):
112 98 """Start the interaction loop, calling the .interact() method for each
113 99 input cell.
114 100 """
@@ -128,37 +114,39 b' class Frontend(object):'
128 114 elif answer == 'n':
129 115 break
130 116
131 def _execute(self, source, hidden = True):
132 """ Execute 'source'. If 'hidden', do not show any output.
117 def _execute(self, source, hidden = True):
118 """ Execute 'source'. If 'hidden', do not show any output.
133 119
134 120 See parent class :meth:`execute` docstring for full details.
135 """
136 self.km.xreq_channel.execute(source, hidden)
137 self.handle_xreq_channel()
138 self.handle_rep_channel()
121 """
122 self.km.xreq_channel.execute(source, hidden)
123 while not self.km.xreq_channel.msg_ready():
124 try:
125 self.handle_rep_channel(timeout=0.1)
126 except Empty:
127 pass
128 self.handle_xreq_channel()
139 129
140 def handle_xreq_channel(self):
141 # Give the kernel up to 0.5s to respond
142 for i in range(5):
143 if self.km.xreq_channel.was_called():
144 self.msg_xreq = self.km.xreq_channel.get_msg()
145 if self.msg_header["session"] == self.msg_xreq["parent_header"]["session"] :
146 if self.msg_xreq["content"]["status"] == 'ok' :
147 if self.msg_xreq["msg_type"] == "execute_reply" :
148 self.handle_sub_channel()
149 self.prompt_count = self.msg_xreq["content"]["execution_count"]+1
150
151 else:
152 etb = self.msg_xreq["content"]["traceback"]
153 print >> sys.stderr, etb[0]
154 print >> sys.stderr, etb[1]
155 print >> sys.stderr, etb[2]
156 self.prompt_count = self.msg_xreq["content"]["execution_count"]+1
157 break
158 time.sleep(0.1)
130 def handle_xreq_channel(self):
131 self.msg_xreq = self.km.xreq_channel.get_msg()
132 if self.msg_header["session"] == self.msg_xreq["parent_header"]["session"]:
133 if self.msg_xreq["content"]["status"] == 'ok' :
134 if self.msg_xreq["msg_type"] == "execute_reply" :
135 self.handle_sub_channel()
136 self.prompt_count = self.msg_xreq["content"]["execution_count"]+1
137
138 else:
139 etb = self.msg_xreq["content"]["traceback"]
140 print >> sys.stderr, etb[0]
141 try: # These bits aren't there for a SyntaxError
142 print >> sys.stderr, etb[1]
143 print >> sys.stderr, etb[2]
144 except IndexError:
145 pass
146 self.prompt_count = self.msg_xreq["content"]["execution_count"]+1
159 147
160 148
161 def handle_sub_channel(self):
149 def handle_sub_channel(self):
162 150 """ Method to procces subscribe channel's messages
163 151
164 152 This method reads a message and processes the content in different
@@ -168,7 +156,7 b' class Frontend(object):'
168 156 sub_msg: message receive from kernel in the sub socket channel
169 157 capture by kernel manager.
170 158 """
171 while self.km.sub_channel.was_called():
159 while self.km.sub_channel.msg_ready():
172 160 sub_msg = self.km.sub_channel.get_msg()
173 161 if self.msg_header["username"] == sub_msg['parent_header']['username'] and \
174 162 self.km.session.session == sub_msg['parent_header']['session']:
@@ -188,14 +176,13 b' class Frontend(object):'
188 176 print >> sys.stdout,"Out[%i]:"%sub_msg["content"]["execution_count"], sub_msg["content"]["data"]["text/plain"]
189 177 sys.stdout.flush()
190 178
191 def handle_rep_channel(self):
192 """ Method to capture raw_input
193 """
194 if self.km.rep_channel.was_called() :
195 self.msg_rep = self.km.rep_channel.get_msg()
196 if self.msg_header["session"] == self.msg_rep["parent_header"]["session"] :
197 raw_data = raw_input(self.msg_rep["content"]["prompt"])
198 self.km.rep_channel.input(raw_data)
179 def handle_rep_channel(self, timeout=0.1):
180 """ Method to capture raw_input
181 """
182 self.msg_rep = self.km.rep_channel.get_msg(timeout=timeout)
183 if self.msg_header["session"] == self.msg_rep["parent_header"]["session"] :
184 raw_data = raw_input(self.msg_rep["content"]["prompt"])
185 self.km.rep_channel.input(raw_data)
199 186
200 187
201 188
@@ -270,7 +257,6 b' def start_frontend():'
270 257
271 258
272 259 kernel_manager.start_channels()
273 time.sleep(4)
274 260
275 261 frontend=Frontend(kernel_manager)
276 262 return frontend
@@ -16,6 +16,7 b' from __future__ import print_function'
16 16
17 17 # Stdlib
18 18 from Queue import Queue, Empty
19 from threading import Event
19 20
20 21 # Our own
21 22 from IPython.utils import io
@@ -104,9 +105,31 b' class BlockingShellSocketChannel(ShellSocketChannel):'
104 105
105 106 class BlockingStdInSocketChannel(StdInSocketChannel):
106 107
108 def __init__(self, context, session, address=None):
109 super(BlockingRepSocketChannel, self).__init__(context, session, address)
110 self._in_queue = Queue()
111
107 112 def call_handlers(self, msg):
108 113 #io.rprint('[[Rep]]', msg) # dbg
109 pass
114 self._in_queue.put(msg)
115
116 def get_msg(self, block=True, timeout=None):
117 "Gets a message if there is one that is ready."
118 return self._in_queue.get(block, timeout)
119
120 def get_msgs(self):
121 """Get all messages that are currently ready."""
122 msgs = []
123 while True:
124 try:
125 msgs.append(self.get_msg(block=False))
126 except Empty:
127 break
128 return msgs
129
130 def msg_ready(self):
131 "Is there a message that has been received?"
132 return not self._in_queue.empty()
110 133
111 134
112 135 class BlockingHBSocketChannel(HBSocketChannel):
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now