##// 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 224 _full_dedent = False
225 225 # Boolean indicating whether the current block is complete
226 226 _is_complete = None
227 # Boolean indicating whether the current block has an unrecoverable syntax error
228 _is_invalid = False
227 229
228 230 def __init__(self):
229 231 """Create a new InputSplitter instance.
@@ -239,6 +241,7 b' class InputSplitter(object):'
239 241 self.source = ''
240 242 self.code = None
241 243 self._is_complete = False
244 self._is_invalid = False
242 245 self._full_dedent = False
243 246
244 247 def source_reset(self):
@@ -248,19 +251,39 b' class InputSplitter(object):'
248 251 self.reset()
249 252 return out
250 253
251 def is_complete(self, source):
254 def check_complete(self, source):
252 255 """Return whether a block of code is ready to execute, or should be continued
253 256
254 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 273 self.reset()
257 274 try:
258 275 self.push(source)
259 return not self.push_accepts_more()
260 276 except SyntaxError:
261 277 # Transformers in IPythonInputSplitter can raise SyntaxError,
262 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 287 finally:
265 288 self.reset()
266 289
@@ -293,6 +316,7 b' class InputSplitter(object):'
293 316 # exception is raised in compilation, we don't mislead by having
294 317 # inconsistent code/source attributes.
295 318 self.code, self._is_complete = None, None
319 self._is_invalid = False
296 320
297 321 # Honor termination lines properly
298 322 if source.endswith('\\\n'):
@@ -309,6 +333,7 b' class InputSplitter(object):'
309 333 except (SyntaxError, OverflowError, ValueError, TypeError,
310 334 MemoryError):
311 335 self._is_complete = True
336 self._is_invalid = True
312 337 else:
313 338 # Compilation didn't produce any exceptions (though it may not have
314 339 # given a complete code object)
@@ -355,12 +355,12 b' class InputSplitterTestCase(unittest.TestCase):'
355 355 isp.push(r"(1 \ ")
356 356 self.assertFalse(isp.push_accepts_more())
357 357
358 def test_is_complete(self):
358 def test_check_complete(self):
359 359 isp = self.isp
360 assert isp.is_complete("a = 1")
361 assert not isp.is_complete("for a in range(5):")
362 assert isp.is_complete("raise = 2") # SyntaxError should mean complete
363 assert not isp.is_complete("a = [1,\n2,")
360 self.assertEqual(isp.check_complete("a = 1"), ('complete', None))
361 self.assertEqual(isp.check_complete("for a in range(5):"), ('incomplete', 4))
362 self.assertEqual(isp.check_complete("raise = 2"), ('invalid', None))
363 self.assertEqual(isp.check_complete("a = [1,\n2,"), ('incomplete', 0))
364 364
365 365 class InteractiveLoopTestCase(unittest.TestCase):
366 366 """Tests for an interactive loop like a python shell.
@@ -211,13 +211,14 b' def test_is_complete():'
211 211 # that the kernel exposes the interface correctly.
212 212 kc.is_complete('2+2')
213 213 reply = kc.get_shell_msg(block=True, timeout=TIMEOUT)
214 assert reply['content']['complete']
214 assert reply['content']['status'] == 'complete'
215 215
216 216 # SyntaxError should mean it's complete
217 217 kc.is_complete('raise = 2')
218 218 reply = kc.get_shell_msg(block=True, timeout=TIMEOUT)
219 assert reply['content']['complete']
219 assert reply['content']['status'] == 'invalid'
220 220
221 221 kc.is_complete('a = [1,\n2,')
222 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 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 175 # IOPub messages
@@ -230,8 +230,11 b' class IPythonKernel(KernelBase):'
230 230 return dict(status='ok', restart=restart)
231 231
232 232 def do_is_complete(self, code):
233 complete = self.shell.input_transformer_manager.is_complete(code)
234 return {'complete': complete}
233 status, indent_spaces = self.shell.input_transformer_manager.check_complete(code)
234 r = {'status': status}
235 if status == 'incomplete':
236 r['indent'] = ' ' * indent_spaces
237 return r
235 238
236 239 def do_apply(self, content, bufs, msg_id, reply_metadata):
237 240 shell = self.shell
@@ -493,7 +493,7 b' class Kernel(Configurable):'
493 493 def do_is_complete(self, code):
494 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 585 continuation prompt for further input. For instance, in Python ``a = 5`` would
586 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 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,
590 the frontend will probably default to sending the code to be executed.
600 execution or forcing a continuation prompt.
591 601
592 602 Message type: ``is_complete_request``::
593 603
@@ -596,11 +606,17 b' Message type: ``is_complete_request``::'
596 606 'code' : str,
597 607 }
598 608
599 Message type: ``complete_reply``::
609 Message type: ``is_complete_reply``::
600 610
601 611 content = {
602 # True if the code is ready to execute, False if not
603 'complete' : bool,
612 # One of 'complete', 'incomplete', 'invalid', 'unknown'
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 622 Connect
General Comments 0
You need to be logged in to leave comments. Login now