Show More
@@ -0,0 +1,48 b'' | |||||
|
1 | """Tests for the IPython tab-completion machinery. | |||
|
2 | """ | |||
|
3 | #----------------------------------------------------------------------------- | |||
|
4 | # Module imports | |||
|
5 | #----------------------------------------------------------------------------- | |||
|
6 | ||||
|
7 | # stdlib | |||
|
8 | import os | |||
|
9 | import sys | |||
|
10 | import unittest | |||
|
11 | ||||
|
12 | # third party | |||
|
13 | import nose.tools as nt | |||
|
14 | ||||
|
15 | # our own packages | |||
|
16 | from IPython.utils.tempdir import TemporaryDirectory | |||
|
17 | from IPython.core.history import HistoryManager | |||
|
18 | ||||
|
19 | def test_history(): | |||
|
20 | ||||
|
21 | ip = get_ipython() | |||
|
22 | with TemporaryDirectory() as tmpdir: | |||
|
23 | #tmpdir = '/software/temp' | |||
|
24 | histfile = os.path.realpath(os.path.join(tmpdir, 'history.json')) | |||
|
25 | # Ensure that we restore the history management that we mess with in | |||
|
26 | # this test doesn't affect the IPython instance used by the test suite | |||
|
27 | # beyond this test. | |||
|
28 | hist_manager_ori = ip.history_manager | |||
|
29 | try: | |||
|
30 | ip.history_manager = HistoryManager(ip) | |||
|
31 | ip.history_manager.hist_file = histfile | |||
|
32 | print 'test',histfile | |||
|
33 | hist = ['a=1\n', 'def f():\n test = 1\n return test\n', 'b=2\n'] | |||
|
34 | # test save and load | |||
|
35 | ip.history_manager.input_hist_raw[:] = [] | |||
|
36 | for h in hist: | |||
|
37 | ip.history_manager.input_hist_raw.append(h) | |||
|
38 | ip.save_history() | |||
|
39 | ip.history_manager.input_hist_raw[:] = [] | |||
|
40 | ip.reload_history() | |||
|
41 | print type(ip.history_manager.input_hist_raw) | |||
|
42 | print ip.history_manager.input_hist_raw | |||
|
43 | nt.assert_equal(len(ip.history_manager.input_hist_raw), len(hist)) | |||
|
44 | for i,h in enumerate(hist): | |||
|
45 | nt.assert_equal(hist[i], ip.history_manager.input_hist_raw[i]) | |||
|
46 | finally: | |||
|
47 | # Restore history manager | |||
|
48 | ip.history_manager = hist_manager_ori |
@@ -90,6 +90,8 b' c = get_config()' | |||||
90 |
|
90 | |||
91 | # c.InteractiveShell.quiet = False |
|
91 | # c.InteractiveShell.quiet = False | |
92 |
|
92 | |||
|
93 | # c.InteractiveShell.history_length = 10000 | |||
|
94 | ||||
93 | # Readline |
|
95 | # Readline | |
94 | # c.InteractiveShell.readline_use = True |
|
96 | # c.InteractiveShell.readline_use = True | |
95 |
|
97 |
@@ -173,7 +173,7 b' class DisplayHook(Configurable):' | |||||
173 | """Should we silence the display hook because of ';'?""" |
|
173 | """Should we silence the display hook because of ';'?""" | |
174 | # do not print output if input ends in ';' |
|
174 | # do not print output if input ends in ';' | |
175 | try: |
|
175 | try: | |
176 | if self.shell.input_hist[self.prompt_count].endswith(';\n'): |
|
176 | if self.shell.history_manager.input_hist_parsed[self.prompt_count].endswith(';\n'): | |
177 | return True |
|
177 | return True | |
178 | except IndexError: |
|
178 | except IndexError: | |
179 | # some uses of ipshellembed may fail here |
|
179 | # some uses of ipshellembed may fail here |
@@ -14,13 +14,13 b' from __future__ import print_function' | |||||
14 |
|
14 | |||
15 | # Stdlib imports |
|
15 | # Stdlib imports | |
16 | import fnmatch |
|
16 | import fnmatch | |
|
17 | import json | |||
17 | import os |
|
18 | import os | |
18 | import sys |
|
19 | import sys | |
19 |
|
20 | |||
20 | # Our own packages |
|
21 | # Our own packages | |
21 | import IPython.utils.io |
|
22 | import IPython.utils.io | |
22 |
|
23 | |||
23 | from IPython.core.inputlist import InputList |
|
|||
24 | from IPython.utils.pickleshare import PickleShareDB |
|
24 | from IPython.utils.pickleshare import PickleShareDB | |
25 | from IPython.utils.io import ask_yes_no |
|
25 | from IPython.utils.io import ask_yes_no | |
26 | from IPython.utils.warn import warn |
|
26 | from IPython.utils.warn import warn | |
@@ -36,9 +36,9 b' class HistoryManager(object):' | |||||
36 |
|
36 | |||
37 | # An instance of the IPython shell we are attached to |
|
37 | # An instance of the IPython shell we are attached to | |
38 | shell = None |
|
38 | shell = None | |
39 |
# A |
|
39 | # A list to hold processed history | |
40 | input_hist = None |
|
40 | input_hist_parsed = None | |
41 |
# A |
|
41 | # A list to hold raw history (as typed by user) | |
42 | input_hist_raw = None |
|
42 | input_hist_raw = None | |
43 | # A list of directories visited during session |
|
43 | # A list of directories visited during session | |
44 | dir_hist = None |
|
44 | dir_hist = None | |
@@ -56,6 +56,11 b' class HistoryManager(object):' | |||||
56 | # history update, we populate the user's namespace with these, shifted as |
|
56 | # history update, we populate the user's namespace with these, shifted as | |
57 | # necessary. |
|
57 | # necessary. | |
58 | _i00, _i, _ii, _iii = '','','','' |
|
58 | _i00, _i, _ii, _iii = '','','','' | |
|
59 | ||||
|
60 | # A set with all forms of the exit command, so that we don't store them in | |||
|
61 | # the history (it's annoying to rewind the first entry and land on an exit | |||
|
62 | # call). | |||
|
63 | _exit_commands = None | |||
59 |
|
64 | |||
60 | def __init__(self, shell): |
|
65 | def __init__(self, shell): | |
61 | """Create a new history manager associated with a shell instance. |
|
66 | """Create a new history manager associated with a shell instance. | |
@@ -64,11 +69,11 b' class HistoryManager(object):' | |||||
64 | self.shell = shell |
|
69 | self.shell = shell | |
65 |
|
70 | |||
66 | # List of input with multi-line handling. |
|
71 | # List of input with multi-line handling. | |
67 |
self.input_hist = |
|
72 | self.input_hist_parsed = [] | |
68 | # This one will hold the 'raw' input history, without any |
|
73 | # This one will hold the 'raw' input history, without any | |
69 | # pre-processing. This will allow users to retrieve the input just as |
|
74 | # pre-processing. This will allow users to retrieve the input just as | |
70 | # it was exactly typed in by the user, with %hist -r. |
|
75 | # it was exactly typed in by the user, with %hist -r. | |
71 |
self.input_hist_raw = |
|
76 | self.input_hist_raw = [] | |
72 |
|
77 | |||
73 | # list of visited directories |
|
78 | # list of visited directories | |
74 | try: |
|
79 | try: | |
@@ -84,29 +89,21 b' class HistoryManager(object):' | |||||
84 | histfname = 'history-%s' % shell.profile |
|
89 | histfname = 'history-%s' % shell.profile | |
85 | else: |
|
90 | else: | |
86 | histfname = 'history' |
|
91 | histfname = 'history' | |
87 | self.hist_file = os.path.join(shell.ipython_dir, histfname) |
|
92 | self.hist_file = os.path.join(shell.ipython_dir, histfname + '.json') | |
88 |
|
93 | |||
89 | # Objects related to shadow history management |
|
94 | # Objects related to shadow history management | |
90 | self._init_shadow_hist() |
|
95 | self._init_shadow_hist() | |
91 |
|
96 | |||
92 | self._i00, self._i, self._ii, self._iii = '','','','' |
|
97 | self._i00, self._i, self._ii, self._iii = '','','','' | |
93 |
|
98 | |||
|
99 | self._exit_commands = set(['Quit', 'quit', 'Exit', 'exit', '%Quit', | |||
|
100 | '%quit', '%Exit', '%exit']) | |||
|
101 | ||||
94 | # Object is fully initialized, we can now call methods on it. |
|
102 | # Object is fully initialized, we can now call methods on it. | |
95 |
|
103 | |||
96 | # Fill the history zero entry, user counter starts at 1 |
|
104 | # Fill the history zero entry, user counter starts at 1 | |
97 | self.store_inputs('\n', '\n') |
|
105 | self.store_inputs('\n', '\n') | |
98 |
|
106 | |||
99 | # For backwards compatibility, we must put these back in the shell |
|
|||
100 | # object, until we've removed all direct uses of the history objects in |
|
|||
101 | # the shell itself. |
|
|||
102 | shell.input_hist = self.input_hist |
|
|||
103 | shell.input_hist_raw = self.input_hist_raw |
|
|||
104 | shell.output_hist = self.output_hist |
|
|||
105 | shell.dir_hist = self.dir_hist |
|
|||
106 | shell.histfile = self.hist_file |
|
|||
107 | shell.shadowhist = self.shadow_hist |
|
|||
108 | shell.db = self.shadow_db |
|
|||
109 |
|
||||
110 | def _init_shadow_hist(self): |
|
107 | def _init_shadow_hist(self): | |
111 | try: |
|
108 | try: | |
112 | self.shadow_db = PickleShareDB(os.path.join( |
|
109 | self.shadow_db = PickleShareDB(os.path.join( | |
@@ -119,24 +116,41 b' class HistoryManager(object):' | |||||
119 | sys.exit() |
|
116 | sys.exit() | |
120 | self.shadow_hist = ShadowHist(self.shadow_db, self.shell) |
|
117 | self.shadow_hist = ShadowHist(self.shadow_db, self.shell) | |
121 |
|
118 | |||
122 |
def |
|
119 | def populate_readline_history(self): | |
123 | """Save input history to a file (via readline library).""" |
|
120 | """Populate the readline history from the raw history. | |
124 |
|
|
121 | ||
125 | try: |
|
122 | We only store one copy of the raw history, which is persisted to a json | |
126 | self.shell.readline.write_history_file(self.hist_file) |
|
123 | file on disk. The readline history is repopulated from the contents of | |
127 | except: |
|
124 | this file.""" | |
128 | print('Unable to save IPython command history to file: ' + |
|
|||
129 | `self.hist_file`) |
|
|||
130 |
|
||||
131 | def reload_hist(self): |
|
|||
132 | """Reload the input history from disk file.""" |
|
|||
133 |
|
125 | |||
134 | try: |
|
126 | try: | |
135 | self.shell.readline.clear_history() |
|
127 | self.shell.readline.clear_history() | |
136 | self.shell.readline.read_history_file(self.hist_file) |
|
|||
137 | except AttributeError: |
|
128 | except AttributeError: | |
138 | pass |
|
129 | pass | |
|
130 | else: | |||
|
131 | for h in self.input_hist_raw: | |||
|
132 | if not h.isspace(): | |||
|
133 | for line in h.splitlines(): | |||
|
134 | self.shell.readline.add_history(line) | |||
139 |
|
135 | |||
|
136 | def save_history(self): | |||
|
137 | """Save input history to a file (via readline library).""" | |||
|
138 | hist = dict(raw=self.input_hist_raw, #[-self.shell.history_length:], | |||
|
139 | parsed=self.input_hist_parsed) #[-self.shell.history_length:]) | |||
|
140 | with open(self.hist_file,'wt') as hfile: | |||
|
141 | json.dump(hist, hfile, | |||
|
142 | sort_keys=True, indent=4) | |||
|
143 | ||||
|
144 | def reload_history(self): | |||
|
145 | """Reload the input history from disk file.""" | |||
|
146 | ||||
|
147 | with open(self.hist_file,'rt') as hfile: | |||
|
148 | hist = json.load(hfile) | |||
|
149 | self.input_hist_parsed = hist['parsed'] | |||
|
150 | self.input_hist_raw = hist['raw'] | |||
|
151 | if self.shell.has_readline: | |||
|
152 | self.populate_readline_history() | |||
|
153 | ||||
140 | def get_history(self, index=None, raw=False, output=True): |
|
154 | def get_history(self, index=None, raw=False, output=True): | |
141 | """Get the history list. |
|
155 | """Get the history list. | |
142 |
|
156 | |||
@@ -163,7 +177,7 b' class HistoryManager(object):' | |||||
163 | if raw: |
|
177 | if raw: | |
164 | input_hist = self.input_hist_raw |
|
178 | input_hist = self.input_hist_raw | |
165 | else: |
|
179 | else: | |
166 | input_hist = self.input_hist |
|
180 | input_hist = self.input_hist_parsed | |
167 | if output: |
|
181 | if output: | |
168 | output_hist = self.output_hist |
|
182 | output_hist = self.output_hist | |
169 | n = len(input_hist) |
|
183 | n = len(input_hist) | |
@@ -201,8 +215,13 b' class HistoryManager(object):' | |||||
201 | """ |
|
215 | """ | |
202 | if source_raw is None: |
|
216 | if source_raw is None: | |
203 | source_raw = source |
|
217 | source_raw = source | |
204 | self.input_hist.append(source) |
|
218 | ||
205 | self.input_hist_raw.append(source_raw) |
|
219 | # do not store exit/quit commands | |
|
220 | if source_raw.strip() in self._exit_commands: | |||
|
221 | return | |||
|
222 | ||||
|
223 | self.input_hist_parsed.append(source.rstrip()) | |||
|
224 | self.input_hist_raw.append(source_raw.rstrip()) | |||
206 | self.shadow_hist.add(source) |
|
225 | self.shadow_hist.add(source) | |
207 |
|
226 | |||
208 | # update the auto _i variables |
|
227 | # update the auto _i variables | |
@@ -221,12 +240,12 b' class HistoryManager(object):' | |||||
221 |
|
240 | |||
222 | def sync_inputs(self): |
|
241 | def sync_inputs(self): | |
223 | """Ensure raw and translated histories have same length.""" |
|
242 | """Ensure raw and translated histories have same length.""" | |
224 | if len(self.input_hist) != len (self.input_hist_raw): |
|
243 | if len(self.input_hist_parsed) != len (self.input_hist_raw): | |
225 |
self.input_hist_raw = |
|
244 | self.input_hist_raw[:] = self.input_hist_parsed | |
226 |
|
245 | |||
227 | def reset(self): |
|
246 | def reset(self): | |
228 | """Clear all histories managed by this object.""" |
|
247 | """Clear all histories managed by this object.""" | |
229 | self.input_hist[:] = [] |
|
248 | self.input_hist_parsed[:] = [] | |
230 | self.input_hist_raw[:] = [] |
|
249 | self.input_hist_raw[:] = [] | |
231 | self.output_hist.clear() |
|
250 | self.output_hist.clear() | |
232 | # The directory history can't be completely empty |
|
251 | # The directory history can't be completely empty | |
@@ -299,12 +318,12 b" def magic_history(self, parameter_s = ''):" | |||||
299 | close_at_end = True |
|
318 | close_at_end = True | |
300 |
|
319 | |||
301 | if 't' in opts: |
|
320 | if 't' in opts: | |
302 | input_hist = self.shell.input_hist |
|
321 | input_hist = self.shell.history_manager.input_hist_parsed | |
303 | elif 'r' in opts: |
|
322 | elif 'r' in opts: | |
304 | input_hist = self.shell.input_hist_raw |
|
323 | input_hist = self.shell.history_manager.input_hist_raw | |
305 | else: |
|
324 | else: | |
306 | # Raw history is the default |
|
325 | # Raw history is the default | |
307 | input_hist = self.shell.input_hist_raw |
|
326 | input_hist = self.shell.history_manager.input_hist_raw | |
308 |
|
327 | |||
309 | default_length = 40 |
|
328 | default_length = 40 | |
310 | pattern = None |
|
329 | pattern = None | |
@@ -337,7 +356,7 b" def magic_history(self, parameter_s = ''):" | |||||
337 |
|
356 | |||
338 | found = False |
|
357 | found = False | |
339 | if pattern is not None: |
|
358 | if pattern is not None: | |
340 | sh = self.shell.shadowhist.all() |
|
359 | sh = self.shell.history_manager.shadowhist.all() | |
341 | for idx, s in sh: |
|
360 | for idx, s in sh: | |
342 | if fnmatch.fnmatch(s, pattern): |
|
361 | if fnmatch.fnmatch(s, pattern): | |
343 | print("0%d: %s" %(idx, s.expandtabs(4)), file=outfile) |
|
362 | print("0%d: %s" %(idx, s.expandtabs(4)), file=outfile) | |
@@ -373,7 +392,7 b" def magic_history(self, parameter_s = ''):" | |||||
373 | else: |
|
392 | else: | |
374 | print(inline, end='', file=outfile) |
|
393 | print(inline, end='', file=outfile) | |
375 | if print_outputs: |
|
394 | if print_outputs: | |
376 | output = self.shell.output_hist.get(in_num) |
|
395 | output = self.shell.history_manager.output_hist.get(in_num) | |
377 | if output is not None: |
|
396 | if output is not None: | |
378 | print(repr(output), file=outfile) |
|
397 | print(repr(output), file=outfile) | |
379 |
|
398 |
@@ -45,7 +45,6 b' from IPython.core.error import TryNext, UsageError' | |||||
45 | from IPython.core.extensions import ExtensionManager |
|
45 | from IPython.core.extensions import ExtensionManager | |
46 | from IPython.core.fakemodule import FakeModule, init_fakemod_dict |
|
46 | from IPython.core.fakemodule import FakeModule, init_fakemod_dict | |
47 | from IPython.core.history import HistoryManager |
|
47 | from IPython.core.history import HistoryManager | |
48 | from IPython.core.inputlist import InputList |
|
|||
49 | from IPython.core.inputsplitter import IPythonInputSplitter |
|
48 | from IPython.core.inputsplitter import IPythonInputSplitter | |
50 | from IPython.core.logger import Logger |
|
49 | from IPython.core.logger import Logger | |
51 | from IPython.core.magic import Magic |
|
50 | from IPython.core.magic import Magic | |
@@ -176,6 +175,8 b' class InteractiveShell(Configurable, Magic):' | |||||
176 | prompts_pad_left = CBool(True, config=True) |
|
175 | prompts_pad_left = CBool(True, config=True) | |
177 | quiet = CBool(False, config=True) |
|
176 | quiet = CBool(False, config=True) | |
178 |
|
177 | |||
|
178 | history_length = Int(10000, config=True) | |||
|
179 | ||||
179 | # The readline stuff will eventually be moved to the terminal subclass |
|
180 | # The readline stuff will eventually be moved to the terminal subclass | |
180 | # but for now, we can't do that as readline is welded in everywhere. |
|
181 | # but for now, we can't do that as readline is welded in everywhere. | |
181 | readline_use = CBool(True, config=True) |
|
182 | readline_use = CBool(True, config=True) | |
@@ -293,6 +294,14 b' class InteractiveShell(Configurable, Magic):' | |||||
293 | self.hooks.late_startup_hook() |
|
294 | self.hooks.late_startup_hook() | |
294 | atexit.register(self.atexit_operations) |
|
295 | atexit.register(self.atexit_operations) | |
295 |
|
296 | |||
|
297 | # While we're trying to have each part of the code directly access what it | |||
|
298 | # needs without keeping redundant references to objects, we have too much | |||
|
299 | # legacy code that expects ip.db to exist, so let's make it a property that | |||
|
300 | # retrieves the underlying object from our new history manager. | |||
|
301 | @property | |||
|
302 | def db(self): | |||
|
303 | return self.history_manager.shadow_db | |||
|
304 | ||||
296 | @classmethod |
|
305 | @classmethod | |
297 | def instance(cls, *args, **kwargs): |
|
306 | def instance(cls, *args, **kwargs): | |
298 | """Returns a global InteractiveShell instance.""" |
|
307 | """Returns a global InteractiveShell instance.""" | |
@@ -947,16 +956,16 b' class InteractiveShell(Configurable, Magic):' | |||||
947 | warn('help() not available - check site.py') |
|
956 | warn('help() not available - check site.py') | |
948 |
|
957 | |||
949 | # make global variables for user access to the histories |
|
958 | # make global variables for user access to the histories | |
950 | ns['_ih'] = self.input_hist |
|
959 | ns['_ih'] = self.history_manager.input_hist_parsed | |
951 | ns['_oh'] = self.output_hist |
|
960 | ns['_oh'] = self.history_manager.output_hist | |
952 | ns['_dh'] = self.dir_hist |
|
961 | ns['_dh'] = self.history_manager.dir_hist | |
953 |
|
962 | |||
954 | ns['_sh'] = shadowns |
|
963 | ns['_sh'] = shadowns | |
955 |
|
964 | |||
956 | # user aliases to input and output histories. These shouldn't show up |
|
965 | # user aliases to input and output histories. These shouldn't show up | |
957 | # in %who, as they can have very large reprs. |
|
966 | # in %who, as they can have very large reprs. | |
958 | ns['In'] = self.input_hist |
|
967 | ns['In'] = self.history_manager.input_hist_parsed | |
959 | ns['Out'] = self.output_hist |
|
968 | ns['Out'] = self.history_manager.output_hist | |
960 |
|
969 | |||
961 | # Store myself as the public api!!! |
|
970 | # Store myself as the public api!!! | |
962 | ns['get_ipython'] = self.get_ipython |
|
971 | ns['get_ipython'] = self.get_ipython | |
@@ -1228,19 +1237,13 b' class InteractiveShell(Configurable, Magic):' | |||||
1228 | def init_history(self): |
|
1237 | def init_history(self): | |
1229 | self.history_manager = HistoryManager(shell=self) |
|
1238 | self.history_manager = HistoryManager(shell=self) | |
1230 |
|
1239 | |||
1231 | def save_hist(self): |
|
1240 | def save_history(self): | |
1232 | """Save input history to a file (via readline library).""" |
|
1241 | """Save input history to a file (via readline library).""" | |
1233 | self.history_manager.save_hist() |
|
1242 | self.history_manager.save_history() | |
1234 |
|
1243 | |||
1235 | # For backwards compatibility |
|
1244 | def reload_history(self): | |
1236 | savehist = save_hist |
|
|||
1237 |
|
||||
1238 | def reload_hist(self): |
|
|||
1239 | """Reload the input history from disk file.""" |
|
1245 | """Reload the input history from disk file.""" | |
1240 | self.history_manager.reload_hist() |
|
1246 | self.history_manager.reload_history() | |
1241 |
|
||||
1242 | # For backwards compatibility |
|
|||
1243 | reloadhist = reload_hist |
|
|||
1244 |
|
1247 | |||
1245 | def history_saving_wrapper(self, func): |
|
1248 | def history_saving_wrapper(self, func): | |
1246 | """ Wrap func for readline history saving |
|
1249 | """ Wrap func for readline history saving | |
@@ -1254,12 +1257,16 b' class InteractiveShell(Configurable, Magic):' | |||||
1254 | return func |
|
1257 | return func | |
1255 |
|
1258 | |||
1256 | def wrapper(): |
|
1259 | def wrapper(): | |
1257 | self.save_hist() |
|
1260 | self.save_history() | |
1258 | try: |
|
1261 | try: | |
1259 | func() |
|
1262 | func() | |
1260 | finally: |
|
1263 | finally: | |
1261 |
|
|
1264 | self.reload_history() | |
1262 | return wrapper |
|
1265 | return wrapper | |
|
1266 | ||||
|
1267 | def get_history(self, index=None, raw=False, output=True): | |||
|
1268 | return self.history_manager.get_history(index, raw, output) | |||
|
1269 | ||||
1263 |
|
1270 | |||
1264 | #------------------------------------------------------------------------- |
|
1271 | #------------------------------------------------------------------------- | |
1265 | # Things related to exception handling and tracebacks (not debugging) |
|
1272 | # Things related to exception handling and tracebacks (not debugging) | |
@@ -1488,8 +1495,6 b' class InteractiveShell(Configurable, Magic):' | |||||
1488 | self.has_readline = False |
|
1495 | self.has_readline = False | |
1489 | self.readline = None |
|
1496 | self.readline = None | |
1490 | # Set a number of methods that depend on readline to be no-op |
|
1497 | # Set a number of methods that depend on readline to be no-op | |
1491 | self.save_hist = no_op |
|
|||
1492 | self.reload_hist = no_op |
|
|||
1493 | self.set_readline_completer = no_op |
|
1498 | self.set_readline_completer = no_op | |
1494 | self.set_custom_completer = no_op |
|
1499 | self.set_custom_completer = no_op | |
1495 | self.set_completer_frame = no_op |
|
1500 | self.set_completer_frame = no_op | |
@@ -1541,17 +1546,13 b' class InteractiveShell(Configurable, Magic):' | |||||
1541 | delims = delims.replace(ESC_MAGIC, '') |
|
1546 | delims = delims.replace(ESC_MAGIC, '') | |
1542 | readline.set_completer_delims(delims) |
|
1547 | readline.set_completer_delims(delims) | |
1543 | # otherwise we end up with a monster history after a while: |
|
1548 | # otherwise we end up with a monster history after a while: | |
1544 |
readline.set_history_length( |
|
1549 | readline.set_history_length(self.history_length) | |
1545 | try: |
|
1550 | try: | |
1546 | #print '*** Reading readline history' # dbg |
|
1551 | #print '*** Reading readline history' # dbg | |
1547 |
|
|
1552 | self.reload_history() | |
1548 | except IOError: |
|
1553 | except IOError: | |
1549 | pass # It doesn't exist yet. |
|
1554 | pass # It doesn't exist yet. | |
1550 |
|
1555 | |||
1551 | # If we have readline, we want our history saved upon ipython |
|
|||
1552 | # exiting. |
|
|||
1553 | atexit.register(self.save_hist) |
|
|||
1554 |
|
||||
1555 | # Configure auto-indent for all platforms |
|
1556 | # Configure auto-indent for all platforms | |
1556 | self.set_autoindent(self.autoindent) |
|
1557 | self.set_autoindent(self.autoindent) | |
1557 |
|
1558 | |||
@@ -2109,7 +2110,8 b' class InteractiveShell(Configurable, Magic):' | |||||
2109 | list.append(self, val) |
|
2110 | list.append(self, val) | |
2110 |
|
2111 | |||
2111 | import new |
|
2112 | import new | |
2112 |
self.input_hist.append = types.MethodType(myapp, |
|
2113 | self.history_manager.input_hist_parsed.append = types.MethodType(myapp, | |
|
2114 | self.history_manager.input_hist_parsed) | |||
2113 | # End dbg |
|
2115 | # End dbg | |
2114 |
|
2116 | |||
2115 | # All user code execution must happen with our context managers active |
|
2117 | # All user code execution must happen with our context managers active | |
@@ -2521,6 +2523,9 b' class InteractiveShell(Configurable, Magic):' | |||||
2521 | except OSError: |
|
2523 | except OSError: | |
2522 | pass |
|
2524 | pass | |
2523 |
|
2525 | |||
|
2526 | ||||
|
2527 | self.save_history() | |||
|
2528 | ||||
2524 | # Clear all user namespaces to release all references cleanly. |
|
2529 | # Clear all user namespaces to release all references cleanly. | |
2525 | self.reset() |
|
2530 | self.reset() | |
2526 |
|
2531 |
@@ -186,9 +186,9 b' python-profiler package from non-free.""")' | |||||
186 | N-M -> include items N..M (closed endpoint).""" |
|
186 | N-M -> include items N..M (closed endpoint).""" | |
187 |
|
187 | |||
188 | if raw: |
|
188 | if raw: | |
189 | hist = self.shell.input_hist_raw |
|
189 | hist = self.shell.history_manager.input_hist_raw | |
190 | else: |
|
190 | else: | |
191 | hist = self.shell.input_hist |
|
191 | hist = self.shell.history_manager.input_hist_parsed | |
192 |
|
192 | |||
193 | cmds = [] |
|
193 | cmds = [] | |
194 | for chunk in slices: |
|
194 | for chunk in slices: | |
@@ -200,7 +200,7 b' python-profiler package from non-free.""")' | |||||
200 | else: |
|
200 | else: | |
201 | ini = int(chunk) |
|
201 | ini = int(chunk) | |
202 | fin = ini+1 |
|
202 | fin = ini+1 | |
203 | cmds.append(hist[ini:fin]) |
|
203 | cmds.append(''.join(hist[ini:fin])) | |
204 | return cmds |
|
204 | return cmds | |
205 |
|
205 | |||
206 | def arg_err(self,func): |
|
206 | def arg_err(self,func): | |
@@ -1106,19 +1106,19 b' Currently the magic system has the following functions:\\n"""' | |||||
1106 | logger.timestamp = False |
|
1106 | logger.timestamp = False | |
1107 |
|
1107 | |||
1108 | if log_raw_input: |
|
1108 | if log_raw_input: | |
1109 | input_hist = self.shell.input_hist_raw |
|
1109 | input_hist = self.shell.history_manager.input_hist_raw | |
1110 | else: |
|
1110 | else: | |
1111 | input_hist = self.shell.input_hist |
|
1111 | input_hist = self.shell.history_manager.input_hist_parsed | |
1112 |
|
1112 | |||
1113 | if log_output: |
|
1113 | if log_output: | |
1114 | log_write = logger.log_write |
|
1114 | log_write = logger.log_write | |
1115 | output_hist = self.shell.output_hist |
|
1115 | output_hist = self.shell.history_manager.output_hist | |
1116 | for n in range(1,len(input_hist)-1): |
|
1116 | for n in range(1,len(input_hist)-1): | |
1117 | log_write(input_hist[n].rstrip()) |
|
1117 | log_write(input_hist[n].rstrip()) | |
1118 | if n in output_hist: |
|
1118 | if n in output_hist: | |
1119 | log_write(repr(output_hist[n]),'output') |
|
1119 | log_write(repr(output_hist[n]),'output') | |
1120 | else: |
|
1120 | else: | |
1121 | logger.log_write(input_hist[1:]) |
|
1121 | logger.log_write(''.join(input_hist[1:])) | |
1122 | if timestamp: |
|
1122 | if timestamp: | |
1123 | # re-enable timestamping |
|
1123 | # re-enable timestamping | |
1124 | logger.timestamp = True |
|
1124 | logger.timestamp = True | |
@@ -1551,7 +1551,7 b' Currently the magic system has the following functions:\\n"""' | |||||
1551 |
|
1551 | |||
1552 | stats = None |
|
1552 | stats = None | |
1553 | try: |
|
1553 | try: | |
1554 | self.shell.save_hist() |
|
1554 | self.shell.save_history() | |
1555 |
|
1555 | |||
1556 | if opts.has_key('p'): |
|
1556 | if opts.has_key('p'): | |
1557 | stats = self.magic_prun('',0,opts,arg_lst,prog_ns) |
|
1557 | stats = self.magic_prun('',0,opts,arg_lst,prog_ns) | |
@@ -1670,7 +1670,7 b' Currently the magic system has the following functions:\\n"""' | |||||
1670 | # contained therein. |
|
1670 | # contained therein. | |
1671 | del sys.modules[main_mod_name] |
|
1671 | del sys.modules[main_mod_name] | |
1672 |
|
1672 | |||
1673 | self.shell.reload_hist() |
|
1673 | self.shell.reload_history() | |
1674 |
|
1674 | |||
1675 | return stats |
|
1675 | return stats | |
1676 |
|
1676 | |||
@@ -2980,8 +2980,8 b' Defaulting color scheme to \'NoColor\'"""' | |||||
2980 | else: |
|
2980 | else: | |
2981 | start_magic = start |
|
2981 | start_magic = start | |
2982 | # Look through the input history in reverse |
|
2982 | # Look through the input history in reverse | |
2983 | for n in range(len(self.shell.input_hist)-2,0,-1): |
|
2983 | for n in range(len(self.shell.history_manager.input_hist_parsed)-2,0,-1): | |
2984 | input = self.shell.input_hist[n] |
|
2984 | input = self.shell.history_manager.input_hist_parsed[n] | |
2985 | # skip plain 'r' lines so we don't recurse to infinity |
|
2985 | # skip plain 'r' lines so we don't recurse to infinity | |
2986 | if input != '_ip.magic("r")\n' and \ |
|
2986 | if input != '_ip.magic("r")\n' and \ | |
2987 | (input.startswith(start) or input.startswith(start_magic)): |
|
2987 | (input.startswith(start) or input.startswith(start_magic)): |
@@ -128,7 +128,7 b' class HistoryConsoleWidget(ConsoleWidget):' | |||||
128 | break |
|
128 | break | |
129 | else: |
|
129 | else: | |
130 | history = None |
|
130 | history = None | |
131 |
|
131 | |||
132 | if history is not None: |
|
132 | if history is not None: | |
133 | self._history_index = index |
|
133 | self._history_index = index | |
134 | self.input_buffer = history |
|
134 | self.input_buffer = history |
@@ -167,7 +167,10 b' class IPythonWidget(FrontendWidget):' | |||||
167 | the IPython kernel. |
|
167 | the IPython kernel. | |
168 | """ |
|
168 | """ | |
169 | history_dict = msg['content']['history'] |
|
169 | history_dict = msg['content']['history'] | |
170 | items = [ history_dict[key] for key in sorted(history_dict.keys()) ] |
|
170 | input_history_dict = {} | |
|
171 | for key,val in history_dict.items(): | |||
|
172 | input_history_dict[int(key)] = val | |||
|
173 | items = [ val.rstrip() for _, val in sorted(input_history_dict.items()) ] | |||
171 | self._set_history(items) |
|
174 | self._set_history(items) | |
172 |
|
175 | |||
173 | def _handle_pyout(self, msg): |
|
176 | def _handle_pyout(self, msg): | |
@@ -184,8 +187,7 b' class IPythonWidget(FrontendWidget):' | |||||
184 | """ Reimplemented to make a history request. |
|
187 | """ Reimplemented to make a history request. | |
185 | """ |
|
188 | """ | |
186 | super(IPythonWidget, self)._started_channels() |
|
189 | super(IPythonWidget, self)._started_channels() | |
187 | # FIXME: Disabled until history requests are properly implemented. |
|
190 | self.kernel_manager.xreq_channel.history(raw=True, output=False) | |
188 | #self.kernel_manager.xreq_channel.history(raw=True, output=False) |
|
|||
189 |
|
191 | |||
190 | #--------------------------------------------------------------------------- |
|
192 | #--------------------------------------------------------------------------- | |
191 | # 'ConsoleWidget' public interface |
|
193 | # 'ConsoleWidget' public interface |
@@ -23,7 +23,6 b' import sys' | |||||
23 |
|
23 | |||
24 | from IPython.core.error import TryNext |
|
24 | from IPython.core.error import TryNext | |
25 | from IPython.core.usage import interactive_usage, default_banner |
|
25 | from IPython.core.usage import interactive_usage, default_banner | |
26 | from IPython.core.inputlist import InputList |
|
|||
27 | from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC |
|
26 | from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC | |
28 | from IPython.lib.inputhook import enable_gui |
|
27 | from IPython.lib.inputhook import enable_gui | |
29 | from IPython.lib.pylabtools import pylab_activate |
|
28 | from IPython.lib.pylabtools import pylab_activate | |
@@ -332,14 +331,14 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
332 | if self.has_readline and self.readline_use: |
|
331 | if self.has_readline and self.readline_use: | |
333 | histlen = self.readline.get_current_history_length() |
|
332 | histlen = self.readline.get_current_history_length() | |
334 | if histlen > 1: |
|
333 | if histlen > 1: | |
335 | newhist = self.input_hist_raw[-1].rstrip() |
|
334 | newhist = self.history_manager.input_hist_raw[-1].rstrip() | |
336 | self.readline.remove_history_item(histlen-1) |
|
335 | self.readline.remove_history_item(histlen-1) | |
337 | self.readline.replace_history_item(histlen-2, |
|
336 | self.readline.replace_history_item(histlen-2, | |
338 | newhist.encode(self.stdin_encoding)) |
|
337 | newhist.encode(self.stdin_encoding)) | |
339 | else: |
|
338 | else: | |
340 | self.input_hist_raw.append('%s\n' % line) |
|
339 | self.history_manager.input_hist_raw.append('%s\n' % line) | |
341 | elif not continue_prompt: |
|
340 | elif not continue_prompt: | |
342 | self.input_hist_raw.append('\n') |
|
341 | self.history_manager.input_hist_raw.append('\n') | |
343 | try: |
|
342 | try: | |
344 | lineout = self.prefilter_manager.prefilter_lines(line,continue_prompt) |
|
343 | lineout = self.prefilter_manager.prefilter_lines(line,continue_prompt) | |
345 | except: |
|
344 | except: |
@@ -50,8 +50,8 b' def clear_f(self,arg):' | |||||
50 | del user_ns[key] |
|
50 | del user_ns[key] | |
51 | except: pass |
|
51 | except: pass | |
52 | # must be done in-place |
|
52 | # must be done in-place | |
53 | self.input_hist[:] = ['\n'] * pc |
|
53 | self.history_manager.input_hist_parsed[:] = ['\n'] * pc | |
54 | self.input_hist_raw[:] = ['\n'] * pc |
|
54 | self.history_manager.input_hist_raw[:] = ['\n'] * pc | |
55 |
|
55 | |||
56 | elif target == 'array': |
|
56 | elif target == 'array': | |
57 | # Support cleaning up numpy arrays |
|
57 | # Support cleaning up numpy arrays |
@@ -118,7 +118,7 b" def jot_obj(self, obj, name, comment=''):" | |||||
118 |
|
118 | |||
119 | # which one works better? |
|
119 | # which one works better? | |
120 | #all = ip.shadowhist.all() |
|
120 | #all = ip.shadowhist.all() | |
121 | all = ip.shell.input_hist |
|
121 | all = ip.shell.history_manager.input_hist_parsed | |
122 |
|
122 | |||
123 | # We may actually want to make snapshot of files that are run-ned. |
|
123 | # We may actually want to make snapshot of files that are run-ned. | |
124 |
|
124 |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now