##// END OF EJS Templates
Merge pull request #929 from juliantaylor/multiline-history...
Min RK -
r5275:7c0ffa59 merge
parent child Browse files
Show More
@@ -0,0 +1,161
1 # -*- coding: utf-8 -*-
2 """Tests for the key interactiveshell module.
3
4 Authors
5 -------
6 * Julian Taylor
7 """
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18 # stdlib
19 import unittest
20
21 from IPython.testing.decorators import skipif
22
23 class InteractiveShellTestCase(unittest.TestCase):
24 def rl_hist_entries(self, rl, n):
25 """Get last n readline history entries as a list"""
26 return [rl.get_history_item(rl.get_current_history_length() - x)
27 for x in range(n - 1, -1, -1)]
28
29 def test_runs_without_rl(self):
30 """Test that function does not throw without readline"""
31 ip = get_ipython()
32 ip.has_readline = False
33 ip.readline = None
34 ip._replace_rlhist_multiline(u'source', 0)
35
36 @skipif(not get_ipython().has_readline, 'no readline')
37 def test_runs_without_remove_history_item(self):
38 """Test that function does not throw on windows without
39 remove_history_item"""
40 ip = get_ipython()
41 if hasattr(ip.readline, 'remove_history_item'):
42 del ip.readline.remove_history_item
43 ip._replace_rlhist_multiline(u'source', 0)
44
45 @skipif(not get_ipython().has_readline, 'no readline')
46 @skipif(not hasattr(get_ipython().readline, 'remove_history_item'),
47 'no remove_history_item')
48 def test_replace_multiline_hist_disabled(self):
49 """Test that multiline replace does nothing if disabled"""
50 ip = get_ipython()
51 ip.multiline_history = False
52
53 ghist = [u'line1', u'line2']
54 for h in ghist:
55 ip.readline.add_history(h)
56 hlen_b4_cell = ip.readline.get_current_history_length()
57 hlen_b4_cell = ip._replace_rlhist_multiline(u'sourc€\nsource2',
58 hlen_b4_cell)
59
60 self.assertEquals(ip.readline.get_current_history_length(),
61 hlen_b4_cell)
62 hist = self.rl_hist_entries(ip.readline, 2)
63 self.assertEquals(hist, ghist)
64
65 @skipif(not get_ipython().has_readline, 'no readline')
66 @skipif(not hasattr(get_ipython().readline, 'remove_history_item'),
67 'no remove_history_item')
68 def test_replace_multiline_hist_adds(self):
69 """Test that multiline replace function adds history"""
70 ip = get_ipython()
71
72 hlen_b4_cell = ip.readline.get_current_history_length()
73 hlen_b4_cell = ip._replace_rlhist_multiline(u'sourc€', hlen_b4_cell)
74
75 self.assertEquals(hlen_b4_cell,
76 ip.readline.get_current_history_length())
77
78 @skipif(not get_ipython().has_readline, 'no readline')
79 @skipif(not hasattr(get_ipython().readline, 'remove_history_item'),
80 'no remove_history_item')
81 def test_replace_multiline_hist_keeps_history(self):
82 """Test that multiline replace does not delete history"""
83 ip = get_ipython()
84 ip.multiline_history = True
85
86 ghist = [u'line1', u'line2']
87 for h in ghist:
88 ip.readline.add_history(h)
89
90 #start cell
91 hlen_b4_cell = ip.readline.get_current_history_length()
92 # nothing added to rl history, should do nothing
93 hlen_b4_cell = ip._replace_rlhist_multiline(u'sourc€\nsource2',
94 hlen_b4_cell)
95
96 self.assertEquals(ip.readline.get_current_history_length(),
97 hlen_b4_cell)
98 hist = self.rl_hist_entries(ip.readline, 2)
99 self.assertEquals(hist, ghist)
100
101
102 @skipif(not get_ipython().has_readline, 'no readline')
103 @skipif(not hasattr(get_ipython().readline, 'remove_history_item'),
104 'no remove_history_item')
105 def test_replace_multiline_hist_replaces_twice(self):
106 """Test that multiline entries are replaced twice"""
107 ip = get_ipython()
108 ip.multiline_history = True
109
110 ip.readline.add_history(u'line0')
111 #start cell
112 hlen_b4_cell = ip.readline.get_current_history_length()
113 ip.readline.add_history('l€ne1')
114 ip.readline.add_history('line2')
115 #replace cell with single line
116 hlen_b4_cell = ip._replace_rlhist_multiline(u'l€ne1\nline2',
117 hlen_b4_cell)
118 ip.readline.add_history('l€ne3')
119 ip.readline.add_history('line4')
120 #replace cell with single line
121 hlen_b4_cell = ip._replace_rlhist_multiline(u'l€ne3\nline4',
122 hlen_b4_cell)
123
124 self.assertEquals(ip.readline.get_current_history_length(),
125 hlen_b4_cell)
126 hist = self.rl_hist_entries(ip.readline, 3)
127 self.assertEquals(hist, ['line0', 'l€ne1\nline2', 'l€ne3\nline4'])
128
129
130 @skipif(not get_ipython().has_readline, 'no readline')
131 @skipif(not hasattr(get_ipython().readline, 'remove_history_item'),
132 'no remove_history_item')
133 def test_replace_multiline_hist_replaces_empty_line(self):
134 """Test that multiline history skips empty line cells"""
135 ip = get_ipython()
136 ip.multiline_history = True
137
138 ip.readline.add_history(u'line0')
139 #start cell
140 hlen_b4_cell = ip.readline.get_current_history_length()
141 ip.readline.add_history('l€ne1')
142 ip.readline.add_history('line2')
143 hlen_b4_cell = ip._replace_rlhist_multiline(u'l€ne1\nline2',
144 hlen_b4_cell)
145 ip.readline.add_history('')
146 hlen_b4_cell = ip._replace_rlhist_multiline(u'', hlen_b4_cell)
147 ip.readline.add_history('l€ne3')
148 hlen_b4_cell = ip._replace_rlhist_multiline(u'l€ne3', hlen_b4_cell)
149 ip.readline.add_history(' ')
150 hlen_b4_cell = ip._replace_rlhist_multiline(' ', hlen_b4_cell)
151 ip.readline.add_history('\t')
152 ip.readline.add_history('\t ')
153 hlen_b4_cell = ip._replace_rlhist_multiline('\t', hlen_b4_cell)
154 ip.readline.add_history('line4')
155 hlen_b4_cell = ip._replace_rlhist_multiline(u'line4', hlen_b4_cell)
156
157 self.assertEquals(ip.readline.get_current_history_length(),
158 hlen_b4_cell)
159 hist = self.rl_hist_entries(ip.readline, 4)
160 # expect no empty cells in history
161 self.assertEquals(hist, ['line0', 'l€ne1\nline2', 'l€ne3', 'line4'])
@@ -308,7 +308,7 class InteractiveShell(SingletonConfigurable, Magic):
308 """
308 """
309 )
309 )
310 multiline_history = CBool(sys.platform != 'win32', config=True,
310 multiline_history = CBool(sys.platform != 'win32', config=True,
311 help="Store multiple line spanning cells as a single entry in history."
311 help="Save multi-line entries as one entry in readline history"
312 )
312 )
313
313
314 prompt_in1 = Unicode('In [\\#]: ', config=True)
314 prompt_in1 = Unicode('In [\\#]: ', config=True)
@@ -231,13 +231,30 class TerminalInteractiveShell(InteractiveShell):
231
231
232 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
232 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
233 """Store multiple lines as a single entry in history"""
233 """Store multiple lines as a single entry in history"""
234 if self.multiline_history and self.has_readline:
234
235 hlen = self.readline.get_current_history_length()
235 # do nothing without readline or disabled multiline
236 for i in range(hlen - hlen_before_cell):
236 if not self.has_readline or not self.multiline_history:
237 self.readline.remove_history_item(hlen - i - 1)
237 return hlen_before_cell
238 stdin_encoding = sys.stdin.encoding or "utf-8"
238
239 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
239 # windows rl has no remove_history_item
240 stdin_encoding))
240 if not hasattr(self.readline, "remove_history_item"):
241 return hlen_before_cell
242
243 # skip empty cells
244 if not source_raw.rstrip():
245 return hlen_before_cell
246
247 # nothing changed do nothing, e.g. when rl removes consecutive dups
248 hlen = self.readline.get_current_history_length()
249 if hlen == hlen_before_cell:
250 return hlen_before_cell
251
252 for i in range(hlen - hlen_before_cell):
253 self.readline.remove_history_item(hlen - i - 1)
254 stdin_encoding = sys.stdin.encoding or "utf-8"
255 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
256 stdin_encoding))
257 return self.readline.get_current_history_length()
241
258
242 def interact(self, display_banner=None):
259 def interact(self, display_banner=None):
243 """Closely emulate the interactive Python console."""
260 """Closely emulate the interactive Python console."""
@@ -255,13 +272,15 class TerminalInteractiveShell(InteractiveShell):
255 self.show_banner()
272 self.show_banner()
256
273
257 more = False
274 more = False
258 hlen_before_cell = self.readline.get_current_history_length()
259
275
260 # Mark activity in the builtins
276 # Mark activity in the builtins
261 __builtin__.__dict__['__IPYTHON__active'] += 1
277 __builtin__.__dict__['__IPYTHON__active'] += 1
262
278
263 if self.has_readline:
279 if self.has_readline:
264 self.readline_startup_hook(self.pre_readline)
280 self.readline_startup_hook(self.pre_readline)
281 hlen_b4_cell = self.readline.get_current_history_length()
282 else:
283 hlen_b4_cell = 0
265 # exit_now is set by a call to %Exit or %Quit, through the
284 # exit_now is set by a call to %Exit or %Quit, through the
266 # ask_exit callback.
285 # ask_exit callback.
267
286
@@ -293,8 +312,8 class TerminalInteractiveShell(InteractiveShell):
293 try:
312 try:
294 self.write('\nKeyboardInterrupt\n')
313 self.write('\nKeyboardInterrupt\n')
295 source_raw = self.input_splitter.source_raw_reset()[1]
314 source_raw = self.input_splitter.source_raw_reset()[1]
296 self._replace_rlhist_multiline(source_raw, hlen_before_cell)
315 hlen_b4_cell = \
297 hlen_before_cell = self.readline.get_current_history_length()
316 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
298 more = False
317 more = False
299 except KeyboardInterrupt:
318 except KeyboardInterrupt:
300 pass
319 pass
@@ -322,9 +341,9 class TerminalInteractiveShell(InteractiveShell):
322 self.edit_syntax_error()
341 self.edit_syntax_error()
323 if not more:
342 if not more:
324 source_raw = self.input_splitter.source_raw_reset()[1]
343 source_raw = self.input_splitter.source_raw_reset()[1]
325 self._replace_rlhist_multiline(source_raw, hlen_before_cell)
326 hlen_before_cell = self.readline.get_current_history_length()
327 self.run_cell(source_raw, store_history=True)
344 self.run_cell(source_raw, store_history=True)
345 hlen_b4_cell = \
346 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
328
347
329 # We are off again...
348 # We are off again...
330 __builtin__.__dict__['__IPYTHON__active'] -= 1
349 __builtin__.__dict__['__IPYTHON__active'] -= 1
General Comments 0
You need to be logged in to leave comments. Login now