##// END OF EJS Templates
Fix `history_manager.search(?, unique=True)` returning old entries
Nikita Kniazev -
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