##// END OF EJS Templates
Use plugin API for storemagic, so autorestore is configurable.
Thomas Kluyver -
Show More
@@ -1,188 +1,208 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 %store magic for lightweight persistence.
3 %store magic for lightweight persistence.
4
4
5 Stores variables, aliases and macros in IPython's database. Stored values will
5 Stores variables, aliases and macros in IPython's database. Stored values will
6 be automatically restored whenever the extension is loaded.
6 be automatically restored whenever the extension is loaded.
7
7
8 To enable this functionality, list it in your default profile
8 To enable this functionality, list it in your default profile
9 `ipython_config.py` file::
9 `ipython_config.py` file::
10
10
11 c.InteractiveShellApp.extensions = ['storemagic']
11 c.InteractiveShellApp.extensions = ['storemagic']
12
12
13 Or to use it temporarily, run this in your IPython session::
13 Or to use it temporarily, run this in your IPython session::
14
14
15 %load_ext storemagic
15 %load_ext storemagic
16
16
17 """
17 """
18
18
19 from IPython.core.error import TryNext, UsageError
19 from IPython.core.error import TryNext, UsageError
20 from IPython.core.plugin import Plugin
20 from IPython.utils import pickleshare
21 from IPython.utils import pickleshare
22 from IPython.utils.traitlets import Bool, Instance
21
23
22 import inspect,pickle,os,sys,textwrap
24 import inspect,pickle,os,sys,textwrap
23 from IPython.core.fakemodule import FakeModule
25 from IPython.core.fakemodule import FakeModule
24
26
25 def restore_aliases(ip):
27 def restore_aliases(ip):
26 staliases = ip.db.get('stored_aliases', {})
28 staliases = ip.db.get('stored_aliases', {})
27 for k,v in staliases.items():
29 for k,v in staliases.items():
28 #print "restore alias",k,v # dbg
30 #print "restore alias",k,v # dbg
29 #self.alias_table[k] = v
31 #self.alias_table[k] = v
30 ip.alias_manager.define_alias(k,v)
32 ip.alias_manager.define_alias(k,v)
31
33
32
34
33 def refresh_variables(ip):
35 def refresh_variables(ip):
34 db = ip.db
36 db = ip.db
35 for key in db.keys('autorestore/*'):
37 for key in db.keys('autorestore/*'):
36 # strip autorestore
38 # strip autorestore
37 justkey = os.path.basename(key)
39 justkey = os.path.basename(key)
38 try:
40 try:
39 obj = db[key]
41 obj = db[key]
40 except KeyError:
42 except KeyError:
41 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
43 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
42 print "The error was:",sys.exc_info()[0]
44 print "The error was:",sys.exc_info()[0]
43 else:
45 else:
44 #print "restored",justkey,"=",obj #dbg
46 #print "restored",justkey,"=",obj #dbg
45 ip.user_ns[justkey] = obj
47 ip.user_ns[justkey] = obj
46
48
47
49
48 def restore_dhist(ip):
50 def restore_dhist(ip):
49 ip.user_ns['_dh'] = ip.db.get('dhist',[])
51 ip.user_ns['_dh'] = ip.db.get('dhist',[])
50
52
51 def restore_data(ip):
53 def restore_data(ip):
52 refresh_variables(ip)
54 refresh_variables(ip)
53 restore_aliases(ip)
55 restore_aliases(ip)
54 restore_dhist(ip)
56 restore_dhist(ip)
55
57
56 def magic_store(self, parameter_s=''):
58 def magic_store(self, parameter_s=''):
57 """Lightweight persistence for python variables.
59 """Lightweight persistence for python variables.
58
60
59 Example::
61 Example::
60
62
61 In [1]: l = ['hello',10,'world']
63 In [1]: l = ['hello',10,'world']
62 In [2]: %store l
64 In [2]: %store l
63 In [3]: exit
65 In [3]: exit
64
66
65 (IPython session is closed and started again...)
67 (IPython session is closed and started again...)
66
68
67 ville@badger:~$ ipython
69 ville@badger:~$ ipython
68 In [1]: l
70 In [1]: l
69 Out[1]: ['hello', 10, 'world']
71 Out[1]: ['hello', 10, 'world']
70
72
71 Usage:
73 Usage:
72
74
73 * ``%store`` - Show list of all variables and their current values
75 * ``%store`` - Show list of all variables and their current values
74 * ``%store spam`` - Store the *current* value of the variable spam to disk
76 * ``%store spam`` - Store the *current* value of the variable spam to disk
75 * ``%store -d spam`` - Remove the variable and its value from storage
77 * ``%store -d spam`` - Remove the variable and its value from storage
76 * ``%store -z`` - Remove all variables from storage
78 * ``%store -z`` - Remove all variables from storage
77 * ``%store -r`` - Refresh all variables from store (delete current vals)
79 * ``%store -r`` - Refresh all variables from store (delete current vals)
78 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
80 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
79 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
81 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
80
82
81 It should be noted that if you change the value of a variable, you
83 It should be noted that if you change the value of a variable, you
82 need to %store it again if you want to persist the new value.
84 need to %store it again if you want to persist the new value.
83
85
84 Note also that the variables will need to be pickleable; most basic
86 Note also that the variables will need to be pickleable; most basic
85 python types can be safely %store'd.
87 python types can be safely %store'd.
86
88
87 Also aliases can be %store'd across sessions.
89 Also aliases can be %store'd across sessions.
88 """
90 """
89
91
90 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
92 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
91 args = argsl.split(None,1)
93 args = argsl.split(None,1)
92 ip = self.shell
94 ip = self.shell
93 db = ip.db
95 db = ip.db
94 # delete
96 # delete
95 if opts.has_key('d'):
97 if opts.has_key('d'):
96 try:
98 try:
97 todel = args[0]
99 todel = args[0]
98 except IndexError:
100 except IndexError:
99 raise UsageError('You must provide the variable to forget')
101 raise UsageError('You must provide the variable to forget')
100 else:
102 else:
101 try:
103 try:
102 del db['autorestore/' + todel]
104 del db['autorestore/' + todel]
103 except:
105 except:
104 raise UsageError("Can't delete variable '%s'" % todel)
106 raise UsageError("Can't delete variable '%s'" % todel)
105 # reset
107 # reset
106 elif opts.has_key('z'):
108 elif opts.has_key('z'):
107 for k in db.keys('autorestore/*'):
109 for k in db.keys('autorestore/*'):
108 del db[k]
110 del db[k]
109
111
110 elif opts.has_key('r'):
112 elif opts.has_key('r'):
111 refresh_variables(ip)
113 refresh_variables(ip)
112
114
113
115
114 # run without arguments -> list variables & values
116 # run without arguments -> list variables & values
115 elif not args:
117 elif not args:
116 vars = self.db.keys('autorestore/*')
118 vars = self.db.keys('autorestore/*')
117 vars.sort()
119 vars.sort()
118 if vars:
120 if vars:
119 size = max(map(len,vars))
121 size = max(map(len,vars))
120 else:
122 else:
121 size = 0
123 size = 0
122
124
123 print 'Stored variables and their in-db values:'
125 print 'Stored variables and their in-db values:'
124 fmt = '%-'+str(size)+'s -> %s'
126 fmt = '%-'+str(size)+'s -> %s'
125 get = db.get
127 get = db.get
126 for var in vars:
128 for var in vars:
127 justkey = os.path.basename(var)
129 justkey = os.path.basename(var)
128 # print 30 first characters from every var
130 # print 30 first characters from every var
129 print fmt % (justkey,repr(get(var,'<unavailable>'))[:50])
131 print fmt % (justkey,repr(get(var,'<unavailable>'))[:50])
130
132
131 # default action - store the variable
133 # default action - store the variable
132 else:
134 else:
133 # %store foo >file.txt or >>file.txt
135 # %store foo >file.txt or >>file.txt
134 if len(args) > 1 and args[1].startswith('>'):
136 if len(args) > 1 and args[1].startswith('>'):
135 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
137 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
136 if args[1].startswith('>>'):
138 if args[1].startswith('>>'):
137 fil = open(fnam,'a')
139 fil = open(fnam,'a')
138 else:
140 else:
139 fil = open(fnam,'w')
141 fil = open(fnam,'w')
140 obj = ip.ev(args[0])
142 obj = ip.ev(args[0])
141 print "Writing '%s' (%s) to file '%s'." % (args[0],
143 print "Writing '%s' (%s) to file '%s'." % (args[0],
142 obj.__class__.__name__, fnam)
144 obj.__class__.__name__, fnam)
143
145
144
146
145 if not isinstance (obj,basestring):
147 if not isinstance (obj,basestring):
146 from pprint import pprint
148 from pprint import pprint
147 pprint(obj,fil)
149 pprint(obj,fil)
148 else:
150 else:
149 fil.write(obj)
151 fil.write(obj)
150 if not obj.endswith('\n'):
152 if not obj.endswith('\n'):
151 fil.write('\n')
153 fil.write('\n')
152
154
153 fil.close()
155 fil.close()
154 return
156 return
155
157
156 # %store foo
158 # %store foo
157 try:
159 try:
158 obj = ip.user_ns[args[0]]
160 obj = ip.user_ns[args[0]]
159 except KeyError:
161 except KeyError:
160 # it might be an alias
162 # it might be an alias
161 # This needs to be refactored to use the new AliasManager stuff.
163 # This needs to be refactored to use the new AliasManager stuff.
162 if args[0] in self.alias_manager:
164 if args[0] in self.alias_manager:
163 name = args[0]
165 name = args[0]
164 nargs, cmd = self.alias_manager.alias_table[ name ]
166 nargs, cmd = self.alias_manager.alias_table[ name ]
165 staliases = db.get('stored_aliases',{})
167 staliases = db.get('stored_aliases',{})
166 staliases[ name ] = cmd
168 staliases[ name ] = cmd
167 db['stored_aliases'] = staliases
169 db['stored_aliases'] = staliases
168 print "Alias stored: %s (%s)" % (name, cmd)
170 print "Alias stored: %s (%s)" % (name, cmd)
169 return
171 return
170 else:
172 else:
171 raise UsageError("Unknown variable '%s'" % args[0])
173 raise UsageError("Unknown variable '%s'" % args[0])
172
174
173 else:
175 else:
174 if isinstance(inspect.getmodule(obj), FakeModule):
176 if isinstance(inspect.getmodule(obj), FakeModule):
175 print textwrap.dedent("""\
177 print textwrap.dedent("""\
176 Warning:%s is %s
178 Warning:%s is %s
177 Proper storage of interactively declared classes (or instances
179 Proper storage of interactively declared classes (or instances
178 of those classes) is not possible! Only instances
180 of those classes) is not possible! Only instances
179 of classes in real modules on file system can be %%store'd.
181 of classes in real modules on file system can be %%store'd.
180 """ % (args[0], obj) )
182 """ % (args[0], obj) )
181 return
183 return
182 #pickled = pickle.dumps(obj)
184 #pickled = pickle.dumps(obj)
183 self.db[ 'autorestore/' + args[0] ] = obj
185 self.db[ 'autorestore/' + args[0] ] = obj
184 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
186 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
185
187
188
189 class StoreMagic(Plugin):
190 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
191 autorestore = Bool(False, config=True)
192
193 def __init__(self, shell, config):
194 super(StoreMagic, self).__init__(shell=shell, config=config)
195 shell.define_magic('store', magic_store)
196
197 if self.autorestore:
198 restore_data(shell)
199
200 _loaded = False
201
186 def load_ipython_extension(ip):
202 def load_ipython_extension(ip):
187 ip.define_magic('store', magic_store)
203 """Load the extension in IPython."""
188 restore_data(ip)
204 global _loaded
205 if not _loaded:
206 plugin = StoreMagic(shell=ip, config=ip.config)
207 ip.plugin_manager.register_plugin('storemagic', plugin)
208 _loaded = True
General Comments 0
You need to be logged in to leave comments. Login now