##// END OF EJS Templates
Add command to trim the history database.
Thomas Kluyver -
Show More
@@ -0,0 +1,119 b''
1 # encoding: utf-8
2 """
3 An application for managing IPython history.
4
5 To be invoked as the `ipython history` subcommand.
6 """
7 from __future__ import print_function
8
9 import os
10 import sqlite3
11
12 from IPython.config.application import Application
13 from IPython.core.application import BaseIPythonApplication
14 from IPython.utils.traitlets import Bool, Int, Dict
15
16 trim_hist_help = """Trim the IPython history database to the last 1000 entries.
17
18 This actually copies the last 1000 entries to a new database, and then replaces
19 the old file with the new.
20 """
21
22 class HistoryTrim(BaseIPythonApplication):
23 description = trim_hist_help
24
25 backup = Bool(False, config=True,
26 help="Keep the old history file as history.sqlite.<N>")
27
28 keep = Int(1000, config=True,
29 help="Number of recent lines to keep in the database.")
30
31 flags = Dict(dict(
32 backup = ({'HistoryTrim' : {'backup' : True}},
33 "Set Application.log_level to 0, maximizing log output."
34 )
35 ))
36
37 def start(self):
38 profile_dir = self.profile_dir.location
39 hist_file = os.path.join(profile_dir, 'history.sqlite')
40 con = sqlite3.connect(hist_file)
41
42 # Grab the recent history from the current database.
43 inputs = list(con.execute('SELECT session, line, source, source_raw FROM '
44 'history ORDER BY session DESC, line DESC LIMIT ?', (self.keep+1,)))
45 if len(inputs) <= self.keep:
46 print("There are already at most %d entries in the history database." % self.keep)
47 print("Not doing anything.")
48 return
49
50 print("Trimming history to the most recent %d entries." % self.keep)
51
52 inputs.pop() # Remove the extra element we got to check the length.
53 inputs.reverse()
54 first_session = inputs[0][0]
55 outputs = list(con.execute('SELECT session, line, output FROM '
56 'output_history WHERE session >= ?', (first_session,)))
57 sessions = list(con.execute('SELECT session, start, end, num_cmds, remark FROM '
58 'sessions WHERE session >= ?', (first_session,)))
59 con.close()
60
61 # Create the new history database.
62 new_hist_file = os.path.join(profile_dir, 'history.sqlite.new')
63 i = 0
64 while os.path.exists(new_hist_file):
65 # Make sure we don't interfere with an existing file.
66 i += 1
67 new_hist_file = os.path.join(profile_dir, 'history.sqlite.new'+str(i))
68 new_db = sqlite3.connect(new_hist_file)
69 new_db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
70 primary key autoincrement, start timestamp,
71 end timestamp, num_cmds integer, remark text)""")
72 new_db.execute("""CREATE TABLE IF NOT EXISTS history
73 (session integer, line integer, source text, source_raw text,
74 PRIMARY KEY (session, line))""")
75 new_db.execute("""CREATE TABLE IF NOT EXISTS output_history
76 (session integer, line integer, output text,
77 PRIMARY KEY (session, line))""")
78 new_db.commit()
79
80
81 with new_db:
82 # Add the recent history into the new database.
83 new_db.executemany('insert into sessions values (?,?,?,?,?)', sessions)
84 new_db.executemany('insert into history values (?,?,?,?)', inputs)
85 new_db.executemany('insert into output_history values (?,?,?)', outputs)
86 new_db.close()
87
88 if self.backup:
89 i = 1
90 backup_hist_file = os.path.join(profile_dir, 'history.sqlite.old.%d' % i)
91 while os.path.exists(backup_hist_file):
92 i += 1
93 backup_hist_file = os.path.join(profile_dir, 'history.sqlite.old.%d' % i)
94 os.rename(hist_file, backup_hist_file)
95 print("Backed up longer history file to", backup_hist_file)
96 else:
97 os.remove(hist_file)
98
99 os.rename(new_hist_file, hist_file)
100
101
102 class HistoryApp(Application):
103 name = u'ipython-history'
104 description = "Manage the IPython history database."
105
106 subcommands = Dict(dict(
107 trim = (HistoryTrim, HistoryTrim.description.splitlines()[0]),
108 ))
109
110 def start(self):
111 if self.subapp is None:
112 print("No subcommand specified. Must specify one of: %s" % \
113 (self.subcommands.keys()))
114 print()
115 self.print_description()
116 self.print_subcommands()
117 self.exit(1)
118 else:
119 return self.subapp.start()
@@ -241,6 +241,9 b' class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):'
241 locate=('IPython.frontend.terminal.ipapp.LocateIPythonApp',
241 locate=('IPython.frontend.terminal.ipapp.LocateIPythonApp',
242 LocateIPythonApp.description
242 LocateIPythonApp.description
243 ),
243 ),
244 history=('IPython.core.historyapp.HistoryApp',
245 "Manage the IPython history database."
246 ),
244 ))
247 ))
245
248
246 # *do* autocreate requested profile, but don't create the config file.
249 # *do* autocreate requested profile, but don't create the config file.
General Comments 0
You need to be logged in to leave comments. Login now