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 datetime | |||
16 | import os |
|
17 | import os | |
17 | import re |
|
18 | import re | |
18 | import sqlite3 |
|
19 | import sqlite3 | |
@@ -90,6 +91,7 b' class HistoryManager(Configurable):' | |||||
90 | histfname = 'history' |
|
91 | histfname = 'history' | |
91 | self.hist_file = os.path.join(shell.ipython_dir, histfname + '.sqlite') |
|
92 | self.hist_file = os.path.join(shell.ipython_dir, histfname + '.sqlite') | |
92 | self.init_db() |
|
93 | self.init_db() | |
|
94 | self.new_session() | |||
93 |
|
95 | |||
94 | self._i00, self._i, self._ii, self._iii = '','','','' |
|
96 | self._i00, self._i, self._ii, self._iii = '','','','' | |
95 |
|
97 | |||
@@ -97,8 +99,11 b' class HistoryManager(Configurable):' | |||||
97 | '%quit', '%Exit', '%exit']) |
|
99 | '%quit', '%Exit', '%exit']) | |
98 |
|
100 | |||
99 | def init_db(self): |
|
101 | def init_db(self): | |
100 |
"""Connect to the database |
|
102 | """Connect to the database, and create tables if necessary.""" | |
101 | self.db = sqlite3.connect(self.hist_file) |
|
103 | self.db = sqlite3.connect(self.hist_file) | |
|
104 | self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer | |||
|
105 | primary key autoincrement, start timestamp, | |||
|
106 | end timestamp, num_cmds integer, remark text)""") | |||
102 | self.db.execute("""CREATE TABLE IF NOT EXISTS history |
|
107 | self.db.execute("""CREATE TABLE IF NOT EXISTS history | |
103 | (session integer, line integer, source text, source_raw text, |
|
108 | (session integer, line integer, source text, source_raw text, | |
104 | PRIMARY KEY (session, line))""") |
|
109 | PRIMARY KEY (session, line))""") | |
@@ -107,23 +112,47 b' class HistoryManager(Configurable):' | |||||
107 | self.db.execute("""CREATE TABLE IF NOT EXISTS output_history |
|
112 | self.db.execute("""CREATE TABLE IF NOT EXISTS output_history | |
108 | (session integer, line integer, output text, |
|
113 | (session integer, line integer, output text, | |
109 | PRIMARY KEY (session, line))""") |
|
114 | PRIMARY KEY (session, line))""") | |
110 | cur = self.db.execute("""SELECT name FROM sqlite_master WHERE |
|
|||
111 | type='table' AND name='singletons'""") |
|
|||
112 | if not cur.fetchone(): |
|
|||
113 | self.db.execute("""CREATE TABLE singletons |
|
|||
114 | (name text PRIMARY KEY, value)""") |
|
|||
115 | self.db.execute("""INSERT INTO singletons VALUES |
|
|||
116 | ('session_number', 1)""") |
|
|||
117 | self.db.commit() |
|
|||
118 | cur = self.db.execute("""SELECT value FROM singletons WHERE |
|
|||
119 | name='session_number'""") |
|
|||
120 | self.session_number = cur.fetchone()[0] |
|
|||
121 |
|
||||
122 | #Increment by one for next session. |
|
|||
123 | self.db.execute("""UPDATE singletons SET value=? WHERE |
|
|||
124 | name='session_number'""", (self.session_number+1,)) |
|
|||
125 | self.db.commit() |
|
115 | self.db.commit() | |
126 |
|
116 | |||
|
117 | def new_session(self): | |||
|
118 | """Get a new session number.""" | |||
|
119 | with self.db: | |||
|
120 | cur = self.db.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL, | |||
|
121 | NULL, "") """, (datetime.datetime.now(),)) | |||
|
122 | self.session_number = cur.lastrowid | |||
|
123 | ||||
|
124 | def end_session(self): | |||
|
125 | """Close the database session, filling in the end time and line count.""" | |||
|
126 | self.writeout_cache() | |||
|
127 | with self.db: | |||
|
128 | self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE | |||
|
129 | session==?""", (datetime.datetime.now(), | |||
|
130 | len(self.input_hist_parsed)-1, self.session_number)) | |||
|
131 | self.session_number = 0 | |||
|
132 | ||||
|
133 | def name_session(self, name): | |||
|
134 | """Give the current session a name in the history database.""" | |||
|
135 | with self.db: | |||
|
136 | self.db.execute("UPDATE sessions SET remark=? WHERE session==?", | |||
|
137 | (name, self.session_number)) | |||
|
138 | ||||
|
139 | def reset(self, new_session=True): | |||
|
140 | """Clear the session history, releasing all object references, and | |||
|
141 | optionally open a new session.""" | |||
|
142 | if self.session_number: | |||
|
143 | self.end_session() | |||
|
144 | self.input_hist_parsed[:] = [""] | |||
|
145 | self.input_hist_raw[:] = [""] | |||
|
146 | self.output_hist.clear() | |||
|
147 | # The directory history can't be completely empty | |||
|
148 | self.dir_hist[:] = [os.getcwd()] | |||
|
149 | ||||
|
150 | if new_session: | |||
|
151 | self.new_session() | |||
|
152 | ||||
|
153 | ## ------------------------------- | |||
|
154 | ## Methods for retrieving history: | |||
|
155 | ## ------------------------------- | |||
127 | def _get_hist_sql(self, sql, params, raw=True, output=False): |
|
156 | def _get_hist_sql(self, sql, params, raw=True, output=False): | |
128 | """Prepares and runs an SQL query for the history database. |
|
157 | """Prepares and runs an SQL query for the history database. | |
129 |
|
158 | |||
@@ -245,7 +274,10 b' class HistoryManager(Configurable):' | |||||
245 | for sess, s, e in extract_hist_ranges(rangestr): |
|
274 | for sess, s, e in extract_hist_ranges(rangestr): | |
246 | for line in self.get_history(sess, s, e, raw=raw, output=output): |
|
275 | for line in self.get_history(sess, s, e, raw=raw, output=output): | |
247 | yield line |
|
276 | yield line | |
248 |
|
277 | |||
|
278 | ## ---------------------------- | |||
|
279 | ## Methods for storing history: | |||
|
280 | ## ---------------------------- | |||
249 | def store_inputs(self, line_num, source, source_raw=None): |
|
281 | def store_inputs(self, line_num, source, source_raw=None): | |
250 | """Store source and raw input in history and create input cache |
|
282 | """Store source and raw input in history and create input cache | |
251 | variables _i*. |
|
283 | variables _i*. | |
@@ -312,27 +344,6 b' class HistoryManager(Configurable):' | |||||
312 | self.db_input_cache = [] |
|
344 | self.db_input_cache = [] | |
313 | self.db_output_cache = [] |
|
345 | self.db_output_cache = [] | |
314 |
|
346 | |||
315 | def sync_inputs(self): |
|
|||
316 | """Ensure raw and translated histories have same length.""" |
|
|||
317 | lr = len(self.input_hist_raw) |
|
|||
318 | lp = len(self.input_hist_parsed) |
|
|||
319 | if lp < lr: |
|
|||
320 | self.input_hist_raw[:lr-lp] = [] |
|
|||
321 | elif lr < lp: |
|
|||
322 | self.input_hist_parsed[:lp-lr] = [] |
|
|||
323 |
|
||||
324 | def reset(self, new_session=True): |
|
|||
325 | """Clear the current session's history, and (optionally) start a new |
|
|||
326 | session.""" |
|
|||
327 | self.input_hist_parsed[:] = [""] |
|
|||
328 | self.input_hist_raw[:] = [""] |
|
|||
329 | self.output_hist.clear() |
|
|||
330 | # The directory history can't be completely empty |
|
|||
331 | self.dir_hist[:] = [os.getcwd()] |
|
|||
332 |
|
||||
333 | if new_session: |
|
|||
334 | self.writeout_cache() |
|
|||
335 | self.init_db() # Get new session number |
|
|||
336 |
|
347 | |||
337 | # To match, e.g. ~5/8-~2/3 |
|
348 | # To match, e.g. ~5/8-~2/3 | |
338 | range_re = re.compile(r""" |
|
349 | range_re = re.compile(r""" |
@@ -2526,10 +2526,10 b' class InteractiveShell(Configurable, Magic):' | |||||
2526 | os.unlink(tfile) |
|
2526 | os.unlink(tfile) | |
2527 | except OSError: |
|
2527 | except OSError: | |
2528 | pass |
|
2528 | pass | |
2529 |
|
|
2529 | ||
2530 | # Write anything in the history cache to the database. |
|
2530 | # Close the history session (this stores the end time and line count) | |
2531 |
self.history_manager. |
|
2531 | self.history_manager.end_session() | |
2532 |
|
2532 | |||
2533 | # Clear all user namespaces to release all references cleanly. |
|
2533 | # Clear all user namespaces to release all references cleanly. | |
2534 | self.reset(new_session=False) |
|
2534 | self.reset(new_session=False) | |
2535 |
|
2535 |
@@ -30,6 +30,7 b' def test_history():' | |||||
30 | ip.history_manager = HistoryManager(shell=ip) |
|
30 | ip.history_manager = HistoryManager(shell=ip) | |
31 | ip.history_manager.hist_file = histfile |
|
31 | ip.history_manager.hist_file = histfile | |
32 | ip.history_manager.init_db() # Has to be called after changing file |
|
32 | ip.history_manager.init_db() # Has to be called after changing file | |
|
33 | ip.history_manager.reset() | |||
33 | print 'test',histfile |
|
34 | print 'test',histfile | |
34 | hist = ['a=1', 'def f():\n test = 1\n return test', 'b=2'] |
|
35 | hist = ['a=1', 'def f():\n test = 1\n return test', 'b=2'] | |
35 | for i, h in enumerate(hist, start=1): |
|
36 | for i, h in enumerate(hist, start=1): |
@@ -185,10 +185,6 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
185 |
|
185 | |||
186 | with nested(self.builtin_trap, self.display_trap): |
|
186 | with nested(self.builtin_trap, self.display_trap): | |
187 |
|
187 | |||
188 | # if you run stuff with -c <cmd>, raw hist is not updated |
|
|||
189 | # ensure that it's in sync |
|
|||
190 | self.history_manager.sync_inputs() |
|
|||
191 |
|
||||
192 | while 1: |
|
188 | while 1: | |
193 | try: |
|
189 | try: | |
194 | self.interact(display_banner=display_banner) |
|
190 | self.interact(display_banner=display_banner) |
General Comments 0
You need to be logged in to leave comments.
Login now