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