##// END OF EJS Templates
add ipy_jot.py
Ville M. Vainio -
Show More
@@ -0,0 +1,311 b''
1 # -*- coding: utf-8 -*-
2 """
3 %jot magic for lightweight persistence.
4
5 Stores variables in Struct with some notes in PicleShare database
6
7
8 """
9
10 from datetime import datetime
11 import IPython.ipapi
12 ip = IPython.ipapi.get()
13
14 import pickleshare
15
16 import inspect,pickle,os,sys,textwrap
17 from IPython.FakeModule import FakeModule
18 from IPython.ipstruct import Struct
19
20
21 def refresh_variables(ip, key=None):
22 db = ip.db
23 if key is None:
24 keys = db.keys('jot/*')
25 else:
26 keys = db.keys('jot/'+key)
27 for key in keys:
28 # strip autorestore
29 justkey = os.path.basename(key)
30 print "Restoring from", justkey, "..."
31 try:
32 obj = db[key]
33 except KeyError:
34 print "Unable to restore variable '%s', ignoring (use %%jot -d to forget!)" % justkey
35 print "The error was:",sys.exc_info()[0]
36 else:
37 #print "restored",justkey,"=",obj #dbg
38 try:
39 origname = obj.name
40 except:
41 ip.user_ns[justkey] = obj
42 print "Restored", justkey
43 else:
44 ip.user_ns[origname] = obj['val']
45 print "Restored", origname
46
47 def read_variables(ip, key=None):
48 db = ip.db
49 if key is None:
50 return None
51 else:
52 keys = db.keys('jot/'+key)
53 for key in keys:
54 # strip autorestore
55 justkey = os.path.basename(key)
56 print "restoring from ", justkey
57 try:
58 obj = db[key]
59 except KeyError:
60 print "Unable to read variable '%s', ignoring (use %%jot -d to forget!)" % justkey
61 print "The error was:",sys.exc_info()[0]
62 else:
63 return obj
64
65
66 def detail_variables(ip, key=None):
67 db, get = ip.db, ip.db.get
68
69 if key is None:
70 keys = db.keys('jot/*')
71 else:
72 keys = db.keys('jot/'+key)
73 if keys:
74 size = max(map(len,keys))
75 else:
76 size = 0
77
78 fmthead = '%-'+str(size)+'s [%s]'
79 fmtbody = 'Comment:\n %s'
80 fmtdata = 'Data:\n %s, %s'
81 for key in keys:
82 v = get(key,'<unavailable>')
83 justkey = os.path.basename(key)
84 try:
85 print fmthead % (justkey, datetime.ctime(v.get('time','<unavailable>')))
86 print fmtbody % (v.get('comment','<unavailable>'))
87 d = v.get('val','unavailable')
88 print fmtdata % (repr(type(d)), '')
89 print repr(d)[0:200]
90 print
91 print
92 except AttributeError:
93 print fmt % (justkey, '<unavailable>', '<unavailable>', repr(v)[:50])
94
95
96 def intm(n):
97 try:
98 return int(n)
99 except:
100 return 0
101
102 def jot_obj(self, obj, name, comment=''):
103 """
104 write obj data to the note database, with whatever that should be noted.
105 """
106 had = self.db.keys('jot/'+name+'*')
107 # if it the same name but a later version, we stupidly add a number to the
108 # so the name doesn't collide. Any better idea?
109 suffix = ''
110 if len(had)>0:
111 pre = os.path.commonprefix(had)
112 suf = [n.split(pre)[1] for n in had]
113 versions = map(intm, suf)
114 suffix = str(max(versions)+1)
115
116 uname = 'jot/'+name+suffix
117
118 # which one works better?
119 #all = ip.IP.shadowhist.all()
120 all = ip.IP.shell.input_hist
121
122 # We may actually want to make snapshot of files that are run-ned.
123
124 # get the comment
125 try:
126 comment = ip.IP.magic_edit('-x').strip()
127 except:
128 print "No comment is recorded."
129 comment = ''
130
131 self.db[uname] = Struct({'val':obj,
132 'time' : datetime.now(),
133 'hist' : all,
134 'name' : name,
135 'comment' : comment,})
136
137 print "Jotted down notes for '%s' (%s)" % (uname, obj.__class__.__name__)
138
139
140
141 def magic_jot(self, parameter_s=''):
142 """Lightweight persistence for python variables.
143
144 Example:
145
146 ville@badger[~]|1> A = ['hello',10,'world']\\
147 ville@badger[~]|2> %jot A\\
148 ville@badger[~]|3> Exit
149
150 (IPython session is closed and started again...)
151
152 ville@badger:~$ ipython -p pysh\\
153 ville@badger[~]|1> print A
154
155 ['hello', 10, 'world']
156
157 Usage:
158
159 %jot - Show list of all variables and their current values\\
160 %jot -l - Show list of all variables and their current values in detail\\
161 %jot -l <var> - Show one variable and its current values in detail\\
162 %jot <var> - Store the *current* value of the variable to disk\\
163 %jot -d <var> - Remove the variable and its value from storage\\
164 %jot -z - Remove all variables from storage (disabled)\\
165 %jot -r <var> - Refresh/Load variable from jot (delete current vals)\\
166 %jot foo >a.txt - Store value of foo to new file a.txt\\
167 %jot foo >>a.txt - Append value of foo to file a.txt\\
168
169 It should be noted that if you change the value of a variable, you
170 need to %note it again if you want to persist the new value.
171
172 Note also that the variables will need to be pickleable; most basic
173 python types can be safely %stored.
174
175 """
176
177 opts,argsl = self.parse_options(parameter_s,'drzl',mode='string')
178 args = argsl.split(None,1)
179 ip = self.getapi()
180 db = ip.db
181 # delete
182 if opts.has_key('d'):
183 try:
184 todel = args[0]
185 except IndexError:
186 error('You must provide the variable to forget')
187 else:
188 try:
189 del db['jot/' + todel]
190 except:
191 error("Can't delete variable '%s'" % todel)
192 # reset the whole database
193 elif opts.has_key('z'):
194 print "reseting the whole database has been disabled."
195 #for k in db.keys('autorestore/*'):
196 # del db[k]
197
198 elif opts.has_key('r'):
199 try:
200 toret = args[0]
201 except:
202 print "restoring all the variables jotted down..."
203 refresh_variables(ip)
204 else:
205 refresh_variables(ip, toret)
206
207 elif opts.has_key('l'):
208 try:
209 tolist = args[0]
210 except:
211 print "List details for all the items."
212 detail_variables(ip)
213 else:
214 print "Details for", tolist, ":"
215 detail_variables(ip, tolist)
216
217 # run without arguments -> list noted variables & notes
218 elif not args:
219 vars = self.db.keys('jot/*')
220 vars.sort()
221 if vars:
222 size = max(map(len,vars)) - 4
223 else:
224 size = 0
225
226 print 'Variables and their in-db values:'
227 fmt = '%-'+str(size)+'s [%s] -> %s'
228 get = db.get
229 for var in vars:
230 justkey = os.path.basename(var)
231 v = get(var,'<unavailable>')
232 try:
233 print fmt % (justkey,\
234 datetime.ctime(v.get('time','<unavailable>')),\
235 v.get('comment','<unavailable>')[:70].replace('\n',' '),)
236 except AttributeError:
237 print fmt % (justkey, '<unavailable>', '<unavailable>', repr(v)[:50])
238
239
240 # default action - store the variable
241 else:
242 # %store foo >file.txt or >>file.txt
243 if len(args) > 1 and args[1].startswith('>'):
244 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
245 if args[1].startswith('>>'):
246 fil = open(fnam,'a')
247 else:
248 fil = open(fnam,'w')
249 obj = ip.ev(args[0])
250 print "Writing '%s' (%s) to file '%s'." % (args[0],
251 obj.__class__.__name__, fnam)
252
253
254 if not isinstance (obj,basestring):
255 from pprint import pprint
256 pprint(obj,fil)
257 else:
258 fil.write(obj)
259 if not obj.endswith('\n'):
260 fil.write('\n')
261
262 fil.close()
263 return
264
265 # %note foo
266 try:
267 obj = ip.user_ns[args[0]]
268 except KeyError:
269 # this should not be alias, for aliases, use %store
270 print
271 print "Error: %s doesn't exist." % args[0]
272 print
273 print "Use %note -r <var> to retrieve variables. This should not be used " +\
274 "to store alias, for saving aliases, use %store"
275 return
276 else:
277 if isinstance(inspect.getmodule(obj), FakeModule):
278 print textwrap.dedent("""\
279 Warning:%s is %s
280 Proper storage of interactively declared classes (or instances
281 of those classes) is not possible! Only instances
282 of classes in real modules on file system can be %%store'd.
283 """ % (args[0], obj) )
284 return
285 #pickled = pickle.dumps(obj)
286 #self.db[ 'jot/' + args[0] ] = obj
287 jot_obj(self, obj, args[0])
288
289
290 def magic_read(self, parameter_s=''):
291 """
292 %read <var> - Load variable from data that is jotted down.\\
293
294 """
295
296 opts,argsl = self.parse_options(parameter_s,'drzl',mode='string')
297 args = argsl.split(None,1)
298 ip = self.getapi()
299 db = ip.db
300 #if opts.has_key('r'):
301 try:
302 toret = args[0]
303 except:
304 print "which record do you want to read out?"
305 return
306 else:
307 return read_variables(ip, toret)
308
309
310 ip.expose_magic('jot',magic_jot)
311 ip.expose_magic('read',magic_read)
@@ -3,6 +3,11 b''
3 * Extensions/ipy_lookfor.py: add %lookfor magic command
3 * Extensions/ipy_lookfor.py: add %lookfor magic command
4 (search docstrings for words) by Pauli Virtanen. Close #245.
4 (search docstrings for words) by Pauli Virtanen. Close #245.
5
5
6 * Extension/ipy_jot.py: %jot and %read magics, analogous
7 to %store but you can specify some notes. Not read
8 in automatically on startup, you need %read.
9 Contributed by Yichun Wei.
10
6 2008-04-18 Fernando Perez <Fernando.Perez@berkeley.edu>
11 2008-04-18 Fernando Perez <Fernando.Perez@berkeley.edu>
7
12
8 * IPython/genutils.py (page): apply workaround to curses bug that
13 * IPython/genutils.py (page): apply workaround to curses bug that
General Comments 0
You need to be logged in to leave comments. Login now