| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 1 | """create portable serialized representations of Python objects. | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 2 |  | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 3 | See module cPickle for a (much) faster implementation. | 
 | 4 | See module copy_reg for a mechanism for registering custom picklers. | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 5 |  | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 6 | Classes: | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 7 |  | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 8 |     Pickler | 
 | 9 |     Unpickler | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 10 |  | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 11 | Functions: | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 12 |  | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 13 |     dump(object, file) | 
 | 14 |     dumps(object) -> string | 
 | 15 |     load(file) -> object | 
 | 16 |     loads(string) -> object | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 17 |  | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 18 | Misc variables: | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 19 |  | 
| Fred Drake | fe82acc | 1998-02-13 03:24:48 +0000 | [diff] [blame] | 20 |     __version__ | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 21 |     format_version | 
 | 22 |     compatible_formats | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 23 |  | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 24 | """ | 
 | 25 |  | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 26 | __version__ = "1.9"                     # Code version | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 27 |  | 
 | 28 | from types import * | 
| Guido van Rossum | 4fb5b28 | 1997-09-12 20:07:24 +0000 | [diff] [blame] | 29 | from copy_reg import dispatch_table, safe_constructors | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 30 | import string, marshal | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 31 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 32 | format_version = "1.2"                  # File format version we write | 
 | 33 | compatible_formats = ["1.0", "1.1"]     # Old format versions we can read | 
 | 34 |  | 
 | 35 | mdumps = marshal.dumps | 
 | 36 | mloads = marshal.loads | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 37 |  | 
| Guido van Rossum | 7849da8 | 1995-03-09 14:08:35 +0000 | [diff] [blame] | 38 | PicklingError = "pickle.PicklingError" | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 39 | UnpicklingError = "pickle.UnpicklingError" | 
| Guido van Rossum | 7849da8 | 1995-03-09 14:08:35 +0000 | [diff] [blame] | 40 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 41 | MARK            = '(' | 
 | 42 | STOP            = '.' | 
 | 43 | POP             = '0' | 
 | 44 | POP_MARK        = '1' | 
 | 45 | DUP             = '2' | 
 | 46 | FLOAT           = 'F' | 
 | 47 | INT             = 'I' | 
 | 48 | BININT          = 'J' | 
 | 49 | BININT1         = 'K' | 
 | 50 | LONG            = 'L' | 
 | 51 | BININT2         = 'M' | 
 | 52 | NONE            = 'N' | 
 | 53 | PERSID          = 'P' | 
 | 54 | BINPERSID       = 'Q' | 
 | 55 | REDUCE          = 'R' | 
 | 56 | STRING          = 'S' | 
 | 57 | BINSTRING       = 'T' | 
 | 58 | SHORT_BINSTRING = 'U' | 
 | 59 | APPEND          = 'a' | 
 | 60 | BUILD           = 'b' | 
 | 61 | GLOBAL          = 'c' | 
 | 62 | DICT            = 'd' | 
 | 63 | EMPTY_DICT      = '}' | 
 | 64 | APPENDS         = 'e' | 
 | 65 | GET             = 'g' | 
 | 66 | BINGET          = 'h' | 
 | 67 | INST            = 'i' | 
 | 68 | LONG_BINGET     = 'j' | 
 | 69 | LIST            = 'l' | 
 | 70 | EMPTY_LIST      = ']' | 
 | 71 | OBJ             = 'o' | 
 | 72 | PUT             = 'p' | 
 | 73 | BINPUT          = 'q' | 
 | 74 | LONG_BINPUT     = 'r' | 
 | 75 | SETITEM         = 's' | 
 | 76 | TUPLE           = 't' | 
 | 77 | EMPTY_TUPLE     = ')' | 
 | 78 | SETITEMS        = 'u' | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 79 |  | 
 | 80 | class Pickler: | 
 | 81 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 82 |     def __init__(self, file, bin = 0): | 
 | 83 |         self.write = file.write | 
 | 84 |         self.memo = {} | 
 | 85 |         self.bin = bin | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 86 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 87 |     def dump(self, object): | 
 | 88 |         self.save(object) | 
 | 89 |         self.write(STOP) | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 90 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 91 |     def dump_special(self, callable, args, state = None): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 92 |         if type(args) is not TupleType and args is not None: | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 93 |             raise PicklingError, "Second argument to dump_special " \ | 
 | 94 |                                  "must be a tuple" | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 95 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 96 |         self.save_reduce(callable, args, state) | 
 | 97 |         self.write(STOP) | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 98 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 99 |     def put(self, i): | 
 | 100 |         if (self.bin): | 
 | 101 |             s = mdumps(i)[1:] | 
 | 102 |             if (i < 256): | 
 | 103 |                 return BINPUT + s[0] | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 104 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 105 |             return LONG_BINPUT + s | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 106 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 107 |         return PUT + `i` + '\n' | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 108 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 109 |     def get(self, i): | 
 | 110 |         if (self.bin): | 
 | 111 |             s = mdumps(i)[1:] | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 112 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 113 |             if (i < 256): | 
 | 114 |                 return BINGET + s[0] | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 115 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 116 |             return LONG_BINGET + s | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 117 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 118 |         return GET + `i` + '\n' | 
 | 119 |          | 
 | 120 |     def save(self, object, pers_save = 0): | 
 | 121 |         memo = self.memo | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 122 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 123 |         if (not pers_save): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 124 |             pid = self.persistent_id(object) | 
 | 125 |             if (pid is not None): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 126 |                 self.save_pers(pid) | 
 | 127 |                 return | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 128 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 129 |         d = id(object) | 
 | 130 |   | 
 | 131 |         t = type(object) | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 132 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 133 |         if ((t is TupleType) and (len(object) == 0)): | 
 | 134 |             if (self.bin): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 135 |                 self.save_empty_tuple(object) | 
 | 136 |             else: | 
 | 137 |                 self.save_tuple(object) | 
 | 138 |             return | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 139 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 140 |         if memo.has_key(d): | 
 | 141 |             self.write(self.get(memo[d][0])) | 
 | 142 |             return | 
 | 143 |  | 
 | 144 |         try: | 
 | 145 |             f = self.dispatch[t] | 
 | 146 |         except KeyError: | 
 | 147 |             pid = self.inst_persistent_id(object) | 
 | 148 |             if pid is not None: | 
 | 149 |                 self.save_pers(pid) | 
 | 150 |                 return | 
 | 151 |  | 
 | 152 |             try: | 
 | 153 |                 reduce = dispatch_table[t] | 
 | 154 |             except KeyError: | 
 | 155 |                 try: | 
 | 156 |                     reduce = object.__reduce__ | 
 | 157 |                 except AttributeError: | 
 | 158 |                     raise PicklingError, \ | 
 | 159 |                         "can't pickle %s objects" % `t.__name__` | 
 | 160 |                 else: | 
 | 161 |                     tup = reduce() | 
 | 162 |             else: | 
 | 163 |                 tup = reduce(object) | 
 | 164 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 165 |             if type(tup) is StringType: | 
 | 166 |                 self.save_global(object, tup) | 
 | 167 |                 return | 
