##// END OF EJS Templates
Continue refactoring input handling across clients....
Fernando Perez -
Show More
@@ -119,10 +119,6 b' class DisplayHook(Configurable):'
119 def prompt_count(self):
119 def prompt_count(self):
120 return self.shell.execution_count
120 return self.shell.execution_count
121
121
122 @prompt_count.setter
123 def _set_prompt_count(self, val):
124 raise ValueError('prompt count is read only')
125
126 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
122 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
127 if p_str is None:
123 if p_str is None:
128 if self.do_full_cache:
124 if self.do_full_cache:
@@ -180,7 +180,6 b' class HistoryManager(object):'
180 if len(self.input_hist) != len (self.input_hist_raw):
180 if len(self.input_hist) != len (self.input_hist_raw):
181 self.input_hist_raw = InputList(self.input_hist)
181 self.input_hist_raw = InputList(self.input_hist)
182
182
183
184 def reset(self):
183 def reset(self):
185 """Clear all histories managed by this object."""
184 """Clear all histories managed by this object."""
186 self.input_hist[:] = []
185 self.input_hist[:] = []
@@ -371,15 +371,6 b' class InputSplitter(object):'
371 if self.input_mode == 'cell':
371 if self.input_mode == 'cell':
372 self.reset()
372 self.reset()
373
373
374 # If the source code has leading blanks, add 'if 1:\n' to it
375 # this allows execution of indented pasted code. It is tempting
376 # to add '\n' at the end of source to run commands like ' a=1'
377 # directly, but this fails for more complicated scenarios
378
379 if not self._buffer and lines[:1] in [' ', '\t'] and \
380 not comment_line_re.match(lines):
381 lines = 'if 1:\n%s' % lines
382
383 self._store(lines)
374 self._store(lines)
384 source = self.source
375 source = self.source
385
376
@@ -594,7 +585,7 b' class InputSplitter(object):'
594 #print 'safety' # dbg
585 #print 'safety' # dbg
595
586
596 return indent_spaces, full_dedent
587 return indent_spaces, full_dedent
597
588
598 def _update_indent(self, lines):
589 def _update_indent(self, lines):
599 for line in remove_comments(lines).splitlines():
590 for line in remove_comments(lines).splitlines():
600 if line and not line.isspace():
591 if line and not line.isspace():
@@ -400,7 +400,7 b' class InteractiveShell(Configurable, Magic):'
400 self.indent_current_nsp = 0
400 self.indent_current_nsp = 0
401
401
402 # Increasing execution counter
402 # Increasing execution counter
403 self.execution_count = 0
403 self.execution_count = 1
404
404
405 def init_environment(self):
405 def init_environment(self):
406 """Any changes we need to make to the user's environment."""
406 """Any changes we need to make to the user's environment."""
@@ -1558,7 +1558,8 b' class InteractiveShell(Configurable, Magic):'
1558
1558
1559 def _indent_current_str(self):
1559 def _indent_current_str(self):
1560 """return the current level of indentation as a string"""
1560 """return the current level of indentation as a string"""
1561 return self.indent_current_nsp * ' '
1561 #return self.indent_current_nsp * ' '
1562 return self.input_splitter.indent_spaces * ' '
1562
1563
1563 #-------------------------------------------------------------------------
1564 #-------------------------------------------------------------------------
1564 # Things related to text completion
1565 # Things related to text completion
@@ -2095,30 +2096,32 b' class InteractiveShell(Configurable, Magic):'
2095 # original cell may contain non-python syntax).
2096 # original cell may contain non-python syntax).
2096 ipy_cell = ''.join(blocks)
2097 ipy_cell = ''.join(blocks)
2097
2098
2098 # Each cell is a *single* input, regardless of how many lines it has
2099 self.execution_count += 1
2100
2101 # Store raw and processed history
2099 # Store raw and processed history
2102 self.history_manager.store_inputs(ipy_cell, cell)
2100 self.history_manager.store_inputs(ipy_cell, cell)
2103
2101
2104 # dbg code!!!
2102 # dbg code!!!
2105 def myapp(self, val): # dbg
2103 if 0:
2106 import traceback as tb
2104 def myapp(self, val): # dbg
2107 stack = ''.join(tb.format_stack())
2105 import traceback as tb
2108 print 'Value:', val
2106 stack = ''.join(tb.format_stack())
2109 print 'Stack:\n', stack
2107 print 'Value:', val
2110 list.append(self, val)
2108 print 'Stack:\n', stack
2111
2109 list.append(self, val)
2112 import new
2110
2113 self.input_hist.append = new.instancemethod(myapp, self.input_hist,
2111 import new
2114 list)
2112 self.input_hist.append = new.instancemethod(myapp, self.input_hist,
2113 list)
2115 # End dbg
2114 # End dbg
2116
2115
2117 # All user code execution must happen with our context managers active
2116 # All user code execution must happen with our context managers active
2118 with nested(self.builtin_trap, self.display_trap):
2117 with nested(self.builtin_trap, self.display_trap):
2118
2119 # Single-block input should behave like an interactive prompt
2119 # Single-block input should behave like an interactive prompt
2120 if len(blocks) == 1:
2120 if len(blocks) == 1:
2121 return self.run_one_block(blocks[0])
2121 # since we return here, we need to update the execution count
2122 out = self.run_one_block(blocks[0])
2123 self.execution_count += 1
2124 return out
2122
2125
2123 # In multi-block input, if the last block is a simple (one-two
2126 # In multi-block input, if the last block is a simple (one-two
2124 # lines) expression, run it in single mode so it produces output.
2127 # lines) expression, run it in single mode so it produces output.
@@ -2145,6 +2148,9 b' class InteractiveShell(Configurable, Magic):'
2145 # processed input in history
2148 # processed input in history
2146 self.runcode(ipy_cell)
2149 self.runcode(ipy_cell)
2147
2150
2151 # Each cell is a *single* input, regardless of how many lines it has
2152 self.execution_count += 1
2153
2148 def run_one_block(self, block):
2154 def run_one_block(self, block):
2149 """Run a single interactive block.
2155 """Run a single interactive block.
2150
2156
@@ -2214,7 +2220,7 b' class InteractiveShell(Configurable, Magic):'
2214 if more:
2220 if more:
2215 self.push_line('\n')
2221 self.push_line('\n')
2216
2222
2217 def runsource(self, source, filename='<input>', symbol='single'):
2223 def runsource(self, source, filename='<ipython console>', symbol='single'):
2218 """Compile and run some source in the interpreter.
2224 """Compile and run some source in the interpreter.
2219
2225
2220 Arguments are as for compile_command().
2226 Arguments are as for compile_command().
@@ -2247,14 +2253,6 b' class InteractiveShell(Configurable, Magic):'
2247 if type(source)==str:
2253 if type(source)==str:
2248 source = source.decode(self.stdin_encoding)
2254 source = source.decode(self.stdin_encoding)
2249
2255
2250 # if the source code has leading blanks, add 'if 1:\n' to it
2251 # this allows execution of indented pasted code. It is tempting
2252 # to add '\n' at the end of source to run commands like ' a=1'
2253 # directly, but this fails for more complicated scenarios
2254
2255 if source[:1] in [' ', '\t']:
2256 source = u'if 1:\n%s' % source
2257
2258 try:
2256 try:
2259 code = self.compile(source,filename,symbol)
2257 code = self.compile(source,filename,symbol)
2260 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
2258 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
@@ -2361,8 +2359,6 b' class InteractiveShell(Configurable, Magic):'
2361 # push).
2359 # push).
2362
2360
2363 #print 'push line: <%s>' % line # dbg
2361 #print 'push line: <%s>' % line # dbg
2364 for subline in line.splitlines():
2365 self._autoindent_update(subline)
2366 self.buffer.append(line)
2362 self.buffer.append(line)
2367 full_source = '\n'.join(self.buffer)
2363 full_source = '\n'.join(self.buffer)
2368 more = self.runsource(full_source, self.filename)
2364 more = self.runsource(full_source, self.filename)
@@ -2377,6 +2373,7 b' class InteractiveShell(Configurable, Magic):'
2377 """Reset the input buffer."""
2373 """Reset the input buffer."""
2378 self.buffer[:] = []
2374 self.buffer[:] = []
2379 self.buffer_raw[:] = []
2375 self.buffer_raw[:] = []
2376 self.input_splitter.reset()
2380
2377
2381 def _is_secondary_block_start(self, s):
2378 def _is_secondary_block_start(self, s):
2382 if not s.endswith(':'):
2379 if not s.endswith(':'):
@@ -2415,24 +2412,6 b' class InteractiveShell(Configurable, Magic):'
2415
2412
2416 return '\n'.join(res) + '\n'
2413 return '\n'.join(res) + '\n'
2417
2414
2418 def _autoindent_update(self,line):
2419 """Keep track of the indent level."""
2420
2421 #debugx('line')
2422 #debugx('self.indent_current_nsp')
2423 if self.autoindent:
2424 if line:
2425 inisp = num_ini_spaces(line)
2426 if inisp < self.indent_current_nsp:
2427 self.indent_current_nsp = inisp
2428
2429 if line[-1] == ':':
2430 self.indent_current_nsp += 4
2431 elif dedent_re.match(line):
2432 self.indent_current_nsp -= 4
2433 else:
2434 self.indent_current_nsp = 0
2435
2436 #-------------------------------------------------------------------------
2415 #-------------------------------------------------------------------------
2437 # Things related to GUI support and pylab
2416 # Things related to GUI support and pylab
2438 #-------------------------------------------------------------------------
2417 #-------------------------------------------------------------------------
@@ -428,7 +428,7 b' class PrefilterManager(Configurable):'
428 which is the case when the user goes back to a multiline history
428 which is the case when the user goes back to a multiline history
429 entry and presses enter.
429 entry and presses enter.
430 """
430 """
431 llines = lines.rstrip('\n').splitlines()
431 llines = lines.rstrip('\n').split('\n')
432 # We can get multiple lines in one shot, where multiline input 'blends'
432 # We can get multiple lines in one shot, where multiline input 'blends'
433 # into one line, in cases like recalling from the readline history
433 # into one line, in cases like recalling from the readline history
434 # buffer. We need to make sure that in such cases, we correctly
434 # buffer. We need to make sure that in such cases, we correctly
@@ -162,6 +162,12 b' class InputSplitterTestCase(unittest.TestCase):'
162 self.assertEqual(isp.indent_spaces, 4)
162 self.assertEqual(isp.indent_spaces, 4)
163 isp.push('y=2\n')
163 isp.push('y=2\n')
164 self.assertEqual(isp.indent_spaces, 0)
164 self.assertEqual(isp.indent_spaces, 0)
165
166 def test_indent2(self):
167 # In cell mode, inputs must be fed in whole blocks, so skip this test
168 if self.isp.input_mode == 'cell': return
169
170 isp = self.isp
165 isp.push('if 1:')
171 isp.push('if 1:')
166 self.assertEqual(isp.indent_spaces, 4)
172 self.assertEqual(isp.indent_spaces, 4)
167 isp.push(' x=1')
173 isp.push(' x=1')
@@ -170,7 +176,10 b' class InputSplitterTestCase(unittest.TestCase):'
170 isp.push(' '*2)
176 isp.push(' '*2)
171 self.assertEqual(isp.indent_spaces, 4)
177 self.assertEqual(isp.indent_spaces, 4)
172
178
173 def test_indent2(self):
179 def test_indent3(self):
180 # In cell mode, inputs must be fed in whole blocks, so skip this test
181 if self.isp.input_mode == 'cell': return
182
174 isp = self.isp
183 isp = self.isp
175 # When a multiline statement contains parens or multiline strings, we
184 # When a multiline statement contains parens or multiline strings, we
176 # shouldn't get confused.
185 # shouldn't get confused.
@@ -195,13 +204,6 b' class InputSplitterTestCase(unittest.TestCase):'
195 for line in [' x=1', '# a comment', ' y=2']:
204 for line in [' x=1', '# a comment', ' y=2']:
196 self.assertTrue(isp.push(line))
205 self.assertTrue(isp.push(line))
197
206
198 def test_push3(self):
199 """Test input with leading whitespace"""
200 isp = self.isp
201 isp.push(' x=1')
202 isp.push(' y=2')
203 self.assertEqual(isp.source, 'if 1:\n x=1\n y=2\n')
204
205 def test_replace_mode(self):
207 def test_replace_mode(self):
206 isp = self.isp
208 isp = self.isp
207 isp.input_mode = 'cell'
209 isp.input_mode = 'cell'
@@ -216,6 +218,9 b' class InputSplitterTestCase(unittest.TestCase):'
216 self.assertFalse(isp.push_accepts_more())
218 self.assertFalse(isp.push_accepts_more())
217
219
218 def test_push_accepts_more2(self):
220 def test_push_accepts_more2(self):
221 # In cell mode, inputs must be fed in whole blocks, so skip this test
222 if self.isp.input_mode == 'cell': return
223
219 isp = self.isp
224 isp = self.isp
220 isp.push('if 1:')
225 isp.push('if 1:')
221 self.assertTrue(isp.push_accepts_more())
226 self.assertTrue(isp.push_accepts_more())
@@ -230,6 +235,9 b' class InputSplitterTestCase(unittest.TestCase):'
230 self.assertFalse(isp.push_accepts_more())
235 self.assertFalse(isp.push_accepts_more())
231
236
232 def test_push_accepts_more4(self):
237 def test_push_accepts_more4(self):
238 # In cell mode, inputs must be fed in whole blocks, so skip this test
239 if self.isp.input_mode == 'cell': return
240
233 isp = self.isp
241 isp = self.isp
234 # When a multiline statement contains parens or multiline strings, we
242 # When a multiline statement contains parens or multiline strings, we
235 # shouldn't get confused.
243 # shouldn't get confused.
@@ -227,11 +227,6 b' class TerminalInteractiveShell(InteractiveShell):'
227 # exit_now is set by a call to %Exit or %Quit, through the
227 # exit_now is set by a call to %Exit or %Quit, through the
228 # ask_exit callback.
228 # ask_exit callback.
229
229
230 # Before showing any prompts, if the counter is at zero, we execute an
231 # empty line to ensure the user only sees prompts starting at one.
232 if self.execution_count == 0:
233 self.execution_count += 1
234
235 while not self.exit_now:
230 while not self.exit_now:
236 self.hooks.pre_prompt_hook()
231 self.hooks.pre_prompt_hook()
237 if more:
232 if more:
@@ -260,11 +255,6 b' class TerminalInteractiveShell(InteractiveShell):'
260 try:
255 try:
261 self.write('\nKeyboardInterrupt\n')
256 self.write('\nKeyboardInterrupt\n')
262 self.resetbuffer()
257 self.resetbuffer()
263 # keep cache in sync with the prompt counter:
264 self.displayhook.prompt_count -= 1
265
266 if self.autoindent:
267 self.indent_current_nsp = 0
268 more = False
258 more = False
269 except KeyboardInterrupt:
259 except KeyboardInterrupt:
270 pass
260 pass
@@ -285,14 +275,14 b' class TerminalInteractiveShell(InteractiveShell):'
285 # asynchronously by signal handlers, for example.
275 # asynchronously by signal handlers, for example.
286 self.showtraceback()
276 self.showtraceback()
287 else:
277 else:
288 #more = self.push_line(line)
289 self.input_splitter.push(line)
278 self.input_splitter.push(line)
290 more = self.input_splitter.push_accepts_more()
279 more = self.input_splitter.push_accepts_more()
291 if (self.SyntaxTB.last_syntax_error and
280 if (self.SyntaxTB.last_syntax_error and
292 self.autoedit_syntax):
281 self.autoedit_syntax):
293 self.edit_syntax_error()
282 self.edit_syntax_error()
294 if not more:
283 if not more:
295 pass
284 source_raw = self.input_splitter.source_raw_reset()[1]
285 self.run_cell(source_raw)
296
286
297 # We are off again...
287 # We are off again...
298 __builtin__.__dict__['__IPYTHON__active'] -= 1
288 __builtin__.__dict__['__IPYTHON__active'] -= 1
@@ -398,69 +388,6 b' class TerminalInteractiveShell(InteractiveShell):'
398
388
399 return line
389 return line
400
390
401
402 # TODO: The following three methods are an early attempt to refactor
403 # the main code execution logic. We don't use them, but they may be
404 # helpful when we refactor the code execution logic further.
405 # def interact_prompt(self):
406 # """ Print the prompt (in read-eval-print loop)
407 #
408 # Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
409 # used in standard IPython flow.
410 # """
411 # if self.more:
412 # try:
413 # prompt = self.hooks.generate_prompt(True)
414 # except:
415 # self.showtraceback()
416 # if self.autoindent:
417 # self.rl_do_indent = True
418 #
419 # else:
420 # try:
421 # prompt = self.hooks.generate_prompt(False)
422 # except:
423 # self.showtraceback()
424 # self.write(prompt)
425 #
426 # def interact_handle_input(self,line):
427 # """ Handle the input line (in read-eval-print loop)
428 #
429 # Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
430 # used in standard IPython flow.
431 # """
432 # if line.lstrip() == line:
433 # self.shadowhist.add(line.strip())
434 # lineout = self.prefilter_manager.prefilter_lines(line,self.more)
435 #
436 # if line.strip():
437 # if self.more:
438 # self.input_hist_raw[-1] += '%s\n' % line
439 # else:
440 # self.input_hist_raw.append('%s\n' % line)
441 #
442 #
443 # self.more = self.push_line(lineout)
444 # if (self.SyntaxTB.last_syntax_error and
445 # self.autoedit_syntax):
446 # self.edit_syntax_error()
447 #
448 # def interact_with_readline(self):
449 # """ Demo of using interact_handle_input, interact_prompt
450 #
451 # This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
452 # it should work like this.
453 # """
454 # self.readline_startup_hook(self.pre_readline)
455 # while not self.exit_now:
456 # self.interact_prompt()
457 # if self.more:
458 # self.rl_do_indent = True
459 # else:
460 # self.rl_do_indent = False
461 # line = raw_input_original().decode(self.stdin_encoding)
462 # self.interact_handle_input(line)
463
464 #-------------------------------------------------------------------------
391 #-------------------------------------------------------------------------
465 # Methods to support auto-editing of SyntaxErrors.
392 # Methods to support auto-editing of SyntaxErrors.
466 #-------------------------------------------------------------------------
393 #-------------------------------------------------------------------------
@@ -240,7 +240,7 b' class Kernel(Configurable):'
240 reply_content[u'status'] = status
240 reply_content[u'status'] = status
241
241
242 # Return the execution counter so clients can display prompts
242 # Return the execution counter so clients can display prompts
243 reply_content['execution_count'] = shell.execution_count
243 reply_content['execution_count'] = shell.execution_count -1
244
244
245 # FIXME - fish exception info out of shell, possibly left there by
245 # FIXME - fish exception info out of shell, possibly left there by
246 # runlines. We'll need to clean up this logic later.
246 # runlines. We'll need to clean up this logic later.
General Comments 0
You need to be logged in to leave comments. Login now