diff --git a/IPython/core/history.py b/IPython/core/history.py index 057fd12..ddd5dd4 100644 --- a/IPython/core/history.py +++ b/IPython/core/history.py @@ -98,7 +98,15 @@ class HistoryManager(Configurable): else: histfname = 'history' self.hist_file = os.path.join(shell.ipython_dir, histfname + '.sqlite') - self.init_db() + try: + self.init_db() + except sqlite3.DatabaseError: + newpath = os.path.join(self.shell.ipython_dir, "hist-corrupt.sqlite") + os.rename(self.hist_file, newpath) + print("ERROR! History file wasn't a valid SQLite database.", + "It was moved to %s" % newpath, "and a new file created.") + self.init_db() + self.new_session() self._i00, self._i, self._ii, self._iii = '','','','' @@ -357,8 +365,7 @@ class HistoryManager(Configurable): self.input_hist_parsed.append(source) self.input_hist_raw.append(source_raw) - self.db_input_cache.append((self.session_number, line_num, - source, source_raw)) + self.db_input_cache.append((line_num, source, source_raw)) # Trigger to flush cache and write to DB. if len(self.db_input_cache) >= self.db_cache_size: self.writeout_cache() @@ -390,22 +397,46 @@ class HistoryManager(Configurable): if (not self.db_log_output) or not self.output_hist_reprs[line_num]: return output = json.dumps(self.output_hist_reprs[line_num]) - db_row = (self.session_number, line_num, output) - if self.db_cache_size > 1: - self.db_output_cache.append(db_row) - else: - with self.db: - self.db.execute("INSERT INTO output_history VALUES (?,?,?)", db_row) + self.db_output_cache.append((line_num, output)) + if self.db_cache_size <= 1: + self.writeout_cache() + + def _writeout_input_cache(self): + for line in self.db_input_cache: + with self.db: + self.db.execute("INSERT INTO history VALUES (?, ?, ?, ?)", + (self.session_number,)+line) + + def _writeout_output_cache(self): + for line in self.db_output_cache: + with self.db: + self.db.execute("INSERT INTO output_history VALUES (?, ?, ?)", + (self.session_number,)+line) + def writeout_cache(self): - #print(self.db_input_cache) - with self.db: - self.db.executemany("INSERT INTO history VALUES (?, ?, ?, ?)", - self.db_input_cache) - self.db.executemany("INSERT INTO output_history VALUES (?, ?, ?)", - self.db_output_cache) - self.db_input_cache = [] - self.db_output_cache = [] + """Write any entries in the cache to the database.""" + try: + self._writeout_input_cache() + except sqlite3.IntegrityError: + self.new_session() + print("ERROR! Session/line number was not unique in", + "database. History logging moved to new session", + self.session_number) + try: # Try writing to the new session. If this fails, don't recurse + self.writeout_cache() + except sqlite3.IntegrityError: + pass + finally: + self.db_input_cache = [] + + try: + self._writeout_output_cache() + except sqlite3.IntegrityError: + print("!! Session/line number for output was not unique", + "in database. Output will not be stored.") + finally: + self.db_output_cache = [] # To match, e.g. ~5/8-~2/3