| Guido van Rossum | d1f4984 | 1997-12-10 23:40:18 +0000 | [diff] [blame] | 168 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 169 |             if (type(tup) is not TupleType): | 
 | 170 |                 raise PicklingError, "Value returned by %s must be a " \ | 
 | 171 |                                      "tuple" % reduce | 
 | 172 |  | 
 | 173 |             l = len(tup) | 
 | 174 |     | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 175 |             if ((l != 2) and (l != 3)): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 176 |                 raise PicklingError, "tuple returned by %s must contain " \ | 
 | 177 |                                      "only two or three elements" % reduce | 
 | 178 |  | 
 | 179 |             callable = tup[0] | 
 | 180 |             arg_tup  = tup[1] | 
 | 181 |            | 
 | 182 |             if (l > 2): | 
 | 183 |                 state = tup[2] | 
 | 184 |             else: | 
 | 185 |                 state = None | 
 | 186 |  | 
| Guido van Rossum | d1f4984 | 1997-12-10 23:40:18 +0000 | [diff] [blame] | 187 |             if type(arg_tup) is not TupleType and arg_tup is not None: | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 188 |                 raise PicklingError, "Second element of tuple returned " \ | 
 | 189 |                                      "by %s must be a tuple" % reduce | 
 | 190 |  | 
 | 191 |             self.save_reduce(callable, arg_tup, state)  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 192 |             memo_len = len(memo) | 
 | 193 |             self.write(self.put(memo_len)) | 
 | 194 |             memo[d] = (memo_len, object) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 195 |             return | 
 | 196 |  | 
 | 197 |         f(self, object) | 
 | 198 |  | 
 | 199 |     def persistent_id(self, object): | 
 | 200 |         return None | 
 | 201 |  | 
 | 202 |     def inst_persistent_id(self, object): | 
 | 203 |         return None | 
 | 204 |  | 
 | 205 |     def save_pers(self, pid): | 
 | 206 |         if (not self.bin): | 
 | 207 |             self.write(PERSID + str(pid) + '\n') | 
 | 208 |         else: | 
 | 209 |             self.save(pid, 1) | 
 | 210 |             self.write(BINPERSID) | 
 | 211 |  | 
 | 212 |     def save_reduce(self, callable, arg_tup, state = None): | 
 | 213 |         write = self.write | 
 | 214 |         save = self.save | 
 | 215 |  | 
 | 216 |         save(callable) | 
 | 217 |         save(arg_tup) | 
 | 218 |         write(REDUCE) | 
 | 219 |          | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 220 |         if (state is not None): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 221 |             save(state) | 
 | 222 |             write(BUILD) | 
 | 223 |  | 
 | 224 |     dispatch = {} | 
 | 225 |  | 
 | 226 |     def save_none(self, object): | 
 | 227 |         self.write(NONE) | 
 | 228 |     dispatch[NoneType] = save_none | 
 | 229 |  | 
 | 230 |     def save_int(self, object): | 
 | 231 |         if (self.bin): | 
 | 232 |             i = mdumps(object)[1:] | 
 | 233 |             if (i[-2:] == '\000\000'): | 
 | 234 |                 if (i[-3] == '\000'): | 
 | 235 |                     self.write(BININT1 + i[:-3]) | 
 | 236 |                     return | 
 | 237 |  | 
 | 238 |                 self.write(BININT2 + i[:-2]) | 
 | 239 |                 return | 
 | 240 |  | 
 | 241 |             self.write(BININT + i) | 
 | 242 |         else: | 
 | 243 |             self.write(INT + `object` + '\n') | 
 | 244 |     dispatch[IntType] = save_int | 
 | 245 |  | 
 | 246 |     def save_long(self, object): | 
 | 247 |         self.write(LONG + `object` + '\n') | 
 | 248 |     dispatch[LongType] = save_long | 
 | 249 |  | 
 | 250 |     def save_float(self, object): | 
 | 251 |         self.write(FLOAT + `object` + '\n') | 
 | 252 |     dispatch[FloatType] = save_float | 
 | 253 |  | 
 | 254 |     def save_string(self, object): | 
 | 255 |         d = id(object) | 
 | 256 |         memo = self.memo | 
 | 257 |  | 
 | 258 |         if (self.bin): | 
 | 259 |             l = len(object) | 
 | 260 |             s = mdumps(l)[1:] | 
 | 261 |             if (l < 256): | 
 | 262 |                 self.write(SHORT_BINSTRING + s[0] + object) | 
 | 263 |             else: | 
 | 264 |                 self.write(BINSTRING + s + object) | 
 | 265 |         else: | 
 | 266 |             self.write(STRING + `object` + '\n') | 
 | 267 |  | 
 | 268 |         memo_len = len(memo) | 
 | 269 |         self.write(self.put(memo_len)) | 
 | 270 |         memo[d] = (memo_len, object) | 
 | 271 |     dispatch[StringType] = save_string | 
 | 272 |  | 
 | 273 |     def save_tuple(self, object): | 
 | 274 |  | 
 | 275 |         write = self.write | 
 | 276 |         save  = self.save | 
 | 277 |         memo  = self.memo | 
 | 278 |  | 
 | 279 |         d = id(object) | 
 | 280 |  | 
 | 281 |         write(MARK) | 
 | 282 |  | 
 | 283 |         for element in object: | 
 | 284 |             save(element) | 
 | 285 |  | 
 | 286 |         if (len(object) and memo.has_key(d)): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 287 |             if (self.bin): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 288 |                 write(POP_MARK + self.get(memo[d][0])) | 
 | 289 |                 return | 
 | 290 |             | 
