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