MCPcopy Index your code
hub / github.com/ipython/ipython / catch_corrupt_db

Function catch_corrupt_db

IPython/core/history.py:115–165  ·  view source on GitHub ↗

A decorator which wraps HistoryAccessor method calls to catch errors from a corrupt SQLite database, move the old database out of the way, and create a new one. We avoid clobbering larger databases because this may be triggered due to filesystem issues, not just a corrupt file.

(f, self, *a, **kw)

Source from the content-addressed store, hash-verified

113
114@decorator
115def catch_corrupt_db(f, self, *a, **kw): # type: ignore [no-untyped-def]
116 """A decorator which wraps HistoryAccessor method calls to catch errors from
117 a corrupt SQLite database, move the old database out of the way, and create
118 a new one.
119
120 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
121 not just a corrupt file.
122 """
123 try:
124 return f(self, *a, **kw)
125 except (DatabaseError, OperationalError) as e:
126 self._corrupt_db_counter += 1
127 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
128 if self.hist_file != ":memory:":
129 if self._corrupt_db_counter > self._corrupt_db_limit:
130 self.hist_file = ":memory:"
131 self.log.error(
132 "Failed to load history too many times, history will not be saved."
133 )
134 elif self.hist_file.is_file():
135 # move the file out of the way
136 base = str(self.hist_file.parent / self.hist_file.stem)
137 ext = self.hist_file.suffix
138 size = self.hist_file.stat().st_size
139 if size >= _SAVE_DB_SIZE:
140 # if there's significant content, avoid clobbering
141 now = (
142 datetime.datetime.now(datetime.timezone.utc)
143 .isoformat()
144 .replace(":", ".")
145 )
146 newpath = base + "-corrupt-" + now + ext
147 # don't clobber previous corrupt backups
148 for i in range(100):
149 if not Path(newpath).exists():
150 break
151 else:
152 newpath = base + "-corrupt-" + now + ("-%i" % i) + ext
153 else:
154 # not much content, possibly empty; don't worry about clobbering
155 # maybe we should just delete it?
156 newpath = base + "-corrupt" + ext
157 self.hist_file.rename(newpath)
158 self.log.error(
159 "History file was moved to %s and a new file created.", newpath
160 )
161 self.init_db()
162 return []
163 else:
164 # Failed with :memory:, something serious is wrong
165 raise
166
167
168class HistoryAccessorBase(LoggingConfigurable):

Callers

nothing calls this directly

Calls 4

errorMethod · 0.80
replaceMethod · 0.80
init_dbMethod · 0.80
fFunction · 0.50

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…