| Guido van Rossum | 599174f | 1998-03-31 16:30:28 +0000 | [diff] [blame] | 291 |             write(POP * (len(object) + 1) + self.get(memo[d][0])) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 292 |             return | 
 | 293 |  | 
 | 294 |         memo_len = len(memo) | 
 | 295 |         self.write(TUPLE + self.put(memo_len)) | 
 | 296 |         memo[d] = (memo_len, object) | 
 | 297 |     dispatch[TupleType] = save_tuple | 
 | 298 |  | 
 | 299 |     def save_empty_tuple(self, object): | 
 | 300 |         self.write(EMPTY_TUPLE) | 
 | 301 |  | 
 | 302 |     def save_list(self, object): | 
 | 303 |         d = id(object) | 
 | 304 |  | 
 | 305 |         write = self.write | 
 | 306 |         save  = self.save | 
 | 307 |         memo  = self.memo | 
 | 308 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 309 |         if (self.bin): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 310 |             write(EMPTY_LIST) | 
 | 311 |         else: | 
 | 312 |             write(MARK + LIST) | 
 | 313 |  | 
 | 314 |         memo_len = len(memo) | 
 | 315 |         write(self.put(memo_len)) | 
 | 316 |         memo[d] = (memo_len, object) | 
 | 317 |  | 
 | 318 |         using_appends = (self.bin and (len(object) > 1)) | 
 | 319 |  | 
 | 320 |         if (using_appends): | 
 | 321 |             write(MARK) | 
 | 322 |  | 
 | 323 |         for element in object: | 
 | 324 |             save(element) | 
 | 325 |    | 
 | 326 |             if (not using_appends): | 
 | 327 |                 write(APPEND) | 
 | 328 |  | 
 | 329 |         if (using_appends): | 
 | 330 |             write(APPENDS) | 
 | 331 |     dispatch[ListType] = save_list | 
 | 332 |  | 
 | 333 |     def save_dict(self, object): | 
 | 334 |         d = id(object) | 
 | 335 |  | 
 | 336 |         write = self.write | 
 | 337 |         save  = self.save | 
 | 338 |         memo  = self.memo | 
 | 339 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 340 |         if (self.bin): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 341 |             write(EMPTY_DICT) | 
 | 342 |         else: | 
 | 343 |             write(MARK + DICT) | 
 | 344 |  | 
 | 345 |         memo_len = len(memo) | 
 | 346 |         self.write(self.put(memo_len)) | 
 | 347 |         memo[d] = (memo_len, object) | 
 | 348 |  | 
 | 349 |         using_setitems = (self.bin and (len(object) > 1)) | 
 | 350 |  | 
 | 351 |         if (using_setitems): | 
 | 352 |             write(MARK) | 
 | 353 |  | 
 | 354 |         items = object.items() | 
 | 355 |         for key, value in items: | 
 | 356 |             save(key) | 
 | 357 |             save(value) | 
 | 358 |  | 
 | 359 |             if (not using_setitems): | 
 | 360 |                 write(SETITEM) | 
 | 361 |  | 
 | 362 |         if (using_setitems): | 
 | 363 |             write(SETITEMS) | 
 | 364 |  | 
 | 365 |     dispatch[DictionaryType] = save_dict | 
 | 366 |  | 
 | 367 |     def save_inst(self, object): | 
 | 368 |         d = id(object) | 
 | 369 |         cls = object.__class__ | 
 | 370 |  | 
 | 371 |         memo  = self.memo | 
 | 372 |         write = self.write | 
 | 373 |         save  = self.save | 
 | 374 |  | 
 | 375 |         if hasattr(object, '__getinitargs__'): | 
 | 376 |             args = object.__getinitargs__() | 
 | 377 |             len(args) # XXX Assert it's a sequence | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 378 |             _keep_alive(args, memo) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 379 |         else: | 
 | 380 |             args = () | 
 | 381 |  | 
 | 382 |         write(MARK) | 
 | 383 |  | 
 | 384 |         if (self.bin): | 
 | 385 |             save(cls) | 
 | 386 |  | 
 | 387 |         for arg in args: | 
 | 388 |             save(arg) | 
 | 389 |  | 
 | 390 |         memo_len = len(memo) | 
 | 391 |         if (self.bin): | 
 | 392 |             write(OBJ + self.put(memo_len)) | 
 | 393 |         else: | 
