blob: 249cc541c4244044184c9c98693a135de2049aff [file] [log] [blame]
Jeremy Hylton66426532001-10-15 21:38:56 +00001import unittest
Tim Peters4190fb82003-02-02 16:09:05 +00002import pickle
3
Guido van Rossum3b0a3292002-08-09 16:38:32 +00004from test.test_support import TestFailed, have_unicode, TESTFN
Tim Peterse089c682001-04-10 03:41:41 +00005
Tim Petersee1a53c2003-02-02 02:57:53 +00006# Tests that try a number of pickle protocols should have a
7# for proto in protocols:
8# kind of outer loop. Bump the 3 to 4 if/when protocol 3 is invented.
9protocols = range(3)
10
Jeremy Hylton66426532001-10-15 21:38:56 +000011class C:
12 def __cmp__(self, other):
13 return cmp(self.__dict__, other.__dict__)
14
15import __main__
16__main__.C = C
17C.__module__ = "__main__"
18
19class myint(int):
20 def __init__(self, x):
21 self.str = str(x)
22
23class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +000024
Jeremy Hylton66426532001-10-15 21:38:56 +000025 def __init__(self, a, b):
26 self.a = a
27 self.b = b
28
29 def __getinitargs__(self):
30 return self.a, self.b
31
Guido van Rossum04a86612001-12-19 16:58:54 +000032class metaclass(type):
33 pass
34
35class use_metaclass(object):
36 __metaclass__ = metaclass
37
Tim Peters70b02d72003-02-02 17:26:40 +000038# DATA0 .. DATA2 are the pickles we expect under the various protocols, for
39# the object returned by create_data().
40# XXX DATA2 doesn't exist yet, as it's not fully implemented in cPickle.
Tim Petersee1a53c2003-02-02 02:57:53 +000041
Jeremy Hylton66426532001-10-15 21:38:56 +000042# break into multiple strings to avoid confusing font-lock-mode
Tim Peters70b02d72003-02-02 17:26:40 +000043DATA0 = """(lp1
Tim Peterse9358162001-01-22 22:05:20 +000044I0
45aL1L
Tim Peters461922a2001-04-09 20:07:05 +000046aF2
Tim Peterse9358162001-01-22 22:05:20 +000047ac__builtin__
48complex
Tim Peters461922a2001-04-09 20:07:05 +000049p2
50""" + \
51"""(F3
52F0
53tRp3
54aI1
55aI-1
56aI255
57aI-255
58aI-256
59aI65535
60aI-65535
61aI-65536
62aI2147483647
63aI-2147483647
64aI-2147483648
65a""" + \
66"""(S'abc'
Tim Peterse9358162001-01-22 22:05:20 +000067p4
68g4
Tim Peters461922a2001-04-09 20:07:05 +000069""" + \
Guido van Rossum42f92da2001-04-16 00:28:21 +000070"""(i__main__
Tim Peterse9358162001-01-22 22:05:20 +000071C
72p5
Tim Peters461922a2001-04-09 20:07:05 +000073""" + \
Tim Peterse9358162001-01-22 22:05:20 +000074"""(dp6
75S'foo'
76p7
77I1
78sS'bar'
79p8
80I2
81sbg5
82tp9
83ag9
84aI5
85a.
86"""
87
Tim Peters70b02d72003-02-02 17:26:40 +000088# Disassembly of DATA0.
89DATA0_DIS = """\
90 0: ( MARK
91 1: l LIST (MARK at 0)
92 2: p PUT 1
93 5: I INT 0
94 8: a APPEND
95 9: L LONG 1L
96 13: a APPEND
97 14: F FLOAT 2.0
98 17: a APPEND
99 18: c GLOBAL '__builtin__ complex'
100 39: p PUT 2
101 42: ( MARK
102 43: F FLOAT 3.0
103 46: F FLOAT 0.0
104 49: t TUPLE (MARK at 42)
105 50: R REDUCE
106 51: p PUT 3
107 54: a APPEND
108 55: I INT 1
109 58: a APPEND
110 59: I INT -1
111 63: a APPEND
112 64: I INT 255
113 69: a APPEND
114 70: I INT -255
115 76: a APPEND
116 77: I INT -256
117 83: a APPEND
118 84: I INT 65535
119 91: a APPEND
120 92: I INT -65535
121 100: a APPEND
122 101: I INT -65536
123 109: a APPEND
124 110: I INT 2147483647
125 122: a APPEND
126 123: I INT -2147483647
127 136: a APPEND
128 137: I INT -2147483648
129 150: a APPEND
130 151: ( MARK
131 152: S STRING 'abc'
132 159: p PUT 4
133 162: g GET 4
134 165: ( MARK
135 166: i INST '__main__ C' (MARK at 165)
136 178: p PUT 5
137 181: ( MARK
138 182: d DICT (MARK at 181)
139 183: p PUT 6
140 186: S STRING 'foo'
141 193: p PUT 7
142 196: I INT 1
143 199: s SETITEM
144 200: S STRING 'bar'
145 207: p PUT 8
146 210: I INT 2
147 213: s SETITEM
148 214: b BUILD
149 215: g GET 5
150 218: t TUPLE (MARK at 151)
151 219: p PUT 9
152 222: a APPEND
153 223: g GET 9
154 226: a APPEND
155 227: I INT 5
156 230: a APPEND
157 231: . STOP
158highest protocol among opcodes = 0
159"""
160
161DATA1 = (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'
162 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'
163 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'
164 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'
165 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'
166 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'
167 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'
168 '\x06tq\nh\nK\x05e.'
169 )
170
171# Disassembly of DATA1.
172DATA1_DIS = """\
173 0: ] EMPTY_LIST
174 1: q BINPUT 1
175 3: ( MARK
176 4: K BININT1 0
177 6: L LONG 1L
178 10: G BINFLOAT 2.0
179 19: c GLOBAL '__builtin__ complex'
180 40: q BINPUT 2
181 42: ( MARK
182 43: G BINFLOAT 3.0
183 52: G BINFLOAT 0.0
184 61: t TUPLE (MARK at 42)
185 62: R REDUCE
186 63: q BINPUT 3
187 65: K BININT1 1
188 67: J BININT -1
189 72: K BININT1 255
190 74: J BININT -255
191 79: J BININT -256
192 84: M BININT2 65535
193 87: J BININT -65535
194 92: J BININT -65536
195 97: J BININT 2147483647
196 102: J BININT -2147483647
197 107: J BININT -2147483648
198 112: ( MARK
199 113: U SHORT_BINSTRING 'abc'
200 118: q BINPUT 4
201 120: h BINGET 4
202 122: ( MARK
203 123: c GLOBAL '__main__ C'
204 135: q BINPUT 5
205 137: o OBJ (MARK at 122)
206 138: q BINPUT 6
207 140: } EMPTY_DICT
208 141: q BINPUT 7
209 143: ( MARK
210 144: U SHORT_BINSTRING 'foo'
211 149: q BINPUT 8
212 151: K BININT1 1
213 153: U SHORT_BINSTRING 'bar'
214 158: q BINPUT 9
215 160: K BININT1 2
216 162: u SETITEMS (MARK at 143)
217 163: b BUILD
218 164: h BINGET 6
219 166: t TUPLE (MARK at 112)
220 167: q BINPUT 10
221 169: h BINGET 10
222 171: K BININT1 5
223 173: e APPENDS (MARK at 3)
224 174: . STOP
225highest protocol among opcodes = 1
226"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000227
Jeremy Hylton66426532001-10-15 21:38:56 +0000228def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000229 c = C()
230 c.foo = 1
231 c.bar = 2
232 x = [0, 1L, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000233 # Append some integer test cases at cPickle.c's internal size
234 # cutoffs.
235 uint1max = 0xff
236 uint2max = 0xffff
237 int4max = 0x7fffffff
238 x.extend([1, -1,
239 uint1max, -uint1max, -uint1max-1,
240 uint2max, -uint2max, -uint2max-1,
241 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000242 y = ('abc', 'abc', c, c)
243 x.append(y)
244 x.append(y)
245 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000246 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000247
Jeremy Hylton66426532001-10-15 21:38:56 +0000248class AbstractPickleTests(unittest.TestCase):
Tim Peters70b02d72003-02-02 17:26:40 +0000249 # Subclass must define self.dumps, self.loads, self.error.
Tim Petersc58440f2001-04-09 17:16:31 +0000250
Jeremy Hylton66426532001-10-15 21:38:56 +0000251 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000252
Jeremy Hylton66426532001-10-15 21:38:56 +0000253 def setUp(self):
Tim Peterse9358162001-01-22 22:05:20 +0000254 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000255
Jeremy Hylton66426532001-10-15 21:38:56 +0000256 def test_misc(self):
257 # test various datatypes not tested by testdata
Tim Peters70b02d72003-02-02 17:26:40 +0000258 for proto in protocols:
259 x = myint(4)
260 s = self.dumps(x, proto)
261 y = self.loads(s)
262 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000263
Tim Peters70b02d72003-02-02 17:26:40 +0000264 x = (1, ())
265 s = self.dumps(x, proto)
266 y = self.loads(s)
267 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000268
Tim Peters70b02d72003-02-02 17:26:40 +0000269 x = initarg(1, x)
270 s = self.dumps(x, proto)
271 y = self.loads(s)
272 self.assertEqual(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000273
Jeremy Hylton66426532001-10-15 21:38:56 +0000274 # XXX test __reduce__ protocol?
275
Tim Peters70b02d72003-02-02 17:26:40 +0000276 def test_roundtrip_equality(self):
277 expected = self._testdata
278 for proto in protocols:
279 s = self.dumps(expected, proto)
280 got = self.loads(s)
281 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000282
Tim Peters70b02d72003-02-02 17:26:40 +0000283 def test_load_from_canned_string(self):
284 expected = self._testdata
285 for canned in DATA0, DATA1:
286 got = self.loads(canned)
287 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000288
Tim Peters70b02d72003-02-02 17:26:40 +0000289 # There are gratuitous differences between pickles produced by
290 # pickle and cPickle, largely because cPickle starts PUT indices at
291 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
292 # there's a comment with an exclamation point there whose meaning
293 # is a mystery. cPickle also suppresses PUT for objects with a refcount
294 # of 1.
295 def dont_test_disassembly(self):
296 from cStringIO import StringIO
297 from pickletools import dis
298
299 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
300 s = self.dumps(self._testdata, proto)
301 filelike = StringIO()
302 dis(s, out=filelike)
303 got = filelike.getvalue()
304 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000305
306 def test_recursive_list(self):
307 l = []
308 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +0000309 for proto in protocols:
310 s = self.dumps(l, proto)
311 x = self.loads(s)
312 self.assertEqual(x, l)
313 self.assertEqual(x, x[0])
314 self.assertEqual(id(x), id(x[0]))
Jeremy Hylton66426532001-10-15 21:38:56 +0000315
316 def test_recursive_dict(self):
317 d = {}
318 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +0000319 for proto in protocols:
320 s = self.dumps(d, proto)
321 x = self.loads(s)
322 self.assertEqual(x, d)
323 self.assertEqual(x[1], x)
324 self.assertEqual(id(x[1]), id(x))
Jeremy Hylton66426532001-10-15 21:38:56 +0000325
326 def test_recursive_inst(self):
327 i = C()
328 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +0000329 for proto in protocols:
330 s = self.dumps(i, 2)
331 x = self.loads(s)
332 self.assertEqual(x, i)
333 self.assertEqual(x.attr, x)
334 self.assertEqual(id(x.attr), id(x))
Jeremy Hylton66426532001-10-15 21:38:56 +0000335
336 def test_recursive_multi(self):
337 l = []
338 d = {1:l}
339 i = C()
340 i.attr = d
341 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +0000342 for proto in protocols:
343 s = self.dumps(l, proto)
344 x = self.loads(s)
345 self.assertEqual(x, l)
346 self.assertEqual(x[0], i)
347 self.assertEqual(x[0].attr, d)
348 self.assertEqual(x[0].attr[1], x)
349 self.assertEqual(x[0].attr[1][0], i)
350 self.assertEqual(x[0].attr[1][0].attr, d)
Jeremy Hylton66426532001-10-15 21:38:56 +0000351
352 def test_garyp(self):
353 self.assertRaises(self.error, self.loads, 'garyp')
354
355 def test_insecure_strings(self):
356 insecure = ["abc", "2 + 2", # not quoted
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000357 #"'abc' + 'def'", # not a single quoted string
Jeremy Hylton66426532001-10-15 21:38:56 +0000358 "'abc", # quote is not closed
359 "'abc\"", # open quote and close quote don't match
360 "'abc' ?", # junk after close quote
Martin v. Löwiseb3f00a2002-08-14 08:22:50 +0000361 "'\\'", # trailing backslash
Jeremy Hylton66426532001-10-15 21:38:56 +0000362 # some tests of the quoting rules
Martin v. Löwis8a8da792002-08-14 07:46:28 +0000363 #"'abc\"\''",
364 #"'\\\\a\'\'\'\\\'\\\\\''",
Jeremy Hylton66426532001-10-15 21:38:56 +0000365 ]
366 for s in insecure:
367 buf = "S" + s + "\012p0\012."
368 self.assertRaises(ValueError, self.loads, buf)
369
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000370 if have_unicode:
Jeremy Hylton66426532001-10-15 21:38:56 +0000371 def test_unicode(self):
372 endcases = [unicode(''), unicode('<\\u>'), unicode('<\\\u1234>'),
373 unicode('<\n>'), unicode('<\\>')]
Tim Petersee1a53c2003-02-02 02:57:53 +0000374 for proto in protocols:
375 for u in endcases:
376 p = self.dumps(u, proto)
377 u2 = self.loads(p)
378 self.assertEqual(u2, u)
Tim Peterse089c682001-04-10 03:41:41 +0000379
Jeremy Hylton66426532001-10-15 21:38:56 +0000380 def test_ints(self):
381 import sys
Tim Petersee1a53c2003-02-02 02:57:53 +0000382 for proto in protocols:
383 n = sys.maxint
384 while n:
385 for expected in (-n, n):
386 s = self.dumps(expected, proto)
387 n2 = self.loads(s)
388 self.assertEqual(expected, n2)
389 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000390
Jeremy Hylton66426532001-10-15 21:38:56 +0000391 def test_maxint64(self):
392 maxint64 = (1L << 63) - 1
393 data = 'I' + str(maxint64) + '\n.'
394 got = self.loads(data)
395 self.assertEqual(got, maxint64)
396
397 # Try too with a bogus literal.
398 data = 'I' + str(maxint64) + 'JUNK\n.'
399 self.assertRaises(ValueError, self.loads, data)
400
Tim Petersee1a53c2003-02-02 02:57:53 +0000401 def test_long(self):
402 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +0000403 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +0000404 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
405 nbase = 1L << nbits
406 for npos in nbase-1, nbase, nbase+1:
407 for n in npos, -npos:
408 pickle = self.dumps(n, proto)
409 got = self.loads(pickle)
410 self.assertEqual(n, got)
411 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
412 # bother with those.
Tim Petersee1a53c2003-02-02 02:57:53 +0000413 nbase = long("deadbeeffeedface", 16)
414 nbase += nbase << 1000000
415 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +0000416 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000417 got = self.loads(p)
Tim Petersee1a53c2003-02-02 02:57:53 +0000418 self.assertEqual(n, got)
419
Jeremy Hylton66426532001-10-15 21:38:56 +0000420 def test_reduce(self):
Tim Peters19ef62d2001-08-28 22:21:18 +0000421 pass
Jeremy Hylton66426532001-10-15 21:38:56 +0000422
423 def test_getinitargs(self):
424 pass
425
Guido van Rossum04a86612001-12-19 16:58:54 +0000426 def test_metaclass(self):
427 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +0000428 for proto in protocols:
429 s = self.dumps(a, proto)
430 b = self.loads(s)
431 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +0000432
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000433 def test_structseq(self):
434 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +0000435 import os
Tim Peters70b02d72003-02-02 17:26:40 +0000436
437 t = time.localtime()
438 for proto in protocols:
439 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000440 u = self.loads(s)
441 self.assertEqual(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000442 if hasattr(os, "stat"):
443 t = os.stat(os.curdir)
444 s = self.dumps(t, proto)
445 u = self.loads(s)
446 self.assertEqual(t, u)
447 if hasattr(os, "statvfs"):
448 t = os.statvfs(os.curdir)
449 s = self.dumps(t, proto)
450 u = self.loads(s)
451 self.assertEqual(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000452
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000453 # Tests for protocol 2
454
Tim Peters4190fb82003-02-02 16:09:05 +0000455 def test_proto(self):
456 build_none = pickle.NONE + pickle.STOP
457 for proto in protocols:
458 expected = build_none
459 if proto >= 2:
460 expected = pickle.PROTO + chr(proto) + expected
461 p = self.dumps(None, proto)
462 self.assertEqual(p, expected)
463
464 oob = protocols[-1] + 1 # a future protocol
465 badpickle = pickle.PROTO + chr(oob) + build_none
466 try:
467 self.loads(badpickle)
468 except ValueError, detail:
469 self.failUnless(str(detail).startswith(
470 "unsupported pickle protocol"))
471 else:
472 self.fail("expected bad protocol number to raise ValueError")
473
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000474 def test_long1(self):
475 x = 12345678910111213141516178920L
476 s = self.dumps(x, 2)
477 y = self.loads(s)
478 self.assertEqual(x, y)
479
480 def test_long4(self):
481 x = 12345678910111213141516178920L << (256*8)
482 s = self.dumps(x, 2)
483 y = self.loads(s)
484 self.assertEqual(x, y)
485
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000486 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +0000487 # Map (proto, len(tuple)) to expected opcode.
488 expected_opcode = {(0, 0): pickle.TUPLE,
489 (0, 1): pickle.TUPLE,
490 (0, 2): pickle.TUPLE,
491 (0, 3): pickle.TUPLE,
492 (0, 4): pickle.TUPLE,
493
494 (1, 0): pickle.EMPTY_TUPLE,
495 (1, 1): pickle.TUPLE,
496 (1, 2): pickle.TUPLE,
497 (1, 3): pickle.TUPLE,
498 (1, 4): pickle.TUPLE,
499
500 (2, 0): pickle.EMPTY_TUPLE,
501 (2, 1): pickle.TUPLE1,
502 (2, 2): pickle.TUPLE2,
503 (2, 3): pickle.TUPLE3,
504 (2, 4): pickle.TUPLE,
505 }
506 all_tuple_opcodes = (pickle.TUPLE, pickle.EMPTY_TUPLE,
507 pickle.TUPLE1, pickle.TUPLE2, pickle.TUPLE3)
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000508 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000509 b = (1,)
510 c = (1, 2)
511 d = (1, 2, 3)
512 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +0000513 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000514 for x in a, b, c, d, e:
515 s = self.dumps(x, proto)
516 y = self.loads(s)
517 self.assertEqual(x, y, (proto, x, s, y))
518
Tim Peters1d63c9f2003-02-02 20:29:39 +0000519 # Verify that the protocol-correct tuple-building opcode
520 # was generated.
521 expected = expected_opcode[proto, len(x)]
522 for opcode in s:
523 if opcode in all_tuple_opcodes:
524 self.assertEqual(expected, opcode)
525 break
526 else:
527 self.fail("didn't find a tuple-building opcode in pickle")
528
Guido van Rossum7d97d312003-01-28 04:25:27 +0000529 def test_singletons(self):
Tim Peters4190fb82003-02-02 16:09:05 +0000530 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +0000531 for x in None, False, True:
532 s = self.dumps(x, proto)
533 y = self.loads(s)
534 self.assert_(x is y, (proto, x, s, y))
535
Tim Peters3c67d792003-02-02 17:59:11 +0000536 # Test that proto >= 2 really uses the bool opcodes.
537 if proto >= 2 and x in (False, True):
538 expected = x and pickle.NEWTRUE or pickle.NEWFALSE
539 # Skip the PROTO opcode at the start.
540 self.assertEqual(s[2], expected)
541
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000542 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000543 x = MyTuple([1, 2, 3])
544 x.foo = 42
545 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000546 s = self.dumps(x, 2)
547 y = self.loads(s)
548 self.assertEqual(tuple(x), tuple(y))
549 self.assertEqual(x.__dict__, y.__dict__)
550
551 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000552 x = MyList([1, 2, 3])
553 x.foo = 42
554 x.bar = "hello"
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000555 s = self.dumps(x, 2)
556 y = self.loads(s)
557 self.assertEqual(list(x), list(y))
558 self.assertEqual(x.__dict__, y.__dict__)
559
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000560 def test_newobj_generic(self):
561 for proto in [0, 1, 2]:
562 for C in myclasses:
563 B = C.__base__
564 x = C(C.sample)
565 x.foo = 42
566 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000567 y = self.loads(s)
568 detail = (proto, C, B, x, y, type(y))
569 self.assertEqual(B(x), B(y), detail)
570 self.assertEqual(x.__dict__, y.__dict__, detail)
571
Tim Peters47a6b132003-01-28 22:34:11 +0000572# XXX Temporary hack, so long as the C implementation of pickle protocol
573# XXX 2 isn't ready. When it is, move the methods in TempAbstractPickleTests
574# XXX into AbstractPickleTests above, and get rid of TempAbstractPickleTests
575# XXX along with the references to it in test_pickle.py.
576class TempAbstractPickleTests(unittest.TestCase):
577
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000578 def test_newobj_list_slots(self):
579 x = SlotList([1, 2, 3])
580 x.foo = 42
581 x.bar = "hello"
582 s = self.dumps(x, 2)
583 y = self.loads(s)
584 self.assertEqual(list(x), list(y))
585 self.assertEqual(x.__dict__, y.__dict__)
586 self.assertEqual(x.foo, y.foo)
587 self.assertEqual(x.bar, y.bar)
588## import pickletools
589## print
590## pickletools.dis(s)
591
Guido van Rossum0322d0f2003-01-29 06:12:46 +0000592 def test_global_ext1(self):
593 import copy_reg
594 copy_reg.add_extension(__name__, "MyList", 0xf0)
595 try:
596 x = MyList([1, 2, 3])
597 x.foo = 42
598 x.bar = "hello"
599
600 # Dump using protocol 1 for comparison
601 s1 = self.dumps(x, 1)
602 y = self.loads(s1)
603 self.assertEqual(list(x), list(y))
604 self.assertEqual(x.__dict__, y.__dict__)
605 self.assert_(s1.find(__name__) >= 0)
606 self.assert_(s1.find("MyList") >= 0)
607## import pickletools
608## print
609## pickletools.dis(s1)
610
611 # Dump using protocol 2 for test
612 s2 = self.dumps(x, 2)
613 self.assertEqual(s2.find(__name__), -1)
614 self.assertEqual(s2.find("MyList"), -1)
615 y = self.loads(s2)
616 self.assertEqual(list(x), list(y))
617 self.assertEqual(x.__dict__, y.__dict__)
618## import pickletools
619## print
620## pickletools.dis(s2)
621
622 finally:
623 copy_reg.remove_extension(__name__, "MyList", 0xf0)
624
625 def test_global_ext2(self):
626 import copy_reg
627 copy_reg.add_extension(__name__, "MyList", 0xfff0)
628 try:
629 x = MyList()
630 s2 = self.dumps(x, 2)
631 self.assertEqual(s2.find(__name__), -1)
632 self.assertEqual(s2.find("MyList"), -1)
633 y = self.loads(s2)
634 self.assertEqual(list(x), list(y))
635 self.assertEqual(x.__dict__, y.__dict__)
636 finally:
637 copy_reg.remove_extension(__name__, "MyList", 0xfff0)
638
639 def test_global_ext4(self):
640 import copy_reg
641 copy_reg.add_extension(__name__, "MyList", 0xfffff0)
642 try:
643 x = MyList()
644 s2 = self.dumps(x, 2)
645 self.assertEqual(s2.find(__name__), -1)
646 self.assertEqual(s2.find("MyList"), -1)
647 y = self.loads(s2)
648 self.assertEqual(list(x), list(y))
649 self.assertEqual(x.__dict__, y.__dict__)
650 finally:
651 copy_reg.remove_extension(__name__, "MyList", 0xfffff0)
652
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000653class MyInt(int):
654 sample = 1
655
656class MyLong(long):
657 sample = 1L
658
659class MyFloat(float):
660 sample = 1.0
661
662class MyComplex(complex):
663 sample = 1.0 + 0.0j
664
665class MyStr(str):
666 sample = "hello"
667
668class MyUnicode(unicode):
669 sample = u"hello \u1234"
670
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000671class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000672 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000673
674class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +0000675 sample = [1, 2, 3]
676
677class MyDict(dict):
678 sample = {"a": 1, "b": 2}
679
680myclasses = [MyInt, MyLong, MyFloat,
681 # MyComplex, # XXX complex somehow doesn't work here :-(
682 MyStr, MyUnicode,
683 MyTuple, MyList, MyDict]
684
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000685
Guido van Rossumc8d6ef52003-01-28 22:02:31 +0000686class SlotList(MyList):
687 __slots__ = ["foo"]
688
Jeremy Hylton66426532001-10-15 21:38:56 +0000689class AbstractPickleModuleTests(unittest.TestCase):
690
691 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000692 import os
693 f = open(TESTFN, "w")
694 try:
695 f.close()
696 self.assertRaises(ValueError, self.module.dump, 123, f)
697 finally:
698 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +0000699
700 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +0000701 import os
702 f = open(TESTFN, "w")
703 try:
704 f.close()
705 self.assertRaises(ValueError, self.module.dump, 123, f)
706 finally:
707 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +0000708
709class AbstractPersistentPicklerTests(unittest.TestCase):
710
711 # This class defines persistent_id() and persistent_load()
712 # functions that should be used by the pickler. All even integers
713 # are pickled using persistent ids.
714
715 def persistent_id(self, object):
716 if isinstance(object, int) and object % 2 == 0:
717 self.id_count += 1
718 return str(object)
719 else:
720 return None
721
722 def persistent_load(self, oid):
723 self.load_count += 1
724 object = int(oid)
725 assert object % 2 == 0
726 return object
727
728 def test_persistence(self):
729 self.id_count = 0
730 self.load_count = 0
731 L = range(10)
732 self.assertEqual(self.loads(self.dumps(L)), L)
733 self.assertEqual(self.id_count, 5)
734 self.assertEqual(self.load_count, 5)
735
736 def test_bin_persistence(self):
737 self.id_count = 0
738 self.load_count = 0
739 L = range(10)
740 self.assertEqual(self.loads(self.dumps(L, 1)), L)
741 self.assertEqual(self.id_count, 5)
742 self.assertEqual(self.load_count, 5)