diff --git a/IPython/core/history.py b/IPython/core/history.py index d2ae229..029d2ba 100644 --- a/IPython/core/history.py +++ b/IPython/core/history.py @@ -129,7 +129,8 @@ class HistoryManager(Configurable): def init_db(self): """Connect to the database, and create tables if necessary.""" - self.db = sqlite3.connect(self.hist_file) + # use detect_types so that timestamps return datetime objects + self.db = sqlite3.connect(self.hist_file, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer primary key autoincrement, start timestamp, end timestamp, num_cmds integer, remark text)""") @@ -213,6 +214,33 @@ class HistoryManager(Configurable): return cur + def get_session_info(self, session=0): + """get info about a session + + Parameters + ---------- + + session : int + Session number to retrieve. The current session is 0, and negative + numbers count back from current session, so -1 is previous session. + + Returns + ------- + + (session_id [int], start [datetime], end [datetime], num_cmds [int], remark [unicode]) + + Sessions that are running or did not exit cleanly will have `end=None` + and `num_cmds=None`. + + """ + + if session <= 0: + session += self.session_number + + query = "SELECT * from sessions where session == ?" + return self.db.execute(query, (session,)).fetchone() + + def get_tail(self, n=10, raw=True, output=False, include_latest=False): """Get the last n lines from the history database. diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 2d807c9..5218375 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -2552,6 +2552,11 @@ class InteractiveShell(SingletonConfigurable, Magic): code that has the appropriate information, rather than trying to clutter """ + # Close the history session (this stores the end time and line count) + # this must be *before* the tempfile cleanup, in case of temporary + # history db + self.history_manager.end_session() + # Cleanup all tempfiles left around for tfile in self.tempfiles: try: @@ -2559,9 +2564,6 @@ class InteractiveShell(SingletonConfigurable, Magic): except OSError: pass - # Close the history session (this stores the end time and line count) - self.history_manager.end_session() - # Clear all user namespaces to release all references cleanly. self.reset(new_session=False) diff --git a/IPython/core/tests/test_history.py b/IPython/core/tests/test_history.py index 9a74a4e..1cbacd2 100644 --- a/IPython/core/tests/test_history.py +++ b/IPython/core/tests/test_history.py @@ -9,7 +9,7 @@ import os import sys import unittest - +from datetime import datetime # third party import nose.tools as nt @@ -107,3 +107,8 @@ def test_magic_rerun(): nt.assert_equal(ip.user_ns["a"], 11) ip.run_cell("%rerun") nt.assert_equal(ip.user_ns["a"], 12) + +def test_timestamp_type(): + ip = get_ipython() + info = ip.history_manager.get_session_info() + nt.assert_true(isinstance(info[1], datetime)) diff --git a/IPython/testing/globalipapp.py b/IPython/testing/globalipapp.py index cee6f2b..4315da3 100644 --- a/IPython/testing/globalipapp.py +++ b/IPython/testing/globalipapp.py @@ -194,6 +194,9 @@ def start_ipython(): # A few more tweaks needed for playing nicely with doctests... + # remove history file + shell.tempfiles.append(config.HistoryManager.hist_file) + # These traps are normally only active for interactive use, set them # permanently since we'll be mocking interactive sessions. shell.builtin_trap.activate() diff --git a/IPython/testing/tools.py b/IPython/testing/tools.py index 4947191..3835d58 100644 --- a/IPython/testing/tools.py +++ b/IPython/testing/tools.py @@ -31,6 +31,7 @@ from __future__ import absolute_import import os import re import sys +import tempfile from contextlib import contextmanager @@ -170,7 +171,7 @@ def default_config(): config.TerminalInteractiveShell.colors = 'NoColor' config.TerminalTerminalInteractiveShell.term_title = False, config.TerminalInteractiveShell.autocall = 0 - config.HistoryManager.hist_file = u'test_hist.sqlite' + config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite') config.HistoryManager.db_cache_size = 10000 return config