| Guido van Rossum | 4fb5b28 | 1997-09-12 20:07:24 +0000 | [diff] [blame] | 394 |             write(INST + cls.__module__ + '\n' + cls.__name__ + '\n' + | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 395 |                 self.put(memo_len)) | 
 | 396 |  | 
 | 397 |         memo[d] = (memo_len, object) | 
 | 398 |  | 
 | 399 |         try: | 
 | 400 |             getstate = object.__getstate__ | 
 | 401 |         except AttributeError: | 
 | 402 |             stuff = object.__dict__ | 
 | 403 |         else: | 
 | 404 |             stuff = getstate() | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 405 |             _keep_alive(stuff, memo) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 406 |         save(stuff) | 
 | 407 |         write(BUILD) | 
 | 408 |     dispatch[InstanceType] = save_inst | 
 | 409 |  | 
 | 410 |     def save_global(self, object, name = None): | 
 | 411 |         write = self.write | 
 | 412 |         memo = self.memo | 
 | 413 |  | 
 | 414 |         if (name is None): | 
 | 415 |             name = object.__name__ | 
 | 416 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 417 |         try: | 
 | 418 |             module = object.__module__ | 
 | 419 |         except AttributeError: | 
 | 420 |             module = whichmodule(object, name) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 421 |  | 
 | 422 |         memo_len = len(memo) | 
 | 423 |         write(GLOBAL + module + '\n' + name + '\n' + | 
 | 424 |             self.put(memo_len)) | 
 | 425 |         memo[id(object)] = (memo_len, object) | 
 | 426 |     dispatch[ClassType] = save_global | 
 | 427 |     dispatch[FunctionType] = save_global | 
 | 428 |     dispatch[BuiltinFunctionType] = save_global | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 429 |  | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 430 |  | 
| Guido van Rossum | 5ed5c4c | 1997-09-03 00:23:54 +0000 | [diff] [blame] | 431 | def _keep_alive(x, memo): | 
 | 432 |     """Keeps a reference to the object x in the memo. | 
 | 433 |  | 
 | 434 |     Because we remember objects by their id, we have | 
 | 435 |     to assure that possibly temporary objects are kept | 
 | 436 |     alive by referencing them. | 
 | 437 |     We store a reference at the id of the memo, which should | 
 | 438 |     normally not be used unless someone tries to deepcopy | 
 | 439 |     the memo itself... | 
 | 440 |     """ | 
 | 441 |     try: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 442 |         memo[id(memo)].append(x) | 
| Guido van Rossum | 5ed5c4c | 1997-09-03 00:23:54 +0000 | [diff] [blame] | 443 |     except KeyError: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 444 |         # aha, this is the first one :-) | 
 | 445 |         memo[id(memo)]=[x] | 
