]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | import unittest\r |
2 | import pickle\r | |
3 | import cPickle\r | |
4 | import StringIO\r | |
5 | import cStringIO\r | |
6 | import pickletools\r | |
7 | import copy_reg\r | |
8 | \r | |
9 | from test.test_support import TestFailed, have_unicode, TESTFN\r | |
10 | \r | |
11 | # Tests that try a number of pickle protocols should have a\r | |
12 | # for proto in protocols:\r | |
13 | # kind of outer loop.\r | |
14 | assert pickle.HIGHEST_PROTOCOL == cPickle.HIGHEST_PROTOCOL == 2\r | |
15 | protocols = range(pickle.HIGHEST_PROTOCOL + 1)\r | |
16 | \r | |
17 | # Copy of test.test_support.run_with_locale. This is needed to support Python\r | |
18 | # 2.4, which didn't include it. This is all to support test_xpickle, which\r | |
19 | # bounces pickled objects through older Python versions to test backwards\r | |
20 | # compatibility.\r | |
21 | def run_with_locale(catstr, *locales):\r | |
22 | def decorator(func):\r | |
23 | def inner(*args, **kwds):\r | |
24 | try:\r | |
25 | import locale\r | |
26 | category = getattr(locale, catstr)\r | |
27 | orig_locale = locale.setlocale(category)\r | |
28 | except AttributeError:\r | |
29 | # if the test author gives us an invalid category string\r | |
30 | raise\r | |
31 | except:\r | |
32 | # cannot retrieve original locale, so do nothing\r | |
33 | locale = orig_locale = None\r | |
34 | else:\r | |
35 | for loc in locales:\r | |
36 | try:\r | |
37 | locale.setlocale(category, loc)\r | |
38 | break\r | |
39 | except:\r | |
40 | pass\r | |
41 | \r | |
42 | # now run the function, resetting the locale on exceptions\r | |
43 | try:\r | |
44 | return func(*args, **kwds)\r | |
45 | finally:\r | |
46 | if locale and orig_locale:\r | |
47 | locale.setlocale(category, orig_locale)\r | |
48 | inner.func_name = func.func_name\r | |
49 | inner.__doc__ = func.__doc__\r | |
50 | return inner\r | |
51 | return decorator\r | |
52 | \r | |
53 | \r | |
54 | # Return True if opcode code appears in the pickle, else False.\r | |
55 | def opcode_in_pickle(code, pickle):\r | |
56 | for op, dummy, dummy in pickletools.genops(pickle):\r | |
57 | if op.code == code:\r | |
58 | return True\r | |
59 | return False\r | |
60 | \r | |
61 | # Return the number of times opcode code appears in pickle.\r | |
62 | def count_opcode(code, pickle):\r | |
63 | n = 0\r | |
64 | for op, dummy, dummy in pickletools.genops(pickle):\r | |
65 | if op.code == code:\r | |
66 | n += 1\r | |
67 | return n\r | |
68 | \r | |
69 | # We can't very well test the extension registry without putting known stuff\r | |
70 | # in it, but we have to be careful to restore its original state. Code\r | |
71 | # should do this:\r | |
72 | #\r | |
73 | # e = ExtensionSaver(extension_code)\r | |
74 | # try:\r | |
75 | # fiddle w/ the extension registry's stuff for extension_code\r | |
76 | # finally:\r | |
77 | # e.restore()\r | |
78 | \r | |
79 | class ExtensionSaver:\r | |
80 | # Remember current registration for code (if any), and remove it (if\r | |
81 | # there is one).\r | |
82 | def __init__(self, code):\r | |
83 | self.code = code\r | |
84 | if code in copy_reg._inverted_registry:\r | |
85 | self.pair = copy_reg._inverted_registry[code]\r | |
86 | copy_reg.remove_extension(self.pair[0], self.pair[1], code)\r | |
87 | else:\r | |
88 | self.pair = None\r | |
89 | \r | |
90 | # Restore previous registration for code.\r | |
91 | def restore(self):\r | |
92 | code = self.code\r | |
93 | curpair = copy_reg._inverted_registry.get(code)\r | |
94 | if curpair is not None:\r | |
95 | copy_reg.remove_extension(curpair[0], curpair[1], code)\r | |
96 | pair = self.pair\r | |
97 | if pair is not None:\r | |
98 | copy_reg.add_extension(pair[0], pair[1], code)\r | |
99 | \r | |
100 | class C:\r | |
101 | def __cmp__(self, other):\r | |
102 | return cmp(self.__dict__, other.__dict__)\r | |
103 | \r | |
104 | import __main__\r | |
105 | __main__.C = C\r | |
106 | C.__module__ = "__main__"\r | |
107 | \r | |
108 | class myint(int):\r | |
109 | def __init__(self, x):\r | |
110 | self.str = str(x)\r | |
111 | \r | |
112 | class initarg(C):\r | |
113 | \r | |
114 | def __init__(self, a, b):\r | |
115 | self.a = a\r | |
116 | self.b = b\r | |
117 | \r | |
118 | def __getinitargs__(self):\r | |
119 | return self.a, self.b\r | |
120 | \r | |
121 | class metaclass(type):\r | |
122 | pass\r | |
123 | \r | |
124 | class use_metaclass(object):\r | |
125 | __metaclass__ = metaclass\r | |
126 | \r | |
127 | # DATA0 .. DATA2 are the pickles we expect under the various protocols, for\r | |
128 | # the object returned by create_data().\r | |
129 | \r | |
130 | # break into multiple strings to avoid confusing font-lock-mode\r | |
131 | DATA0 = """(lp1\r | |
132 | I0\r | |
133 | aL1L\r | |
134 | aF2\r | |
135 | ac__builtin__\r | |
136 | complex\r | |
137 | p2\r | |
138 | """ + \\r | |
139 | """(F3\r | |
140 | F0\r | |
141 | tRp3\r | |
142 | aI1\r | |
143 | aI-1\r | |
144 | aI255\r | |
145 | aI-255\r | |
146 | aI-256\r | |
147 | aI65535\r | |
148 | aI-65535\r | |
149 | aI-65536\r | |
150 | aI2147483647\r | |
151 | aI-2147483647\r | |
152 | aI-2147483648\r | |
153 | a""" + \\r | |
154 | """(S'abc'\r | |
155 | p4\r | |
156 | g4\r | |
157 | """ + \\r | |
158 | """(i__main__\r | |
159 | C\r | |
160 | p5\r | |
161 | """ + \\r | |
162 | """(dp6\r | |
163 | S'foo'\r | |
164 | p7\r | |
165 | I1\r | |
166 | sS'bar'\r | |
167 | p8\r | |
168 | I2\r | |
169 | sbg5\r | |
170 | tp9\r | |
171 | ag9\r | |
172 | aI5\r | |
173 | a.\r | |
174 | """\r | |
175 | \r | |
176 | # Disassembly of DATA0.\r | |
177 | DATA0_DIS = """\\r | |
178 | 0: ( MARK\r | |
179 | 1: l LIST (MARK at 0)\r | |
180 | 2: p PUT 1\r | |
181 | 5: I INT 0\r | |
182 | 8: a APPEND\r | |
183 | 9: L LONG 1L\r | |
184 | 13: a APPEND\r | |
185 | 14: F FLOAT 2.0\r | |
186 | 17: a APPEND\r | |
187 | 18: c GLOBAL '__builtin__ complex'\r | |
188 | 39: p PUT 2\r | |
189 | 42: ( MARK\r | |
190 | 43: F FLOAT 3.0\r | |
191 | 46: F FLOAT 0.0\r | |
192 | 49: t TUPLE (MARK at 42)\r | |
193 | 50: R REDUCE\r | |
194 | 51: p PUT 3\r | |
195 | 54: a APPEND\r | |
196 | 55: I INT 1\r | |
197 | 58: a APPEND\r | |
198 | 59: I INT -1\r | |
199 | 63: a APPEND\r | |
200 | 64: I INT 255\r | |
201 | 69: a APPEND\r | |
202 | 70: I INT -255\r | |
203 | 76: a APPEND\r | |
204 | 77: I INT -256\r | |
205 | 83: a APPEND\r | |
206 | 84: I INT 65535\r | |
207 | 91: a APPEND\r | |
208 | 92: I INT -65535\r | |
209 | 100: a APPEND\r | |
210 | 101: I INT -65536\r | |
211 | 109: a APPEND\r | |
212 | 110: I INT 2147483647\r | |
213 | 122: a APPEND\r | |
214 | 123: I INT -2147483647\r | |
215 | 136: a APPEND\r | |
216 | 137: I INT -2147483648\r | |
217 | 150: a APPEND\r | |
218 | 151: ( MARK\r | |
219 | 152: S STRING 'abc'\r | |
220 | 159: p PUT 4\r | |
221 | 162: g GET 4\r | |
222 | 165: ( MARK\r | |
223 | 166: i INST '__main__ C' (MARK at 165)\r | |
224 | 178: p PUT 5\r | |
225 | 181: ( MARK\r | |
226 | 182: d DICT (MARK at 181)\r | |
227 | 183: p PUT 6\r | |
228 | 186: S STRING 'foo'\r | |
229 | 193: p PUT 7\r | |
230 | 196: I INT 1\r | |
231 | 199: s SETITEM\r | |
232 | 200: S STRING 'bar'\r | |
233 | 207: p PUT 8\r | |
234 | 210: I INT 2\r | |
235 | 213: s SETITEM\r | |
236 | 214: b BUILD\r | |
237 | 215: g GET 5\r | |
238 | 218: t TUPLE (MARK at 151)\r | |
239 | 219: p PUT 9\r | |
240 | 222: a APPEND\r | |
241 | 223: g GET 9\r | |
242 | 226: a APPEND\r | |
243 | 227: I INT 5\r | |
244 | 230: a APPEND\r | |
245 | 231: . STOP\r | |
246 | highest protocol among opcodes = 0\r | |
247 | """\r | |
248 | \r | |
249 | DATA1 = (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'\r | |
250 | 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'\r | |
251 | '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'\r | |
252 | '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'\r | |
253 | 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'\r | |
254 | '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'\r | |
255 | 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'\r | |
256 | '\x06tq\nh\nK\x05e.'\r | |
257 | )\r | |
258 | \r | |
259 | # Disassembly of DATA1.\r | |
260 | DATA1_DIS = """\\r | |
261 | 0: ] EMPTY_LIST\r | |
262 | 1: q BINPUT 1\r | |
263 | 3: ( MARK\r | |
264 | 4: K BININT1 0\r | |
265 | 6: L LONG 1L\r | |
266 | 10: G BINFLOAT 2.0\r | |
267 | 19: c GLOBAL '__builtin__ complex'\r | |
268 | 40: q BINPUT 2\r | |
269 | 42: ( MARK\r | |
270 | 43: G BINFLOAT 3.0\r | |
271 | 52: G BINFLOAT 0.0\r | |
272 | 61: t TUPLE (MARK at 42)\r | |
273 | 62: R REDUCE\r | |
274 | 63: q BINPUT 3\r | |
275 | 65: K BININT1 1\r | |
276 | 67: J BININT -1\r | |
277 | 72: K BININT1 255\r | |
278 | 74: J BININT -255\r | |
279 | 79: J BININT -256\r | |
280 | 84: M BININT2 65535\r | |
281 | 87: J BININT -65535\r | |
282 | 92: J BININT -65536\r | |
283 | 97: J BININT 2147483647\r | |
284 | 102: J BININT -2147483647\r | |
285 | 107: J BININT -2147483648\r | |
286 | 112: ( MARK\r | |
287 | 113: U SHORT_BINSTRING 'abc'\r | |
288 | 118: q BINPUT 4\r | |
289 | 120: h BINGET 4\r | |
290 | 122: ( MARK\r | |
291 | 123: c GLOBAL '__main__ C'\r | |
292 | 135: q BINPUT 5\r | |
293 | 137: o OBJ (MARK at 122)\r | |
294 | 138: q BINPUT 6\r | |
295 | 140: } EMPTY_DICT\r | |
296 | 141: q BINPUT 7\r | |
297 | 143: ( MARK\r | |
298 | 144: U SHORT_BINSTRING 'foo'\r | |
299 | 149: q BINPUT 8\r | |
300 | 151: K BININT1 1\r | |
301 | 153: U SHORT_BINSTRING 'bar'\r | |
302 | 158: q BINPUT 9\r | |
303 | 160: K BININT1 2\r | |
304 | 162: u SETITEMS (MARK at 143)\r | |
305 | 163: b BUILD\r | |
306 | 164: h BINGET 6\r | |
307 | 166: t TUPLE (MARK at 112)\r | |
308 | 167: q BINPUT 10\r | |
309 | 169: h BINGET 10\r | |
310 | 171: K BININT1 5\r | |
311 | 173: e APPENDS (MARK at 3)\r | |
312 | 174: . STOP\r | |
313 | highest protocol among opcodes = 1\r | |
314 | """\r | |
315 | \r | |
316 | DATA2 = ('\x80\x02]q\x01(K\x00\x8a\x01\x01G@\x00\x00\x00\x00\x00\x00\x00'\r | |
317 | 'c__builtin__\ncomplex\nq\x02G@\x08\x00\x00\x00\x00\x00\x00G\x00'\r | |
318 | '\x00\x00\x00\x00\x00\x00\x00\x86Rq\x03K\x01J\xff\xff\xff\xffK'\r | |
319 | '\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xff'\r | |
320 | 'J\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00'\r | |
321 | '\x80(U\x03abcq\x04h\x04(c__main__\nC\nq\x05oq\x06}q\x07(U\x03foo'\r | |
322 | 'q\x08K\x01U\x03barq\tK\x02ubh\x06tq\nh\nK\x05e.')\r | |
323 | \r | |
324 | # Disassembly of DATA2.\r | |
325 | DATA2_DIS = """\\r | |
326 | 0: \x80 PROTO 2\r | |
327 | 2: ] EMPTY_LIST\r | |
328 | 3: q BINPUT 1\r | |
329 | 5: ( MARK\r | |
330 | 6: K BININT1 0\r | |
331 | 8: \x8a LONG1 1L\r | |
332 | 11: G BINFLOAT 2.0\r | |
333 | 20: c GLOBAL '__builtin__ complex'\r | |
334 | 41: q BINPUT 2\r | |
335 | 43: G BINFLOAT 3.0\r | |
336 | 52: G BINFLOAT 0.0\r | |
337 | 61: \x86 TUPLE2\r | |
338 | 62: R REDUCE\r | |
339 | 63: q BINPUT 3\r | |
340 | 65: K BININT1 1\r | |
341 | 67: J BININT -1\r | |
342 | 72: K BININT1 255\r | |
343 | 74: J BININT -255\r | |
344 | 79: J BININT -256\r | |
345 | 84: M BININT2 65535\r | |
346 | 87: J BININT -65535\r | |
347 | 92: J BININT -65536\r | |
348 | 97: J BININT 2147483647\r | |
349 | 102: J BININT -2147483647\r | |
350 | 107: J BININT -2147483648\r | |
351 | 112: ( MARK\r | |
352 | 113: U SHORT_BINSTRING 'abc'\r | |
353 | 118: q BINPUT 4\r | |
354 | 120: h BINGET 4\r | |
355 | 122: ( MARK\r | |
356 | 123: c GLOBAL '__main__ C'\r | |
357 | 135: q BINPUT 5\r | |
358 | 137: o OBJ (MARK at 122)\r | |
359 | 138: q BINPUT 6\r | |
360 | 140: } EMPTY_DICT\r | |
361 | 141: q BINPUT 7\r | |
362 | 143: ( MARK\r | |
363 | 144: U SHORT_BINSTRING 'foo'\r | |
364 | 149: q BINPUT 8\r | |
365 | 151: K BININT1 1\r | |
366 | 153: U SHORT_BINSTRING 'bar'\r | |
367 | 158: q BINPUT 9\r | |
368 | 160: K BININT1 2\r | |
369 | 162: u SETITEMS (MARK at 143)\r | |
370 | 163: b BUILD\r | |
371 | 164: h BINGET 6\r | |
372 | 166: t TUPLE (MARK at 112)\r | |
373 | 167: q BINPUT 10\r | |
374 | 169: h BINGET 10\r | |
375 | 171: K BININT1 5\r | |
376 | 173: e APPENDS (MARK at 5)\r | |
377 | 174: . STOP\r | |
378 | highest protocol among opcodes = 2\r | |
379 | """\r | |
380 | \r | |
381 | def create_data():\r | |
382 | c = C()\r | |
383 | c.foo = 1\r | |
384 | c.bar = 2\r | |
385 | x = [0, 1L, 2.0, 3.0+0j]\r | |
386 | # Append some integer test cases at cPickle.c's internal size\r | |
387 | # cutoffs.\r | |
388 | uint1max = 0xff\r | |
389 | uint2max = 0xffff\r | |
390 | int4max = 0x7fffffff\r | |
391 | x.extend([1, -1,\r | |
392 | uint1max, -uint1max, -uint1max-1,\r | |
393 | uint2max, -uint2max, -uint2max-1,\r | |
394 | int4max, -int4max, -int4max-1])\r | |
395 | y = ('abc', 'abc', c, c)\r | |
396 | x.append(y)\r | |
397 | x.append(y)\r | |
398 | x.append(5)\r | |
399 | return x\r | |
400 | \r | |
401 | class AbstractPickleTests(unittest.TestCase):\r | |
402 | # Subclass must define self.dumps, self.loads, self.error.\r | |
403 | \r | |
404 | _testdata = create_data()\r | |
405 | \r | |
406 | def setUp(self):\r | |
407 | pass\r | |
408 | \r | |
409 | def test_misc(self):\r | |
410 | # test various datatypes not tested by testdata\r | |
411 | for proto in protocols:\r | |
412 | x = myint(4)\r | |
413 | s = self.dumps(x, proto)\r | |
414 | y = self.loads(s)\r | |
415 | self.assertEqual(x, y)\r | |
416 | \r | |
417 | x = (1, ())\r | |
418 | s = self.dumps(x, proto)\r | |
419 | y = self.loads(s)\r | |
420 | self.assertEqual(x, y)\r | |
421 | \r | |
422 | x = initarg(1, x)\r | |
423 | s = self.dumps(x, proto)\r | |
424 | y = self.loads(s)\r | |
425 | self.assertEqual(x, y)\r | |
426 | \r | |
427 | # XXX test __reduce__ protocol?\r | |
428 | \r | |
429 | def test_roundtrip_equality(self):\r | |
430 | expected = self._testdata\r | |
431 | for proto in protocols:\r | |
432 | s = self.dumps(expected, proto)\r | |
433 | got = self.loads(s)\r | |
434 | self.assertEqual(expected, got)\r | |
435 | \r | |
436 | def test_load_from_canned_string(self):\r | |
437 | expected = self._testdata\r | |
438 | for canned in DATA0, DATA1, DATA2:\r | |
439 | got = self.loads(canned)\r | |
440 | self.assertEqual(expected, got)\r | |
441 | \r | |
442 | # There are gratuitous differences between pickles produced by\r | |
443 | # pickle and cPickle, largely because cPickle starts PUT indices at\r | |
444 | # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --\r | |
445 | # there's a comment with an exclamation point there whose meaning\r | |
446 | # is a mystery. cPickle also suppresses PUT for objects with a refcount\r | |
447 | # of 1.\r | |
448 | def dont_test_disassembly(self):\r | |
449 | from pickletools import dis\r | |
450 | \r | |
451 | for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):\r | |
452 | s = self.dumps(self._testdata, proto)\r | |
453 | filelike = cStringIO.StringIO()\r | |
454 | dis(s, out=filelike)\r | |
455 | got = filelike.getvalue()\r | |
456 | self.assertEqual(expected, got)\r | |
457 | \r | |
458 | def test_recursive_list(self):\r | |
459 | l = []\r | |
460 | l.append(l)\r | |
461 | for proto in protocols:\r | |
462 | s = self.dumps(l, proto)\r | |
463 | x = self.loads(s)\r | |
464 | self.assertEqual(len(x), 1)\r | |
465 | self.assertTrue(x is x[0])\r | |
466 | \r | |
467 | def test_recursive_tuple(self):\r | |
468 | t = ([],)\r | |
469 | t[0].append(t)\r | |
470 | for proto in protocols:\r | |
471 | s = self.dumps(t, proto)\r | |
472 | x = self.loads(s)\r | |
473 | self.assertEqual(len(x), 1)\r | |
474 | self.assertEqual(len(x[0]), 1)\r | |
475 | self.assertTrue(x is x[0][0])\r | |
476 | \r | |
477 | def test_recursive_dict(self):\r | |
478 | d = {}\r | |
479 | d[1] = d\r | |
480 | for proto in protocols:\r | |
481 | s = self.dumps(d, proto)\r | |
482 | x = self.loads(s)\r | |
483 | self.assertEqual(x.keys(), [1])\r | |
484 | self.assertTrue(x[1] is x)\r | |
485 | \r | |
486 | def test_recursive_inst(self):\r | |
487 | i = C()\r | |
488 | i.attr = i\r | |
489 | for proto in protocols:\r | |
490 | s = self.dumps(i, 2)\r | |
491 | x = self.loads(s)\r | |
492 | self.assertEqual(dir(x), dir(i))\r | |
493 | self.assertTrue(x.attr is x)\r | |
494 | \r | |
495 | def test_recursive_multi(self):\r | |
496 | l = []\r | |
497 | d = {1:l}\r | |
498 | i = C()\r | |
499 | i.attr = d\r | |
500 | l.append(i)\r | |
501 | for proto in protocols:\r | |
502 | s = self.dumps(l, proto)\r | |
503 | x = self.loads(s)\r | |
504 | self.assertEqual(len(x), 1)\r | |
505 | self.assertEqual(dir(x[0]), dir(i))\r | |
506 | self.assertEqual(x[0].attr.keys(), [1])\r | |
507 | self.assertTrue(x[0].attr[1] is x)\r | |
508 | \r | |
509 | def test_garyp(self):\r | |
510 | self.assertRaises(self.error, self.loads, 'garyp')\r | |
511 | \r | |
512 | def test_insecure_strings(self):\r | |
513 | insecure = ["abc", "2 + 2", # not quoted\r | |
514 | #"'abc' + 'def'", # not a single quoted string\r | |
515 | "'abc", # quote is not closed\r | |
516 | "'abc\"", # open quote and close quote don't match\r | |
517 | "'abc' ?", # junk after close quote\r | |
518 | "'\\'", # trailing backslash\r | |
519 | # some tests of the quoting rules\r | |
520 | #"'abc\"\''",\r | |
521 | #"'\\\\a\'\'\'\\\'\\\\\''",\r | |
522 | ]\r | |
523 | for s in insecure:\r | |
524 | buf = "S" + s + "\012p0\012."\r | |
525 | self.assertRaises(ValueError, self.loads, buf)\r | |
526 | \r | |
527 | if have_unicode:\r | |
528 | def test_unicode(self):\r | |
529 | endcases = [u'', u'<\\u>', u'<\\\u1234>', u'<\n>',\r | |
530 | u'<\\>', u'<\\\U00012345>']\r | |
531 | for proto in protocols:\r | |
532 | for u in endcases:\r | |
533 | p = self.dumps(u, proto)\r | |
534 | u2 = self.loads(p)\r | |
535 | self.assertEqual(u2, u)\r | |
536 | \r | |
537 | def test_unicode_high_plane(self):\r | |
538 | t = u'\U00012345'\r | |
539 | for proto in protocols:\r | |
540 | p = self.dumps(t, proto)\r | |
541 | t2 = self.loads(p)\r | |
542 | self.assertEqual(t2, t)\r | |
543 | \r | |
544 | def test_ints(self):\r | |
545 | import sys\r | |
546 | for proto in protocols:\r | |
547 | n = sys.maxint\r | |
548 | while n:\r | |
549 | for expected in (-n, n):\r | |
550 | s = self.dumps(expected, proto)\r | |
551 | n2 = self.loads(s)\r | |
552 | self.assertEqual(expected, n2)\r | |
553 | n = n >> 1\r | |
554 | \r | |
555 | def test_maxint64(self):\r | |
556 | maxint64 = (1L << 63) - 1\r | |
557 | data = 'I' + str(maxint64) + '\n.'\r | |
558 | got = self.loads(data)\r | |
559 | self.assertEqual(got, maxint64)\r | |
560 | \r | |
561 | # Try too with a bogus literal.\r | |
562 | data = 'I' + str(maxint64) + 'JUNK\n.'\r | |
563 | self.assertRaises(ValueError, self.loads, data)\r | |
564 | \r | |
565 | def test_long(self):\r | |
566 | for proto in protocols:\r | |
567 | # 256 bytes is where LONG4 begins.\r | |
568 | for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:\r | |
569 | nbase = 1L << nbits\r | |
570 | for npos in nbase-1, nbase, nbase+1:\r | |
571 | for n in npos, -npos:\r | |
572 | pickle = self.dumps(n, proto)\r | |
573 | got = self.loads(pickle)\r | |
574 | self.assertEqual(n, got)\r | |
575 | # Try a monster. This is quadratic-time in protos 0 & 1, so don't\r | |
576 | # bother with those.\r | |
577 | nbase = long("deadbeeffeedface", 16)\r | |
578 | nbase += nbase << 1000000\r | |
579 | for n in nbase, -nbase:\r | |
580 | p = self.dumps(n, 2)\r | |
581 | got = self.loads(p)\r | |
582 | self.assertEqual(n, got)\r | |
583 | \r | |
584 | def test_float(self):\r | |
585 | test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,\r | |
586 | 3.14, 263.44582062374053, 6.022e23, 1e30]\r | |
587 | test_values = test_values + [-x for x in test_values]\r | |
588 | for proto in protocols:\r | |
589 | for value in test_values:\r | |
590 | pickle = self.dumps(value, proto)\r | |
591 | got = self.loads(pickle)\r | |
592 | self.assertEqual(value, got)\r | |
593 | \r | |
594 | @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')\r | |
595 | def test_float_format(self):\r | |
596 | # make sure that floats are formatted locale independent\r | |
597 | self.assertEqual(self.dumps(1.2)[0:3], 'F1.')\r | |
598 | \r | |
599 | def test_reduce(self):\r | |
600 | pass\r | |
601 | \r | |
602 | def test_getinitargs(self):\r | |
603 | pass\r | |
604 | \r | |
605 | def test_metaclass(self):\r | |
606 | a = use_metaclass()\r | |
607 | for proto in protocols:\r | |
608 | s = self.dumps(a, proto)\r | |
609 | b = self.loads(s)\r | |
610 | self.assertEqual(a.__class__, b.__class__)\r | |
611 | \r | |
612 | def test_structseq(self):\r | |
613 | import time\r | |
614 | import os\r | |
615 | \r | |
616 | t = time.localtime()\r | |
617 | for proto in protocols:\r | |
618 | s = self.dumps(t, proto)\r | |
619 | u = self.loads(s)\r | |
620 | self.assertEqual(t, u)\r | |
621 | if hasattr(os, "stat"):\r | |
622 | t = os.stat(os.curdir)\r | |
623 | s = self.dumps(t, proto)\r | |
624 | u = self.loads(s)\r | |
625 | self.assertEqual(t, u)\r | |
626 | if hasattr(os, "statvfs"):\r | |
627 | t = os.statvfs(os.curdir)\r | |
628 | s = self.dumps(t, proto)\r | |
629 | u = self.loads(s)\r | |
630 | self.assertEqual(t, u)\r | |
631 | \r | |
632 | # Tests for protocol 2\r | |
633 | \r | |
634 | def test_proto(self):\r | |
635 | build_none = pickle.NONE + pickle.STOP\r | |
636 | for proto in protocols:\r | |
637 | expected = build_none\r | |
638 | if proto >= 2:\r | |
639 | expected = pickle.PROTO + chr(proto) + expected\r | |
640 | p = self.dumps(None, proto)\r | |
641 | self.assertEqual(p, expected)\r | |
642 | \r | |
643 | oob = protocols[-1] + 1 # a future protocol\r | |
644 | badpickle = pickle.PROTO + chr(oob) + build_none\r | |
645 | try:\r | |
646 | self.loads(badpickle)\r | |
647 | except ValueError, detail:\r | |
648 | self.assertTrue(str(detail).startswith(\r | |
649 | "unsupported pickle protocol"))\r | |
650 | else:\r | |
651 | self.fail("expected bad protocol number to raise ValueError")\r | |
652 | \r | |
653 | def test_long1(self):\r | |
654 | x = 12345678910111213141516178920L\r | |
655 | for proto in protocols:\r | |
656 | s = self.dumps(x, proto)\r | |
657 | y = self.loads(s)\r | |
658 | self.assertEqual(x, y)\r | |
659 | self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)\r | |
660 | \r | |
661 | def test_long4(self):\r | |
662 | x = 12345678910111213141516178920L << (256*8)\r | |
663 | for proto in protocols:\r | |
664 | s = self.dumps(x, proto)\r | |
665 | y = self.loads(s)\r | |
666 | self.assertEqual(x, y)\r | |
667 | self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)\r | |
668 | \r | |
669 | def test_short_tuples(self):\r | |
670 | # Map (proto, len(tuple)) to expected opcode.\r | |
671 | expected_opcode = {(0, 0): pickle.TUPLE,\r | |
672 | (0, 1): pickle.TUPLE,\r | |
673 | (0, 2): pickle.TUPLE,\r | |
674 | (0, 3): pickle.TUPLE,\r | |
675 | (0, 4): pickle.TUPLE,\r | |
676 | \r | |
677 | (1, 0): pickle.EMPTY_TUPLE,\r | |
678 | (1, 1): pickle.TUPLE,\r | |
679 | (1, 2): pickle.TUPLE,\r | |
680 | (1, 3): pickle.TUPLE,\r | |
681 | (1, 4): pickle.TUPLE,\r | |
682 | \r | |
683 | (2, 0): pickle.EMPTY_TUPLE,\r | |
684 | (2, 1): pickle.TUPLE1,\r | |
685 | (2, 2): pickle.TUPLE2,\r | |
686 | (2, 3): pickle.TUPLE3,\r | |
687 | (2, 4): pickle.TUPLE,\r | |
688 | }\r | |
689 | a = ()\r | |
690 | b = (1,)\r | |
691 | c = (1, 2)\r | |
692 | d = (1, 2, 3)\r | |
693 | e = (1, 2, 3, 4)\r | |
694 | for proto in protocols:\r | |
695 | for x in a, b, c, d, e:\r | |
696 | s = self.dumps(x, proto)\r | |
697 | y = self.loads(s)\r | |
698 | self.assertEqual(x, y, (proto, x, s, y))\r | |
699 | expected = expected_opcode[proto, len(x)]\r | |
700 | self.assertEqual(opcode_in_pickle(expected, s), True)\r | |
701 | \r | |
702 | def test_singletons(self):\r | |
703 | # Map (proto, singleton) to expected opcode.\r | |
704 | expected_opcode = {(0, None): pickle.NONE,\r | |
705 | (1, None): pickle.NONE,\r | |
706 | (2, None): pickle.NONE,\r | |
707 | \r | |
708 | (0, True): pickle.INT,\r | |
709 | (1, True): pickle.INT,\r | |
710 | (2, True): pickle.NEWTRUE,\r | |
711 | \r | |
712 | (0, False): pickle.INT,\r | |
713 | (1, False): pickle.INT,\r | |
714 | (2, False): pickle.NEWFALSE,\r | |
715 | }\r | |
716 | for proto in protocols:\r | |
717 | for x in None, False, True:\r | |
718 | s = self.dumps(x, proto)\r | |
719 | y = self.loads(s)\r | |
720 | self.assertTrue(x is y, (proto, x, s, y))\r | |
721 | expected = expected_opcode[proto, x]\r | |
722 | self.assertEqual(opcode_in_pickle(expected, s), True)\r | |
723 | \r | |
724 | def test_newobj_tuple(self):\r | |
725 | x = MyTuple([1, 2, 3])\r | |
726 | x.foo = 42\r | |
727 | x.bar = "hello"\r | |
728 | for proto in protocols:\r | |
729 | s = self.dumps(x, proto)\r | |
730 | y = self.loads(s)\r | |
731 | self.assertEqual(tuple(x), tuple(y))\r | |
732 | self.assertEqual(x.__dict__, y.__dict__)\r | |
733 | \r | |
734 | def test_newobj_list(self):\r | |
735 | x = MyList([1, 2, 3])\r | |
736 | x.foo = 42\r | |
737 | x.bar = "hello"\r | |
738 | for proto in protocols:\r | |
739 | s = self.dumps(x, proto)\r | |
740 | y = self.loads(s)\r | |
741 | self.assertEqual(list(x), list(y))\r | |
742 | self.assertEqual(x.__dict__, y.__dict__)\r | |
743 | \r | |
744 | def test_newobj_generic(self):\r | |
745 | for proto in protocols:\r | |
746 | for C in myclasses:\r | |
747 | B = C.__base__\r | |
748 | x = C(C.sample)\r | |
749 | x.foo = 42\r | |
750 | s = self.dumps(x, proto)\r | |
751 | y = self.loads(s)\r | |
752 | detail = (proto, C, B, x, y, type(y))\r | |
753 | self.assertEqual(B(x), B(y), detail)\r | |
754 | self.assertEqual(x.__dict__, y.__dict__, detail)\r | |
755 | \r | |
756 | # Register a type with copy_reg, with extension code extcode. Pickle\r | |
757 | # an object of that type. Check that the resulting pickle uses opcode\r | |
758 | # (EXT[124]) under proto 2, and not in proto 1.\r | |
759 | \r | |
760 | def produce_global_ext(self, extcode, opcode):\r | |
761 | e = ExtensionSaver(extcode)\r | |
762 | try:\r | |
763 | copy_reg.add_extension(__name__, "MyList", extcode)\r | |
764 | x = MyList([1, 2, 3])\r | |
765 | x.foo = 42\r | |
766 | x.bar = "hello"\r | |
767 | \r | |
768 | # Dump using protocol 1 for comparison.\r | |
769 | s1 = self.dumps(x, 1)\r | |
770 | self.assertIn(__name__, s1)\r | |
771 | self.assertIn("MyList", s1)\r | |
772 | self.assertEqual(opcode_in_pickle(opcode, s1), False)\r | |
773 | \r | |
774 | y = self.loads(s1)\r | |
775 | self.assertEqual(list(x), list(y))\r | |
776 | self.assertEqual(x.__dict__, y.__dict__)\r | |
777 | \r | |
778 | # Dump using protocol 2 for test.\r | |
779 | s2 = self.dumps(x, 2)\r | |
780 | self.assertNotIn(__name__, s2)\r | |
781 | self.assertNotIn("MyList", s2)\r | |
782 | self.assertEqual(opcode_in_pickle(opcode, s2), True)\r | |
783 | \r | |
784 | y = self.loads(s2)\r | |
785 | self.assertEqual(list(x), list(y))\r | |
786 | self.assertEqual(x.__dict__, y.__dict__)\r | |
787 | \r | |
788 | finally:\r | |
789 | e.restore()\r | |
790 | \r | |
791 | def test_global_ext1(self):\r | |
792 | self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code\r | |
793 | self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code\r | |
794 | \r | |
795 | def test_global_ext2(self):\r | |
796 | self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code\r | |
797 | self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code\r | |
798 | self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness\r | |
799 | \r | |
800 | def test_global_ext4(self):\r | |
801 | self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code\r | |
802 | self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code\r | |
803 | self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness\r | |
804 | \r | |
805 | def test_list_chunking(self):\r | |
806 | n = 10 # too small to chunk\r | |
807 | x = range(n)\r | |
808 | for proto in protocols:\r | |
809 | s = self.dumps(x, proto)\r | |
810 | y = self.loads(s)\r | |
811 | self.assertEqual(x, y)\r | |
812 | num_appends = count_opcode(pickle.APPENDS, s)\r | |
813 | self.assertEqual(num_appends, proto > 0)\r | |
814 | \r | |
815 | n = 2500 # expect at least two chunks when proto > 0\r | |
816 | x = range(n)\r | |
817 | for proto in protocols:\r | |
818 | s = self.dumps(x, proto)\r | |
819 | y = self.loads(s)\r | |
820 | self.assertEqual(x, y)\r | |
821 | num_appends = count_opcode(pickle.APPENDS, s)\r | |
822 | if proto == 0:\r | |
823 | self.assertEqual(num_appends, 0)\r | |
824 | else:\r | |
825 | self.assertTrue(num_appends >= 2)\r | |
826 | \r | |
827 | def test_dict_chunking(self):\r | |
828 | n = 10 # too small to chunk\r | |
829 | x = dict.fromkeys(range(n))\r | |
830 | for proto in protocols:\r | |
831 | s = self.dumps(x, proto)\r | |
832 | y = self.loads(s)\r | |
833 | self.assertEqual(x, y)\r | |
834 | num_setitems = count_opcode(pickle.SETITEMS, s)\r | |
835 | self.assertEqual(num_setitems, proto > 0)\r | |
836 | \r | |
837 | n = 2500 # expect at least two chunks when proto > 0\r | |
838 | x = dict.fromkeys(range(n))\r | |
839 | for proto in protocols:\r | |
840 | s = self.dumps(x, proto)\r | |
841 | y = self.loads(s)\r | |
842 | self.assertEqual(x, y)\r | |
843 | num_setitems = count_opcode(pickle.SETITEMS, s)\r | |
844 | if proto == 0:\r | |
845 | self.assertEqual(num_setitems, 0)\r | |
846 | else:\r | |
847 | self.assertTrue(num_setitems >= 2)\r | |
848 | \r | |
849 | def test_simple_newobj(self):\r | |
850 | x = object.__new__(SimpleNewObj) # avoid __init__\r | |
851 | x.abc = 666\r | |
852 | for proto in protocols:\r | |
853 | s = self.dumps(x, proto)\r | |
854 | self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s), proto >= 2)\r | |
855 | y = self.loads(s) # will raise TypeError if __init__ called\r | |
856 | self.assertEqual(y.abc, 666)\r | |
857 | self.assertEqual(x.__dict__, y.__dict__)\r | |
858 | \r | |
859 | def test_newobj_list_slots(self):\r | |
860 | x = SlotList([1, 2, 3])\r | |
861 | x.foo = 42\r | |
862 | x.bar = "hello"\r | |
863 | s = self.dumps(x, 2)\r | |
864 | y = self.loads(s)\r | |
865 | self.assertEqual(list(x), list(y))\r | |
866 | self.assertEqual(x.__dict__, y.__dict__)\r | |
867 | self.assertEqual(x.foo, y.foo)\r | |
868 | self.assertEqual(x.bar, y.bar)\r | |
869 | \r | |
870 | def test_reduce_overrides_default_reduce_ex(self):\r | |
871 | for proto in protocols:\r | |
872 | x = REX_one()\r | |
873 | self.assertEqual(x._reduce_called, 0)\r | |
874 | s = self.dumps(x, proto)\r | |
875 | self.assertEqual(x._reduce_called, 1)\r | |
876 | y = self.loads(s)\r | |
877 | self.assertEqual(y._reduce_called, 0)\r | |
878 | \r | |
879 | def test_reduce_ex_called(self):\r | |
880 | for proto in protocols:\r | |
881 | x = REX_two()\r | |
882 | self.assertEqual(x._proto, None)\r | |
883 | s = self.dumps(x, proto)\r | |
884 | self.assertEqual(x._proto, proto)\r | |
885 | y = self.loads(s)\r | |
886 | self.assertEqual(y._proto, None)\r | |
887 | \r | |
888 | def test_reduce_ex_overrides_reduce(self):\r | |
889 | for proto in protocols:\r | |
890 | x = REX_three()\r | |
891 | self.assertEqual(x._proto, None)\r | |
892 | s = self.dumps(x, proto)\r | |
893 | self.assertEqual(x._proto, proto)\r | |
894 | y = self.loads(s)\r | |
895 | self.assertEqual(y._proto, None)\r | |
896 | \r | |
897 | def test_reduce_ex_calls_base(self):\r | |
898 | for proto in protocols:\r | |
899 | x = REX_four()\r | |
900 | self.assertEqual(x._proto, None)\r | |
901 | s = self.dumps(x, proto)\r | |
902 | self.assertEqual(x._proto, proto)\r | |
903 | y = self.loads(s)\r | |
904 | self.assertEqual(y._proto, proto)\r | |
905 | \r | |
906 | def test_reduce_calls_base(self):\r | |
907 | for proto in protocols:\r | |
908 | x = REX_five()\r | |
909 | self.assertEqual(x._reduce_called, 0)\r | |
910 | s = self.dumps(x, proto)\r | |
911 | self.assertEqual(x._reduce_called, 1)\r | |
912 | y = self.loads(s)\r | |
913 | self.assertEqual(y._reduce_called, 1)\r | |
914 | \r | |
915 | def test_reduce_bad_iterator(self):\r | |
916 | # Issue4176: crash when 4th and 5th items of __reduce__()\r | |
917 | # are not iterators\r | |
918 | class C(object):\r | |
919 | def __reduce__(self):\r | |
920 | # 4th item is not an iterator\r | |
921 | return list, (), None, [], None\r | |
922 | class D(object):\r | |
923 | def __reduce__(self):\r | |
924 | # 5th item is not an iterator\r | |
925 | return dict, (), None, None, []\r | |
926 | \r | |
927 | # Protocol 0 is less strict and also accept iterables.\r | |
928 | for proto in protocols:\r | |
929 | try:\r | |
930 | self.dumps(C(), proto)\r | |
931 | except (AttributeError, pickle.PickleError, cPickle.PickleError):\r | |
932 | pass\r | |
933 | try:\r | |
934 | self.dumps(D(), proto)\r | |
935 | except (AttributeError, pickle.PickleError, cPickle.PickleError):\r | |
936 | pass\r | |
937 | \r | |
938 | def test_many_puts_and_gets(self):\r | |
939 | # Test that internal data structures correctly deal with lots of\r | |
940 | # puts/gets.\r | |
941 | keys = ("aaa" + str(i) for i in xrange(100))\r | |
942 | large_dict = dict((k, [4, 5, 6]) for k in keys)\r | |
943 | obj = [dict(large_dict), dict(large_dict), dict(large_dict)]\r | |
944 | \r | |
945 | for proto in protocols:\r | |
946 | dumped = self.dumps(obj, proto)\r | |
947 | loaded = self.loads(dumped)\r | |
948 | self.assertEqual(loaded, obj,\r | |
949 | "Failed protocol %d: %r != %r"\r | |
950 | % (proto, obj, loaded))\r | |
951 | \r | |
952 | def test_attribute_name_interning(self):\r | |
953 | # Test that attribute names of pickled objects are interned when\r | |
954 | # unpickling.\r | |
955 | for proto in protocols:\r | |
956 | x = C()\r | |
957 | x.foo = 42\r | |
958 | x.bar = "hello"\r | |
959 | s = self.dumps(x, proto)\r | |
960 | y = self.loads(s)\r | |
961 | x_keys = sorted(x.__dict__)\r | |
962 | y_keys = sorted(y.__dict__)\r | |
963 | for x_key, y_key in zip(x_keys, y_keys):\r | |
964 | self.assertIs(x_key, y_key)\r | |
965 | \r | |
966 | \r | |
967 | # Test classes for reduce_ex\r | |
968 | \r | |
969 | class REX_one(object):\r | |
970 | _reduce_called = 0\r | |
971 | def __reduce__(self):\r | |
972 | self._reduce_called = 1\r | |
973 | return REX_one, ()\r | |
974 | # No __reduce_ex__ here, but inheriting it from object\r | |
975 | \r | |
976 | class REX_two(object):\r | |
977 | _proto = None\r | |
978 | def __reduce_ex__(self, proto):\r | |
979 | self._proto = proto\r | |
980 | return REX_two, ()\r | |
981 | # No __reduce__ here, but inheriting it from object\r | |
982 | \r | |
983 | class REX_three(object):\r | |
984 | _proto = None\r | |
985 | def __reduce_ex__(self, proto):\r | |
986 | self._proto = proto\r | |
987 | return REX_two, ()\r | |
988 | def __reduce__(self):\r | |
989 | raise TestFailed, "This __reduce__ shouldn't be called"\r | |
990 | \r | |
991 | class REX_four(object):\r | |
992 | _proto = None\r | |
993 | def __reduce_ex__(self, proto):\r | |
994 | self._proto = proto\r | |
995 | return object.__reduce_ex__(self, proto)\r | |
996 | # Calling base class method should succeed\r | |
997 | \r | |
998 | class REX_five(object):\r | |
999 | _reduce_called = 0\r | |
1000 | def __reduce__(self):\r | |
1001 | self._reduce_called = 1\r | |
1002 | return object.__reduce__(self)\r | |
1003 | # This one used to fail with infinite recursion\r | |
1004 | \r | |
1005 | # Test classes for newobj\r | |
1006 | \r | |
1007 | class MyInt(int):\r | |
1008 | sample = 1\r | |
1009 | \r | |
1010 | class MyLong(long):\r | |
1011 | sample = 1L\r | |
1012 | \r | |
1013 | class MyFloat(float):\r | |
1014 | sample = 1.0\r | |
1015 | \r | |
1016 | class MyComplex(complex):\r | |
1017 | sample = 1.0 + 0.0j\r | |
1018 | \r | |
1019 | class MyStr(str):\r | |
1020 | sample = "hello"\r | |
1021 | \r | |
1022 | class MyUnicode(unicode):\r | |
1023 | sample = u"hello \u1234"\r | |
1024 | \r | |
1025 | class MyTuple(tuple):\r | |
1026 | sample = (1, 2, 3)\r | |
1027 | \r | |
1028 | class MyList(list):\r | |
1029 | sample = [1, 2, 3]\r | |
1030 | \r | |
1031 | class MyDict(dict):\r | |
1032 | sample = {"a": 1, "b": 2}\r | |
1033 | \r | |
1034 | myclasses = [MyInt, MyLong, MyFloat,\r | |
1035 | MyComplex,\r | |
1036 | MyStr, MyUnicode,\r | |
1037 | MyTuple, MyList, MyDict]\r | |
1038 | \r | |
1039 | \r | |
1040 | class SlotList(MyList):\r | |
1041 | __slots__ = ["foo"]\r | |
1042 | \r | |
1043 | class SimpleNewObj(object):\r | |
1044 | def __init__(self, a, b, c):\r | |
1045 | # raise an error, to make sure this isn't called\r | |
1046 | raise TypeError("SimpleNewObj.__init__() didn't expect to get called")\r | |
1047 | \r | |
1048 | class AbstractPickleModuleTests(unittest.TestCase):\r | |
1049 | \r | |
1050 | def test_dump_closed_file(self):\r | |
1051 | import os\r | |
1052 | f = open(TESTFN, "w")\r | |
1053 | try:\r | |
1054 | f.close()\r | |
1055 | self.assertRaises(ValueError, self.module.dump, 123, f)\r | |
1056 | finally:\r | |
1057 | os.remove(TESTFN)\r | |
1058 | \r | |
1059 | def test_load_closed_file(self):\r | |
1060 | import os\r | |
1061 | f = open(TESTFN, "w")\r | |
1062 | try:\r | |
1063 | f.close()\r | |
1064 | self.assertRaises(ValueError, self.module.dump, 123, f)\r | |
1065 | finally:\r | |
1066 | os.remove(TESTFN)\r | |
1067 | \r | |
1068 | def test_load_from_and_dump_to_file(self):\r | |
1069 | stream = cStringIO.StringIO()\r | |
1070 | data = [123, {}, 124]\r | |
1071 | self.module.dump(data, stream)\r | |
1072 | stream.seek(0)\r | |
1073 | unpickled = self.module.load(stream)\r | |
1074 | self.assertEqual(unpickled, data)\r | |
1075 | \r | |
1076 | def test_highest_protocol(self):\r | |
1077 | # Of course this needs to be changed when HIGHEST_PROTOCOL changes.\r | |
1078 | self.assertEqual(self.module.HIGHEST_PROTOCOL, 2)\r | |
1079 | \r | |
1080 | def test_callapi(self):\r | |
1081 | f = cStringIO.StringIO()\r | |
1082 | # With and without keyword arguments\r | |
1083 | self.module.dump(123, f, -1)\r | |
1084 | self.module.dump(123, file=f, protocol=-1)\r | |
1085 | self.module.dumps(123, -1)\r | |
1086 | self.module.dumps(123, protocol=-1)\r | |
1087 | self.module.Pickler(f, -1)\r | |
1088 | self.module.Pickler(f, protocol=-1)\r | |
1089 | \r | |
1090 | def test_incomplete_input(self):\r | |
1091 | s = StringIO.StringIO("X''.")\r | |
1092 | self.assertRaises(EOFError, self.module.load, s)\r | |
1093 | \r | |
1094 | def test_restricted(self):\r | |
1095 | # issue7128: cPickle failed in restricted mode\r | |
1096 | builtins = {self.module.__name__: self.module,\r | |
1097 | '__import__': __import__}\r | |
1098 | d = {}\r | |
1099 | teststr = "def f(): {0}.dumps(0)".format(self.module.__name__)\r | |
1100 | exec teststr in {'__builtins__': builtins}, d\r | |
1101 | d['f']()\r | |
1102 | \r | |
1103 | def test_bad_input(self):\r | |
1104 | # Test issue4298\r | |
1105 | s = '\x58\0\0\0\x54'\r | |
1106 | self.assertRaises(EOFError, self.module.loads, s)\r | |
1107 | # Test issue7455\r | |
1108 | s = '0'\r | |
1109 | # XXX Why doesn't pickle raise UnpicklingError?\r | |
1110 | self.assertRaises((IndexError, cPickle.UnpicklingError),\r | |
1111 | self.module.loads, s)\r | |
1112 | \r | |
1113 | class AbstractPersistentPicklerTests(unittest.TestCase):\r | |
1114 | \r | |
1115 | # This class defines persistent_id() and persistent_load()\r | |
1116 | # functions that should be used by the pickler. All even integers\r | |
1117 | # are pickled using persistent ids.\r | |
1118 | \r | |
1119 | def persistent_id(self, object):\r | |
1120 | if isinstance(object, int) and object % 2 == 0:\r | |
1121 | self.id_count += 1\r | |
1122 | return str(object)\r | |
1123 | else:\r | |
1124 | return None\r | |
1125 | \r | |
1126 | def persistent_load(self, oid):\r | |
1127 | self.load_count += 1\r | |
1128 | object = int(oid)\r | |
1129 | assert object % 2 == 0\r | |
1130 | return object\r | |
1131 | \r | |
1132 | def test_persistence(self):\r | |
1133 | self.id_count = 0\r | |
1134 | self.load_count = 0\r | |
1135 | L = range(10)\r | |
1136 | self.assertEqual(self.loads(self.dumps(L)), L)\r | |
1137 | self.assertEqual(self.id_count, 5)\r | |
1138 | self.assertEqual(self.load_count, 5)\r | |
1139 | \r | |
1140 | def test_bin_persistence(self):\r | |
1141 | self.id_count = 0\r | |
1142 | self.load_count = 0\r | |
1143 | L = range(10)\r | |
1144 | self.assertEqual(self.loads(self.dumps(L, 1)), L)\r | |
1145 | self.assertEqual(self.id_count, 5)\r | |
1146 | self.assertEqual(self.load_count, 5)\r | |
1147 | \r | |
1148 | class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):\r | |
1149 | \r | |
1150 | pickler_class = None\r | |
1151 | unpickler_class = None\r | |
1152 | \r | |
1153 | def setUp(self):\r | |
1154 | assert self.pickler_class\r | |
1155 | assert self.unpickler_class\r | |
1156 | \r | |
1157 | def test_clear_pickler_memo(self):\r | |
1158 | # To test whether clear_memo() has any effect, we pickle an object,\r | |
1159 | # then pickle it again without clearing the memo; the two serialized\r | |
1160 | # forms should be different. If we clear_memo() and then pickle the\r | |
1161 | # object again, the third serialized form should be identical to the\r | |
1162 | # first one we obtained.\r | |
1163 | data = ["abcdefg", "abcdefg", 44]\r | |
1164 | f = cStringIO.StringIO()\r | |
1165 | pickler = self.pickler_class(f)\r | |
1166 | \r | |
1167 | pickler.dump(data)\r | |
1168 | first_pickled = f.getvalue()\r | |
1169 | \r | |
1170 | # Reset StringIO object.\r | |
1171 | f.seek(0)\r | |
1172 | f.truncate()\r | |
1173 | \r | |
1174 | pickler.dump(data)\r | |
1175 | second_pickled = f.getvalue()\r | |
1176 | \r | |
1177 | # Reset the Pickler and StringIO objects.\r | |
1178 | pickler.clear_memo()\r | |
1179 | f.seek(0)\r | |
1180 | f.truncate()\r | |
1181 | \r | |
1182 | pickler.dump(data)\r | |
1183 | third_pickled = f.getvalue()\r | |
1184 | \r | |
1185 | self.assertNotEqual(first_pickled, second_pickled)\r | |
1186 | self.assertEqual(first_pickled, third_pickled)\r | |
1187 | \r | |
1188 | def test_priming_pickler_memo(self):\r | |
1189 | # Verify that we can set the Pickler's memo attribute.\r | |
1190 | data = ["abcdefg", "abcdefg", 44]\r | |
1191 | f = cStringIO.StringIO()\r | |
1192 | pickler = self.pickler_class(f)\r | |
1193 | \r | |
1194 | pickler.dump(data)\r | |
1195 | first_pickled = f.getvalue()\r | |
1196 | \r | |
1197 | f = cStringIO.StringIO()\r | |
1198 | primed = self.pickler_class(f)\r | |
1199 | primed.memo = pickler.memo\r | |
1200 | \r | |
1201 | primed.dump(data)\r | |
1202 | primed_pickled = f.getvalue()\r | |
1203 | \r | |
1204 | self.assertNotEqual(first_pickled, primed_pickled)\r | |
1205 | \r | |
1206 | def test_priming_unpickler_memo(self):\r | |
1207 | # Verify that we can set the Unpickler's memo attribute.\r | |
1208 | data = ["abcdefg", "abcdefg", 44]\r | |
1209 | f = cStringIO.StringIO()\r | |
1210 | pickler = self.pickler_class(f)\r | |
1211 | \r | |
1212 | pickler.dump(data)\r | |
1213 | first_pickled = f.getvalue()\r | |
1214 | \r | |
1215 | f = cStringIO.StringIO()\r | |
1216 | primed = self.pickler_class(f)\r | |
1217 | primed.memo = pickler.memo\r | |
1218 | \r | |
1219 | primed.dump(data)\r | |
1220 | primed_pickled = f.getvalue()\r | |
1221 | \r | |
1222 | unpickler = self.unpickler_class(cStringIO.StringIO(first_pickled))\r | |
1223 | unpickled_data1 = unpickler.load()\r | |
1224 | \r | |
1225 | self.assertEqual(unpickled_data1, data)\r | |
1226 | \r | |
1227 | primed = self.unpickler_class(cStringIO.StringIO(primed_pickled))\r | |
1228 | primed.memo = unpickler.memo\r | |
1229 | unpickled_data2 = primed.load()\r | |
1230 | \r | |
1231 | primed.memo.clear()\r | |
1232 | \r | |
1233 | self.assertEqual(unpickled_data2, data)\r | |
1234 | self.assertTrue(unpickled_data2 is unpickled_data1)\r | |
1235 | \r | |
1236 | def test_reusing_unpickler_objects(self):\r | |
1237 | data1 = ["abcdefg", "abcdefg", 44]\r | |
1238 | f = cStringIO.StringIO()\r | |
1239 | pickler = self.pickler_class(f)\r | |
1240 | pickler.dump(data1)\r | |
1241 | pickled1 = f.getvalue()\r | |
1242 | \r | |
1243 | data2 = ["abcdefg", 44, 44]\r | |
1244 | f = cStringIO.StringIO()\r | |
1245 | pickler = self.pickler_class(f)\r | |
1246 | pickler.dump(data2)\r | |
1247 | pickled2 = f.getvalue()\r | |
1248 | \r | |
1249 | f = cStringIO.StringIO()\r | |
1250 | f.write(pickled1)\r | |
1251 | f.seek(0)\r | |
1252 | unpickler = self.unpickler_class(f)\r | |
1253 | self.assertEqual(unpickler.load(), data1)\r | |
1254 | \r | |
1255 | f.seek(0)\r | |
1256 | f.truncate()\r | |
1257 | f.write(pickled2)\r | |
1258 | f.seek(0)\r | |
1259 | self.assertEqual(unpickler.load(), data2)\r |