##// END OF EJS Templates
Merge pull request #5619 from takluyver/i5611...
Thomas Kluyver -
r16281:f9529882 merge
parent child Browse files
Show More
@@ -1,243 +1,243 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.
5 Stores variables, aliases and macros in IPython's database.
6
6
7 To automatically restore stored variables at startup, add this to your
7 To automatically restore stored variables at startup, add this to your
8 :file:`ipython_config.py` file::
8 :file:`ipython_config.py` file::
9
9
10 c.StoreMagic.autorestore = True
10 c.StoreMagics.autorestore = True
11 """
11 """
12 from __future__ import print_function
12 from __future__ import print_function
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (c) 2012, The IPython Development Team.
14 # Copyright (c) 2012, The IPython Development Team.
15 #
15 #
16 # Distributed under the terms of the Modified BSD License.
16 # Distributed under the terms of the Modified BSD License.
17 #
17 #
18 # The full license is in the file COPYING.txt, distributed with this software.
18 # The full license is in the file COPYING.txt, distributed with this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 # Stdlib
25 # Stdlib
26 import inspect, os, sys, textwrap
26 import inspect, os, sys, textwrap
27
27
28 # Our own
28 # Our own
29 from IPython.core.error import UsageError
29 from IPython.core.error import UsageError
30 from IPython.core.magic import Magics, magics_class, line_magic
30 from IPython.core.magic import Magics, magics_class, line_magic
31 from IPython.testing.skipdoctest import skip_doctest
31 from IPython.testing.skipdoctest import skip_doctest
32 from IPython.utils.traitlets import Bool
32 from IPython.utils.traitlets import Bool
33 from IPython.utils.py3compat import string_types
33 from IPython.utils.py3compat import string_types
34
34
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # Functions and classes
36 # Functions and classes
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38
38
39 def restore_aliases(ip):
39 def restore_aliases(ip):
40 staliases = ip.db.get('stored_aliases', {})
40 staliases = ip.db.get('stored_aliases', {})
41 for k,v in staliases.items():
41 for k,v in staliases.items():
42 #print "restore alias",k,v # dbg
42 #print "restore alias",k,v # dbg
43 #self.alias_table[k] = v
43 #self.alias_table[k] = v
44 ip.alias_manager.define_alias(k,v)
44 ip.alias_manager.define_alias(k,v)
45
45
46
46
47 def refresh_variables(ip):
47 def refresh_variables(ip):
48 db = ip.db
48 db = ip.db
49 for key in db.keys('autorestore/*'):
49 for key in db.keys('autorestore/*'):
50 # strip autorestore
50 # strip autorestore
51 justkey = os.path.basename(key)
51 justkey = os.path.basename(key)
52 try:
52 try:
53 obj = db[key]
53 obj = db[key]
54 except KeyError:
54 except KeyError:
55 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
55 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
56 print("The error was:", sys.exc_info()[0])
56 print("The error was:", sys.exc_info()[0])
57 else:
57 else:
58 #print "restored",justkey,"=",obj #dbg
58 #print "restored",justkey,"=",obj #dbg
59 ip.user_ns[justkey] = obj
59 ip.user_ns[justkey] = obj
60
60
61
61
62 def restore_dhist(ip):
62 def restore_dhist(ip):
63 ip.user_ns['_dh'] = ip.db.get('dhist',[])
63 ip.user_ns['_dh'] = ip.db.get('dhist',[])
64
64
65
65
66 def restore_data(ip):
66 def restore_data(ip):
67 refresh_variables(ip)
67 refresh_variables(ip)
68 restore_aliases(ip)
68 restore_aliases(ip)
69 restore_dhist(ip)
69 restore_dhist(ip)
70
70
71
71
72 @magics_class
72 @magics_class
73 class StoreMagics(Magics):
73 class StoreMagics(Magics):
74 """Lightweight persistence for python variables.
74 """Lightweight persistence for python variables.
75
75
76 Provides the %store magic."""
76 Provides the %store magic."""
77
77
78 autorestore = Bool(False, config=True, help=
78 autorestore = Bool(False, config=True, help=
79 """If True, any %store-d variables will be automatically restored
79 """If True, any %store-d variables will be automatically restored
80 when IPython starts.
80 when IPython starts.
81 """
81 """
82 )
82 )
83
83
84 def __init__(self, shell):
84 def __init__(self, shell):
85 super(StoreMagics, self).__init__(shell=shell)
85 super(StoreMagics, self).__init__(shell=shell)
86 self.shell.configurables.append(self)
86 self.shell.configurables.append(self)
87 if self.autorestore:
87 if self.autorestore:
88 restore_data(self.shell)
88 restore_data(self.shell)
89
89
90 @skip_doctest
90 @skip_doctest
91 @line_magic
91 @line_magic
92 def store(self, parameter_s=''):
92 def store(self, parameter_s=''):
93 """Lightweight persistence for python variables.
93 """Lightweight persistence for python variables.
94
94
95 Example::
95 Example::
96
96
97 In [1]: l = ['hello',10,'world']
97 In [1]: l = ['hello',10,'world']
98 In [2]: %store l
98 In [2]: %store l
99 In [3]: exit
99 In [3]: exit
100
100
101 (IPython session is closed and started again...)
101 (IPython session is closed and started again...)
102
102
103 ville@badger:~$ ipython
103 ville@badger:~$ ipython
104 In [1]: l
104 In [1]: l
105 NameError: name 'l' is not defined
105 NameError: name 'l' is not defined
106 In [2]: %store -r
106 In [2]: %store -r
107 In [3]: l
107 In [3]: l
108 Out[3]: ['hello', 10, 'world']
108 Out[3]: ['hello', 10, 'world']
109
109
110 Usage:
110 Usage:
111
111
112 * ``%store`` - Show list of all variables and their current
112 * ``%store`` - Show list of all variables and their current
113 values
113 values
114 * ``%store spam`` - Store the *current* value of the variable spam
114 * ``%store spam`` - Store the *current* value of the variable spam
115 to disk
115 to disk
116 * ``%store -d spam`` - Remove the variable and its value from storage
116 * ``%store -d spam`` - Remove the variable and its value from storage
117 * ``%store -z`` - Remove all variables from storage
117 * ``%store -z`` - Remove all variables from storage
118 * ``%store -r`` - Refresh all variables from store (overwrite
118 * ``%store -r`` - Refresh all variables from store (overwrite
119 current vals)
119 current vals)
120 * ``%store -r spam bar`` - Refresh specified variables from store
120 * ``%store -r spam bar`` - Refresh specified variables from store
121 (delete current val)
121 (delete current val)
122 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
122 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
123 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
123 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
124
124
125 It should be noted that if you change the value of a variable, you
125 It should be noted that if you change the value of a variable, you
126 need to %store it again if you want to persist the new value.
126 need to %store it again if you want to persist the new value.
127
127
128 Note also that the variables will need to be pickleable; most basic
128 Note also that the variables will need to be pickleable; most basic
129 python types can be safely %store'd.
129 python types can be safely %store'd.
130
130
131 Also aliases can be %store'd across sessions.
131 Also aliases can be %store'd across sessions.
132 """
132 """
133
133
134 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
134 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
135 args = argsl.split(None,1)
135 args = argsl.split(None,1)
136 ip = self.shell
136 ip = self.shell
137 db = ip.db
137 db = ip.db
138 # delete
138 # delete
139 if 'd' in opts:
139 if 'd' in opts:
140 try:
140 try:
141 todel = args[0]
141 todel = args[0]
142 except IndexError:
142 except IndexError:
143 raise UsageError('You must provide the variable to forget')
143 raise UsageError('You must provide the variable to forget')
144 else:
144 else:
145 try:
145 try:
146 del db['autorestore/' + todel]
146 del db['autorestore/' + todel]
147 except:
147 except:
148 raise UsageError("Can't delete variable '%s'" % todel)
148 raise UsageError("Can't delete variable '%s'" % todel)
149 # reset
149 # reset
150 elif 'z' in opts:
150 elif 'z' in opts:
151 for k in db.keys('autorestore/*'):
151 for k in db.keys('autorestore/*'):
152 del db[k]
152 del db[k]
153
153
154 elif 'r' in opts:
154 elif 'r' in opts:
155 if args:
155 if args:
156 for arg in args:
156 for arg in args:
157 try:
157 try:
158 obj = db['autorestore/' + arg]
158 obj = db['autorestore/' + arg]
159 except KeyError:
159 except KeyError:
160 print("no stored variable %s" % arg)
160 print("no stored variable %s" % arg)
161 else:
161 else:
162 ip.user_ns[arg] = obj
162 ip.user_ns[arg] = obj
163 else:
163 else:
164 restore_data(ip)
164 restore_data(ip)
165
165
166 # run without arguments -> list variables & values
166 # run without arguments -> list variables & values
167 elif not args:
167 elif not args:
168 vars = db.keys('autorestore/*')
168 vars = db.keys('autorestore/*')
169 vars.sort()
169 vars.sort()
170 if vars:
170 if vars:
171 size = max(map(len, vars))
171 size = max(map(len, vars))
172 else:
172 else:
173 size = 0
173 size = 0
174
174
175 print('Stored variables and their in-db values:')
175 print('Stored variables and their in-db values:')
176 fmt = '%-'+str(size)+'s -> %s'
176 fmt = '%-'+str(size)+'s -> %s'
177 get = db.get
177 get = db.get
178 for var in vars:
178 for var in vars:
179 justkey = os.path.basename(var)
179 justkey = os.path.basename(var)
180 # print 30 first characters from every var
180 # print 30 first characters from every var
181 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
181 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
182
182
183 # default action - store the variable
183 # default action - store the variable
184 else:
184 else:
185 # %store foo >file.txt or >>file.txt
185 # %store foo >file.txt or >>file.txt
186 if len(args) > 1 and args[1].startswith('>'):
186 if len(args) > 1 and args[1].startswith('>'):
187 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
187 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
188 if args[1].startswith('>>'):
188 if args[1].startswith('>>'):
189 fil = open(fnam, 'a')
189 fil = open(fnam, 'a')
190 else:
190 else:
191 fil = open(fnam, 'w')
191 fil = open(fnam, 'w')
192 obj = ip.ev(args[0])
192 obj = ip.ev(args[0])
193 print("Writing '%s' (%s) to file '%s'." % (args[0],
193 print("Writing '%s' (%s) to file '%s'." % (args[0],
194 obj.__class__.__name__, fnam))
194 obj.__class__.__name__, fnam))
195
195
196
196
197 if not isinstance (obj, string_types):
197 if not isinstance (obj, string_types):
198 from pprint import pprint
198 from pprint import pprint
199 pprint(obj, fil)
199 pprint(obj, fil)
200 else:
200 else:
201 fil.write(obj)
201 fil.write(obj)
202 if not obj.endswith('\n'):
202 if not obj.endswith('\n'):
203 fil.write('\n')
203 fil.write('\n')
204
204
205 fil.close()
205 fil.close()
206 return
206 return
207
207
208 # %store foo
208 # %store foo
209 try:
209 try:
210 obj = ip.user_ns[args[0]]
210 obj = ip.user_ns[args[0]]
211 except KeyError:
211 except KeyError:
212 # it might be an alias
212 # it might be an alias
213 name = args[0]
213 name = args[0]
214 try:
214 try:
215 cmd = ip.alias_manager.retrieve_alias(name)
215 cmd = ip.alias_manager.retrieve_alias(name)
216 except ValueError:
216 except ValueError:
217 raise UsageError("Unknown variable '%s'" % name)
217 raise UsageError("Unknown variable '%s'" % name)
218
218
219 staliases = db.get('stored_aliases',{})
219 staliases = db.get('stored_aliases',{})
220 staliases[name] = cmd
220 staliases[name] = cmd
221 db['stored_aliases'] = staliases
221 db['stored_aliases'] = staliases
222 print("Alias stored: %s (%s)" % (name, cmd))
222 print("Alias stored: %s (%s)" % (name, cmd))
223 return
223 return
224
224
225 else:
225 else:
226 modname = getattr(inspect.getmodule(obj), '__name__', '')
226 modname = getattr(inspect.getmodule(obj), '__name__', '')
227 if modname == '__main__':
227 if modname == '__main__':
228 print(textwrap.dedent("""\
228 print(textwrap.dedent("""\
229 Warning:%s is %s
229 Warning:%s is %s
230 Proper storage of interactively declared classes (or instances
230 Proper storage of interactively declared classes (or instances
231 of those classes) is not possible! Only instances
231 of those classes) is not possible! Only instances
232 of classes in real modules on file system can be %%store'd.
232 of classes in real modules on file system can be %%store'd.
233 """ % (args[0], obj) ))
233 """ % (args[0], obj) ))
234 return
234 return
235 #pickled = pickle.dumps(obj)
235 #pickled = pickle.dumps(obj)
236 db[ 'autorestore/' + args[0] ] = obj
236 db[ 'autorestore/' + args[0] ] = obj
237 print("Stored '%s' (%s)" % (args[0], obj.__class__.__name__))
237 print("Stored '%s' (%s)" % (args[0], obj.__class__.__name__))
238
238
239
239
240 def load_ipython_extension(ip):
240 def load_ipython_extension(ip):
241 """Load the extension in IPython."""
241 """Load the extension in IPython."""
242 ip.register_magics(StoreMagics)
242 ip.register_magics(StoreMagics)
243
243
General Comments 0
You need to be logged in to leave comments. Login now