##// END OF EJS Templates
Add support for accessing raw data to inputsplitter....
Fernando Perez -
Show More
@@ -61,13 +61,12 b' class HistoryManager(object):'
61 61 histfname = 'history'
62 62 self.hist_file = os.path.join(shell.ipython_dir, histfname)
63 63
64 # Fill the history zero entry, user counter starts at 1
65 self.input_hist.append('\n')
66 self.input_hist_raw.append('\n')
67
68 64 # Objects related to shadow history management
69 65 self._init_shadow_hist()
70 66
67 # Fill the history zero entry, user counter starts at 1
68 self.store_inputs('\n', '\n')
69
71 70 # For backwards compatibility, we must put these back in the shell
72 71 # object, until we've removed all direct uses of the history objects in
73 72 # the shell itself.
@@ -154,10 +153,42 b' class HistoryManager(object):'
154 153 hist[i] = (input_hist[i], output_hist.get(i))
155 154 else:
156 155 hist[i] = input_hist[i]
157 if len(hist)==0:
156 if not hist:
158 157 raise IndexError('No history for range of indices: %r' % index)
159 158 return hist
160 159
160 def store_inputs(self, source, source_raw=None):
161 """Store source and raw input in history.
162
163 Parameters
164 ----------
165 source : str
166 Python input.
167
168 source_raw : str, optional
169 If given, this is the raw input without any IPython transformations
170 applied to it. If not given, ``source`` is used.
171 """
172 if source_raw is None:
173 source_raw = source
174 self.input_hist.append(source)
175 self.input_hist_raw.append(source_raw)
176 self.shadow_hist.add(source)
177
178 def sync_inputs(self):
179 """Ensure raw and translated histories have same length."""
180 if len(self.input_hist) != len (self.input_hist_raw):
181 self.input_hist_raw = InputList(self.input_hist)
182
183
184 def reset(self):
185 """Clear all histories managed by this object."""
186 self.input_hist[:] = []
187 self.input_hist_raw[:] = []
188 self.output_hist.clear()
189 # The directory history can't be completely empty
190 self.dir_hist[:] = [os.getcwd()]
191
161 192
162 193 def magic_history(self, parameter_s = ''):
163 194 """Print input history (_i<n> variables), with most recent last.
@@ -600,20 +600,23 b' class InputSplitter(object):'
600 600 if line and not line.isspace():
601 601 self.indent_spaces, self._full_dedent = self._find_indent(line)
602 602
603 def _store(self, lines):
603 def _store(self, lines, buffer=None, store='source'):
604 604 """Store one or more lines of input.
605 605
606 606 If input lines are not newline-terminated, a newline is automatically
607 607 appended."""
608 608
609 if buffer is None:
610 buffer = self._buffer
611
609 612 if lines.endswith('\n'):
610 self._buffer.append(lines)
613 buffer.append(lines)
611 614 else:
612 self._buffer.append(lines+'\n')
613 self._set_source()
615 buffer.append(lines+'\n')
616 setattr(self, store, self._set_source(buffer))
614 617
615 def _set_source(self):
616 self.source = ''.join(self._buffer).encode(self.encoding)
618 def _set_source(self, buffer):
619 return ''.join(buffer).encode(self.encoding)
617 620
618 621
619 622 #-----------------------------------------------------------------------------
@@ -933,6 +936,32 b' transform_escaped = EscapedTransformer()'
933 936 class IPythonInputSplitter(InputSplitter):
934 937 """An input splitter that recognizes all of IPython's special syntax."""
935 938
939 # String with raw, untransformed input.
940 source_raw = ''
941
942 # Private attributes
943
944 # List with lines of raw input accumulated so far.
945 _buffer_raw = None
946
947 def __init__(self, input_mode=None):
948 InputSplitter.__init__(self, input_mode)
949 self._buffer_raw = []
950
951 def reset(self):
952 """Reset the input buffer and associated state."""
953 InputSplitter.reset(self)
954 self._buffer_raw[:] = []
955 self.source_raw = ''
956
957 def source_raw_reset(self):
958 """Return input and raw source and perform a full reset.
959 """
960 out = self.source
961 out_r = self.source_raw
962 self.reset()
963 return out, out_r
964
936 965 def push(self, lines):
937 966 """Push one or more lines of IPython input.
938 967 """
@@ -965,12 +994,17 b' class IPythonInputSplitter(InputSplitter):'
965 994 # line.
966 995 changed_input_mode = False
967 996
968 if len(lines_list)>1 and self.input_mode == 'cell':
997 if self.input_mode == 'cell':
969 998 self.reset()
970 999 changed_input_mode = True
971 1000 saved_input_mode = 'cell'
972 1001 self.input_mode = 'line'
973 1002
1003 # Store raw source before applying any transformations to it. Note
1004 # that this must be done *after* the reset() call that would otherwise
1005 # flush the buffer.
1006 self._store(lines, self._buffer_raw, 'source_raw')
1007
974 1008 try:
975 1009 push = super(IPythonInputSplitter, self).push
976 1010 for line in lines_list:
@@ -983,5 +1017,4 b' class IPythonInputSplitter(InputSplitter):'
983 1017 finally:
984 1018 if changed_input_mode:
985 1019 self.input_mode = saved_input_mode
986
987 1020 return out
@@ -369,8 +369,9 b' class InteractiveShell(Configurable, Magic):'
369 369 # command compiler
370 370 self.compile = codeop.CommandCompiler()
371 371
372 # User input buffer
372 # User input buffers
373 373 self.buffer = []
374 self.buffer_raw = []
374 375
375 376 # Make an empty namespace, which extension writers can rely on both
376 377 # existing and NEVER being used by ipython itself. This gives them a
@@ -965,30 +966,25 b' class InteractiveShell(Configurable, Magic):'
965 966 # Finally, update the real user's namespace
966 967 self.user_ns.update(ns)
967 968
968
969 969 def reset(self):
970 970 """Clear all internal namespaces.
971 971
972 972 Note that this is much more aggressive than %reset, since it clears
973 973 fully all namespaces, as well as all input/output lists.
974 974 """
975 for ns in self.ns_refs_table:
976 ns.clear()
977
978 self.alias_manager.clear_aliases()
979
980 # Clear input and output histories
981 self.input_hist[:] = []
982 self.input_hist_raw[:] = []
983 self.output_hist.clear()
975 # Clear histories
976 self.history_manager.reset()
984 977
985 978 # Reset counter used to index all histories
986 979 self.execution_count = 0
987 980
988 981 # Restore the user namespaces to minimal usability
982 for ns in self.ns_refs_table:
983 ns.clear()
989 984 self.init_user_ns()
990 985
991 986 # Restore the default and user aliases
987 self.alias_manager.clear_aliases()
992 988 self.alias_manager.init_aliases()
993 989
994 990 def reset_selective(self, regex=None):
@@ -2103,9 +2099,7 b' class InteractiveShell(Configurable, Magic):'
2103 2099 self.execution_count += 1
2104 2100
2105 2101 # Store raw and processed history
2106 self.input_hist_raw.append(cell)
2107 self.input_hist.append(ipy_cell)
2108
2102 self.history_manager.store_inputs(ipy_cell, cell)
2109 2103
2110 2104 # dbg code!!!
2111 2105 def myapp(self, val): # dbg
@@ -2194,7 +2188,13 b' class InteractiveShell(Configurable, Magic):'
2194 2188 # interactive IPython session (via a magic, for example).
2195 2189 self.resetbuffer()
2196 2190 lines = lines.splitlines()
2197 more = 0
2191
2192 # Since we will prefilter all lines, store the user's raw input too
2193 # before we apply any transformations
2194 self.buffer_raw[:] = [ l+'\n' for l in lines]
2195
2196 more = False
2197 prefilter_lines = self.prefilter_manager.prefilter_lines
2198 2198 with nested(self.builtin_trap, self.display_trap):
2199 2199 for line in lines:
2200 2200 # skip blank lines so we don't mess up the prompt counter, but
@@ -2202,19 +2202,13 b' class InteractiveShell(Configurable, Magic):'
2202 2202 # is true)
2203 2203
2204 2204 if line or more:
2205 # push to raw history, so hist line numbers stay in sync
2206 self.input_hist_raw.append(line + '\n')
2207 prefiltered = self.prefilter_manager.prefilter_lines(line,
2208 more)
2209 more = self.push_line(prefiltered)
2205 more = self.push_line(prefilter_lines(line, more))
2210 2206 # IPython's runsource returns None if there was an error
2211 2207 # compiling the code. This allows us to stop processing
2212 2208 # right away, so the user gets the error message at the
2213 2209 # right place.
2214 2210 if more is None:
2215 2211 break
2216 else:
2217 self.input_hist_raw.append("\n")
2218 2212 # final newline in case the input didn't have it, so that the code
2219 2213 # actually does get executed
2220 2214 if more:
@@ -2370,8 +2364,11 b' class InteractiveShell(Configurable, Magic):'
2370 2364 for subline in line.splitlines():
2371 2365 self._autoindent_update(subline)
2372 2366 self.buffer.append(line)
2373 more = self.runsource('\n'.join(self.buffer), self.filename)
2367 full_source = '\n'.join(self.buffer)
2368 more = self.runsource(full_source, self.filename)
2374 2369 if not more:
2370 self.history_manager.store_inputs('\n'.join(self.buffer_raw),
2371 full_source)
2375 2372 self.resetbuffer()
2376 2373 self.execution_count += 1
2377 2374 return more
@@ -2379,6 +2376,7 b' class InteractiveShell(Configurable, Magic):'
2379 2376 def resetbuffer(self):
2380 2377 """Reset the input buffer."""
2381 2378 self.buffer[:] = []
2379 self.buffer_raw[:] = []
2382 2380
2383 2381 def _is_secondary_block_start(self, s):
2384 2382 if not s.endswith(':'):
@@ -194,7 +194,8 b' which already exists. But you must first start the logging process with'
194 194 # add blank lines if the input cache fell out of sync.
195 195 if out_cache.do_full_cache and \
196 196 out_cache.prompt_count +1 > len(input_hist):
197 input_hist.extend(['\n'] * (out_cache.prompt_count - len(input_hist)))
197 pass
198 #input_hist.extend(['\n'] * (out_cache.prompt_count - len(input_hist)))
198 199
199 200 if not continuation and line_mod:
200 201 self._iii = self._ii
@@ -203,7 +204,7 b' which already exists. But you must first start the logging process with'
203 204 # put back the final \n of every input line
204 205 self._i00 = line_mod+'\n'
205 206 #print 'Logging input:<%s>' % line_mod # dbg
206 input_hist.append(self._i00)
207 #input_hist.append(self._i00)
207 208 #print '---[%s]' % (len(input_hist)-1,) # dbg
208 209
209 210 # hackish access to top-level namespace to create _i1,_i2... dynamically
@@ -222,7 +223,7 b' which already exists. But you must first start the logging process with'
222 223 new_i = '_i%s' % in_num
223 224 if continuation:
224 225 self._i00 = '%s%s\n' % (self.shell.user_ns[new_i],line_mod)
225 input_hist[in_num] = self._i00
226 #input_hist[in_num] = self._i00
226 227 to_main[new_i] = self._i00
227 228 self.shell.user_ns.update(to_main)
228 229
@@ -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').split('\n')
431 llines = lines.rstrip('\n').splitlines()
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
@@ -563,6 +563,8 b' class IPythonInputTestCase(InputSplitterTestCase):'
563 563
564 564 In addition, this runs the tests over the syntax and syntax_ml dicts that
565 565 were tested by individual functions, as part of the OO interface.
566
567 It also makes some checks on the raw buffer storage.
566 568 """
567 569
568 570 def setUp(self):
@@ -577,21 +579,26 b' class IPythonInputTestCase(InputSplitterTestCase):'
577 579 continue
578 580
579 581 isp.push(raw)
580 out = isp.source_reset().rstrip()
581 self.assertEqual(out, out_t)
582 out, out_raw = isp.source_raw_reset()
583 self.assertEqual(out.rstrip(), out_t)
584 self.assertEqual(out_raw.rstrip(), raw.rstrip())
582 585
583 586 def test_syntax_multiline(self):
584 587 isp = self.isp
585 588 for example in syntax_ml.itervalues():
586 589 out_t_parts = []
590 raw_parts = []
587 591 for line_pairs in example:
588 for raw, out_t_part in line_pairs:
589 isp.push(raw)
592 for lraw, out_t_part in line_pairs:
593 isp.push(lraw)
590 594 out_t_parts.append(out_t_part)
595 raw_parts.append(lraw)
591 596
592 out = isp.source_reset().rstrip()
597 out, out_raw = isp.source_raw_reset()
593 598 out_t = '\n'.join(out_t_parts).rstrip()
594 self.assertEqual(out, out_t)
599 raw = '\n'.join(raw_parts).rstrip()
600 self.assertEqual(out.rstrip(), out_t)
601 self.assertEqual(out_raw.rstrip(), raw)
595 602
596 603
597 604 class BlockIPythonInputTestCase(IPythonInputTestCase):
@@ -616,9 +623,10 b' class BlockIPythonInputTestCase(IPythonInputTestCase):'
616 623 out_t = '\n'.join(out_t_parts)
617 624
618 625 isp.push(raw)
619 out = isp.source_reset()
626 out, out_raw = isp.source_raw_reset()
620 627 # Match ignoring trailing whitespace
621 628 self.assertEqual(out.rstrip(), out_t.rstrip())
629 self.assertEqual(out_raw.rstrip(), raw.rstrip())
622 630
623 631
624 632 #-----------------------------------------------------------------------------
@@ -652,7 +660,8 b" if __name__ == '__main__':"
652 660 # Here we just return input so we can use it in a test suite, but a
653 661 # real interpreter would instead send it for execution somewhere.
654 662 #src = isp.source; raise EOFError # dbg
655 src = isp.source_reset()
663 src, raw = isp.source_raw_reset()
656 664 print 'Input source was:\n', src
665 print 'Raw source was:\n', raw
657 666 except EOFError:
658 667 print 'Bye'
@@ -191,8 +191,7 b' class TerminalInteractiveShell(InteractiveShell):'
191 191
192 192 # if you run stuff with -c <cmd>, raw hist is not updated
193 193 # ensure that it's in sync
194 if len(self.input_hist) != len (self.input_hist_raw):
195 self.input_hist_raw = InputList(self.input_hist)
194 self.history_manager.sync_inputs()
196 195
197 196 while 1:
198 197 try:
@@ -218,7 +217,7 b' class TerminalInteractiveShell(InteractiveShell):'
218 217 if display_banner:
219 218 self.show_banner()
220 219
221 more = 0
220 more = False
222 221
223 222 # Mark activity in the builtins
224 223 __builtin__.__dict__['__IPYTHON__active'] += 1
@@ -231,7 +230,7 b' class TerminalInteractiveShell(InteractiveShell):'
231 230 # Before showing any prompts, if the counter is at zero, we execute an
232 231 # empty line to ensure the user only sees prompts starting at one.
233 232 if self.execution_count == 0:
234 self.push_line('\n')
233 self.execution_count += 1
235 234
236 235 while not self.exit_now:
237 236 self.hooks.pre_prompt_hook()
@@ -249,7 +248,7 b' class TerminalInteractiveShell(InteractiveShell):'
249 248 except:
250 249 self.showtraceback()
251 250 try:
252 line = self.raw_input(prompt, more)
251 line = self.raw_input(prompt)
253 252 if self.exit_now:
254 253 # quick exit on sys.std[in|out] close
255 254 break
@@ -266,7 +265,7 b' class TerminalInteractiveShell(InteractiveShell):'
266 265
267 266 if self.autoindent:
268 267 self.indent_current_nsp = 0
269 more = 0
268 more = False
270 269 except KeyboardInterrupt:
271 270 pass
272 271 except EOFError:
@@ -286,10 +285,14 b' class TerminalInteractiveShell(InteractiveShell):'
286 285 # asynchronously by signal handlers, for example.
287 286 self.showtraceback()
288 287 else:
289 more = self.push_line(line)
288 #more = self.push_line(line)
289 self.input_splitter.push(line)
290 more = self.input_splitter.push_accepts_more()
290 291 if (self.SyntaxTB.last_syntax_error and
291 292 self.autoedit_syntax):
292 293 self.edit_syntax_error()
294 if not more:
295 pass
293 296
294 297 # We are off again...
295 298 __builtin__.__dict__['__IPYTHON__active'] -= 1
@@ -310,8 +313,6 b' class TerminalInteractiveShell(InteractiveShell):'
310 313 - continue_prompt(False): whether this line is the first one or a
311 314 continuation in a sequence of inputs.
312 315 """
313 # growl.notify("raw_input: ", "prompt = %r\ncontinue_prompt = %s" % (prompt, continue_prompt))
314
315 316 # Code run by the user may have modified the readline completer state.
316 317 # We must ensure that our completer is back in place.
317 318
@@ -329,8 +330,6 b' class TerminalInteractiveShell(InteractiveShell):'
329 330 # Try to be reasonably smart about not re-indenting pasted input more
330 331 # than necessary. We do this by trimming out the auto-indent initial
331 332 # spaces, if the user's actual input started itself with whitespace.
332 #debugx('self.buffer[-1]')
333
334 333 if self.autoindent:
335 334 if num_ini_spaces(line) > self.indent_current_nsp:
336 335 line = line[self.indent_current_nsp:]
@@ -340,22 +339,15 b' class TerminalInteractiveShell(InteractiveShell):'
340 339 # it.
341 340 if line.strip():
342 341 if continue_prompt:
343 self.input_hist_raw[-1] += '%s\n' % line
344 342 if self.has_readline and self.readline_use:
345 try:
346 343 histlen = self.readline.get_current_history_length()
347 344 if histlen > 1:
348 345 newhist = self.input_hist_raw[-1].rstrip()
349 346 self.readline.remove_history_item(histlen-1)
350 347 self.readline.replace_history_item(histlen-2,
351 348 newhist.encode(self.stdin_encoding))
352 except AttributeError:
353 pass # re{move,place}_history_item are new in 2.4.
354 349 else:
355 350 self.input_hist_raw.append('%s\n' % line)
356 # only entries starting at first column go to shadow history
357 if line.lstrip() == line:
358 self.shadowhist.add(line.strip())
359 351 elif not continue_prompt:
360 352 self.input_hist_raw.append('\n')
361 353 try:
@@ -368,6 +360,45 b' class TerminalInteractiveShell(InteractiveShell):'
368 360 else:
369 361 return lineout
370 362
363
364 def raw_input(self, prompt=''):
365 """Write a prompt and read a line.
366
367 The returned line does not include the trailing newline.
368 When the user enters the EOF key sequence, EOFError is raised.
369
370 Optional inputs:
371
372 - prompt(''): a string to be printed to prompt the user.
373
374 - continue_prompt(False): whether this line is the first one or a
375 continuation in a sequence of inputs.
376 """
377 # Code run by the user may have modified the readline completer state.
378 # We must ensure that our completer is back in place.
379
380 if self.has_readline:
381 self.set_readline_completer()
382
383 try:
384 line = raw_input_original(prompt).decode(self.stdin_encoding)
385 except ValueError:
386 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
387 " or sys.stdout.close()!\nExiting IPython!")
388 self.ask_exit()
389 return ""
390
391 # Try to be reasonably smart about not re-indenting pasted input more
392 # than necessary. We do this by trimming out the auto-indent initial
393 # spaces, if the user's actual input started itself with whitespace.
394 if self.autoindent:
395 if num_ini_spaces(line) > self.indent_current_nsp:
396 line = line[self.indent_current_nsp:]
397 self.indent_current_nsp = 0
398
399 return line
400
401
371 402 # TODO: The following three methods are an early attempt to refactor
372 403 # the main code execution logic. We don't use them, but they may be
373 404 # helpful when we refactor the code execution logic further.
General Comments 0
You need to be logged in to leave comments. Login now