##// END OF EJS Templates
Continue refactoring input handling across clients....
Fernando Perez -
Show More
@@ -119,10 +119,6 b' class DisplayHook(Configurable):'
119 119 def prompt_count(self):
120 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 122 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
127 123 if p_str is None:
128 124 if self.do_full_cache:
@@ -180,7 +180,6 b' class HistoryManager(object):'
180 180 if len(self.input_hist) != len (self.input_hist_raw):
181 181 self.input_hist_raw = InputList(self.input_hist)
182 182
183
184 183 def reset(self):
185 184 """Clear all histories managed by this object."""
186 185 self.input_hist[:] = []
@@ -371,15 +371,6 b' class InputSplitter(object):'
371 371 if self.input_mode == 'cell':
372 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 374 self._store(lines)
384 375 source = self.source
385 376
@@ -594,7 +585,7 b' class InputSplitter(object):'
594 585 #print 'safety' # dbg
595 586
596 587 return indent_spaces, full_dedent
597
588
598 589 def _update_indent(self, lines):
599 590 for line in remove_comments(lines).splitlines():
600 591 if line and not line.isspace():
@@ -400,7 +400,7 b' class InteractiveShell(Configurable, Magic):'
400 400 self.indent_current_nsp = 0
401 401
402 402 # Increasing execution counter
403 self.execution_count = 0
403 self.execution_count = 1
404 404
405 405 def init_environment(self):
406 406 """Any changes we need to make to the user's environment."""
@@ -1558,7 +1558,8 b' class InteractiveShell(Configurable, Magic):'
1558 1558
1559 1559 def _indent_current_str(self):
1560 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 1565 # Things related to text completion
@@ -2095,30 +2096,32 b' class InteractiveShell(Configurable, Magic):'
2095 2096 # original cell may contain non-python syntax).
2096 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 2099 # Store raw and processed history
2102 2100 self.history_manager.store_inputs(ipy_cell, cell)
2103 2101
2104 2102 # dbg code!!!
2105 def myapp(self, val): # dbg
2106 import traceback as tb
2107 stack = ''.join(tb.format_stack())
2108 print 'Value:', val
2109 print 'Stack:\n', stack
2110 list.append(self, val)
2111
2112 import new
2113 self.input_hist.append = new.instancemethod(myapp, self.input_hist,
2114 list)
2103 if 0:
2104 def myapp(self, val): # dbg
2105 import traceback as tb
2106 stack = ''.join(tb.format_stack())
2107 print 'Value:', val
2108 print 'Stack:\n', stack
2109 list.append(self, val)
2110
2111 import new
2112 self.input_hist.append = new.instancemethod(myapp, self.input_hist,
2113 list)
2115 2114 # End dbg
2116 2115
2117 2116 # All user code execution must happen with our context managers active
2118 2117 with nested(self.builtin_trap, self.display_trap):
2118
2119 2119 # Single-block input should behave like an interactive prompt
2120 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 2126 # In multi-block input, if the last block is a simple (one-two
2124 2127 # lines) expression, run it in single mode so it produces output.
@@ -2145,6 +2148,9 b' class InteractiveShell(Configurable, Magic):'
2145 2148 # processed input in history
2146 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 2154 def run_one_block(self, block):
2149 2155 """Run a single interactive block.
2150 2156
@@ -2214,7 +2220,7 b' class InteractiveShell(Configurable, Magic):'
2214 2220 if more:
2215 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 2224 """Compile and run some source in the interpreter.
2219 2225
2220 2226 Arguments are as for compile_command().
@@ -2247,14 +2253,6 b' class InteractiveShell(Configurable, Magic):'
2247 2253 if type(source)==str:
2248 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 2256 try:
2259 2257 code = self.compile(source,filename,symbol)
2260 2258 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
@@ -2361,8 +2359,6 b' class InteractiveShell(Configurable, Magic):'
2361 2359 # push).
2362 2360
2363 2361 #print 'push line: <%s>' % line # dbg
2364 for subline in line.splitlines():
2365 self._autoindent_update(subline)
2366 2362 self.buffer.append(line)
2367 2363 full_source = '\n'.join(self.buffer)
2368 2364 more = self.runsource(full_source, self.filename)
@@ -2377,6 +2373,7 b' class InteractiveShell(Configurable, Magic):'
2377 2373 """Reset the input buffer."""
2378 2374 self.buffer[:] = []
2379 2375 self.buffer_raw[:] = []
2376 self.input_splitter.reset()
2380 2377
2381 2378 def _is_secondary_block_start(self, s):
2382 2379 if not s.endswith(':'):
@@ -2415,24 +2412,6 b' class InteractiveShell(Configurable, Magic):'
2415 2412
2416 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 2416 # Things related to GUI support and pylab
2438 2417 #-------------------------------------------------------------------------
@@ -428,7 +428,7 b' class PrefilterManager(Configurable):'
428 428 which is the case when the user goes back to a multiline history
429 429 entry and presses enter.
430 430 """
431 llines = lines.rstrip('\n').splitlines()
431 llines = lines.rstrip('\n').split('\n')
432 432 # We can get multiple lines in one shot, where multiline input 'blends'
433 433 # into one line, in cases like recalling from the readline history
434 434 # buffer. We need to make sure that in such cases, we correctly
@@ -162,6 +162,12 b' class InputSplitterTestCase(unittest.TestCase):'
162 162 self.assertEqual(isp.indent_spaces, 4)
163 163 isp.push('y=2\n')
164 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 171 isp.push('if 1:')
166 172 self.assertEqual(isp.indent_spaces, 4)
167 173 isp.push(' x=1')
@@ -170,7 +176,10 b' class InputSplitterTestCase(unittest.TestCase):'
170 176 isp.push(' '*2)
171 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 183 isp = self.isp
175 184 # When a multiline statement contains parens or multiline strings, we
176 185 # shouldn't get confused.
@@ -195,13 +204,6 b' class InputSplitterTestCase(unittest.TestCase):'
195 204 for line in [' x=1', '# a comment', ' y=2']:
196 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 207 def test_replace_mode(self):
206 208 isp = self.isp
207 209 isp.input_mode = 'cell'
@@ -216,6 +218,9 b' class InputSplitterTestCase(unittest.TestCase):'
216 218 self.assertFalse(isp.push_accepts_more())
217 219
218 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 224 isp = self.isp
220 225 isp.push('if 1:')
221 226 self.assertTrue(isp.push_accepts_more())
@@ -230,6 +235,9 b' class InputSplitterTestCase(unittest.TestCase):'
230 235 self.assertFalse(isp.push_accepts_more())
231 236
232 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 241 isp = self.isp
234 242 # When a multiline statement contains parens or multiline strings, we
235 243 # shouldn't get confused.
@@ -227,11 +227,6 b' class TerminalInteractiveShell(InteractiveShell):'
227 227 # exit_now is set by a call to %Exit or %Quit, through the
228 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 230 while not self.exit_now:
236 231 self.hooks.pre_prompt_hook()
237 232 if more:
@@ -260,11 +255,6 b' class TerminalInteractiveShell(InteractiveShell):'
260 255 try:
261 256 self.write('\nKeyboardInterrupt\n')
262 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 258 more = False
269 259 except KeyboardInterrupt:
270 260 pass
@@ -285,14 +275,14 b' class TerminalInteractiveShell(InteractiveShell):'
285 275 # asynchronously by signal handlers, for example.
286 276 self.showtraceback()
287 277 else:
288 #more = self.push_line(line)
289 278 self.input_splitter.push(line)
290 279 more = self.input_splitter.push_accepts_more()
291 280 if (self.SyntaxTB.last_syntax_error and
292 281 self.autoedit_syntax):
293 282 self.edit_syntax_error()
294 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 287 # We are off again...
298 288 __builtin__.__dict__['__IPYTHON__active'] -= 1
@@ -398,69 +388,6 b' class TerminalInteractiveShell(InteractiveShell):'
398 388
399 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 392 # Methods to support auto-editing of SyntaxErrors.
466 393 #-------------------------------------------------------------------------
@@ -240,7 +240,7 b' class Kernel(Configurable):'
240 240 reply_content[u'status'] = status
241 241
242 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 245 # FIXME - fish exception info out of shell, possibly left there by
246 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