1 """
2 Extensions to pickle allowing items in __main__ to be saved.
3 """
4
5 import new
6 import pickle
7 import new
8 import types
9 import __main__
10 from StringIO import StringIO
11
12
13
14 -class PickleMain(object):
15 """
16 Pickle support for types and functions defined in __main__.
17
18 When pickled, saves types and functions defined in __main__ by
19 value (i.e. as bytecode). When unpickled, loads previously saved
20 types and functions back into __main__.
21 """
23
24
25
26
27
28
29
30
31
32 self.pickled_bytecode = StringIO()
33 self.pickler = pickle.Pickler(self.pickled_bytecode,-1)
34
35 self.pickler.dispatch[new.code] = save_code
36 self.pickler.dispatch[new.function] = save_function
37 self.pickler.dispatch[dict] = save_module_dict
38 self.pickler.dispatch[new.classobj] = save_classobj
39 self.pickler.dispatch[new.instancemethod] = save_instancemethod
40 self.pickler.dispatch[new.module] = save_module
41 self.pickler.dispatch[type] = save_type
42
43 import param
44 self.pickler.dispatch[param.parameterized.ParameterizedMetaclass] = save_type
45
46
47 - def __getstate__(self):
48 self._create_pickler()
49
50 bytecode = {}
51 for name,obj in __main__.__dict__.items():
52 if not name.startswith('_'):
53 if isinstance(obj,types.FunctionType) or isinstance(obj,type):
54
55 if obj.__module__ == "__main__":
56
57 print "%s is defined in __main__: saving bytecode."%name
58 bytecode[name] = obj
59
60 self.pickler.dump(bytecode)
61 return {'pickled_bytecode':self.pickled_bytecode}
62
63
64 - def __setstate__(self,state):
65 bytecode = pickle.load(StringIO(state['pickled_bytecode'].getvalue()))
66
67 for name,obj in bytecode.items():
68 print "%s restored from bytecode into __main__"%name
69 __main__.__dict__[name] = obj
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
92 """ Save a code object by value """
93 args = (
94 obj.co_argcount, obj.co_nlocals, obj.co_stacksize, obj.co_flags, obj.co_code,
95 obj.co_consts, obj.co_names, obj.co_varnames, obj.co_filename, obj.co_name,
96 obj.co_firstlineno, obj.co_lnotab, obj.co_freevars, obj.co_cellvars
97 )
98 self.save_reduce(new.code, args, obj=obj)
99
101 """ Save functions by value if they are defined interactively """
102 if obj.__module__ == '__main__' or obj.func_name == '<lambda>':
103 args = (obj.func_code, obj.func_globals, obj.func_name, obj.func_defaults, obj.func_closure)
104 self.save_reduce(new.function, args, obj=obj)
105 else:
106 pickle.Pickler.save_global(self, obj)
107
109 """ Save obj as a global reference. Used for objects that pickle does not find correctly. """
110 self.write('%s%s\n%s\n' % (pickle.GLOBAL, modname, objname))
111 self.memoize(obj)
112
114 """ Special-case __main__.__dict__. Useful for a function's func_globals member. """
115 if obj is main_dict:
116 save_global_byname(self, obj, '__main__', '__dict__')
117 else:
118 return pickle.Pickler.save_dict(self, obj)
119
121 """ Save an interactively defined classic class object by value """
122 if obj.__module__ == '__main__':
123 args = (obj.__name__, obj.__bases__, obj.__dict__)
124 self.save_reduce(new.classobj, args, obj=obj)
125 else:
126
127 pickle.Pickler.save_global(self, obj, name)
128
130 """ Save an instancemethod object """
131
132 args = (obj.im_func, obj.im_self, obj.im_class)
133 self.save_reduce(new.instancemethod, args)
134
136 """ Save modules by reference, except __main__ which also gets its contents saved by value """
137 if obj.__name__ == '__main__':
138 self.save_reduce(__import__, (obj.__name__,), obj=obj, state=vars(obj).copy())
139 elif obj.__name__.count('.') == 0:
140 self.save_reduce(__import__, (obj.__name__,), obj=obj)
141 else:
142 save_global_byname(self, obj, *obj.__name__.rsplit('.', 1))
143
145 if getattr(new, obj.__name__, None) is obj:
146
147 save_global_byname(self, obj, 'new', obj.__name__)
148 elif obj.__module__ == '__main__':
149
150
151
152 if id(type.__new__) not in self.memo:
153 self.save_reduce(getattr, (type, '__new__'), obj=type.__new__)
154 self.write(pickle.POP)
155
156
157 d = dict(obj.__dict__)
158
159 d.pop('__dict__', None)
160 d.pop('__weakref__', None)
161
162 args = (type(obj), obj.__name__, obj.__bases__, d)
163 self.save_reduce(type.__new__, args, obj=obj)
164 else:
165
166 pickle.Pickler.save_global(self, obj)
167
168