##// END OF EJS Templates
Update IPython/core/historyapp.py to use the new traitlets API.
Matthias Bussonnier -
Show More
@@ -1,159 +1,159 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for managing IPython history.
3 An application for managing IPython history.
4
4
5 To be invoked as the `ipython history` subcommand.
5 To be invoked as the `ipython history` subcommand.
6 """
6 """
7 from __future__ import print_function
7 from __future__ import print_function
8
8
9 import os
9 import os
10 import sqlite3
10 import sqlite3
11
11
12 from traitlets.config.application import Application
12 from traitlets.config.application import Application
13 from IPython.core.application import BaseIPythonApplication
13 from IPython.core.application import BaseIPythonApplication
14 from traitlets import Bool, Int, Dict
14 from traitlets import Bool, Int, Dict
15 from IPython.utils.io import ask_yes_no
15 from IPython.utils.io import ask_yes_no
16
16
17 trim_hist_help = """Trim the IPython history database to the last 1000 entries.
17 trim_hist_help = """Trim the IPython history database to the last 1000 entries.
18
18
19 This actually copies the last 1000 entries to a new database, and then replaces
19 This actually copies the last 1000 entries to a new database, and then replaces
20 the old file with the new. Use the `--keep=` argument to specify a number
20 the old file with the new. Use the `--keep=` argument to specify a number
21 other than 1000.
21 other than 1000.
22 """
22 """
23
23
24 clear_hist_help = """Clear the IPython history database, deleting all entries.
24 clear_hist_help = """Clear the IPython history database, deleting all entries.
25
25
26 Because this is a destructive operation, IPython will prompt the user if they
26 Because this is a destructive operation, IPython will prompt the user if they
27 really want to do this. Passing a `-f` flag will force clearing without a
27 really want to do this. Passing a `-f` flag will force clearing without a
28 prompt.
28 prompt.
29
29
30 This is an handy alias to `ipython history trim --keep=0`
30 This is an handy alias to `ipython history trim --keep=0`
31 """
31 """
32
32
33
33
34 class HistoryTrim(BaseIPythonApplication):
34 class HistoryTrim(BaseIPythonApplication):
35 description = trim_hist_help
35 description = trim_hist_help
36
36
37 backup = Bool(False, config=True,
37 backup = Bool(False).tag(config=True,
38 help="Keep the old history file as history.sqlite.<N>")
38 help="Keep the old history file as history.sqlite.<N>")
39
39
40 keep = Int(1000, config=True,
40 keep = Int(1000).tag(config=True,
41 help="Number of recent lines to keep in the database.")
41 help="Number of recent lines to keep in the database.")
42
42
43 flags = Dict(dict(
43 flags = Dict(dict(
44 backup = ({'HistoryTrim' : {'backup' : True}},
44 backup = ({'HistoryTrim' : {'backup' : True}},
45 backup.get_metadata('help')
45 backup.help
46 )
46 )
47 ))
47 ))
48
48
49 aliases=Dict(dict(
49 aliases=Dict(dict(
50 keep = 'HistoryTrim.keep'
50 keep = 'HistoryTrim.keep'
51 ))
51 ))
52
52
53 def start(self):
53 def start(self):
54 profile_dir = self.profile_dir.location
54 profile_dir = self.profile_dir.location
55 hist_file = os.path.join(profile_dir, 'history.sqlite')
55 hist_file = os.path.join(profile_dir, 'history.sqlite')
56 con = sqlite3.connect(hist_file)
56 con = sqlite3.connect(hist_file)
57
57
58 # Grab the recent history from the current database.
58 # Grab the recent history from the current database.
59 inputs = list(con.execute('SELECT session, line, source, source_raw FROM '
59 inputs = list(con.execute('SELECT session, line, source, source_raw FROM '
60 'history ORDER BY session DESC, line DESC LIMIT ?', (self.keep+1,)))
60 'history ORDER BY session DESC, line DESC LIMIT ?', (self.keep+1,)))
61 if len(inputs) <= self.keep:
61 if len(inputs) <= self.keep:
62 print("There are already at most %d entries in the history database." % self.keep)
62 print("There are already at most %d entries in the history database." % self.keep)
63 print("Not doing anything. Use --keep= argument to keep fewer entries")
63 print("Not doing anything. Use --keep= argument to keep fewer entries")
64 return
64 return
65
65
66 print("Trimming history to the most recent %d entries." % self.keep)
66 print("Trimming history to the most recent %d entries." % self.keep)
67
67
68 inputs.pop() # Remove the extra element we got to check the length.
68 inputs.pop() # Remove the extra element we got to check the length.
69 inputs.reverse()
69 inputs.reverse()
70 if inputs:
70 if inputs:
71 first_session = inputs[0][0]
71 first_session = inputs[0][0]
72 outputs = list(con.execute('SELECT session, line, output FROM '
72 outputs = list(con.execute('SELECT session, line, output FROM '
73 'output_history WHERE session >= ?', (first_session,)))
73 'output_history WHERE session >= ?', (first_session,)))
74 sessions = list(con.execute('SELECT session, start, end, num_cmds, remark FROM '
74 sessions = list(con.execute('SELECT session, start, end, num_cmds, remark FROM '
75 'sessions WHERE session >= ?', (first_session,)))
75 'sessions WHERE session >= ?', (first_session,)))
76 con.close()
76 con.close()
77
77
78 # Create the new history database.
78 # Create the new history database.
79 new_hist_file = os.path.join(profile_dir, 'history.sqlite.new')
79 new_hist_file = os.path.join(profile_dir, 'history.sqlite.new')
80 i = 0
80 i = 0
81 while os.path.exists(new_hist_file):
81 while os.path.exists(new_hist_file):
82 # Make sure we don't interfere with an existing file.
82 # Make sure we don't interfere with an existing file.
83 i += 1
83 i += 1
84 new_hist_file = os.path.join(profile_dir, 'history.sqlite.new'+str(i))
84 new_hist_file = os.path.join(profile_dir, 'history.sqlite.new'+str(i))
85 new_db = sqlite3.connect(new_hist_file)
85 new_db = sqlite3.connect(new_hist_file)
86 new_db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
86 new_db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
87 primary key autoincrement, start timestamp,
87 primary key autoincrement, start timestamp,
88 end timestamp, num_cmds integer, remark text)""")
88 end timestamp, num_cmds integer, remark text)""")
89 new_db.execute("""CREATE TABLE IF NOT EXISTS history
89 new_db.execute("""CREATE TABLE IF NOT EXISTS history
90 (session integer, line integer, source text, source_raw text,
90 (session integer, line integer, source text, source_raw text,
91 PRIMARY KEY (session, line))""")
91 PRIMARY KEY (session, line))""")
92 new_db.execute("""CREATE TABLE IF NOT EXISTS output_history
92 new_db.execute("""CREATE TABLE IF NOT EXISTS output_history
93 (session integer, line integer, output text,
93 (session integer, line integer, output text,
94 PRIMARY KEY (session, line))""")
94 PRIMARY KEY (session, line))""")
95 new_db.commit()
95 new_db.commit()
96
96
97
97
98 if inputs:
98 if inputs:
99 with new_db:
99 with new_db:
100 # Add the recent history into the new database.
100 # Add the recent history into the new database.
101 new_db.executemany('insert into sessions values (?,?,?,?,?)', sessions)
101 new_db.executemany('insert into sessions values (?,?,?,?,?)', sessions)
102 new_db.executemany('insert into history values (?,?,?,?)', inputs)
102 new_db.executemany('insert into history values (?,?,?,?)', inputs)
103 new_db.executemany('insert into output_history values (?,?,?)', outputs)
103 new_db.executemany('insert into output_history values (?,?,?)', outputs)
104 new_db.close()
104 new_db.close()
105
105
106 if self.backup:
106 if self.backup:
107 i = 1
107 i = 1
108 backup_hist_file = os.path.join(profile_dir, 'history.sqlite.old.%d' % i)
108 backup_hist_file = os.path.join(profile_dir, 'history.sqlite.old.%d' % i)
109 while os.path.exists(backup_hist_file):
109 while os.path.exists(backup_hist_file):
110 i += 1
110 i += 1
111 backup_hist_file = os.path.join(profile_dir, 'history.sqlite.old.%d' % i)
111 backup_hist_file = os.path.join(profile_dir, 'history.sqlite.old.%d' % i)
112 os.rename(hist_file, backup_hist_file)
112 os.rename(hist_file, backup_hist_file)
113 print("Backed up longer history file to", backup_hist_file)
113 print("Backed up longer history file to", backup_hist_file)
114 else:
114 else:
115 os.remove(hist_file)
115 os.remove(hist_file)
116
116
117 os.rename(new_hist_file, hist_file)
117 os.rename(new_hist_file, hist_file)
118
118
119 class HistoryClear(HistoryTrim):
119 class HistoryClear(HistoryTrim):
120 description = clear_hist_help
120 description = clear_hist_help
121 keep = Int(0, config=False,
121 keep = Int(0).tag(config=False,
122 help="Number of recent lines to keep in the database.")
122 help="Number of recent lines to keep in the database.")
123
123
124 force = Bool(False, config=True,
124 force = Bool(False).tag(config=True,
125 help="Don't prompt user for confirmation")
125 help="Don't prompt user for confirmation")
126
126
127 flags = Dict(dict(
127 flags = Dict(dict(
128 force = ({'HistoryClear' : {'force' : True}},
128 force = ({'HistoryClear' : {'force' : True}},
129 force.get_metadata('help')),
129 force.help),
130 f = ({'HistoryTrim' : {'force' : True}},
130 f = ({'HistoryTrim' : {'force' : True}},
131 force.get_metadata('help')
131 force.help
132 )
132 )
133 ))
133 ))
134 aliases = Dict()
134 aliases = Dict()
135
135
136 def start(self):
136 def start(self):
137 if self.force or ask_yes_no("Really delete all ipython history? ",
137 if self.force or ask_yes_no("Really delete all ipython history? ",
138 default="no", interrupt="no"):
138 default="no", interrupt="no"):
139 HistoryTrim.start(self)
139 HistoryTrim.start(self)
140
140
141 class HistoryApp(Application):
141 class HistoryApp(Application):
142 name = u'ipython-history'
142 name = u'ipython-history'
143 description = "Manage the IPython history database."
143 description = "Manage the IPython history database."
144
144
145 subcommands = Dict(dict(
145 subcommands = Dict(dict(
146 trim = (HistoryTrim, HistoryTrim.description.splitlines()[0]),
146 trim = (HistoryTrim, HistoryTrim.description.splitlines()[0]),
147 clear = (HistoryClear, HistoryClear.description.splitlines()[0]),
147 clear = (HistoryClear, HistoryClear.description.splitlines()[0]),
148 ))
148 ))
149
149
150 def start(self):
150 def start(self):
151 if self.subapp is None:
151 if self.subapp is None:
152 print("No subcommand specified. Must specify one of: %s" % \
152 print("No subcommand specified. Must specify one of: %s" % \
153 (self.subcommands.keys()))
153 (self.subcommands.keys()))
154 print()
154 print()
155 self.print_description()
155 self.print_description()
156 self.print_subcommands()
156 self.print_subcommands()
157 self.exit(1)
157 self.exit(1)
158 else:
158 else:
159 return self.subapp.start()
159 return self.subapp.start()
General Comments 0
You need to be logged in to leave comments. Login now