|
@@
-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 and get new session number."""
|
|
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()
|
|
115
|
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
|
|
|
116
|
|
|
122
|
#Increment by one for next session.
|
|
117
|
def new_session(self):
|
|
123
|
self.db.execute("""UPDATE singletons SET value=? WHERE
|
|
118
|
"""Get a new session number."""
|
|
124
|
name='session_number'""", (self.session_number+1,))
|
|
119
|
with self.db:
|
|
125
|
self.db.commit()
|
|
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()
|
|
126
|
|
|
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
|
|
|
@@
-246,6
+275,9
b' class HistoryManager(Configurable):'
|
|
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"""
|