| Guido van Rossum | 5ed5c4c | 1997-09-03 00:23:54 +0000 | [diff] [blame] | 446 |  | 
 | 447 |  | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 448 | classmap = {} | 
 | 449 |  | 
| Guido van Rossum | 4fb5b28 | 1997-09-12 20:07:24 +0000 | [diff] [blame] | 450 | # This is no longer used to find classes, but still for functions | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 451 | def whichmodule(cls, clsname): | 
 | 452 |     """Figure out the module in which a class occurs. | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 453 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 454 |     Search sys.modules for the module. | 
 | 455 |     Cache in classmap. | 
 | 456 |     Return a module name. | 
 | 457 |     If the class cannot be found, return __main__. | 
 | 458 |     """ | 
 | 459 |     if classmap.has_key(cls): | 
 | 460 |         return classmap[cls] | 
 | 461 |     import sys | 
 | 462 |  | 
 | 463 |     for name, module in sys.modules.items(): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 464 |         if name != '__main__' and \ | 
 | 465 |             hasattr(module, clsname) and \ | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 466 |             getattr(module, clsname) is cls: | 
 | 467 |             break | 
 | 468 |     else: | 
 | 469 |         name = '__main__' | 
 | 470 |     classmap[cls] = name | 
 | 471 |     return name | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 472 |  | 
 | 473 |  | 
 | 474 | class Unpickler: | 
 | 475 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 476 |     def __init__(self, file): | 
 | 477 |         self.readline = file.readline | 
 | 478 |         self.read = file.read | 
 | 479 |         self.memo = {} | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 480 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 481 |     def load(self): | 
 | 482 |         self.mark = ['spam'] # Any new unique object | 
 | 483 |         self.stack = [] | 
 | 484 |         self.append = self.stack.append | 
 | 485 |         read = self.read | 
 | 486 |         dispatch = self.dispatch | 
 | 487 |         try: | 
 | 488 |             while 1: | 
 | 489 |                 key = read(1) | 
 | 490 |                 dispatch[key](self) | 
 | 491 |         except STOP, value: | 
 | 492 |             return value | 
 | 493 |  | 
 | 494 |     def marker(self): | 
 | 495 |         stack = self.stack | 
 | 496 |         mark = self.mark | 
 | 497 |         k = len(stack)-1 | 
 | 498 |         while stack[k] is not mark: k = k-1 | 
 | 499 |         return k | 
 | 500 |  | 
 | 501 |     dispatch = {} | 
 | 502 |  | 
 | 503 |     def load_eof(self): | 
 | 504 |         raise EOFError | 
 | 505 |     dispatch[''] = load_eof | 
 | 506 |  | 
 | 507 |     def load_persid(self): | 
 | 508 |         pid = self.readline()[:-1] | 
 | 509 |         self.append(self.persistent_load(pid)) | 
 | 510 |     dispatch[PERSID] = load_persid | 
 | 511 |  | 
 | 512 |     def load_binpersid(self): | 
 | 513 |         stack = self.stack | 
 | 514 |           | 
 | 515 |         pid = stack[-1] | 
 | 516 |         del stack[-1] | 
 | 517 |  | 
 | 518 |         self.append(self.persistent_load(pid)) | 
 | 519 |     dispatch[BINPERSID] = load_binpersid | 
 | 520 |  | 
 | 521 |     def load_none(self): | 
 | 522 |         self.append(None) | 
 | 523 |     dispatch[NONE] = load_none | 
 | 524 |  | 
 | 525 |     def load_int(self): | 
