##// END OF EJS Templates
update message spec adapter per review...
MinRK -
Show More
@@ -81,16 +81,23 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):'
81 km = self.kernel_manager
81 km = self.kernel_manager
82 meth = getattr(km, 'connect_%s' % self.channel)
82 meth = getattr(km, 'connect_%s' % self.channel)
83 self.zmq_stream = meth(self.kernel_id, identity=self.session.bsession)
83 self.zmq_stream = meth(self.kernel_id, identity=self.session.bsession)
84 # Create a kernel_info channel to query the kernel protocol version.
85 # This channel will be closed after the kernel_info reply is received.
84 self.kernel_info_channel = None
86 self.kernel_info_channel = None
85 self.kernel_info_channel = km.connect_shell(self.kernel_id)
87 self.kernel_info_channel = km.connect_shell(self.kernel_id)
86 self.kernel_info_channel.on_recv(self._handle_kernel_info)
88 self.kernel_info_channel.on_recv(self._handle_kernel_info_reply)
87 self._request_kernel_info()
89 self._request_kernel_info()
88
90
89 def _request_kernel_info(self):
91 def _request_kernel_info(self):
92 """send a request for kernel_info"""
90 self.log.debug("requesting kernel info")
93 self.log.debug("requesting kernel info")
91 self.session.send(self.kernel_info_channel, "kernel_info_request")
94 self.session.send(self.kernel_info_channel, "kernel_info_request")
92
95
93 def _handle_kernel_info(self, msg):
96 def _handle_kernel_info_reply(self, msg):
97 """process the kernel_info_reply
98
99 enabling msg spec adaptation, if necessary
100 """
94 idents,msg = self.session.feed_identities(msg)
101 idents,msg = self.session.feed_identities(msg)
95 try:
102 try:
96 msg = self.session.unserialize(msg)
103 msg = self.session.unserialize(msg)
@@ -171,6 +171,15 b' var IPython = (function (IPython) {'
171 var matches = content.matches;
171 var matches = content.matches;
172
172
173 var cur = this.editor.getCursor();
173 var cur = this.editor.getCursor();
174 if (end === null) {
175 // adapted message spec replies don't have cursor position info,
176 // interpret end=null as current position,
177 // and negative start relative to that
178 end = utils.to_absolute_cursor_pos(this.editor, cur);
179 if (start < 0) {
180 start = end + start;
181 }
182 }
174 var results = CodeMirror.contextHint(this.editor);
183 var results = CodeMirror.contextHint(this.editor);
175 var filtered_results = [];
184 var filtered_results = [];
176 //remove results from context completion
185 //remove results from context completion
@@ -5,7 +5,7 b''
5
5
6 import json
6 import json
7
7
8 from IPython.core.release import kernel_protocol_version, kernel_protocol_version_info
8 from IPython.core.release import kernel_protocol_version_info
9 from IPython.utils.tokenutil import token_at_cursor
9 from IPython.utils.tokenutil import token_at_cursor
10
10
11
11
@@ -45,6 +45,13 b' class Adapter(object):'
45 msg['msg_type'] = header['msg_type'] = self.msg_type_map[msg_type]
45 msg['msg_type'] = header['msg_type'] = self.msg_type_map[msg_type]
46 return msg
46 return msg
47
47
48 def handle_reply_status_error(msg):
49 """This will be called *instead of* the regular handler
50
51 on any reply with status != ok
52 """
53 return msg
54
48 def __call__(self, msg):
55 def __call__(self, msg):
49 msg = self.update_header(msg)
56 msg = self.update_header(msg)
50 msg = self.update_metadata(msg)
57 msg = self.update_metadata(msg)
@@ -54,9 +61,10 b' class Adapter(object):'
54 handler = getattr(self, header['msg_type'], None)
61 handler = getattr(self, header['msg_type'], None)
55 if handler is None:
62 if handler is None:
56 return msg
63 return msg
57 # no transform for status=error
64
65 # handle status=error replies separately (no change, at present)
58 if msg['content'].get('status', None) in {'error', 'aborted'}:
66 if msg['content'].get('status', None) in {'error', 'aborted'}:
59 return msg
67 return self.handle_reply_status_error(msg)
60 return handler(msg)
68 return handler(msg)
61
69
62 def _version_str_to_list(version):
70 def _version_str_to_list(version):
@@ -143,7 +151,7 b' class V5toV4(Adapter):'
143 cursor_pos = content['cursor_pos']
151 cursor_pos = content['cursor_pos']
144 line, _ = code_to_line(code, cursor_pos)
152 line, _ = code_to_line(code, cursor_pos)
145
153
146 new_content = msg['content'] = {'status' : 'ok'}
154 new_content = msg['content'] = {}
147 new_content['oname'] = token_at_cursor(code, cursor_pos)
155 new_content['oname'] = token_at_cursor(code, cursor_pos)
148 new_content['detail_level'] = content['detail_level']
156 new_content['detail_level'] = content['detail_level']
149 return msg
157 return msg
@@ -173,12 +181,10 b' class V5toV4(Adapter):'
173 msg['content'].pop('password', None)
181 msg['content'].pop('password', None)
174 return msg
182 return msg
175
183
176 def _tuple_to_str(version):
177 return ".".join(map(str, version))
178
184
179 class V4toV5(Adapter):
185 class V4toV5(Adapter):
180 """Convert msg spec V4 to V5"""
186 """Convert msg spec V4 to V5"""
181 version = kernel_protocol_version
187 version = '5.0'
182
188
183 # invert message renames above
189 # invert message renames above
184 msg_type_map = {v:k for k,v in V5toV4.msg_type_map.items()}
190 msg_type_map = {v:k for k,v in V5toV4.msg_type_map.items()}
@@ -227,13 +233,14 b' class V4toV5(Adapter):'
227 return msg
233 return msg
228
234
229 def complete_reply(self, msg):
235 def complete_reply(self, msg):
230 # TODO: complete_reply needs more context than we have
236 # complete_reply needs more context than we have to get cursor_start and end.
231 # Maybe strip common prefix and give magic cursor_start = cursor_end = 0?
237 # use special value of `-1` to indicate to frontend that it should be at
238 # the current cursor position.
232 content = msg['content']
239 content = msg['content']
233 new_content = msg['content'] = {'status' : 'ok'}
240 new_content = msg['content'] = {'status' : 'ok'}
234 n = len(content['matched_text'])
241 new_content['matches'] = content['matches']
235 new_content['matches'] = [ m[n:] for m in content['matches'] ]
242 new_content['cursor_start'] = -len(content['matched_text'])
236 new_content['cursor_start'] = new_content['cursor_end'] = 0
243 new_content['cursor_end'] = None
237 new_content['metadata'] = {}
244 new_content['metadata'] = {}
238 return msg
245 return msg
239
246
@@ -114,13 +114,11 b' class V4toV5TestCase(AdapterTest):'
114 v4, v5 = self.adapt(msg)
114 v4, v5 = self.adapt(msg)
115 v4c = v4['content']
115 v4c = v4['content']
116 v5c = v5['content']
116 v5c = v5['content']
117 n = len(v4c['matched_text'])
118 expected_matches = [ m[n:] for m in v4c['matches'] ]
119
117
120 self.assertEqual(v5c['matches'], expected_matches)
118 self.assertEqual(v5c['matches'], v4c['matches'])
121 self.assertEqual(v5c['metadata'], {})
119 self.assertEqual(v5c['metadata'], {})
122 self.assertEqual(v5c['cursor_start'], 0)
120 self.assertEqual(v5c['cursor_start'], -4)
123 self.assertEqual(v5c['cursor_end'], 0)
121 self.assertEqual(v5c['cursor_end'], None)
124
122
125 def test_object_info_request(self):
123 def test_object_info_request(self):
126 msg = self.msg("object_info_request", {
124 msg = self.msg("object_info_request", {
General Comments 0
You need to be logged in to leave comments. Login now