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