##// END OF EJS Templates
Four possible states for completion reply, & indent hint
Thomas Kluyver -
Show More
@@ -224,6 +224,8 b' class InputSplitter(object):'
224 _full_dedent = False
224 _full_dedent = False
225 # Boolean indicating whether the current block is complete
225 # Boolean indicating whether the current block is complete
226 _is_complete = None
226 _is_complete = None
227 # Boolean indicating whether the current block has an unrecoverable syntax error
228 _is_invalid = False
227
229
228 def __init__(self):
230 def __init__(self):
229 """Create a new InputSplitter instance.
231 """Create a new InputSplitter instance.
@@ -239,6 +241,7 b' class InputSplitter(object):'
239 self.source = ''
241 self.source = ''
240 self.code = None
242 self.code = None
241 self._is_complete = False
243 self._is_complete = False
244 self._is_invalid = False
242 self._full_dedent = False
245 self._full_dedent = False
243
246
244 def source_reset(self):
247 def source_reset(self):
@@ -248,19 +251,39 b' class InputSplitter(object):'
248 self.reset()
251 self.reset()
249 return out
252 return out
250
253
251 def is_complete(self, source):
254 def check_complete(self, source):
252 """Return whether a block of code is ready to execute, or should be continued
255 """Return whether a block of code is ready to execute, or should be continued
253
256
254 This is a non-stateful API, and will reset the state of this InputSplitter.
257 This is a non-stateful API, and will reset the state of this InputSplitter.
258
259 Parameters
260 ----------
261 source : string
262 Python input code, which can be multiline.
263
264 Returns
265 -------
266 status : str
267 One of 'complete', 'incomplete', or 'invalid' if source is not a
268 prefix of valid code.
269 indent_spaces : int or None
270 The number of spaces by which to indent the next line of code. If
271 status is not 'incomplete', this is None.
255 """
272 """
256 self.reset()
273 self.reset()
257 try:
274 try:
258 self.push(source)
275 self.push(source)
259 return not self.push_accepts_more()
260 except SyntaxError:
276 except SyntaxError:
261 # Transformers in IPythonInputSplitter can raise SyntaxError,
277 # Transformers in IPythonInputSplitter can raise SyntaxError,
262 # which push() will not catch.
278 # which push() will not catch.
263 return True
279 return 'invalid', None
280 else:
281 if self._is_invalid:
282 return 'invalid', None
283 elif self.push_accepts_more():
284 return 'incomplete', self.indent_spaces
285 else:
286 return 'complete', None
264 finally:
287 finally:
265 self.reset()
288 self.reset()
266
289
@@ -293,6 +316,7 b' class InputSplitter(object):'
293 # exception is raised in compilation, we don't mislead by having
316 # exception is raised in compilation, we don't mislead by having
294 # inconsistent code/source attributes.
317 # inconsistent code/source attributes.
295 self.code, self._is_complete = None, None
318 self.code, self._is_complete = None, None
319 self._is_invalid = False
296
320
297 # Honor termination lines properly
321 # Honor termination lines properly
298 if source.endswith('\\\n'):
322 if source.endswith('\\\n'):
@@ -309,6 +333,7 b' class InputSplitter(object):'
309 except (SyntaxError, OverflowError, ValueError, TypeError,
333 except (SyntaxError, OverflowError, ValueError, TypeError,
310 MemoryError):
334 MemoryError):
311 self._is_complete = True
335 self._is_complete = True
336 self._is_invalid = True
312 else:
337 else:
313 # Compilation didn't produce any exceptions (though it may not have
338 # Compilation didn't produce any exceptions (though it may not have
314 # given a complete code object)
339 # given a complete code object)
@@ -355,12 +355,12 b' class InputSplitterTestCase(unittest.TestCase):'
355 isp.push(r"(1 \ ")
355 isp.push(r"(1 \ ")
356 self.assertFalse(isp.push_accepts_more())
356 self.assertFalse(isp.push_accepts_more())
357
357
358 def test_is_complete(self):
358 def test_check_complete(self):
359 isp = self.isp
359 isp = self.isp
360 assert isp.is_complete("a = 1")
360 self.assertEqual(isp.check_complete("a = 1"), ('complete', None))
361 assert not isp.is_complete("for a in range(5):")
361 self.assertEqual(isp.check_complete("for a in range(5):"), ('incomplete', 4))
362 assert isp.is_complete("raise = 2") # SyntaxError should mean complete
362 self.assertEqual(isp.check_complete("raise = 2"), ('invalid', None))
363 assert not isp.is_complete("a = [1,\n2,")
363 self.assertEqual(isp.check_complete("a = [1,\n2,"), ('incomplete', 0))
364
364
365 class InteractiveLoopTestCase(unittest.TestCase):
365 class InteractiveLoopTestCase(unittest.TestCase):
366 """Tests for an interactive loop like a python shell.
366 """Tests for an interactive loop like a python shell.
@@ -211,13 +211,14 b' def test_is_complete():'
211 # that the kernel exposes the interface correctly.
211 # that the kernel exposes the interface correctly.
212 kc.is_complete('2+2')
212 kc.is_complete('2+2')
213 reply = kc.get_shell_msg(block=True, timeout=TIMEOUT)
213 reply = kc.get_shell_msg(block=True, timeout=TIMEOUT)
214 assert reply['content']['complete']
214 assert reply['content']['status'] == 'complete'
215
215
216 # SyntaxError should mean it's complete
216 # SyntaxError should mean it's complete
217 kc.is_complete('raise = 2')
217 kc.is_complete('raise = 2')
218 reply = kc.get_shell_msg(block=True, timeout=TIMEOUT)
218 reply = kc.get_shell_msg(block=True, timeout=TIMEOUT)
219 assert reply['content']['complete']
219 assert reply['content']['status'] == 'invalid'
220
220
221 kc.is_complete('a = [1,\n2,')
221 kc.is_complete('a = [1,\n2,')
222 reply = kc.get_shell_msg(block=True, timeout=TIMEOUT)
222 reply = kc.get_shell_msg(block=True, timeout=TIMEOUT)
223 assert not reply['content']['complete']
223 assert reply['content']['status'] == 'incomplete'
224 assert reply['content']['indent'] == '' No newline at end of file
@@ -161,7 +161,15 b' class KernelInfoReply(Reference):'
161
161
162
162
163 class IsCompleteReply(Reference):
163 class IsCompleteReply(Reference):
164 complete = Bool()
164 status = Enum((u'complete', u'incomplete', u'invalid', u'unknown'))
165
166 def check(self, d):
167 Reference.check(self, d)
168 if d['status'] == 'incomplete':
169 IsCompleteReplyIncomplete().check(d)
170
171 class IsCompleteReplyIncomplete(Reference):
172 indent = Unicode()
165
173
166
174
167 # IOPub messages
175 # IOPub messages
@@ -230,8 +230,11 b' class IPythonKernel(KernelBase):'
230 return dict(status='ok', restart=restart)
230 return dict(status='ok', restart=restart)
231
231
232 def do_is_complete(self, code):
232 def do_is_complete(self, code):
233 complete = self.shell.input_transformer_manager.is_complete(code)
233 status, indent_spaces = self.shell.input_transformer_manager.check_complete(code)
234 return {'complete': complete}
234 r = {'status': status}
235 if status == 'incomplete':
236 r['indent'] = ' ' * indent_spaces
237 return r
235
238
236 def do_apply(self, content, bufs, msg_id, reply_metadata):
239 def do_apply(self, content, bufs, msg_id, reply_metadata):
237 shell = self.shell
240 shell = self.shell
@@ -493,7 +493,7 b' class Kernel(Configurable):'
493 def do_is_complete(self, code):
493 def do_is_complete(self, code):
494 """Override in subclasses to find completions.
494 """Override in subclasses to find completions.
495 """
495 """
496 return {'complete' : True,
496 return {'status' : 'unknown',
497 }
497 }
498
498
499 #---------------------------------------------------------------------------
499 #---------------------------------------------------------------------------
@@ -585,9 +585,19 b' decide whether to immediately execute the current code, or whether to show a'
585 continuation prompt for further input. For instance, in Python ``a = 5`` would
585 continuation prompt for further input. For instance, in Python ``a = 5`` would
586 be executed immediately, while ``for i in range(5):`` would expect further input.
586 be executed immediately, while ``for i in range(5):`` would expect further input.
587
587
588 There are four possible replies:
589
590 - *complete* code is ready to be executed
591 - *incomplete* code should prompt for another line
592 - *invalid* code will typically be sent for execution, so that the user sees the
593 error soonest.
594 - *unknown* - if the kernel is not able to determine this. The frontend should
595 also handle the kernel not replying promptly. It may default to sending the
596 code for execution, or it may implement simple fallback heuristics for whether
597 to execute the code (e.g. execute after a blank line).
598
588 Frontends may have ways to override this, forcing the code to be sent for
599 Frontends may have ways to override this, forcing the code to be sent for
589 execution or forcing a continuation prompt. If the kernel does not reply promptly,
600 execution or forcing a continuation prompt.
590 the frontend will probably default to sending the code to be executed.
591
601
592 Message type: ``is_complete_request``::
602 Message type: ``is_complete_request``::
593
603
@@ -596,11 +606,17 b' Message type: ``is_complete_request``::'
596 'code' : str,
606 'code' : str,
597 }
607 }
598
608
599 Message type: ``complete_reply``::
609 Message type: ``is_complete_reply``::
600
610
601 content = {
611 content = {
602 # True if the code is ready to execute, False if not
612 # One of 'complete', 'incomplete', 'invalid', 'unknown'
603 'complete' : bool,
613 'status' : str,
614
615 # If status is 'incomplete', indent should contain the characters to use
616 # to indent the next line. This is only a hint: frontends may ignore it
617 # and use their own autoindentation rules. For other statuses, this
618 # field does not exist.
619 'indent': str,
604 }
620 }
605
621
606 Connect
622 Connect
General Comments 0
You need to be logged in to leave comments. Login now