This thread takes care of writing history to the database, so that the UI isn't held up while that happens. It waits for the HistoryManager's save_flag to be set, then writes out the history cache. The main thread is responsible for setting the flag when the cache size reaches a def
| 1120 | |
| 1121 | |
| 1122 | class HistorySavingThread(threading.Thread): |
| 1123 | """This thread takes care of writing history to the database, so that |
| 1124 | the UI isn't held up while that happens. |
| 1125 | |
| 1126 | It waits for the HistoryManager's save_flag to be set, then writes out |
| 1127 | the history cache. The main thread is responsible for setting the flag when |
| 1128 | the cache size reaches a defined threshold.""" |
| 1129 | |
| 1130 | save_flag: threading.Event |
| 1131 | daemon: bool = True |
| 1132 | _stop_now: bool = False |
| 1133 | enabled: bool = True |
| 1134 | history_manager: ref[HistoryManager] |
| 1135 | _stopped = False |
| 1136 | |
| 1137 | def __init__(self, history_manager: HistoryManager) -> None: |
| 1138 | super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread") |
| 1139 | self.history_manager = ref(history_manager) |
| 1140 | self.enabled = history_manager.enabled |
| 1141 | self.save_flag = threading.Event() |
| 1142 | |
| 1143 | @only_when_enabled |
| 1144 | def run(self) -> None: |
| 1145 | atexit.register(self.stop) |
| 1146 | # We need a separate db connection per thread: |
| 1147 | try: |
| 1148 | hm: ReferenceType[HistoryManager] |
| 1149 | with hold(self.history_manager) as hm: |
| 1150 | if hm() is not None: |
| 1151 | self.db = sqlite3.connect( |
| 1152 | str(hm().hist_file), # type: ignore [union-attr] |
| 1153 | **cast(dict[str, t.Any], hm().connection_options), # type: ignore [union-attr] |
| 1154 | ) |
| 1155 | while True: |
| 1156 | self.save_flag.wait() |
| 1157 | with hold(self.history_manager) as hm: |
| 1158 | if hm() is None: |
| 1159 | self._stop_now = True |
| 1160 | if self._stop_now: |
| 1161 | self.db.close() |
| 1162 | return |
| 1163 | self.save_flag.clear() |
| 1164 | if hm() is not None: |
| 1165 | hm().writeout_cache(self.db) # type: ignore [union-attr] |
| 1166 | |
| 1167 | except Exception as e: |
| 1168 | print( |
| 1169 | ( |
| 1170 | "The history saving thread hit an unexpected error (%s)." |
| 1171 | "History will not be written to the database." |
| 1172 | ) |
| 1173 | % repr(e) |
| 1174 | ) |
| 1175 | finally: |
| 1176 | atexit.unregister(self.stop) |
| 1177 | |
| 1178 | def stop(self) -> None: |
| 1179 | """This can be called from the main thread to safely stop this thread. |
no outgoing calls
no test coverage detected
searching dependent graphs…