| Guido van Rossum | e680546 | 1997-12-10 19:36:41 +0000 | [diff] [blame] | 526 |         self.append(string.atoi(self.readline()[:-1])) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 527 |     dispatch[INT] = load_int | 
 | 528 |  | 
 | 529 |     def load_binint(self): | 
 | 530 |         self.append(mloads('i' + self.read(4))) | 
 | 531 |     dispatch[BININT] = load_binint | 
 | 532 |  | 
 | 533 |     def load_binint1(self): | 
 | 534 |         self.append(mloads('i' + self.read(1) + '\000\000\000')) | 
 | 535 |     dispatch[BININT1] = load_binint1 | 
 | 536 |  | 
 | 537 |     def load_binint2(self): | 
 | 538 |         self.append(mloads('i' + self.read(2) + '\000\000')) | 
 | 539 |     dispatch[BININT2] = load_binint2 | 
 | 540 |   | 
 | 541 |     def load_long(self): | 
 | 542 |         self.append(string.atol(self.readline()[:-1], 0)) | 
 | 543 |     dispatch[LONG] = load_long | 
 | 544 |  | 
 | 545 |     def load_float(self): | 
 | 546 |         self.append(string.atof(self.readline()[:-1])) | 
 | 547 |     dispatch[FLOAT] = load_float | 
 | 548 |  | 
 | 549 |     def load_string(self): | 
 | 550 |         self.append(eval(self.readline()[:-1], | 
 | 551 |                          {'__builtins__': {}})) # Let's be careful | 
 | 552 |     dispatch[STRING] = load_string | 
 | 553 |  | 
 | 554 |     def load_binstring(self): | 
 | 555 |         len = mloads('i' + self.read(4)) | 
 | 556 |         self.append(self.read(len)) | 
 | 557 |     dispatch[BINSTRING] = load_binstring | 
 | 558 |  | 
 | 559 |     def load_short_binstring(self): | 
 | 560 |         len = mloads('i' + self.read(1) + '\000\000\000') | 
 | 561 |         self.append(self.read(len)) | 
 | 562 |     dispatch[SHORT_BINSTRING] = load_short_binstring | 
 | 563 |  | 
 | 564 |     def load_tuple(self): | 
 | 565 |         k = self.marker() | 
 | 566 |         self.stack[k:] = [tuple(self.stack[k+1:])] | 
 | 567 |     dispatch[TUPLE] = load_tuple | 
 | 568 |  | 
 | 569 |     def load_empty_tuple(self): | 
 | 570 |         self.stack.append(()) | 
 | 571 |     dispatch[EMPTY_TUPLE] = load_empty_tuple | 
 | 572 |  | 
 | 573 |     def load_empty_list(self): | 
 | 574 |         self.stack.append([]) | 
 | 575 |     dispatch[EMPTY_LIST] = load_empty_list | 
 | 576 |  | 
 | 577 |     def load_empty_dictionary(self): | 
 | 578 |         self.stack.append({}) | 
 | 579 |     dispatch[EMPTY_DICT] = load_empty_dictionary | 
 | 580 |  | 
 | 581 |     def load_list(self): | 
 | 582 |         k = self.marker() | 
 | 583 |         self.stack[k:] = [self.stack[k+1:]] | 
 | 584 |     dispatch[LIST] = load_list | 
 | 585 |  | 
 | 586 |     def load_dict(self): | 
 | 587 |         k = self.marker() | 
 | 588 |         d = {} | 
 | 589 |         items = self.stack[k+1:] | 
 | 590 |         for i in range(0, len(items), 2): | 
 | 591 |             key = items[i] | 
 | 592 |             value = items[i+1] | 
 | 593 |             d[key] = value | 
 | 594 |         self.stack[k:] = [d] | 
 | 595 |     dispatch[DICT] = load_dict | 
 | 596 |  | 
 | 597 |     def load_inst(self): | 
 | 598 |         k = self.marker() | 
 | 599 |         args = tuple(self.stack[k+1:]) | 
 | 600 |         del self.stack[k:] | 
 | 601 |         module = self.readline()[:-1] | 
 | 602 |         name = self.readline()[:-1] | 
 | 603 |         klass = self.find_class(module, name) | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 604 |         instantiated = 0 | 
 | 605 |         if (not args and type(klass) is ClassType and | 
 | 606 |             not hasattr(klass, "__getinitargs__")): | 
 | 607 |             try: | 
 | 608 |                 value = _EmptyClass() | 
 | 609 |                 value.__class__ = klass | 
| Guido van Rossum | b19e2a3 | 1998-04-13 18:08:45 +0000 | [diff] [blame] | 610 |                 instantiated = 1 | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 611 |             except RuntimeError: | 
 | 612 |                 # In restricted execution, assignment to inst.__class__ is | 
 | 613 |                 # prohibited | 
 | 614 |                 pass | 
 | 615 |         if not instantiated: | 
 | 616 |             value = apply(klass, args) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 617 |         self.append(value) | 
 | 618 |     dispatch[INST] = load_inst | 
 | 619 |  | 
 | 620 |     def load_obj(self): | 
 | 621 |         stack = self.stack | 
 | 622 |         k = self.marker() | 
 | 623 |         klass = stack[k + 1] | 
 | 624 |         del stack[k + 1] | 
 | 625 |         args = tuple(stack[k + 1:])  | 
 | 626 |         del stack[k:] | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 627 |         instantiated = 0 | 
 | 628 |         if (not args and type(klass) is ClassType and | 
 | 629 |             not hasattr(klass, "__getinitargs__")): | 
 | 630 |             try: | 
 | 631 |                 value = _EmptyClass() | 
 | 632 |                 value.__class__ = klass | 
 | 633 |                 instantiated = 1 | 
 | 634 |             except RuntimeError: | 
 | 635 |                 # In restricted execution, assignment to inst.__class__ is | 
 | 636 |                 # prohibited | 
 | 637 |                 pass | 
 | 638 |         if not instantiated: | 
 | 639 |             value = apply(klass, args) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 640 |         self.append(value) | 
 | 641 |     dispatch[OBJ] = load_obj                 | 
 | 642 |  | 
 | 643 |     def load_global(self): | 
 | 644 |         module = self.readline()[:-1] | 
 | 645 |         name = self.readline()[:-1] | 
 | 646 |         klass = self.find_class(module, name) | 
 | 647 |         self.append(klass) | 
 | 648 |     dispatch[GLOBAL] = load_global | 
 | 649 |  | 
 | 650 |     def find_class(self, module, name): | 
 | 651 |         env = {} | 
 | 652 |  | 
 | 653 |         try: | 
 | 654 |             exec 'from %s import %s' % (module, name) in env | 
 | 655 |         except ImportError: | 
 | 656 |             raise SystemError, \ | 
 | 657 |                   "Failed to import class %s from module %s" % \ | 
 | 658 |                   (name, module) | 
 | 659 |         klass = env[name] | 
 | 660 |         return klass | 
 | 661 |  | 
 | 662 |     def load_reduce(self): | 
 | 663 |         stack = self.stack | 
 | 664 |  | 
 | 665 |         callable = stack[-2] | 
 | 666 |         arg_tup  = stack[-1] | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 667 |         del stack[-2:] | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 668 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 669 |         if type(callable) is not ClassType: | 
 | 670 |             if not safe_constructors.has_key(callable): | 
 | 671 |                 try: | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 672 |                     safe = callable.__safe_for_unpickling__ | 
 | 673 |                 except AttributeError: | 
 | 674 |                     safe = None | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 675 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 676 |                 if (not safe): | 
 | 677 |                    raise UnpicklingError, "%s is not safe for " \ | 
 | 678 |                                           "unpickling" % callable | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 679 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 680 |         if arg_tup is None: | 
 | 681 |             value = callable.__basicnew__() | 
 | 682 |         else: | 
 | 683 |             value = apply(callable, arg_tup) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 684 |         self.append(value) | 
 | 685 |     dispatch[REDUCE] = load_reduce | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 686 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 687 |     def load_pop(self): | 
 | 688 |         del self.stack[-1] | 
 | 689 |     dispatch[POP] = load_pop | 
