Show More
@@ -16,7 +16,6 b' except ImportError:' | |||
|
16 | 16 | from pysqlite2 import dbapi2 as sqlite3 |
|
17 | 17 | except ImportError: |
|
18 | 18 | sqlite3 = None |
|
19 | import sys | |
|
20 | 19 | import threading |
|
21 | 20 | |
|
22 | 21 | from traitlets.config.configurable import LoggingConfigurable |
@@ -81,18 +80,29 b' def catch_corrupt_db(f, self, *a, **kw):' | |||
|
81 | 80 | try: |
|
82 | 81 | return f(self, *a, **kw) |
|
83 | 82 | except (DatabaseError, OperationalError) as e: |
|
84 | if os.path.isfile(self.hist_file): | |
|
85 | # Try to move the file out of the way | |
|
86 | base,ext = os.path.splitext(self.hist_file) | |
|
87 | newpath = base + '-corrupt' + ext | |
|
88 |
|
|
|
89 | print("ERROR! History file wasn't a valid SQLite database (%s)." % e, | |
|
90 | "It was moved to %s" % newpath, "and a new file created.", file=sys.stderr) | |
|
83 | self._corrupt_db_counter += 1 | |
|
84 | self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e) | |
|
85 | if self.hist_file != ':memory:': | |
|
86 | if self._corrupt_db_counter > self._corrupt_db_limit: | |
|
87 | self.hist_file = ':memory:' | |
|
88 | self.log.error("Failed to load history too many times, history will not be saved.") | |
|
89 | elif os.path.isfile(self.hist_file): | |
|
90 | # Try to move the file out of the way | |
|
91 | base,ext = os.path.splitext(self.hist_file) | |
|
92 | now = datetime.datetime.now().isoformat().replace(':', '.') | |
|
93 | newpath = base + '-corrupt-' + now + ext | |
|
94 | # don't clobber previous corrupt backups | |
|
95 | for i in range(100): | |
|
96 | if not os.path.isfile(newpath): | |
|
97 | break | |
|
98 | else: | |
|
99 | newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext | |
|
100 | os.rename(self.hist_file, newpath) | |
|
101 | self.log.error("History file was moved to %s and a new file created.", newpath) | |
|
91 | 102 | self.init_db() |
|
92 | 103 | return [] |
|
93 | ||
|
94 | 104 | else: |
|
95 |
# |
|
|
105 | # Failed with :memory:, something serious is wrong | |
|
96 | 106 | raise |
|
97 | 107 | |
|
98 | 108 | class HistoryAccessorBase(LoggingConfigurable): |
@@ -118,6 +128,11 b' class HistoryAccessor(HistoryAccessorBase):' | |||
|
118 | 128 | This is intended for use by standalone history tools. IPython shells use |
|
119 | 129 | HistoryManager, below, which is a subclass of this.""" |
|
120 | 130 | |
|
131 | # counter for init_db retries, so we don't keep trying over and over | |
|
132 | _corrupt_db_counter = 0 | |
|
133 | # after two failures, fallback on :memory: | |
|
134 | _corrupt_db_limit = 2 | |
|
135 | ||
|
121 | 136 | # String holding the path to the history file |
|
122 | 137 | hist_file = Unicode(config=True, |
|
123 | 138 | help="""Path to file to use for SQLite history database. |
@@ -231,6 +246,8 b' class HistoryAccessor(HistoryAccessorBase):' | |||
|
231 | 246 | (session integer, line integer, output text, |
|
232 | 247 | PRIMARY KEY (session, line))""") |
|
233 | 248 | self.db.commit() |
|
249 | # success! reset corrupt db count | |
|
250 | self._corrupt_db_counter = 0 | |
|
234 | 251 | |
|
235 | 252 | def writeout_cache(self): |
|
236 | 253 | """Overridden by HistoryManager to dump the cache before certain |
General Comments 0
You need to be logged in to leave comments.
Login now