blob: f8372e32e6117860a08d52c0f63c0739ea909e21 [file] [log] [blame]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001import copyreg
Collin Winter771d8342009-04-16 03:18:06 +00002import io
Tim Peters4190fb82003-02-02 16:09:05 +00003import pickle
Tim Peters31f119e2003-02-03 16:20:13 +00004import pickletools
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01005import random
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08006import struct
Antoine Pitrou82be19f2011-08-29 23:09:33 +02007import sys
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01008import unittest
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01009import weakref
Antoine Pitroud9dfaa92009-06-04 20:32:06 +000010from http.cookies import SimpleCookie
Tim Peters4190fb82003-02-02 16:09:05 +000011
Antoine Pitrou82be19f2011-08-29 23:09:33 +020012from test.support import (
Antoine Pitrouee763e22011-08-29 23:14:53 +020013 TestFailed, TESTFN, run_with_locale, no_tracing,
Antoine Pitrou94190bb2011-10-04 10:22:36 +020014 _2G, _4G, bigmemtest,
Antoine Pitrou82be19f2011-08-29 23:09:33 +020015 )
Tim Peterse089c682001-04-10 03:41:41 +000016
Guido van Rossum98297ee2007-11-06 21:34:58 +000017from pickle import bytes_types
18
Tim Petersee1a53c2003-02-02 02:57:53 +000019# Tests that try a number of pickle protocols should have a
20# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000021# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000022protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000023
Tim Peters22e71712003-02-03 22:27:38 +000024
25# Return True if opcode code appears in the pickle, else False.
26def opcode_in_pickle(code, pickle):
27 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000028 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000029 return True
30 return False
31
Tim Peters8d2613a2003-02-11 16:40:16 +000032# Return the number of times opcode code appears in pickle.
33def count_opcode(code, pickle):
34 n = 0
35 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000036 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000037 n += 1
38 return n
39
Antoine Pitrou04248a82010-10-12 20:51:21 +000040
41class UnseekableIO(io.BytesIO):
42 def peek(self, *args):
43 raise NotImplementedError
44
45 def seekable(self):
46 return False
47
48 def seek(self, *args):
49 raise io.UnsupportedOperation
50
51 def tell(self):
52 raise io.UnsupportedOperation
53
54
Tim Peters3e667d52003-02-04 21:47:44 +000055# We can't very well test the extension registry without putting known stuff
56# in it, but we have to be careful to restore its original state. Code
57# should do this:
58#
59# e = ExtensionSaver(extension_code)
60# try:
61# fiddle w/ the extension registry's stuff for extension_code
62# finally:
63# e.restore()
64
65class ExtensionSaver:
66 # Remember current registration for code (if any), and remove it (if
67 # there is one).
68 def __init__(self, code):
69 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000070 if code in copyreg._inverted_registry:
71 self.pair = copyreg._inverted_registry[code]
72 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000073 else:
74 self.pair = None
75
76 # Restore previous registration for code.
77 def restore(self):
78 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000079 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +000080 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000081 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000082 pair = self.pair
83 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000084 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000085
Jeremy Hylton66426532001-10-15 21:38:56 +000086class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +000087 def __eq__(self, other):
88 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +000089
Alexander Belopolskyd92f0402010-07-17 22:50:45 +000090class D(C):
91 def __init__(self, arg):
92 pass
93
94class E(C):
95 def __getinitargs__(self):
96 return ()
97
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +010098class H(object):
99 pass
100
Jeremy Hylton66426532001-10-15 21:38:56 +0000101import __main__
102__main__.C = C
103C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000104__main__.D = D
105D.__module__ = "__main__"
106__main__.E = E
107E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100108__main__.H = H
109H.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000110
111class myint(int):
112 def __init__(self, x):
113 self.str = str(x)
114
115class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000116
Jeremy Hylton66426532001-10-15 21:38:56 +0000117 def __init__(self, a, b):
118 self.a = a
119 self.b = b
120
121 def __getinitargs__(self):
122 return self.a, self.b
123
Guido van Rossum04a86612001-12-19 16:58:54 +0000124class metaclass(type):
125 pass
126
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000127class use_metaclass(object, metaclass=metaclass):
128 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000129
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200130class pickling_metaclass(type):
131 def __eq__(self, other):
132 return (type(self) == type(other) and
133 self.reduce_args == other.reduce_args)
134
135 def __reduce__(self):
136 return (create_dynamic_class, self.reduce_args)
137
138def create_dynamic_class(name, bases):
139 result = pickling_metaclass(name, bases, dict())
140 result.reduce_args = (name, bases)
141 return result
142
Tim Peters70b02d72003-02-02 17:26:40 +0000143# DATA0 .. DATA2 are the pickles we expect under the various protocols, for
144# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000145
Guido van Rossum98297ee2007-11-06 21:34:58 +0000146DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200147 b'(lp0\nL0L\naL1L\naF2.0\n'
148 b'ac__builtin__\ncomple'
149 b'x\np1\n(F3.0\nF0.0\ntp2\n'
150 b'Rp3\naL1L\naL-1L\naL255'
151 b'L\naL-255L\naL-256L\naL'
152 b'65535L\naL-65535L\naL-'
153 b'65536L\naL2147483647L'
154 b'\naL-2147483647L\naL-2'
155 b'147483648L\na(Vabc\np4'
156 b'\ng4\nccopy_reg\n_recon'
157 b'structor\np5\n(c__main'
158 b'__\nC\np6\nc__builtin__'
159 b'\nobject\np7\nNtp8\nRp9\n'
160 b'(dp10\nVfoo\np11\nL1L\ns'
161 b'Vbar\np12\nL2L\nsbg9\ntp'
162 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000163)
Tim Peterse9358162001-01-22 22:05:20 +0000164
Guido van Rossum98297ee2007-11-06 21:34:58 +0000165# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000166DATA0_DIS = """\
167 0: ( MARK
168 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000169 2: p PUT 0
170 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000171 9: a APPEND
172 10: L LONG 1
173 14: a APPEND
174 15: F FLOAT 2.0
175 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200176 21: c GLOBAL '__builtin__ complex'
177 42: p PUT 1
178 45: ( MARK
179 46: F FLOAT 3.0
180 51: F FLOAT 0.0
181 56: t TUPLE (MARK at 45)
182 57: p PUT 2
183 60: R REDUCE
184 61: p PUT 3
185 64: a APPEND
186 65: L LONG 1
187 69: a APPEND
188 70: L LONG -1
189 75: a APPEND
190 76: L LONG 255
191 82: a APPEND
192 83: L LONG -255
193 90: a APPEND
194 91: L LONG -256
195 98: a APPEND
196 99: L LONG 65535
197 107: a APPEND
198 108: L LONG -65535
199 117: a APPEND
200 118: L LONG -65536
201 127: a APPEND
202 128: L LONG 2147483647
203 141: a APPEND
204 142: L LONG -2147483647
205 156: a APPEND
206 157: L LONG -2147483648
207 171: a APPEND
208 172: ( MARK
209 173: V UNICODE 'abc'
210 178: p PUT 4
211 181: g GET 4
212 184: c GLOBAL 'copy_reg _reconstructor'
213 209: p PUT 5
214 212: ( MARK
215 213: c GLOBAL '__main__ C'
216 225: p PUT 6
217 228: c GLOBAL '__builtin__ object'
218 248: p PUT 7
219 251: N NONE
220 252: t TUPLE (MARK at 212)
221 253: p PUT 8
222 256: R REDUCE
223 257: p PUT 9
224 260: ( MARK
225 261: d DICT (MARK at 260)
226 262: p PUT 10
227 266: V UNICODE 'foo'
228 271: p PUT 11
229 275: L LONG 1
230 279: s SETITEM
231 280: V UNICODE 'bar'
232 285: p PUT 12
233 289: L LONG 2
234 293: s SETITEM
235 294: b BUILD
236 295: g GET 9
237 298: t TUPLE (MARK at 172)
238 299: p PUT 13
239 303: a APPEND
240 304: g GET 13
241 308: a APPEND
242 309: L LONG 5
243 313: a APPEND
244 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000245highest protocol among opcodes = 0
246"""
247
Guido van Rossum98297ee2007-11-06 21:34:58 +0000248DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200249 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
250 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000251 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
252 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
253 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
254 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200255 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000256 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200257 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000258 b'object\nq\x07Ntq\x08Rq\t}q\n('
259 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
260 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
261)
Tim Peters70b02d72003-02-02 17:26:40 +0000262
Guido van Rossum98297ee2007-11-06 21:34:58 +0000263# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000264DATA1_DIS = """\
265 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000266 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000267 3: ( MARK
268 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000269 6: K BININT1 1
270 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200271 17: c GLOBAL '__builtin__ complex'
272 38: q BINPUT 1
273 40: ( MARK
274 41: G BINFLOAT 3.0
275 50: G BINFLOAT 0.0
276 59: t TUPLE (MARK at 40)
277 60: q BINPUT 2
278 62: R REDUCE
279 63: q BINPUT 3
280 65: K BININT1 1
281 67: J BININT -1
282 72: K BININT1 255
283 74: J BININT -255
284 79: J BININT -256
285 84: M BININT2 65535
286 87: J BININT -65535
287 92: J BININT -65536
288 97: J BININT 2147483647
289 102: J BININT -2147483647
290 107: J BININT -2147483648
291 112: ( MARK
292 113: X BINUNICODE 'abc'
293 121: q BINPUT 4
294 123: h BINGET 4
295 125: c GLOBAL 'copy_reg _reconstructor'
296 150: q BINPUT 5
297 152: ( MARK
298 153: c GLOBAL '__main__ C'
299 165: q BINPUT 6
300 167: c GLOBAL '__builtin__ object'
301 187: q BINPUT 7
302 189: N NONE
303 190: t TUPLE (MARK at 152)
304 191: q BINPUT 8
305 193: R REDUCE
306 194: q BINPUT 9
307 196: } EMPTY_DICT
308 197: q BINPUT 10
309 199: ( MARK
310 200: X BINUNICODE 'foo'
311 208: q BINPUT 11
312 210: K BININT1 1
313 212: X BINUNICODE 'bar'
314 220: q BINPUT 12
315 222: K BININT1 2
316 224: u SETITEMS (MARK at 199)
317 225: b BUILD
318 226: h BINGET 9
319 228: t TUPLE (MARK at 112)
320 229: q BINPUT 13
321 231: h BINGET 13
322 233: K BININT1 5
323 235: e APPENDS (MARK at 3)
324 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000325highest protocol among opcodes = 1
326"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000327
Guido van Rossum98297ee2007-11-06 21:34:58 +0000328DATA2 = (
329 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200330 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000331 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
332 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
333 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
334 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
335 b'bcq\x04h\x04c__main__\nC\nq\x05'
336 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
337 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
338 b'\nK\x05e.'
339)
Tim Petersfc273752003-03-02 04:54:24 +0000340
Guido van Rossum98297ee2007-11-06 21:34:58 +0000341# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000342DATA2_DIS = """\
343 0: \x80 PROTO 2
344 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000345 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000346 5: ( MARK
347 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000348 8: K BININT1 1
349 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200350 19: c GLOBAL '__builtin__ complex'
351 40: q BINPUT 1
352 42: G BINFLOAT 3.0
353 51: G BINFLOAT 0.0
354 60: \x86 TUPLE2
355 61: q BINPUT 2
356 63: R REDUCE
357 64: q BINPUT 3
358 66: K BININT1 1
359 68: J BININT -1
360 73: K BININT1 255
361 75: J BININT -255
362 80: J BININT -256
363 85: M BININT2 65535
364 88: J BININT -65535
365 93: J BININT -65536
366 98: J BININT 2147483647
367 103: J BININT -2147483647
368 108: J BININT -2147483648
369 113: ( MARK
370 114: X BINUNICODE 'abc'
371 122: q BINPUT 4
372 124: h BINGET 4
373 126: c GLOBAL '__main__ C'
374 138: q BINPUT 5
375 140: ) EMPTY_TUPLE
376 141: \x81 NEWOBJ
377 142: q BINPUT 6
378 144: } EMPTY_DICT
379 145: q BINPUT 7
380 147: ( MARK
381 148: X BINUNICODE 'foo'
382 156: q BINPUT 8
383 158: K BININT1 1
384 160: X BINUNICODE 'bar'
385 168: q BINPUT 9
386 170: K BININT1 2
387 172: u SETITEMS (MARK at 147)
388 173: b BUILD
389 174: h BINGET 6
390 176: t TUPLE (MARK at 113)
391 177: q BINPUT 10
392 179: h BINGET 10
393 181: K BININT1 5
394 183: e APPENDS (MARK at 5)
395 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000396highest protocol among opcodes = 2
397"""
398
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000399# set([1,2]) pickled from 2.x with protocol 2
400DATA3 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
401
402# xrange(5) pickled from 2.x with protocol 2
403DATA4 = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
404
405# a SimpleCookie() object pickled from 2.x with protocol 2
406DATA5 = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
407 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
408 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
409 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
410 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
411 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
412
413# set([3]) pickled from 2.x with protocol 2
414DATA6 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
415
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100416python2_exceptions_without_args = (
417 ArithmeticError,
418 AssertionError,
419 AttributeError,
420 BaseException,
421 BufferError,
422 BytesWarning,
423 DeprecationWarning,
424 EOFError,
425 EnvironmentError,
426 Exception,
427 FloatingPointError,
428 FutureWarning,
429 GeneratorExit,
430 IOError,
431 ImportError,
432 ImportWarning,
433 IndentationError,
434 IndexError,
435 KeyError,
436 KeyboardInterrupt,
437 LookupError,
438 MemoryError,
439 NameError,
440 NotImplementedError,
441 OSError,
442 OverflowError,
443 PendingDeprecationWarning,
444 ReferenceError,
445 RuntimeError,
446 RuntimeWarning,
447 # StandardError is gone in Python 3, we map it to Exception
448 StopIteration,
449 SyntaxError,
450 SyntaxWarning,
451 SystemError,
452 SystemExit,
453 TabError,
454 TypeError,
455 UnboundLocalError,
456 UnicodeError,
457 UnicodeWarning,
458 UserWarning,
459 ValueError,
460 Warning,
461 ZeroDivisionError,
462)
463
464exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
465
466# Exception objects without arguments pickled from 2.x with protocol 2
467DATA7 = {
468 exception :
469 exception_pickle.replace(b'?', exception.__name__.encode("ascii"))
470 for exception in python2_exceptions_without_args
471}
472
473# StandardError is mapped to Exception, test that separately
474DATA8 = exception_pickle.replace(b'?', b'StandardError')
475
476# UnicodeEncodeError object pickled from 2.x with protocol 2
477DATA9 = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
478 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
479 b'U\x03badq\x03tq\x04Rq\x05.')
480
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000481
Jeremy Hylton66426532001-10-15 21:38:56 +0000482def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000483 c = C()
484 c.foo = 1
485 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000486 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000487 # Append some integer test cases at cPickle.c's internal size
488 # cutoffs.
489 uint1max = 0xff
490 uint2max = 0xffff
491 int4max = 0x7fffffff
492 x.extend([1, -1,
493 uint1max, -uint1max, -uint1max-1,
494 uint2max, -uint2max, -uint2max-1,
495 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000496 y = ('abc', 'abc', c, c)
497 x.append(y)
498 x.append(y)
499 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000500 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000501
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100502
Jeremy Hylton66426532001-10-15 21:38:56 +0000503class AbstractPickleTests(unittest.TestCase):
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000504 # Subclass must define self.dumps, self.loads.
Tim Petersc58440f2001-04-09 17:16:31 +0000505
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100506 optimized = False
507
Jeremy Hylton66426532001-10-15 21:38:56 +0000508 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000509
Jeremy Hylton66426532001-10-15 21:38:56 +0000510 def setUp(self):
Tim Peterse9358162001-01-22 22:05:20 +0000511 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000512
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100513 def assert_is_copy(self, obj, objcopy, msg=None):
514 """Utility method to verify if two objects are copies of each others.
515 """
516 if msg is None:
517 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
518 self.assertEqual(obj, objcopy, msg=msg)
519 self.assertIs(type(obj), type(objcopy), msg=msg)
520 if hasattr(obj, '__dict__'):
521 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
522 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
523 if hasattr(obj, '__slots__'):
524 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
525 for slot in obj.__slots__:
526 self.assertEqual(
527 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
528 self.assertEqual(getattr(obj, slot, None),
529 getattr(objcopy, slot, None), msg=msg)
530
Jeremy Hylton66426532001-10-15 21:38:56 +0000531 def test_misc(self):
532 # test various datatypes not tested by testdata
Tim Peters70b02d72003-02-02 17:26:40 +0000533 for proto in protocols:
534 x = myint(4)
535 s = self.dumps(x, proto)
536 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100537 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000538
Tim Peters70b02d72003-02-02 17:26:40 +0000539 x = (1, ())
540 s = self.dumps(x, proto)
541 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100542 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000543
Tim Peters70b02d72003-02-02 17:26:40 +0000544 x = initarg(1, x)
545 s = self.dumps(x, proto)
546 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100547 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000548
Jeremy Hylton66426532001-10-15 21:38:56 +0000549 # XXX test __reduce__ protocol?
550
Tim Peters70b02d72003-02-02 17:26:40 +0000551 def test_roundtrip_equality(self):
552 expected = self._testdata
553 for proto in protocols:
554 s = self.dumps(expected, proto)
555 got = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100556 self.assert_is_copy(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000557
Guido van Rossum98297ee2007-11-06 21:34:58 +0000558 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100559 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000560
561 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100562 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000563
564 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100565 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000566
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000567 def test_load_classic_instance(self):
568 # See issue5180. Test loading 2.x pickles that
569 # contain an instance of old style class.
570 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
571 xname = X.__name__.encode('ascii')
572 # Protocol 0 (text mode pickle):
573 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200574 0: ( MARK
575 1: i INST '__main__ X' (MARK at 0)
576 13: p PUT 0
577 16: ( MARK
578 17: d DICT (MARK at 16)
579 18: p PUT 1
580 21: b BUILD
581 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000582 """
583 pickle0 = (b"(i__main__\n"
584 b"X\n"
585 b"p0\n"
586 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100587 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000588
589 # Protocol 1 (binary mode pickle)
590 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200591 0: ( MARK
592 1: c GLOBAL '__main__ X'
593 13: q BINPUT 0
594 15: o OBJ (MARK at 0)
595 16: q BINPUT 1
596 18: } EMPTY_DICT
597 19: q BINPUT 2
598 21: b BUILD
599 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000600 """
601 pickle1 = (b'(c__main__\n'
602 b'X\n'
603 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100604 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000605
606 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
607 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200608 0: \x80 PROTO 2
609 2: ( MARK
610 3: c GLOBAL '__main__ X'
611 15: q BINPUT 0
612 17: o OBJ (MARK at 2)
613 18: q BINPUT 1
614 20: } EMPTY_DICT
615 21: q BINPUT 2
616 23: b BUILD
617 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000618 """
619 pickle2 = (b'\x80\x02(c__main__\n'
620 b'X\n'
621 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100622 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000623
Tim Peters70b02d72003-02-02 17:26:40 +0000624 # There are gratuitous differences between pickles produced by
625 # pickle and cPickle, largely because cPickle starts PUT indices at
626 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
627 # there's a comment with an exclamation point there whose meaning
628 # is a mystery. cPickle also suppresses PUT for objects with a refcount
629 # of 1.
630 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +0000631 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +0000632 from pickletools import dis
633
634 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
635 s = self.dumps(self._testdata, proto)
636 filelike = StringIO()
637 dis(s, out=filelike)
638 got = filelike.getvalue()
639 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000640
641 def test_recursive_list(self):
642 l = []
643 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +0000644 for proto in protocols:
645 s = self.dumps(l, proto)
646 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100647 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000648 self.assertEqual(len(x), 1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000649 self.assertTrue(x is x[0])
Jeremy Hylton66426532001-10-15 21:38:56 +0000650
Collin Winter8ca69de2009-05-26 16:53:41 +0000651 def test_recursive_tuple(self):
652 t = ([],)
653 t[0].append(t)
654 for proto in protocols:
655 s = self.dumps(t, proto)
656 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100657 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +0000658 self.assertEqual(len(x), 1)
659 self.assertEqual(len(x[0]), 1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000660 self.assertTrue(x is x[0][0])
Collin Winter8ca69de2009-05-26 16:53:41 +0000661
Jeremy Hylton66426532001-10-15 21:38:56 +0000662 def test_recursive_dict(self):
663 d = {}
664 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +0000665 for proto in protocols:
666 s = self.dumps(d, proto)
667 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100668 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000669 self.assertEqual(list(x.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000670 self.assertTrue(x[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000671
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100672 def test_recursive_set(self):
673 h = H()
674 y = set({h})
675 h.attr = y
676 for proto in protocols:
677 s = self.dumps(y, proto)
678 x = self.loads(s)
679 self.assertIsInstance(x, set)
680 self.assertIs(list(x)[0].attr, x)
681 self.assertEqual(len(x), 1)
682
683 def test_recursive_frozenset(self):
684 h = H()
685 y = frozenset({h})
686 h.attr = y
687 for proto in protocols:
688 s = self.dumps(y, proto)
689 x = self.loads(s)
690 self.assertIsInstance(x, frozenset)
691 self.assertIs(list(x)[0].attr, x)
692 self.assertEqual(len(x), 1)
693
Jeremy Hylton66426532001-10-15 21:38:56 +0000694 def test_recursive_inst(self):
695 i = C()
696 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +0000697 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200698 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +0000699 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100700 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000701 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +0200702 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000703
704 def test_recursive_multi(self):
705 l = []
706 d = {1:l}
707 i = C()
708 i.attr = d
709 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +0000710 for proto in protocols:
711 s = self.dumps(l, proto)
712 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100713 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000714 self.assertEqual(len(x), 1)
715 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000716 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000717 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000718
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000719 def test_get(self):
720 self.assertRaises(KeyError, self.loads, b'g0\np0')
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100721 self.assert_is_copy([(100,), (100,)],
722 self.loads(b'((Kdtp0\nh\x00l.))'))
Jeremy Hylton66426532001-10-15 21:38:56 +0000723
Walter Dörwald9b775532007-06-08 14:30:53 +0000724 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +0000725 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +0000726 '<\\>', '<\\\U00012345>',
727 # surrogates
728 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +0000729 for proto in protocols:
730 for u in endcases:
731 p = self.dumps(u, proto)
732 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100733 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +0000734
Alexandre Vassalotti554d8782008-12-27 07:32:41 +0000735 def test_unicode_high_plane(self):
736 t = '\U00012345'
737 for proto in protocols:
738 p = self.dumps(t, proto)
739 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100740 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +0000741
Guido van Rossumf4169812008-03-17 22:56:06 +0000742 def test_bytes(self):
743 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -0500744 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200745 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100746 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -0500747 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200748 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100749 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -0500750 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200751 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100752 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +0000753
Jeremy Hylton66426532001-10-15 21:38:56 +0000754 def test_ints(self):
755 import sys
Tim Petersee1a53c2003-02-02 02:57:53 +0000756 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +0000757 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +0000758 while n:
759 for expected in (-n, n):
760 s = self.dumps(expected, proto)
761 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100762 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000763 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000764
Jeremy Hylton66426532001-10-15 21:38:56 +0000765 def test_maxint64(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000766 maxint64 = (1 << 63) - 1
Guido van Rossum39478e82007-08-27 17:23:59 +0000767 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
Jeremy Hylton66426532001-10-15 21:38:56 +0000768 got = self.loads(data)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100769 self.assert_is_copy(maxint64, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000770
771 # Try too with a bogus literal.
Guido van Rossum39478e82007-08-27 17:23:59 +0000772 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Jeremy Hylton66426532001-10-15 21:38:56 +0000773 self.assertRaises(ValueError, self.loads, data)
774
Tim Petersee1a53c2003-02-02 02:57:53 +0000775 def test_long(self):
776 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +0000777 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +0000778 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000779 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +0000780 for npos in nbase-1, nbase, nbase+1:
781 for n in npos, -npos:
782 pickle = self.dumps(n, proto)
783 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100784 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +0000785 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
786 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000787 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +0000788 nbase += nbase << 1000000
789 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +0000790 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000791 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +0100792 # assert_is_copy is very expensive here as it precomputes
793 # a failure message by computing the repr() of n and got,
794 # we just do the check ourselves.
795 self.assertIs(type(got), int)
796 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +0000797
Mark Dickinsoncddcf442009-01-24 21:46:33 +0000798 def test_float(self):
799 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
800 3.14, 263.44582062374053, 6.022e23, 1e30]
801 test_values = test_values + [-x for x in test_values]
802 for proto in protocols:
803 for value in test_values:
804 pickle = self.dumps(value, proto)
805 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100806 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +0000807
Thomas Wouters477c8d52006-05-27 19:21:47 +0000808 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
809 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +0000810 # make sure that floats are formatted locale independent with proto 0
811 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000812
Jeremy Hylton66426532001-10-15 21:38:56 +0000813 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +0100814 for proto in protocols:
815 inst = AAA()
816 dumped = self.dumps(inst, proto)
817 loaded = self.loads(dumped)
818 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +0000819
820 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +0100821 for proto in protocols:
822 inst = initarg(1, 2)
823 dumped = self.dumps(inst, proto)
824 loaded = self.loads(dumped)
825 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +0000826
Antoine Pitrou79035bd2012-06-26 23:04:48 +0200827 def test_pop_empty_stack(self):
828 # Test issue7455
829 s = b'0'
830 self.assertRaises((pickle.UnpicklingError, IndexError), self.loads, s)
831
Guido van Rossum04a86612001-12-19 16:58:54 +0000832 def test_metaclass(self):
833 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +0000834 for proto in protocols:
835 s = self.dumps(a, proto)
836 b = self.loads(s)
837 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +0000838
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200839 def test_dynamic_class(self):
840 a = create_dynamic_class("my_dynamic_class", (object,))
841 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
842 for proto in protocols:
843 s = self.dumps(a, proto)
844 b = self.loads(s)
845 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100846 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200847
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000848 def test_structseq(self):
849 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +0000850 import os
Tim Peters70b02d72003-02-02 17:26:40 +0000851
852 t = time.localtime()
853 for proto in protocols:
854 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000855 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100856 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000857 if hasattr(os, "stat"):
858 t = os.stat(os.curdir)
859 s = self.dumps(t, proto)
860 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100861 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000862 if hasattr(os, "statvfs"):
863 t = os.statvfs(os.curdir)
864 s = self.dumps(t, proto)
865 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100866 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000867
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100868 def test_ellipsis(self):
869 for proto in protocols:
870 s = self.dumps(..., proto)
871 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100872 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100873
874 def test_notimplemented(self):
875 for proto in protocols:
876 s = self.dumps(NotImplemented, proto)
877 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100878 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100879
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -0800880 def test_singleton_types(self):
881 # Issue #6477: Test that types of built-in singletons can be pickled.
882 singletons = [None, ..., NotImplemented]
883 for singleton in singletons:
884 for proto in protocols:
885 s = self.dumps(type(singleton), proto)
886 u = self.loads(s)
887 self.assertIs(type(singleton), u)
888
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000889 # Tests for protocol 2
890
Tim Peters4190fb82003-02-02 16:09:05 +0000891 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +0000892 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100893 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +0000894 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100895 proto_header = pickle.PROTO + bytes([proto])
896 self.assertTrue(pickled.startswith(proto_header))
897 else:
898 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +0000899
900 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100901 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +0000902 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +0000903 try:
904 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100905 except ValueError as err:
906 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +0000907 else:
908 self.fail("expected bad protocol number to raise ValueError")
909
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000910 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000911 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +0000912 for proto in protocols:
913 s = self.dumps(x, proto)
914 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100915 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000916 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000917
918 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000919 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +0000920 for proto in protocols:
921 s = self.dumps(x, proto)
922 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100923 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000924 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000925
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000926 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +0000927 # Map (proto, len(tuple)) to expected opcode.
928 expected_opcode = {(0, 0): pickle.TUPLE,
929 (0, 1): pickle.TUPLE,
930 (0, 2): pickle.TUPLE,
931 (0, 3): pickle.TUPLE,
932 (0, 4): pickle.TUPLE,
933
934 (1, 0): pickle.EMPTY_TUPLE,
935 (1, 1): pickle.TUPLE,
936 (1, 2): pickle.TUPLE,
937 (1, 3): pickle.TUPLE,
938 (1, 4): pickle.TUPLE,
939
940 (2, 0): pickle.EMPTY_TUPLE,
941 (2, 1): pickle.TUPLE1,
942 (2, 2): pickle.TUPLE2,
943 (2, 3): pickle.TUPLE3,
944 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000945
946 (3, 0): pickle.EMPTY_TUPLE,
947 (3, 1): pickle.TUPLE1,
948 (3, 2): pickle.TUPLE2,
949 (3, 3): pickle.TUPLE3,
950 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +0000951 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000952 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000953 b = (1,)
954 c = (1, 2)
955 d = (1, 2, 3)
956 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +0000957 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000958 for x in a, b, c, d, e:
959 s = self.dumps(x, proto)
960 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100961 self.assert_is_copy(x, y)
962 expected = expected_opcode[min(proto, 3), len(x)]
963 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +0000964
Guido van Rossum7d97d312003-01-28 04:25:27 +0000965 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +0000966 # Map (proto, singleton) to expected opcode.
967 expected_opcode = {(0, None): pickle.NONE,
968 (1, None): pickle.NONE,
969 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000970 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +0000971
972 (0, True): pickle.INT,
973 (1, True): pickle.INT,
974 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000975 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +0000976
977 (0, False): pickle.INT,
978 (1, False): pickle.INT,
979 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000980 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +0000981 }
Tim Peters4190fb82003-02-02 16:09:05 +0000982 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +0000983 for x in None, False, True:
984 s = self.dumps(x, proto)
985 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000986 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100987 expected = expected_opcode[min(proto, 3), x]
988 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +0000989
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000990 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000991 x = MyTuple([1, 2, 3])
992 x.foo = 42
993 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +0000994 for proto in protocols:
995 s = self.dumps(x, proto)
996 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100997 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000998
999 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001000 x = MyList([1, 2, 3])
1001 x.foo = 42
1002 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001003 for proto in protocols:
1004 s = self.dumps(x, proto)
1005 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001006 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001007
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001008 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001009 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001010 for C in myclasses:
1011 B = C.__base__
1012 x = C(C.sample)
1013 x.foo = 42
1014 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001015 y = self.loads(s)
1016 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001017 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001018 self.assertEqual(B(x), B(y), detail)
1019 self.assertEqual(x.__dict__, y.__dict__, detail)
1020
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001021 def test_newobj_proxies(self):
1022 # NEWOBJ should use the __class__ rather than the raw type
1023 classes = myclasses[:]
1024 # Cannot create weakproxies to these classes
1025 for c in (MyInt, MyTuple):
1026 classes.remove(c)
1027 for proto in protocols:
1028 for C in classes:
1029 B = C.__base__
1030 x = C(C.sample)
1031 x.foo = 42
1032 p = weakref.proxy(x)
1033 s = self.dumps(p, proto)
1034 y = self.loads(s)
1035 self.assertEqual(type(y), type(x)) # rather than type(p)
1036 detail = (proto, C, B, x, y, type(y))
1037 self.assertEqual(B(x), B(y), detail)
1038 self.assertEqual(x.__dict__, y.__dict__, detail)
1039
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001040 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001041 # an object of that type. Check that the resulting pickle uses opcode
1042 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001043
Tim Peters22e71712003-02-03 22:27:38 +00001044 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001045 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001046 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001047 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001048 x = MyList([1, 2, 3])
1049 x.foo = 42
1050 x.bar = "hello"
1051
Tim Peters22e71712003-02-03 22:27:38 +00001052 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001053 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001054 self.assertIn(__name__.encode("utf-8"), s1)
1055 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001056 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001057
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001058 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001059 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001060
Tim Peters22e71712003-02-03 22:27:38 +00001061 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001062 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001063 self.assertNotIn(__name__.encode("utf-8"), s2)
1064 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001065 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001066
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001067 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001068 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001069 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001070 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001071
1072 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001073 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1074 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001075
1076 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001077 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1078 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1079 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001080
1081 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001082 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1083 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
1084 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
1085
Tim Peters8d2613a2003-02-11 16:40:16 +00001086 def test_list_chunking(self):
1087 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00001088 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001089 for proto in protocols:
1090 s = self.dumps(x, proto)
1091 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001092 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001093 num_appends = count_opcode(pickle.APPENDS, s)
1094 self.assertEqual(num_appends, proto > 0)
1095
1096 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001097 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001098 for proto in protocols:
1099 s = self.dumps(x, proto)
1100 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001101 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001102 num_appends = count_opcode(pickle.APPENDS, s)
1103 if proto == 0:
1104 self.assertEqual(num_appends, 0)
1105 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001106 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00001107
1108 def test_dict_chunking(self):
1109 n = 10 # too small to chunk
1110 x = dict.fromkeys(range(n))
1111 for proto in protocols:
1112 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00001113 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00001114 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001115 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001116 num_setitems = count_opcode(pickle.SETITEMS, s)
1117 self.assertEqual(num_setitems, proto > 0)
1118
1119 n = 2500 # expect at least two chunks when proto > 0
1120 x = dict.fromkeys(range(n))
1121 for proto in protocols:
1122 s = self.dumps(x, proto)
1123 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001124 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001125 num_setitems = count_opcode(pickle.SETITEMS, s)
1126 if proto == 0:
1127 self.assertEqual(num_setitems, 0)
1128 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001129 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001130
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001131 def test_set_chunking(self):
1132 n = 10 # too small to chunk
1133 x = set(range(n))
1134 for proto in protocols:
1135 s = self.dumps(x, proto)
1136 y = self.loads(s)
1137 self.assert_is_copy(x, y)
1138 num_additems = count_opcode(pickle.ADDITEMS, s)
1139 if proto < 4:
1140 self.assertEqual(num_additems, 0)
1141 else:
1142 self.assertEqual(num_additems, 1)
1143
1144 n = 2500 # expect at least two chunks when proto >= 4
1145 x = set(range(n))
1146 for proto in protocols:
1147 s = self.dumps(x, proto)
1148 y = self.loads(s)
1149 self.assert_is_copy(x, y)
1150 num_additems = count_opcode(pickle.ADDITEMS, s)
1151 if proto < 4:
1152 self.assertEqual(num_additems, 0)
1153 else:
1154 self.assertGreaterEqual(num_additems, 2)
1155
Tim Peterse9ef2032003-02-13 18:42:00 +00001156 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001157 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00001158 x.abc = 666
1159 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001160 with self.subTest(proto=proto):
1161 s = self.dumps(x, proto)
1162 if proto < 1:
1163 self.assertIn(b'\nL64206', s) # LONG
1164 else:
1165 self.assertIn(b'M\xce\xfa', s) # BININT2
1166 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
1167 2 <= proto)
1168 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
1169 y = self.loads(s) # will raise TypeError if __init__ called
1170 self.assert_is_copy(x, y)
1171
1172 def test_complex_newobj(self):
1173 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
1174 x.abc = 666
1175 for proto in protocols:
1176 with self.subTest(proto=proto):
1177 s = self.dumps(x, proto)
1178 if proto < 1:
1179 self.assertIn(b'\nL64206', s) # LONG
1180 elif proto < 2:
1181 self.assertIn(b'M\xce\xfa', s) # BININT2
1182 elif proto < 4:
1183 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
1184 else:
1185 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
1186 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
1187 2 <= proto)
1188 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
1189 y = self.loads(s) # will raise TypeError if __init__ called
1190 self.assert_is_copy(x, y)
1191
1192 def test_complex_newobj_ex(self):
1193 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
1194 x.abc = 666
1195 for proto in protocols:
1196 with self.subTest(proto=proto):
1197 if 2 <= proto < 4:
1198 self.assertRaises(ValueError, self.dumps, x, proto)
1199 continue
1200 s = self.dumps(x, proto)
1201 if proto < 1:
1202 self.assertIn(b'\nL64206', s) # LONG
1203 elif proto < 2:
1204 self.assertIn(b'M\xce\xfa', s) # BININT2
1205 else:
1206 assert proto >= 4
1207 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
1208 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
1209 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
1210 4 <= proto)
1211 y = self.loads(s) # will raise TypeError if __init__ called
1212 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00001213
Tim Peters42f08ac2003-02-11 22:43:24 +00001214 def test_newobj_list_slots(self):
1215 x = SlotList([1, 2, 3])
1216 x.foo = 42
1217 x.bar = "hello"
1218 s = self.dumps(x, 2)
1219 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001220 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00001221
Guido van Rossum2a30b212003-02-18 22:41:24 +00001222 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00001223 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001224 x = REX_one()
1225 self.assertEqual(x._reduce_called, 0)
1226 s = self.dumps(x, proto)
1227 self.assertEqual(x._reduce_called, 1)
1228 y = self.loads(s)
1229 self.assertEqual(y._reduce_called, 0)
1230
1231 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00001232 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001233 x = REX_two()
1234 self.assertEqual(x._proto, None)
1235 s = self.dumps(x, proto)
1236 self.assertEqual(x._proto, proto)
1237 y = self.loads(s)
1238 self.assertEqual(y._proto, None)
1239
1240 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00001241 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001242 x = REX_three()
1243 self.assertEqual(x._proto, None)
1244 s = self.dumps(x, proto)
1245 self.assertEqual(x._proto, proto)
1246 y = self.loads(s)
1247 self.assertEqual(y._proto, None)
1248
Guido van Rossumd8faa362007-04-27 19:54:29 +00001249 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00001250 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001251 x = REX_four()
1252 self.assertEqual(x._proto, None)
1253 s = self.dumps(x, proto)
1254 self.assertEqual(x._proto, proto)
1255 y = self.loads(s)
1256 self.assertEqual(y._proto, proto)
1257
1258 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00001259 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001260 x = REX_five()
1261 self.assertEqual(x._reduce_called, 0)
1262 s = self.dumps(x, proto)
1263 self.assertEqual(x._reduce_called, 1)
1264 y = self.loads(s)
1265 self.assertEqual(y._reduce_called, 1)
1266
Brett Cannon31f59292011-02-21 19:29:56 +00001267 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001268 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001269 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001270 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001271 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001272 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001273
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001274 def test_reduce_bad_iterator(self):
1275 # Issue4176: crash when 4th and 5th items of __reduce__()
1276 # are not iterators
1277 class C(object):
1278 def __reduce__(self):
1279 # 4th item is not an iterator
1280 return list, (), None, [], None
1281 class D(object):
1282 def __reduce__(self):
1283 # 5th item is not an iterator
1284 return dict, (), None, None, []
1285
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00001286 # Protocol 0 is less strict and also accept iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001287 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00001288 try:
1289 self.dumps(C(), proto)
1290 except (pickle.PickleError):
1291 pass
1292 try:
1293 self.dumps(D(), proto)
1294 except (pickle.PickleError):
1295 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001296
Collin Winter771d8342009-04-16 03:18:06 +00001297 def test_many_puts_and_gets(self):
1298 # Test that internal data structures correctly deal with lots of
1299 # puts/gets.
1300 keys = ("aaa" + str(i) for i in range(100))
1301 large_dict = dict((k, [4, 5, 6]) for k in keys)
1302 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
1303
1304 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001305 with self.subTest(proto=proto):
1306 dumped = self.dumps(obj, proto)
1307 loaded = self.loads(dumped)
1308 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00001309
Antoine Pitroua9f48a02009-05-02 21:41:14 +00001310 def test_attribute_name_interning(self):
1311 # Test that attribute names of pickled objects are interned when
1312 # unpickling.
1313 for proto in protocols:
1314 x = C()
1315 x.foo = 42
1316 x.bar = "hello"
1317 s = self.dumps(x, proto)
1318 y = self.loads(s)
1319 x_keys = sorted(x.__dict__)
1320 y_keys = sorted(y.__dict__)
1321 for x_key, y_key in zip(x_keys, y_keys):
1322 self.assertIs(x_key, y_key)
1323
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001324 def test_unpickle_from_2x(self):
1325 # Unpickle non-trivial data from Python 2.x.
1326 loaded = self.loads(DATA3)
1327 self.assertEqual(loaded, set([1, 2]))
1328 loaded = self.loads(DATA4)
1329 self.assertEqual(type(loaded), type(range(0)))
1330 self.assertEqual(list(loaded), list(range(5)))
1331 loaded = self.loads(DATA5)
1332 self.assertEqual(type(loaded), SimpleCookie)
1333 self.assertEqual(list(loaded.keys()), ["key"])
Serhiy Storchaka8cf7c1c2014-11-02 22:18:25 +02001334 self.assertEqual(loaded["key"].value, "value")
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001335
Walter Doerwald9d1dbca2013-12-02 11:41:01 +01001336 for (exc, data) in DATA7.items():
1337 loaded = self.loads(data)
1338 self.assertIs(type(loaded), exc)
1339
1340 loaded = self.loads(DATA8)
1341 self.assertIs(type(loaded), Exception)
1342
1343 loaded = self.loads(DATA9)
1344 self.assertIs(type(loaded), UnicodeEncodeError)
1345 self.assertEqual(loaded.object, "foo")
1346 self.assertEqual(loaded.encoding, "ascii")
1347 self.assertEqual(loaded.start, 0)
1348 self.assertEqual(loaded.end, 1)
1349 self.assertEqual(loaded.reason, "bad")
1350
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001351 def test_pickle_to_2x(self):
1352 # Pickle non-trivial data with protocol 2, expecting that it yields
1353 # the same result as Python 2.x did.
1354 # NOTE: this test is a bit too strong since we can produce different
1355 # bytecode that 2.x will still understand.
1356 dumped = self.dumps(range(5), 2)
1357 self.assertEqual(dumped, DATA4)
1358 dumped = self.dumps(set([3]), 2)
1359 self.assertEqual(dumped, DATA6)
1360
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -08001361 def test_load_python2_str_as_bytes(self):
1362 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
1363 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
1364 encoding="bytes"), b'a\x00\xa0')
1365 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
1366 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
1367 encoding="bytes"), b'a\x00\xa0')
1368 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
1369 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
1370 encoding="bytes"), b'a\x00\xa0')
1371
1372 def test_load_python2_unicode_as_str(self):
1373 # From Python 2: pickle.dumps(u'π', protocol=0)
1374 self.assertEqual(self.loads(b'V\\u03c0\n.',
1375 encoding='bytes'), 'π')
1376 # From Python 2: pickle.dumps(u'π', protocol=1)
1377 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
1378 encoding="bytes"), 'π')
1379 # From Python 2: pickle.dumps(u'π', protocol=2)
1380 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
1381 encoding="bytes"), 'π')
1382
1383 def test_load_long_python2_str_as_bytes(self):
1384 # From Python 2: pickle.dumps('x' * 300, protocol=1)
1385 self.assertEqual(self.loads(pickle.BINSTRING +
1386 struct.pack("<I", 300) +
1387 b'x' * 300 + pickle.STOP,
1388 encoding='bytes'), b'x' * 300)
1389
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001390 def test_large_pickles(self):
1391 # Test the correctness of internal buffering routines when handling
1392 # large data.
1393 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00001394 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001395 dumped = self.dumps(data, proto)
1396 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00001397 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001398 self.assertEqual(loaded, data)
1399
Alexander Belopolsky1ce92dc2011-02-24 19:40:09 +00001400 def test_empty_bytestring(self):
1401 # issue 11286
1402 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1403 self.assertEqual(empty, '')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001404
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001405 def test_int_pickling_efficiency(self):
1406 # Test compacity of int representation (see issue #12744)
1407 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001408 with self.subTest(proto=proto):
1409 pickles = [self.dumps(2**n, proto) for n in range(70)]
1410 sizes = list(map(len, pickles))
1411 # the size function is monotonic
1412 self.assertEqual(sorted(sizes), sizes)
1413 if proto >= 2:
1414 for p in pickles:
1415 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001416
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001417 def check_negative_32b_binXXX(self, dumped):
1418 if sys.maxsize > 2**32:
1419 self.skipTest("test is only meaningful on 32-bit builds")
1420 # XXX Pure Python pickle reads lengths as signed and passes
1421 # them directly to read() (hence the EOFError)
1422 with self.assertRaises((pickle.UnpicklingError, EOFError,
1423 ValueError, OverflowError)):
1424 self.loads(dumped)
1425
1426 def test_negative_32b_binbytes(self):
1427 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1428 self.check_negative_32b_binXXX(b'\x80\x03B\xff\xff\xff\xffxyzq\x00.')
1429
1430 def test_negative_32b_binunicode(self):
1431 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1432 self.check_negative_32b_binXXX(b'\x80\x03X\xff\xff\xff\xffxyzq\x00.')
1433
Antoine Pitrou55549ec2011-08-30 00:27:10 +02001434 def test_negative_put(self):
1435 # Issue #12847
1436 dumped = b'Va\np-1\n.'
1437 self.assertRaises(ValueError, self.loads, dumped)
1438
1439 def test_negative_32b_binput(self):
1440 # Issue #12847
1441 if sys.maxsize > 2**32:
1442 self.skipTest("test is only meaningful on 32-bit builds")
1443 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
1444 self.assertRaises(ValueError, self.loads, dumped)
1445
Alexandre Vassalotti7c5e0942013-04-15 23:14:55 -07001446 def test_badly_escaped_string(self):
1447 self.assertRaises(ValueError, self.loads, b"S'\\'\n.")
1448
1449 def test_badly_quoted_string(self):
1450 # Issue #17710
1451 badpickles = [b"S'\n.",
1452 b'S"\n.',
1453 b'S\' \n.',
1454 b'S" \n.',
1455 b'S\'"\n.',
1456 b'S"\'\n.',
1457 b"S' ' \n.",
1458 b'S" " \n.',
1459 b"S ''\n.",
1460 b'S ""\n.',
1461 b'S \n.',
1462 b'S\n.',
1463 b'S.']
1464 for p in badpickles:
1465 self.assertRaises(pickle.UnpicklingError, self.loads, p)
1466
1467 def test_correctly_quoted_string(self):
1468 goodpickles = [(b"S''\n.", ''),
1469 (b'S""\n.', ''),
1470 (b'S"\\n"\n.', '\n'),
1471 (b"S'\\n'\n.", '\n')]
1472 for p, expected in goodpickles:
1473 self.assertEqual(self.loads(p), expected)
1474
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001475 def _check_pickling_with_opcode(self, obj, opcode, proto):
1476 pickled = self.dumps(obj, proto)
1477 self.assertTrue(opcode_in_pickle(opcode, pickled))
1478 unpickled = self.loads(pickled)
1479 self.assertEqual(obj, unpickled)
1480
1481 def test_appends_on_non_lists(self):
1482 # Issue #17720
1483 obj = REX_six([1, 2, 3])
1484 for proto in protocols:
1485 if proto == 0:
1486 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
1487 else:
1488 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
1489
1490 def test_setitems_on_non_dicts(self):
1491 obj = REX_seven({1: -1, 2: -2, 3: -3})
1492 for proto in protocols:
1493 if proto == 0:
1494 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
1495 else:
1496 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
1497
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001498 # Exercise framing (proto >= 4) for significant workloads
1499
1500 FRAME_SIZE_TARGET = 64 * 1024
1501
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001502 def check_frame_opcodes(self, pickled):
1503 """
1504 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
1505 """
1506 frame_opcode_size = 9
1507 last_arg = last_pos = None
1508 for op, arg, pos in pickletools.genops(pickled):
1509 if op.name != 'FRAME':
1510 continue
1511 if last_pos is not None:
1512 # The previous frame's size should be equal to the number
1513 # of bytes up to the current frame.
1514 frame_size = pos - last_pos - frame_opcode_size
1515 self.assertEqual(frame_size, last_arg)
1516 last_arg, last_pos = arg, pos
1517 # The last frame's size should be equal to the number of bytes up
1518 # to the pickle's end.
1519 frame_size = len(pickled) - last_pos - frame_opcode_size
1520 self.assertEqual(frame_size, last_arg)
1521
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001522 def test_framing_many_objects(self):
1523 obj = list(range(10**5))
1524 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1525 with self.subTest(proto=proto):
1526 pickled = self.dumps(obj, proto)
1527 unpickled = self.loads(pickled)
1528 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01001529 bytes_per_frame = (len(pickled) /
1530 count_opcode(pickle.FRAME, pickled))
1531 self.assertGreater(bytes_per_frame,
1532 self.FRAME_SIZE_TARGET / 2)
1533 self.assertLessEqual(bytes_per_frame,
1534 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001535 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001536
1537 def test_framing_large_objects(self):
1538 N = 1024 * 1024
1539 obj = [b'x' * N, b'y' * N, b'z' * N]
1540 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1541 with self.subTest(proto=proto):
1542 pickled = self.dumps(obj, proto)
1543 unpickled = self.loads(pickled)
1544 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01001545 n_frames = count_opcode(pickle.FRAME, pickled)
Alexandre Vassalotti28d271e2013-12-01 16:27:46 -08001546 self.assertGreaterEqual(n_frames, len(obj))
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001547 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001548
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001549 def test_optional_frames(self):
1550 if pickle.HIGHEST_PROTOCOL < 4:
1551 return
1552
1553 def remove_frames(pickled, keep_frame=None):
1554 """Remove frame opcodes from the given pickle."""
1555 frame_starts = []
1556 # 1 byte for the opcode and 8 for the argument
1557 frame_opcode_size = 9
1558 for opcode, _, pos in pickletools.genops(pickled):
1559 if opcode.name == 'FRAME':
1560 frame_starts.append(pos)
1561
1562 newpickle = bytearray()
1563 last_frame_end = 0
1564 for i, pos in enumerate(frame_starts):
1565 if keep_frame and keep_frame(i):
1566 continue
1567 newpickle += pickled[last_frame_end:pos]
1568 last_frame_end = pos + frame_opcode_size
1569 newpickle += pickled[last_frame_end:]
1570 return newpickle
1571
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001572 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001573 num_frames = 20
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001574 obj = [bytes([i]) * frame_size for i in range(num_frames)]
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001575
1576 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1577 pickled = self.dumps(obj, proto)
1578
1579 frameless_pickle = remove_frames(pickled)
1580 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
1581 self.assertEqual(obj, self.loads(frameless_pickle))
1582
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001583 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001584 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
1585 count_opcode(pickle.FRAME, pickled))
1586 self.assertEqual(obj, self.loads(some_frames_pickle))
1587
Serhiy Storchaka21d75332015-01-26 10:37:01 +02001588 def test_frame_readline(self):
1589 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1590 # 0: \x80 PROTO 4
1591 # 2: \x95 FRAME 5
1592 # 11: I INT 42
1593 # 15: . STOP
1594 self.assertEqual(self.loads(pickled), 42)
1595
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001596 def test_nested_names(self):
1597 global Nested
1598 class Nested:
1599 class A:
1600 class B:
1601 class C:
1602 pass
1603
1604 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1605 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
1606 with self.subTest(proto=proto, obj=obj):
1607 unpickled = self.loads(self.dumps(obj, proto))
1608 self.assertIs(obj, unpickled)
1609
1610 def test_py_methods(self):
1611 global PyMethodsTest
1612 class PyMethodsTest:
1613 @staticmethod
1614 def cheese():
1615 return "cheese"
1616 @classmethod
1617 def wine(cls):
1618 assert cls is PyMethodsTest
1619 return "wine"
1620 def biscuits(self):
1621 assert isinstance(self, PyMethodsTest)
1622 return "biscuits"
1623 class Nested:
1624 "Nested class"
1625 @staticmethod
1626 def ketchup():
1627 return "ketchup"
1628 @classmethod
1629 def maple(cls):
1630 assert cls is PyMethodsTest.Nested
1631 return "maple"
1632 def pie(self):
1633 assert isinstance(self, PyMethodsTest.Nested)
1634 return "pie"
1635
1636 py_methods = (
1637 PyMethodsTest.cheese,
1638 PyMethodsTest.wine,
1639 PyMethodsTest().biscuits,
1640 PyMethodsTest.Nested.ketchup,
1641 PyMethodsTest.Nested.maple,
1642 PyMethodsTest.Nested().pie
1643 )
1644 py_unbound_methods = (
1645 (PyMethodsTest.biscuits, PyMethodsTest),
1646 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
1647 )
1648 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1649 for method in py_methods:
1650 with self.subTest(proto=proto, method=method):
1651 unpickled = self.loads(self.dumps(method, proto))
1652 self.assertEqual(method(), unpickled())
1653 for method, cls in py_unbound_methods:
1654 obj = cls()
1655 with self.subTest(proto=proto, method=method):
1656 unpickled = self.loads(self.dumps(method, proto))
1657 self.assertEqual(method(obj), unpickled(obj))
1658
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001659 def test_c_methods(self):
1660 global Subclass
1661 class Subclass(tuple):
1662 class Nested(str):
1663 pass
1664
1665 c_methods = (
1666 # bound built-in method
1667 ("abcd".index, ("c",)),
1668 # unbound built-in method
1669 (str.index, ("abcd", "c")),
1670 # bound "slot" method
1671 ([1, 2, 3].__len__, ()),
1672 # unbound "slot" method
1673 (list.__len__, ([1, 2, 3],)),
1674 # bound "coexist" method
1675 ({1, 2}.__contains__, (2,)),
1676 # unbound "coexist" method
1677 (set.__contains__, ({1, 2}, 2)),
1678 # built-in class method
1679 (dict.fromkeys, (("a", 1), ("b", 2))),
1680 # built-in static method
1681 (bytearray.maketrans, (b"abc", b"xyz")),
1682 # subclass methods
1683 (Subclass([1,2,2]).count, (2,)),
1684 (Subclass.count, (Subclass([1,2,2]), 2)),
1685 (Subclass.Nested("sweet").count, ("e",)),
1686 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
1687 )
1688 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1689 for method, args in c_methods:
1690 with self.subTest(proto=proto, method=method):
1691 unpickled = self.loads(self.dumps(method, proto))
1692 self.assertEqual(method(*args), unpickled(*args))
1693
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01001694 def test_local_lookup_error(self):
1695 # Test that whichmodule() errors out cleanly when looking up
1696 # an assumed globally-reachable object fails.
1697 def f():
1698 pass
1699 # Since the function is local, lookup will fail
1700 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
1701 with self.assertRaises((AttributeError, pickle.PicklingError)):
1702 pickletools.dis(self.dumps(f, proto))
1703 # Same without a __module__ attribute (exercises a different path
1704 # in _pickle.c).
1705 del f.__module__
1706 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
1707 with self.assertRaises((AttributeError, pickle.PicklingError)):
1708 pickletools.dis(self.dumps(f, proto))
1709 # Yet a different path.
1710 f.__name__ = f.__qualname__
1711 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
1712 with self.assertRaises((AttributeError, pickle.PicklingError)):
1713 pickletools.dis(self.dumps(f, proto))
1714
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001715
1716class BigmemPickleTests(unittest.TestCase):
1717
1718 # Binary protocols can serialize longs of up to 2GB-1
1719
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001720 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001721 def test_huge_long_32b(self, size):
1722 data = 1 << (8 * size)
1723 try:
1724 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001725 if proto < 2:
1726 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001727 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001728 with self.assertRaises((ValueError, OverflowError)):
1729 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001730 finally:
1731 data = None
1732
1733 # Protocol 3 can serialize up to 4GB-1 as a bytes object
1734 # (older protocols don't have a dedicated opcode for bytes and are
1735 # too inefficient)
1736
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001737 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001738 def test_huge_bytes_32b(self, size):
1739 data = b"abcd" * (size // 4)
1740 try:
1741 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001742 if proto < 3:
1743 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001744 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001745 try:
1746 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001747 header = (pickle.BINBYTES +
1748 struct.pack("<I", len(data)))
1749 data_start = pickled.index(data)
1750 self.assertEqual(
1751 header,
1752 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001753 finally:
1754 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001755 finally:
1756 data = None
1757
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001758 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001759 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001760 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001761 try:
1762 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001763 if proto < 3:
1764 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001765 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001766 if proto == 3:
1767 # Protocol 3 does not support large bytes objects.
1768 # Verify that we do not crash when processing one.
1769 with self.assertRaises((ValueError, OverflowError)):
1770 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001771 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001772 try:
1773 pickled = self.dumps(data, protocol=proto)
1774 header = (pickle.BINBYTES8 +
1775 struct.pack("<Q", len(data)))
1776 data_start = pickled.index(data)
1777 self.assertEqual(
1778 header,
1779 pickled[data_start-len(header):data_start])
1780 finally:
1781 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001782 finally:
1783 data = None
1784
1785 # All protocols use 1-byte per printable ASCII character; we add another
1786 # byte because the encoded form has to be copied into the internal buffer.
1787
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001788 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001789 def test_huge_str_32b(self, size):
1790 data = "abcd" * (size // 4)
1791 try:
1792 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001793 if proto == 0:
1794 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001795 with self.subTest(proto=proto):
1796 try:
1797 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001798 header = (pickle.BINUNICODE +
1799 struct.pack("<I", len(data)))
1800 data_start = pickled.index(b'abcd')
1801 self.assertEqual(
1802 header,
1803 pickled[data_start-len(header):data_start])
1804 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
1805 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001806 finally:
1807 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001808 finally:
1809 data = None
1810
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001811 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
1812 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
1813 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02001814
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001815 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001816 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001817 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001818 try:
1819 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001820 if proto == 0:
1821 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001822 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001823 if proto < 4:
1824 with self.assertRaises((ValueError, OverflowError)):
1825 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001826 continue
1827 try:
1828 pickled = self.dumps(data, protocol=proto)
1829 header = (pickle.BINUNICODE8 +
1830 struct.pack("<Q", len(data)))
1831 data_start = pickled.index(b'abcd')
1832 self.assertEqual(
1833 header,
1834 pickled[data_start-len(header):data_start])
1835 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
1836 pickled.index(b"abcd")), len(data))
1837 finally:
1838 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001839 finally:
1840 data = None
1841
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001842
Guido van Rossum2a30b212003-02-18 22:41:24 +00001843# Test classes for reduce_ex
1844
1845class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001846 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00001847 _reduce_called = 0
1848 def __reduce__(self):
1849 self._reduce_called = 1
1850 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00001851
1852class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001853 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00001854 _proto = None
1855 def __reduce_ex__(self, proto):
1856 self._proto = proto
1857 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00001858
1859class REX_three(object):
1860 _proto = None
1861 def __reduce_ex__(self, proto):
1862 self._proto = proto
1863 return REX_two, ()
1864 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00001865 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00001866
Guido van Rossumd8faa362007-04-27 19:54:29 +00001867class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001868 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001869 _proto = None
1870 def __reduce_ex__(self, proto):
1871 self._proto = proto
1872 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001873
1874class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001875 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001876 _reduce_called = 0
1877 def __reduce__(self):
1878 self._reduce_called = 1
1879 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001880
1881class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001882 """This class is used to check the 4th argument (list iterator) of
1883 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001884 """
1885 def __init__(self, items=None):
1886 self.items = items if items is not None else []
1887 def __eq__(self, other):
1888 return type(self) is type(other) and self.items == self.items
1889 def append(self, item):
1890 self.items.append(item)
1891 def __reduce__(self):
1892 return type(self), (), None, iter(self.items), None
1893
1894class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001895 """This class is used to check the 5th argument (dict iterator) of
1896 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001897 """
1898 def __init__(self, table=None):
1899 self.table = table if table is not None else {}
1900 def __eq__(self, other):
1901 return type(self) is type(other) and self.table == self.table
1902 def __setitem__(self, key, value):
1903 self.table[key] = value
1904 def __reduce__(self):
1905 return type(self), (), None, None, iter(self.table.items())
1906
Guido van Rossumd8faa362007-04-27 19:54:29 +00001907
Guido van Rossum2a30b212003-02-18 22:41:24 +00001908# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00001909
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001910class MyInt(int):
1911 sample = 1
1912
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001913class MyFloat(float):
1914 sample = 1.0
1915
1916class MyComplex(complex):
1917 sample = 1.0 + 0.0j
1918
1919class MyStr(str):
1920 sample = "hello"
1921
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001922class MyUnicode(str):
1923 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001924
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001925class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001926 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001927
1928class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001929 sample = [1, 2, 3]
1930
1931class MyDict(dict):
1932 sample = {"a": 1, "b": 2}
1933
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001934class MySet(set):
1935 sample = {"a", "b"}
1936
1937class MyFrozenSet(frozenset):
1938 sample = frozenset({"a", "b"})
1939
Mark Dickinson5c2db372009-12-05 20:28:34 +00001940myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00001941 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001942 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001943 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001944
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001945
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00001946class SlotList(MyList):
1947 __slots__ = ["foo"]
1948
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001949class SimpleNewObj(int):
1950 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00001951 # raise an error, to make sure this isn't called
1952 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001953 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001954 return int(self) == int(other) and self.__dict__ == other.__dict__
1955
1956class ComplexNewObj(SimpleNewObj):
1957 def __getnewargs__(self):
1958 return ('%X' % self, 16)
1959
1960class ComplexNewObjEx(SimpleNewObj):
1961 def __getnewargs_ex__(self):
1962 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00001963
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001964class BadGetattr:
1965 def __getattr__(self, key):
1966 self.foo
1967
Collin Winter771d8342009-04-16 03:18:06 +00001968
Jeremy Hylton66426532001-10-15 21:38:56 +00001969class AbstractPickleModuleTests(unittest.TestCase):
1970
1971 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001972 import os
Walter Dörwald11b41f62007-06-20 12:46:31 +00001973 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001974 try:
1975 f.close()
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00001976 self.assertRaises(ValueError, pickle.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001977 finally:
1978 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00001979
1980 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001981 import os
Walter Dörwald11b41f62007-06-20 12:46:31 +00001982 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001983 try:
1984 f.close()
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00001985 self.assertRaises(ValueError, pickle.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001986 finally:
1987 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00001988
Collin Winter771d8342009-04-16 03:18:06 +00001989 def test_load_from_and_dump_to_file(self):
1990 stream = io.BytesIO()
1991 data = [123, {}, 124]
1992 pickle.dump(data, stream)
1993 stream.seek(0)
1994 unpickled = pickle.load(stream)
1995 self.assertEqual(unpickled, data)
1996
Tim Petersc0c93702003-02-13 19:30:57 +00001997 def test_highest_protocol(self):
1998 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001999 self.assertEqual(pickle.HIGHEST_PROTOCOL, 4)
Tim Petersc0c93702003-02-13 19:30:57 +00002000
Martin v. Löwis544f1192004-07-27 05:22:33 +00002001 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00002002 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00002003 # With and without keyword arguments
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00002004 pickle.dump(123, f, -1)
2005 pickle.dump(123, file=f, protocol=-1)
2006 pickle.dumps(123, -1)
2007 pickle.dumps(123, protocol=-1)
2008 pickle.Pickler(f, -1)
2009 pickle.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00002010
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002011 def test_bad_init(self):
2012 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002013 # Override initialization without calling __init__() of the superclass.
2014 class BadPickler(pickle.Pickler):
2015 def __init__(self): pass
2016
2017 class BadUnpickler(pickle.Unpickler):
2018 def __init__(self): pass
2019
2020 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
2021 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
2022
Amaury Forgeot d'Arc3e4e72f2008-11-11 20:05:06 +00002023 def test_bad_input(self):
2024 # Test issue4298
2025 s = bytes([0x58, 0, 0, 0, 0x54])
2026 self.assertRaises(EOFError, pickle.loads, s)
2027
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002028
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002029class AbstractPersistentPicklerTests(unittest.TestCase):
2030
2031 # This class defines persistent_id() and persistent_load()
2032 # functions that should be used by the pickler. All even integers
2033 # are pickled using persistent ids.
2034
2035 def persistent_id(self, object):
2036 if isinstance(object, int) and object % 2 == 0:
2037 self.id_count += 1
2038 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002039 elif object == "test_false_value":
2040 self.false_count += 1
2041 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002042 else:
2043 return None
2044
2045 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002046 if not oid:
2047 self.load_false_count += 1
2048 return "test_false_value"
2049 else:
2050 self.load_count += 1
2051 object = int(oid)
2052 assert object % 2 == 0
2053 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002054
2055 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002056 L = list(range(10)) + ["test_false_value"]
2057 for proto in protocols:
2058 self.id_count = 0
2059 self.false_count = 0
2060 self.load_false_count = 0
2061 self.load_count = 0
2062 self.assertEqual(self.loads(self.dumps(L, proto)), L)
2063 self.assertEqual(self.id_count, 5)
2064 self.assertEqual(self.false_count, 1)
2065 self.assertEqual(self.load_count, 5)
2066 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00002067
Collin Winter771d8342009-04-16 03:18:06 +00002068
2069class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
2070
2071 pickler_class = None
2072 unpickler_class = None
2073
2074 def setUp(self):
2075 assert self.pickler_class
2076 assert self.unpickler_class
2077
2078 def test_clear_pickler_memo(self):
2079 # To test whether clear_memo() has any effect, we pickle an object,
2080 # then pickle it again without clearing the memo; the two serialized
2081 # forms should be different. If we clear_memo() and then pickle the
2082 # object again, the third serialized form should be identical to the
2083 # first one we obtained.
2084 data = ["abcdefg", "abcdefg", 44]
2085 f = io.BytesIO()
2086 pickler = self.pickler_class(f)
2087
2088 pickler.dump(data)
2089 first_pickled = f.getvalue()
2090
Serhiy Storchaka50254c52013-08-29 11:35:43 +03002091 # Reset BytesIO object.
Collin Winter771d8342009-04-16 03:18:06 +00002092 f.seek(0)
2093 f.truncate()
2094
2095 pickler.dump(data)
2096 second_pickled = f.getvalue()
2097
Serhiy Storchaka50254c52013-08-29 11:35:43 +03002098 # Reset the Pickler and BytesIO objects.
Collin Winter771d8342009-04-16 03:18:06 +00002099 pickler.clear_memo()
2100 f.seek(0)
2101 f.truncate()
2102
2103 pickler.dump(data)
2104 third_pickled = f.getvalue()
2105
2106 self.assertNotEqual(first_pickled, second_pickled)
2107 self.assertEqual(first_pickled, third_pickled)
2108
2109 def test_priming_pickler_memo(self):
2110 # Verify that we can set the Pickler's memo attribute.
2111 data = ["abcdefg", "abcdefg", 44]
2112 f = io.BytesIO()
2113 pickler = self.pickler_class(f)
2114
2115 pickler.dump(data)
2116 first_pickled = f.getvalue()
2117
2118 f = io.BytesIO()
2119 primed = self.pickler_class(f)
2120 primed.memo = pickler.memo
2121
2122 primed.dump(data)
2123 primed_pickled = f.getvalue()
2124
2125 self.assertNotEqual(first_pickled, primed_pickled)
2126
2127 def test_priming_unpickler_memo(self):
2128 # Verify that we can set the Unpickler's memo attribute.
2129 data = ["abcdefg", "abcdefg", 44]
2130 f = io.BytesIO()
2131 pickler = self.pickler_class(f)
2132
2133 pickler.dump(data)
2134 first_pickled = f.getvalue()
2135
2136 f = io.BytesIO()
2137 primed = self.pickler_class(f)
2138 primed.memo = pickler.memo
2139
2140 primed.dump(data)
2141 primed_pickled = f.getvalue()
2142
2143 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
2144 unpickled_data1 = unpickler.load()
2145
2146 self.assertEqual(unpickled_data1, data)
2147
2148 primed = self.unpickler_class(io.BytesIO(primed_pickled))
2149 primed.memo = unpickler.memo
2150 unpickled_data2 = primed.load()
2151
2152 primed.memo.clear()
2153
2154 self.assertEqual(unpickled_data2, data)
2155 self.assertTrue(unpickled_data2 is unpickled_data1)
2156
2157 def test_reusing_unpickler_objects(self):
2158 data1 = ["abcdefg", "abcdefg", 44]
2159 f = io.BytesIO()
2160 pickler = self.pickler_class(f)
2161 pickler.dump(data1)
2162 pickled1 = f.getvalue()
2163
2164 data2 = ["abcdefg", 44, 44]
2165 f = io.BytesIO()
2166 pickler = self.pickler_class(f)
2167 pickler.dump(data2)
2168 pickled2 = f.getvalue()
2169
2170 f = io.BytesIO()
2171 f.write(pickled1)
2172 f.seek(0)
2173 unpickler = self.unpickler_class(f)
2174 self.assertEqual(unpickler.load(), data1)
2175
2176 f.seek(0)
2177 f.truncate()
2178 f.write(pickled2)
2179 f.seek(0)
2180 self.assertEqual(unpickler.load(), data2)
2181
Antoine Pitrou04248a82010-10-12 20:51:21 +00002182 def _check_multiple_unpicklings(self, ioclass):
2183 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002184 with self.subTest(proto=proto):
2185 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
2186 f = ioclass()
2187 pickler = self.pickler_class(f, protocol=proto)
2188 pickler.dump(data1)
2189 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00002190
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002191 N = 5
2192 f = ioclass(pickled * N)
2193 unpickler = self.unpickler_class(f)
2194 for i in range(N):
2195 if f.seekable():
2196 pos = f.tell()
2197 self.assertEqual(unpickler.load(), data1)
2198 if f.seekable():
2199 self.assertEqual(f.tell(), pos + len(pickled))
2200 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002201
2202 def test_multiple_unpicklings_seekable(self):
2203 self._check_multiple_unpicklings(io.BytesIO)
2204
2205 def test_multiple_unpicklings_unseekable(self):
2206 self._check_multiple_unpicklings(UnseekableIO)
2207
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02002208 def test_unpickling_buffering_readline(self):
2209 # Issue #12687: the unpickler's buffering logic could fail with
2210 # text mode opcodes.
2211 data = list(range(10))
2212 for proto in protocols:
2213 for buf_size in range(1, 11):
2214 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
2215 pickler = self.pickler_class(f, protocol=proto)
2216 pickler.dump(data)
2217 f.seek(0)
2218 unpickler = self.unpickler_class(f)
2219 self.assertEqual(unpickler.load(), data)
2220
Collin Winter771d8342009-04-16 03:18:06 +00002221
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01002222# Tests for dispatch_table attribute
2223
2224REDUCE_A = 'reduce_A'
2225
2226class AAA(object):
2227 def __reduce__(self):
2228 return str, (REDUCE_A,)
2229
2230class BBB(object):
2231 pass
2232
2233class AbstractDispatchTableTests(unittest.TestCase):
2234
2235 def test_default_dispatch_table(self):
2236 # No dispatch_table attribute by default
2237 f = io.BytesIO()
2238 p = self.pickler_class(f, 0)
2239 with self.assertRaises(AttributeError):
2240 p.dispatch_table
2241 self.assertFalse(hasattr(p, 'dispatch_table'))
2242
2243 def test_class_dispatch_table(self):
2244 # A dispatch_table attribute can be specified class-wide
2245 dt = self.get_dispatch_table()
2246
2247 class MyPickler(self.pickler_class):
2248 dispatch_table = dt
2249
2250 def dumps(obj, protocol=None):
2251 f = io.BytesIO()
2252 p = MyPickler(f, protocol)
2253 self.assertEqual(p.dispatch_table, dt)
2254 p.dump(obj)
2255 return f.getvalue()
2256
2257 self._test_dispatch_table(dumps, dt)
2258
2259 def test_instance_dispatch_table(self):
2260 # A dispatch_table attribute can also be specified instance-wide
2261 dt = self.get_dispatch_table()
2262
2263 def dumps(obj, protocol=None):
2264 f = io.BytesIO()
2265 p = self.pickler_class(f, protocol)
2266 p.dispatch_table = dt
2267 self.assertEqual(p.dispatch_table, dt)
2268 p.dump(obj)
2269 return f.getvalue()
2270
2271 self._test_dispatch_table(dumps, dt)
2272
2273 def _test_dispatch_table(self, dumps, dispatch_table):
2274 def custom_load_dump(obj):
2275 return pickle.loads(dumps(obj, 0))
2276
2277 def default_load_dump(obj):
2278 return pickle.loads(pickle.dumps(obj, 0))
2279
2280 # pickling complex numbers using protocol 0 relies on copyreg
2281 # so check pickling a complex number still works
2282 z = 1 + 2j
2283 self.assertEqual(custom_load_dump(z), z)
2284 self.assertEqual(default_load_dump(z), z)
2285
2286 # modify pickling of complex
2287 REDUCE_1 = 'reduce_1'
2288 def reduce_1(obj):
2289 return str, (REDUCE_1,)
2290 dispatch_table[complex] = reduce_1
2291 self.assertEqual(custom_load_dump(z), REDUCE_1)
2292 self.assertEqual(default_load_dump(z), z)
2293
2294 # check picklability of AAA and BBB
2295 a = AAA()
2296 b = BBB()
2297 self.assertEqual(custom_load_dump(a), REDUCE_A)
2298 self.assertIsInstance(custom_load_dump(b), BBB)
2299 self.assertEqual(default_load_dump(a), REDUCE_A)
2300 self.assertIsInstance(default_load_dump(b), BBB)
2301
2302 # modify pickling of BBB
2303 dispatch_table[BBB] = reduce_1
2304 self.assertEqual(custom_load_dump(a), REDUCE_A)
2305 self.assertEqual(custom_load_dump(b), REDUCE_1)
2306 self.assertEqual(default_load_dump(a), REDUCE_A)
2307 self.assertIsInstance(default_load_dump(b), BBB)
2308
2309 # revert pickling of BBB and modify pickling of AAA
2310 REDUCE_2 = 'reduce_2'
2311 def reduce_2(obj):
2312 return str, (REDUCE_2,)
2313 dispatch_table[AAA] = reduce_2
2314 del dispatch_table[BBB]
2315 self.assertEqual(custom_load_dump(a), REDUCE_2)
2316 self.assertIsInstance(custom_load_dump(b), BBB)
2317 self.assertEqual(default_load_dump(a), REDUCE_A)
2318 self.assertIsInstance(default_load_dump(b), BBB)
2319
2320
Guido van Rossum98297ee2007-11-06 21:34:58 +00002321if __name__ == "__main__":
2322 # Print some stuff that can be used to rewrite DATA{0,1,2}
2323 from pickletools import dis
2324 x = create_data()
2325 for i in range(3):
2326 p = pickle.dumps(x, i)
2327 print("DATA{0} = (".format(i))
2328 for j in range(0, len(p), 20):
2329 b = bytes(p[j:j+20])
2330 print(" {0!r}".format(b))
2331 print(")")
2332 print()
2333 print("# Disassembly of DATA{0}".format(i))
2334 print("DATA{0}_DIS = \"\"\"\\".format(i))
2335 dis(p)
2336 print("\"\"\"")
2337 print()