Spaces:
No application file
No application file
| # -*- coding: utf-8 -*- | |
| """ | |
| %store magic for lightweight persistence. | |
| Stores variables, aliases and macros in IPython's database. | |
| To automatically restore stored variables at startup, add this to your | |
| :file:`ipython_config.py` file:: | |
| c.StoreMagics.autorestore = True | |
| """ | |
| # Copyright (c) IPython Development Team. | |
| # Distributed under the terms of the Modified BSD License. | |
| import inspect, os, sys, textwrap | |
| from IPython.core.error import UsageError | |
| from IPython.core.magic import Magics, magics_class, line_magic | |
| from IPython.testing.skipdoctest import skip_doctest | |
| from traitlets import Bool | |
| def restore_aliases(ip, alias=None): | |
| staliases = ip.db.get('stored_aliases', {}) | |
| if alias is None: | |
| for k,v in staliases.items(): | |
| #print "restore alias",k,v # dbg | |
| #self.alias_table[k] = v | |
| ip.alias_manager.define_alias(k,v) | |
| else: | |
| ip.alias_manager.define_alias(alias, staliases[alias]) | |
| def refresh_variables(ip): | |
| db = ip.db | |
| for key in db.keys('autorestore/*'): | |
| # strip autorestore | |
| justkey = os.path.basename(key) | |
| try: | |
| obj = db[key] | |
| except KeyError: | |
| print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey) | |
| print("The error was:", sys.exc_info()[0]) | |
| else: | |
| #print "restored",justkey,"=",obj #dbg | |
| ip.user_ns[justkey] = obj | |
| def restore_dhist(ip): | |
| ip.user_ns['_dh'] = ip.db.get('dhist',[]) | |
| def restore_data(ip): | |
| refresh_variables(ip) | |
| restore_aliases(ip) | |
| restore_dhist(ip) | |
| class StoreMagics(Magics): | |
| """Lightweight persistence for python variables. | |
| Provides the %store magic.""" | |
| autorestore = Bool(False, help= | |
| """If True, any %store-d variables will be automatically restored | |
| when IPython starts. | |
| """ | |
| ).tag(config=True) | |
| def __init__(self, shell): | |
| super(StoreMagics, self).__init__(shell=shell) | |
| self.shell.configurables.append(self) | |
| if self.autorestore: | |
| restore_data(self.shell) | |
| def store(self, parameter_s=''): | |
| """Lightweight persistence for python variables. | |
| Example:: | |
| In [1]: l = ['hello',10,'world'] | |
| In [2]: %store l | |
| Stored 'l' (list) | |
| In [3]: exit | |
| (IPython session is closed and started again...) | |
| ville@badger:~$ ipython | |
| In [1]: l | |
| NameError: name 'l' is not defined | |
| In [2]: %store -r | |
| In [3]: l | |
| Out[3]: ['hello', 10, 'world'] | |
| Usage: | |
| * ``%store`` - Show list of all variables and their current | |
| values | |
| * ``%store spam bar`` - Store the *current* value of the variables spam | |
| and bar to disk | |
| * ``%store -d spam`` - Remove the variable and its value from storage | |
| * ``%store -z`` - Remove all variables from storage | |
| * ``%store -r`` - Refresh all variables, aliases and directory history | |
| from store (overwrite current vals) | |
| * ``%store -r spam bar`` - Refresh specified variables and aliases from store | |
| (delete current val) | |
| * ``%store foo >a.txt`` - Store value of foo to new file a.txt | |
| * ``%store foo >>a.txt`` - Append value of foo to file a.txt | |
| It should be noted that if you change the value of a variable, you | |
| need to %store it again if you want to persist the new value. | |
| Note also that the variables will need to be pickleable; most basic | |
| python types can be safely %store'd. | |
| Also aliases can be %store'd across sessions. | |
| To remove an alias from the storage, use the %unalias magic. | |
| """ | |
| opts,argsl = self.parse_options(parameter_s,'drz',mode='string') | |
| args = argsl.split() | |
| ip = self.shell | |
| db = ip.db | |
| # delete | |
| if 'd' in opts: | |
| try: | |
| todel = args[0] | |
| except IndexError as e: | |
| raise UsageError('You must provide the variable to forget') from e | |
| else: | |
| try: | |
| del db['autorestore/' + todel] | |
| except BaseException as e: | |
| raise UsageError("Can't delete variable '%s'" % todel) from e | |
| # reset | |
| elif 'z' in opts: | |
| for k in db.keys('autorestore/*'): | |
| del db[k] | |
| elif 'r' in opts: | |
| if args: | |
| for arg in args: | |
| try: | |
| obj = db['autorestore/' + arg] | |
| except KeyError: | |
| try: | |
| restore_aliases(ip, alias=arg) | |
| except KeyError: | |
| print("no stored variable or alias %s" % arg) | |
| else: | |
| ip.user_ns[arg] = obj | |
| else: | |
| restore_data(ip) | |
| # run without arguments -> list variables & values | |
| elif not args: | |
| vars = db.keys('autorestore/*') | |
| vars.sort() | |
| if vars: | |
| size = max(map(len, vars)) | |
| else: | |
| size = 0 | |
| print('Stored variables and their in-db values:') | |
| fmt = '%-'+str(size)+'s -> %s' | |
| get = db.get | |
| for var in vars: | |
| justkey = os.path.basename(var) | |
| # print 30 first characters from every var | |
| print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50])) | |
| # default action - store the variable | |
| else: | |
| # %store foo >file.txt or >>file.txt | |
| if len(args) > 1 and args[1].startswith(">"): | |
| fnam = os.path.expanduser(args[1].lstrip(">").lstrip()) | |
| if args[1].startswith(">>"): | |
| fil = open(fnam, "a", encoding="utf-8") | |
| else: | |
| fil = open(fnam, "w", encoding="utf-8") | |
| with fil: | |
| obj = ip.ev(args[0]) | |
| print("Writing '%s' (%s) to file '%s'." % (args[0], | |
| obj.__class__.__name__, fnam)) | |
| if not isinstance (obj, str): | |
| from pprint import pprint | |
| pprint(obj, fil) | |
| else: | |
| fil.write(obj) | |
| if not obj.endswith('\n'): | |
| fil.write('\n') | |
| return | |
| # %store foo | |
| for arg in args: | |
| try: | |
| obj = ip.user_ns[arg] | |
| except KeyError: | |
| # it might be an alias | |
| name = arg | |
| try: | |
| cmd = ip.alias_manager.retrieve_alias(name) | |
| except ValueError as e: | |
| raise UsageError("Unknown variable '%s'" % name) from e | |
| staliases = db.get('stored_aliases',{}) | |
| staliases[name] = cmd | |
| db['stored_aliases'] = staliases | |
| print("Alias stored: %s (%s)" % (name, cmd)) | |
| return | |
| else: | |
| modname = getattr(inspect.getmodule(obj), '__name__', '') | |
| if modname == '__main__': | |
| print(textwrap.dedent("""\ | |
| Warning:%s is %s | |
| Proper storage of interactively declared classes (or instances | |
| of those classes) is not possible! Only instances | |
| of classes in real modules on file system can be %%store'd. | |
| """ % (arg, obj) )) | |
| return | |
| #pickled = pickle.dumps(obj) | |
| db[ 'autorestore/' + arg ] = obj | |
| print("Stored '%s' (%s)" % (arg, obj.__class__.__name__)) | |
| def load_ipython_extension(ip): | |
| """Load the extension in IPython.""" | |
| ip.register_magics(StoreMagics) | |