##// END OF EJS Templates
Catch sqlite DatabaseErrors in more places when reading the history database....
Thomas Kluyver -
Show More
@@ -62,6 +62,37 b' def needs_sqlite(f, self, *a, **kw):'
62 return f(self, *a, **kw)
62 return f(self, *a, **kw)
63
63
64
64
65 if sqlite3 is not None:
66 DatabaseError = sqlite3.DatabaseError
67 else:
68 class DatabaseError(Exception):
69 "Dummy exception when sqlite could not be imported. Should never occur."
70
71 @decorator
72 def catch_corrupt_db(f, self, *a, **kw):
73 """A decorator which wraps HistoryAccessor method calls to catch errors from
74 a corrupt SQLite database, move the old database out of the way, create a
75 new one, and optionally retry the function.
76 """
77 try:
78 return f(self, *a, **kw)
79 except DatabaseError:
80 if os.path.isfile(self.hist_file):
81 # Try to move the file out of the way
82 base,ext = os.path.splitext(self.hist_file)
83 newpath = base + '-corrupt' + ext
84 os.rename(self.hist_file, newpath)
85 self.init_db()
86 print("ERROR! History file wasn't a valid SQLite database.",
87 "It was moved to %s" % newpath, "and a new file created.")
88 return []
89
90 else:
91 # The hist_file is probably :memory: or something else.
92 raise
93
94
95
65 class HistoryAccessor(Configurable):
96 class HistoryAccessor(Configurable):
66 """Access the history database without adding to it.
97 """Access the history database without adding to it.
67
98
@@ -143,25 +174,7 b' class HistoryAccessor(Configurable):'
143 warn("IPython History requires SQLite, your history will not be saved\n")
174 warn("IPython History requires SQLite, your history will not be saved\n")
144 self.enabled = False
175 self.enabled = False
145
176
146 if sqlite3 is not None:
177 self.init_db()
147 DatabaseError = sqlite3.DatabaseError
148 else:
149 DatabaseError = Exception
150
151 try:
152 self.init_db()
153 except DatabaseError:
154 if os.path.isfile(self.hist_file):
155 # Try to move the file out of the way
156 base,ext = os.path.splitext(self.hist_file)
157 newpath = base + '-corrupt' + ext
158 os.rename(self.hist_file, newpath)
159 print("ERROR! History file wasn't a valid SQLite database.",
160 "It was moved to %s" % newpath, "and a new file created.")
161 self.init_db()
162 else:
163 # The hist_file is probably :memory: or something else.
164 raise
165
178
166 def _get_hist_file_name(self, profile='default'):
179 def _get_hist_file_name(self, profile='default'):
167 """Find the history file for the given profile name.
180 """Find the history file for the given profile name.
@@ -176,6 +189,7 b' class HistoryAccessor(Configurable):'
176 """
189 """
177 return os.path.join(locate_profile(profile), 'history.sqlite')
190 return os.path.join(locate_profile(profile), 'history.sqlite')
178
191
192 @catch_corrupt_db
179 def init_db(self):
193 def init_db(self):
180 """Connect to the database, and create tables if necessary."""
194 """Connect to the database, and create tables if necessary."""
181 if not self.enabled:
195 if not self.enabled:
@@ -207,6 +221,7 b' class HistoryAccessor(Configurable):'
207 ## -------------------------------
221 ## -------------------------------
208 ## Methods for retrieving history:
222 ## Methods for retrieving history:
209 ## -------------------------------
223 ## -------------------------------
224 @catch_corrupt_db
210 def _run_sql(self, sql, params, raw=True, output=False):
225 def _run_sql(self, sql, params, raw=True, output=False):
211 """Prepares and runs an SQL query for the history database.
226 """Prepares and runs an SQL query for the history database.
212
227
@@ -235,6 +250,7 b' class HistoryAccessor(Configurable):'
235 return cur
250 return cur
236
251
237 @needs_sqlite
252 @needs_sqlite
253 @catch_corrupt_db
238 def get_session_info(self, session=0):
254 def get_session_info(self, session=0):
239 """get info about a session
255 """get info about a session
240
256
General Comments 0
You need to be logged in to leave comments. Login now