| Guido van Rossum | 7b5430f | 1995-03-04 22:25:21 +0000 | [diff] [blame] | 690 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 691 |     def load_pop_mark(self): | 
 | 692 |         k = self.marker() | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 693 |         del self.stack[k:] | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 694 |     dispatch[POP_MARK] = load_pop_mark | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 695 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 696 |     def load_dup(self): | 
| Guido van Rossum | b1062fc | 1998-03-31 17:00:46 +0000 | [diff] [blame] | 697 |         self.append(self.stack[-1]) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 698 |     dispatch[DUP] = load_dup | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 699 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 700 |     def load_get(self): | 
 | 701 |         self.append(self.memo[self.readline()[:-1]]) | 
 | 702 |     dispatch[GET] = load_get | 
| Guido van Rossum | 7853647 | 1996-04-12 13:36:27 +0000 | [diff] [blame] | 703 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 704 |     def load_binget(self): | 
 | 705 |         i = mloads('i' + self.read(1) + '\000\000\000') | 
 | 706 |         self.append(self.memo[`i`]) | 
 | 707 |     dispatch[BINGET] = load_binget | 
| Guido van Rossum | 7853647 | 1996-04-12 13:36:27 +0000 | [diff] [blame] | 708 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 709 |     def load_long_binget(self): | 
 | 710 |         i = mloads('i' + self.read(4)) | 
 | 711 |         self.append(self.memo[`i`]) | 
 | 712 |     dispatch[LONG_BINGET] = load_long_binget | 
