Show More
@@ -13,6 +13,7 b'' | |||||
13 | from __future__ import print_function |
|
13 | from __future__ import print_function | |
14 |
|
14 | |||
15 | # Stdlib imports |
|
15 | # Stdlib imports | |
|
16 | import atexit | |||
16 | import fnmatch |
|
17 | import fnmatch | |
17 | import json |
|
18 | import json | |
18 | import os |
|
19 | import os | |
@@ -105,6 +106,13 b' class HistoryManager(object):' | |||||
105 |
|
106 | |||
106 | # Fill the history zero entry, user counter starts at 1 |
|
107 | # Fill the history zero entry, user counter starts at 1 | |
107 | self.store_inputs('\n', '\n') |
|
108 | self.store_inputs('\n', '\n') | |
|
109 | ||||
|
110 | # Autosave every 60 seconds: | |||
|
111 | self.autosave_flag = threading.Event() | |||
|
112 | self.autosave_timer = HistorySaveThread(self.autosave_flag, 60) | |||
|
113 | self.autosave_timer.start() | |||
|
114 | self.shell.register_post_execute(self.autosave_if_due) | |||
|
115 | # Ensure that any autosave thread we start is stopped tidily. | |||
108 |
|
116 | |||
109 | def _init_shadow_hist(self): |
|
117 | def _init_shadow_hist(self): | |
110 | try: |
|
118 | try: | |
@@ -142,6 +150,13 b' class HistoryManager(object):' | |||||
142 | with open(self.hist_file,'wt') as hfile: |
|
150 | with open(self.hist_file,'wt') as hfile: | |
143 | json.dump(hist, hfile, |
|
151 | json.dump(hist, hfile, | |
144 | sort_keys=True, indent=4) |
|
152 | sort_keys=True, indent=4) | |
|
153 | ||||
|
154 | def autosave_if_due(self): | |||
|
155 | """Check if the autosave event is set; if so, save history. We do it | |||
|
156 | this way so that the save takes place in the main thread.""" | |||
|
157 | if self.autosave_flag.is_set(): | |||
|
158 | self.save_history() | |||
|
159 | self.autosave_flag.clear() | |||
145 |
|
160 | |||
146 | def reload_history(self): |
|
161 | def reload_history(self): | |
147 | """Reload the input history from disk file.""" |
|
162 | """Reload the input history from disk file.""" | |
@@ -257,29 +272,34 b' class HistoryManager(object):' | |||||
257 | self.dir_hist[:] = [os.getcwd()] |
|
272 | self.dir_hist[:] = [os.getcwd()] | |
258 |
|
273 | |||
259 | class HistorySaveThread(threading.Thread): |
|
274 | class HistorySaveThread(threading.Thread): | |
260 |
"""This thread save |
|
275 | """This thread makes IPython save history periodically (the current default | |
261 |
minute), so that it is not lost in the event of a crash. It also |
|
276 | is once per minute), so that it is not lost in the event of a crash. It also | |
262 |
commands in the current IPython shell to be accessed in a newly |
|
277 | allows the commands in the current IPython shell to be accessed in a newly | |
263 |
instance. |
|
278 | started instance. | |
|
279 | ||||
|
280 | This simply sets an event to indicate that history should be saved. The | |||
|
281 | actual save is carried out after executing a user command, to avoid | |||
|
282 | thread issues.""" | |||
264 | daemon = True |
|
283 | daemon = True | |
265 |
|
284 | |||
266 |
def __init__(self, |
|
285 | def __init__(self, autosave_flag, time_interval=60): | |
267 | threading.Thread.__init__(self) |
|
286 | threading.Thread.__init__(self) | |
268 | self.IPython_object = IPython_object |
|
|||
269 | self.time_interval = time_interval |
|
287 | self.time_interval = time_interval | |
|
288 | self.autosave_flag = autosave_flag | |||
270 | self.exit_now = threading.Event() |
|
289 | self.exit_now = threading.Event() | |
|
290 | # Ensure the thread is stopped tidily when exiting normally | |||
|
291 | atexit.register(self.stop) | |||
271 |
|
292 | |||
272 | def run(self): |
|
293 | def run(self): | |
273 | while True: |
|
294 | while True: | |
274 | self.exit_now.wait(self.time_interval) |
|
295 | self.exit_now.wait(self.time_interval) | |
275 | if self.exit_now.is_set(): |
|
296 | if self.exit_now.is_set(): | |
276 | break |
|
297 | break | |
277 |
#print(" |
|
298 | #print("Setting flag for autosaving history...") # DEBUG | |
278 |
self. |
|
299 | self.autosave_flag.set() | |
279 |
|
300 | |||
280 | def stop(self): |
|
301 | def stop(self): | |
281 |
"""Safely and quickly stop the autosave thread. |
|
302 | """Safely and quickly stop the autosave timer thread.""" | |
282 | history to be saved before stopping.""" |
|
|||
283 | self.exit_now.set() |
|
303 | self.exit_now.set() | |
284 | self.join() |
|
304 | self.join() | |
285 |
|
305 |
@@ -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.history import HistorySaveThread |
|
|||
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 | |
@@ -1238,8 +1237,6 b' class InteractiveShell(Configurable, Magic):' | |||||
1238 | def init_history(self): |
|
1237 | def init_history(self): | |
1239 | """Sets up the command history, and starts regular autosaves.""" |
|
1238 | """Sets up the command history, and starts regular autosaves.""" | |
1240 | self.history_manager = HistoryManager(shell=self) |
|
1239 | self.history_manager = HistoryManager(shell=self) | |
1241 | self.history_thread = HistorySaveThread(self, time_interval=60) |
|
|||
1242 | self.history_thread.start() |
|
|||
1243 |
|
1240 | |||
1244 | def save_history(self): |
|
1241 | def save_history(self): | |
1245 | """Save input history to a file (via readline library).""" |
|
1242 | """Save input history to a file (via readline library).""" | |
@@ -2527,7 +2524,6 b' class InteractiveShell(Configurable, Magic):' | |||||
2527 | except OSError: |
|
2524 | except OSError: | |
2528 | pass |
|
2525 | pass | |
2529 |
|
2526 | |||
2530 | self.history_thread.stop() |
|
|||
2531 | self.save_history() |
|
2527 | self.save_history() | |
2532 |
|
2528 | |||
2533 | # Clear all user namespaces to release all references cleanly. |
|
2529 | # Clear all user namespaces to release all references cleanly. |
@@ -24,7 +24,6 b' import sys' | |||||
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.interactiveshell import InteractiveShell, InteractiveShellABC |
|
26 | from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC | |
27 | from IPython.core.history import HistorySaveThread |
|
|||
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 | |
30 | from IPython.utils.terminal import toggle_set_term_title, set_term_title |
|
29 | from IPython.utils.terminal import toggle_set_term_title, set_term_title |
General Comments 0
You need to be logged in to leave comments.
Login now