Show More
@@ -265,7 +265,7 b' class HistoryAccessor(HistoryAccessorBase):' | |||
|
265 | 265 | ## ------------------------------- |
|
266 | 266 | ## Methods for retrieving history: |
|
267 | 267 | ## ------------------------------- |
|
268 | def _run_sql(self, sql, params, raw=True, output=False): | |
|
268 | def _run_sql(self, sql, params, raw=True, output=False, latest=False): | |
|
269 | 269 | """Prepares and runs an SQL query for the history database. |
|
270 | 270 | |
|
271 | 271 | Parameters |
@@ -276,6 +276,8 b' class HistoryAccessor(HistoryAccessorBase):' | |||
|
276 | 276 | Parameters passed to the SQL query (to replace "?") |
|
277 | 277 | raw, output : bool |
|
278 | 278 | See :meth:`get_range` |
|
279 | latest : bool | |
|
280 | Select rows with max (session, line) | |
|
279 | 281 | |
|
280 | 282 | Returns |
|
281 | 283 | ------- |
@@ -286,8 +288,12 b' class HistoryAccessor(HistoryAccessorBase):' | |||
|
286 | 288 | if output: |
|
287 | 289 | sqlfrom = "history LEFT JOIN output_history USING (session, line)" |
|
288 | 290 | toget = "history.%s, output_history.output" % toget |
|
291 | if latest: | |
|
292 | toget += ", MAX(session * 128 * 1024 + line)" | |
|
289 | 293 | cur = self.db.execute("SELECT session, line, %s FROM %s " %\ |
|
290 | 294 | (toget, sqlfrom) + sql, params) |
|
295 | if latest: | |
|
296 | cur = (row[:-1] for row in cur) | |
|
291 | 297 | if output: # Regroup into 3-tuples, and parse JSON |
|
292 | 298 | return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur) |
|
293 | 299 | return cur |
@@ -395,7 +401,7 b' class HistoryAccessor(HistoryAccessorBase):' | |||
|
395 | 401 | params += (n,) |
|
396 | 402 | elif unique: |
|
397 | 403 | sqlform += " ORDER BY session, line" |
|
398 | cur = self._run_sql(sqlform, params, raw=raw, output=output) | |
|
404 | cur = self._run_sql(sqlform, params, raw=raw, output=output, latest=unique) | |
|
399 | 405 | if n is not None: |
|
400 | 406 | return reversed(list(cur)) |
|
401 | 407 | return cur |
@@ -817,7 +823,7 b' class HistorySavingThread(threading.Thread):' | |||
|
817 | 823 | try: |
|
818 | 824 | self.db = sqlite3.connect( |
|
819 | 825 | str(self.history_manager.hist_file), |
|
820 | **self.history_manager.connection_options | |
|
826 | **self.history_manager.connection_options, | |
|
821 | 827 | ) |
|
822 | 828 | while True: |
|
823 | 829 | self.history_manager.save_flag.wait() |
@@ -17,12 +17,10 b' import sqlite3' | |||
|
17 | 17 | from traitlets.config.loader import Config |
|
18 | 18 | from IPython.utils.tempdir import TemporaryDirectory |
|
19 | 19 | from IPython.core.history import HistoryManager, extract_hist_ranges |
|
20 | from IPython.testing.decorators import skipif | |
|
21 | 20 | |
|
22 | 21 | def test_proper_default_encoding(): |
|
23 | 22 | assert sys.getdefaultencoding() == "utf-8" |
|
24 | 23 | |
|
25 | @skipif(sqlite3.sqlite_version_info > (3,24,0)) | |
|
26 | 24 | def test_history(): |
|
27 | 25 | ip = get_ipython() |
|
28 | 26 | with TemporaryDirectory() as tmpdir: |
@@ -133,6 +131,17 b' def test_history():' | |||
|
133 | 131 | ip.history_manager.store_inputs(1, "rogue") |
|
134 | 132 | ip.history_manager.writeout_cache() |
|
135 | 133 | assert ip.history_manager.session_number == 3 |
|
134 | ||
|
135 | # Check that session and line values are not just max values | |
|
136 | sessid, lineno, entry = newhist[-1] | |
|
137 | assert lineno > 1 | |
|
138 | ip.history_manager.reset() | |
|
139 | lineno = 1 | |
|
140 | ip.history_manager.store_inputs(lineno, entry) | |
|
141 | gothist = ip.history_manager.search("*=*", unique=True) | |
|
142 | hist = list(gothist)[-1] | |
|
143 | assert sessid < hist[0] | |
|
144 | assert hist[1:] == (lineno, entry) | |
|
136 | 145 | finally: |
|
137 | 146 | # Ensure saving thread is shut down before we try to clean up the files |
|
138 | 147 | ip.history_manager.save_thread.stop() |
General Comments 0
You need to be logged in to leave comments.
Login now