| Guido van Rossum | 7853647 | 1996-04-12 13:36:27 +0000 | [diff] [blame] | 713 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 714 |     def load_put(self): | 
 | 715 |         self.memo[self.readline()[:-1]] = self.stack[-1] | 
 | 716 |     dispatch[PUT] = load_put | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 717 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 718 |     def load_binput(self): | 
 | 719 |         i = mloads('i' + self.read(1) + '\000\000\000') | 
 | 720 |         self.memo[`i`] = self.stack[-1] | 
 | 721 |     dispatch[BINPUT] = load_binput | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 722 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 723 |     def load_long_binput(self): | 
 | 724 |         i = mloads('i' + self.read(4)) | 
 | 725 |         self.memo[`i`] = self.stack[-1] | 
 | 726 |     dispatch[LONG_BINPUT] = load_long_binput | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 727 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 728 |     def load_append(self): | 
 | 729 |         stack = self.stack | 
 | 730 |         value = stack[-1] | 
 | 731 |         del stack[-1] | 
 | 732 |         list = stack[-1] | 
 | 733 |         list.append(value) | 
 | 734 |     dispatch[APPEND] = load_append | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 735 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 736 |     def load_appends(self): | 
 | 737 |         stack = self.stack | 
 | 738 |         mark = self.marker() | 
 | 739 |         list = stack[mark - 1] | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 740 |         for i in range(mark + 1, len(stack)): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 741 |             list.append(stack[i]) | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 742 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 743 |         del stack[mark:] | 
 | 744 |     dispatch[APPENDS] = load_appends | 
 | 745 |             | 
 | 746 |     def load_setitem(self): | 
 | 747 |         stack = self.stack | 
 | 748 |         value = stack[-1] | 
 | 749 |         key = stack[-2] | 
 | 750 |         del stack[-2:] | 
 | 751 |         dict = stack[-1] | 
 | 752 |         dict[key] = value | 
 | 753 |     dispatch[SETITEM] = load_setitem | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 754 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 755 |     def load_setitems(self): | 
 | 756 |         stack = self.stack | 
 | 757 |         mark = self.marker() | 
 | 758 |         dict = stack[mark - 1] | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 759 |         for i in range(mark + 1, len(stack), 2): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 760 |             dict[stack[i]] = stack[i + 1] | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 761 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 762 |         del stack[mark:] | 
 | 763 |     dispatch[SETITEMS] = load_setitems | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 764 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 765 |     def load_build(self): | 
 | 766 |         stack = self.stack | 
 | 767 |         value = stack[-1] | 
 | 768 |         del stack[-1] | 
 | 769 |         inst = stack[-1] | 
 | 770 |         try: | 
 | 771 |             setstate = inst.__setstate__ | 
 | 772 |         except AttributeError: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 773 |             try: | 
 | 774 |                 inst.__dict__.update(value) | 
 | 775 |             except RuntimeError: | 
 | 776 |                 # XXX In restricted execution, the instance's __dict__ is not | 
 | 777 |                 # accessible.  Use the old way of unpickling the instance | 
 | 778 |                 # variables.  This is a semantic different when unpickling in | 
 | 779 |                 # restricted vs. unrestricted modes. | 
 | 780 |                 for k, v in value.items(): | 
 | 781 |                     setattr(inst, k, v) | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 782 |         else: | 
 | 783 |             setstate(value) | 
 | 784 |     dispatch[BUILD] = load_build | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 785 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 786 |     def load_mark(self): | 
 | 787 |         self.append(self.mark) | 
 | 788 |     dispatch[MARK] = load_mark | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 789 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 790 |     def load_stop(self): | 
 | 791 |         value = self.stack[-1] | 
 | 792 |         del self.stack[-1] | 
 | 793 |         raise STOP, value | 
 | 794 |     dispatch[STOP] = load_stop | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 795 |  | 
| Guido van Rossum | e467be6 | 1997-12-05 19:42:42 +0000 | [diff] [blame] | 796 | # Helper class for load_inst/load_obj | 
 | 797 |  | 
 | 798 | class _EmptyClass: | 
 | 799 |     pass | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 800 |  | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 801 | # Shorthands | 
 | 802 |  | 
| Guido van Rossum | c7c5e69 | 1996-07-22 22:26:07 +0000 | [diff] [blame] | 803 | from StringIO import StringIO | 
 | 804 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 805 | def dump(object, file, bin = 0): | 
 | 806 |     Pickler(file, bin).dump(object) | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 807 |  | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 808 | def dumps(object, bin = 0): | 
 | 809 |     file = StringIO() | 
 | 810 |     Pickler(file, bin).dump(object) | 
 | 811 |     return file.getvalue() | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 812 |  | 
 | 813 | def load(file): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 814 |     return Unpickler(file).load() | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 815 |  | 
 | 816 | def loads(str): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 817 |     file = StringIO(str) | 
 | 818 |     return Unpickler(file).load() | 
| Guido van Rossum | 0c891ce | 1995-03-14 15:09:05 +0000 | [diff] [blame] | 819 |  | 
 | 820 |  | 
 | 821 | # The rest is used for testing only | 
 | 822 |  | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 823 | class C: | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 824 |     def __cmp__(self, other): | 
 | 825 |         return cmp(self.__dict__, other.__dict__) | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 826 |  | 
 | 827 | def test(): | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 828 |     fn = 'out' | 
 | 829 |     c = C() | 
 | 830 |     c.foo = 1 | 
 | 831 |     c.bar = 2 | 
 | 832 |     x = [0, 1, 2, 3] | 
 | 833 |     y = ('abc', 'abc', c, c) | 
 | 834 |     x.append(y) | 
 | 835 |     x.append(y) | 
 | 836 |     x.append(5) | 
 | 837 |     f = open(fn, 'w') | 
 | 838 |     F = Pickler(f) | 
 | 839 |     F.dump(x) | 
 | 840 |     f.close() | 
 | 841 |     f = open(fn, 'r') | 
 | 842 |     U = Unpickler(f) | 
 | 843 |     x2 = U.load() | 
 | 844 |     print x | 
 | 845 |     print x2 | 
 | 846 |     print x == x2 | 
 | 847 |     print map(id, x) | 
 | 848 |     print map(id, x2) | 
 | 849 |     print F.memo | 
 | 850 |     print U.memo | 
| Guido van Rossum | a48061a | 1995-01-10 00:31:14 +0000 | [diff] [blame] | 851 |  | 
 | 852 | if __name__ == '__main__': | 
| Guido van Rossum | b72cf2d | 1997-04-09 17:32:51 +0000 | [diff] [blame] | 853 |     test() |