blob: 4f8c2942df93dd72b1508930908c2d050fdaae08 [file] [log] [blame]
Serhiy Storchakabfe18242015-03-31 13:12:37 +03001import collections
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002import copyreg
Serhiy Storchakabfe18242015-03-31 13:12:37 +03003import dbm
Collin Winter771d8342009-04-16 03:18:06 +00004import io
Serhiy Storchakabfe18242015-03-31 13:12:37 +03005import functools
tjb9004371c0a2019-02-18 23:30:51 +08006import os
Pierre Glaser289f1f82019-05-08 23:08:25 +02007import math
Tim Peters4190fb82003-02-02 16:09:05 +00008import pickle
Tim Peters31f119e2003-02-03 16:20:13 +00009import pickletools
tjb9004371c0a2019-02-18 23:30:51 +080010import shutil
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -080011import struct
Antoine Pitrou82be19f2011-08-29 23:09:33 +020012import sys
tjb9004371c0a2019-02-18 23:30:51 +080013import threading
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +010014import unittest
Antoine Pitrou16c4ce12011-03-11 21:30:43 +010015import weakref
tjb9004371c0a2019-02-18 23:30:51 +080016from textwrap import dedent
Antoine Pitroud9dfaa92009-06-04 20:32:06 +000017from http.cookies import SimpleCookie
Tim Peters4190fb82003-02-02 16:09:05 +000018
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020019from test import support
Antoine Pitrou82be19f2011-08-29 23:09:33 +020020from test.support import (
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020021 TestFailed, TESTFN, run_with_locale, no_tracing,
tjb9004371c0a2019-02-18 23:30:51 +080022 _2G, _4G, bigmemtest, reap_threads, forget,
Antoine Pitrou82be19f2011-08-29 23:09:33 +020023 )
Tim Peterse089c682001-04-10 03:41:41 +000024
Guido van Rossum98297ee2007-11-06 21:34:58 +000025from pickle import bytes_types
26
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030027requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
28 "test is only meaningful on 32-bit builds")
29
Tim Petersee1a53c2003-02-02 02:57:53 +000030# Tests that try a number of pickle protocols should have a
31# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000032# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000033protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000034
Tim Peters22e71712003-02-03 22:27:38 +000035
36# Return True if opcode code appears in the pickle, else False.
37def opcode_in_pickle(code, pickle):
38 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000039 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000040 return True
41 return False
42
Tim Peters8d2613a2003-02-11 16:40:16 +000043# Return the number of times opcode code appears in pickle.
44def count_opcode(code, pickle):
45 n = 0
46 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000047 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000048 n += 1
49 return n
50
Antoine Pitrou04248a82010-10-12 20:51:21 +000051
52class UnseekableIO(io.BytesIO):
53 def peek(self, *args):
54 raise NotImplementedError
55
56 def seekable(self):
57 return False
58
59 def seek(self, *args):
60 raise io.UnsupportedOperation
61
62 def tell(self):
63 raise io.UnsupportedOperation
64
65
Tim Peters3e667d52003-02-04 21:47:44 +000066# We can't very well test the extension registry without putting known stuff
67# in it, but we have to be careful to restore its original state. Code
68# should do this:
69#
70# e = ExtensionSaver(extension_code)
71# try:
72# fiddle w/ the extension registry's stuff for extension_code
73# finally:
74# e.restore()
75
76class ExtensionSaver:
77 # Remember current registration for code (if any), and remove it (if
78 # there is one).
79 def __init__(self, code):
80 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000081 if code in copyreg._inverted_registry:
82 self.pair = copyreg._inverted_registry[code]
83 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000084 else:
85 self.pair = None
86
87 # Restore previous registration for code.
88 def restore(self):
89 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000090 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +000091 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000092 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000093 pair = self.pair
94 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000095 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000096
Jeremy Hylton66426532001-10-15 21:38:56 +000097class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +000098 def __eq__(self, other):
99 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000100
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000101class D(C):
102 def __init__(self, arg):
103 pass
104
105class E(C):
106 def __getinitargs__(self):
107 return ()
108
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100109class H(object):
110 pass
111
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200112# Hashable mutable key
113class K(object):
114 def __init__(self, value):
115 self.value = value
116
117 def __reduce__(self):
118 # Shouldn't support the recursion itself
119 return K, (self.value,)
120
Jeremy Hylton66426532001-10-15 21:38:56 +0000121import __main__
122__main__.C = C
123C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000124__main__.D = D
125D.__module__ = "__main__"
126__main__.E = E
127E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100128__main__.H = H
129H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200130__main__.K = K
131K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000132
133class myint(int):
134 def __init__(self, x):
135 self.str = str(x)
136
137class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000138
Jeremy Hylton66426532001-10-15 21:38:56 +0000139 def __init__(self, a, b):
140 self.a = a
141 self.b = b
142
143 def __getinitargs__(self):
144 return self.a, self.b
145
Guido van Rossum04a86612001-12-19 16:58:54 +0000146class metaclass(type):
147 pass
148
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000149class use_metaclass(object, metaclass=metaclass):
150 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000151
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200152class pickling_metaclass(type):
153 def __eq__(self, other):
154 return (type(self) == type(other) and
155 self.reduce_args == other.reduce_args)
156
157 def __reduce__(self):
158 return (create_dynamic_class, self.reduce_args)
159
160def create_dynamic_class(name, bases):
161 result = pickling_metaclass(name, bases, dict())
162 result.reduce_args = (name, bases)
163 return result
164
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300165# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000166# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000167
Guido van Rossum98297ee2007-11-06 21:34:58 +0000168DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200169 b'(lp0\nL0L\naL1L\naF2.0\n'
170 b'ac__builtin__\ncomple'
171 b'x\np1\n(F3.0\nF0.0\ntp2\n'
172 b'Rp3\naL1L\naL-1L\naL255'
173 b'L\naL-255L\naL-256L\naL'
174 b'65535L\naL-65535L\naL-'
175 b'65536L\naL2147483647L'
176 b'\naL-2147483647L\naL-2'
177 b'147483648L\na(Vabc\np4'
178 b'\ng4\nccopy_reg\n_recon'
179 b'structor\np5\n(c__main'
180 b'__\nC\np6\nc__builtin__'
181 b'\nobject\np7\nNtp8\nRp9\n'
182 b'(dp10\nVfoo\np11\nL1L\ns'
183 b'Vbar\np12\nL2L\nsbg9\ntp'
184 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000185)
Tim Peterse9358162001-01-22 22:05:20 +0000186
Guido van Rossum98297ee2007-11-06 21:34:58 +0000187# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000188DATA0_DIS = """\
189 0: ( MARK
190 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000191 2: p PUT 0
192 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000193 9: a APPEND
194 10: L LONG 1
195 14: a APPEND
196 15: F FLOAT 2.0
197 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200198 21: c GLOBAL '__builtin__ complex'
199 42: p PUT 1
200 45: ( MARK
201 46: F FLOAT 3.0
202 51: F FLOAT 0.0
203 56: t TUPLE (MARK at 45)
204 57: p PUT 2
205 60: R REDUCE
206 61: p PUT 3
207 64: a APPEND
208 65: L LONG 1
209 69: a APPEND
210 70: L LONG -1
211 75: a APPEND
212 76: L LONG 255
213 82: a APPEND
214 83: L LONG -255
215 90: a APPEND
216 91: L LONG -256
217 98: a APPEND
218 99: L LONG 65535
219 107: a APPEND
220 108: L LONG -65535
221 117: a APPEND
222 118: L LONG -65536
223 127: a APPEND
224 128: L LONG 2147483647
225 141: a APPEND
226 142: L LONG -2147483647
227 156: a APPEND
228 157: L LONG -2147483648
229 171: a APPEND
230 172: ( MARK
231 173: V UNICODE 'abc'
232 178: p PUT 4
233 181: g GET 4
234 184: c GLOBAL 'copy_reg _reconstructor'
235 209: p PUT 5
236 212: ( MARK
237 213: c GLOBAL '__main__ C'
238 225: p PUT 6
239 228: c GLOBAL '__builtin__ object'
240 248: p PUT 7
241 251: N NONE
242 252: t TUPLE (MARK at 212)
243 253: p PUT 8
244 256: R REDUCE
245 257: p PUT 9
246 260: ( MARK
247 261: d DICT (MARK at 260)
248 262: p PUT 10
249 266: V UNICODE 'foo'
250 271: p PUT 11
251 275: L LONG 1
252 279: s SETITEM
253 280: V UNICODE 'bar'
254 285: p PUT 12
255 289: L LONG 2
256 293: s SETITEM
257 294: b BUILD
258 295: g GET 9
259 298: t TUPLE (MARK at 172)
260 299: p PUT 13
261 303: a APPEND
262 304: g GET 13
263 308: a APPEND
264 309: L LONG 5
265 313: a APPEND
266 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000267highest protocol among opcodes = 0
268"""
269
Guido van Rossum98297ee2007-11-06 21:34:58 +0000270DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200271 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
272 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000273 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
274 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
275 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
276 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200277 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000278 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200279 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000280 b'object\nq\x07Ntq\x08Rq\t}q\n('
281 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
282 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
283)
Tim Peters70b02d72003-02-02 17:26:40 +0000284
Guido van Rossum98297ee2007-11-06 21:34:58 +0000285# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000286DATA1_DIS = """\
287 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000288 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000289 3: ( MARK
290 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000291 6: K BININT1 1
292 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200293 17: c GLOBAL '__builtin__ complex'
294 38: q BINPUT 1
295 40: ( MARK
296 41: G BINFLOAT 3.0
297 50: G BINFLOAT 0.0
298 59: t TUPLE (MARK at 40)
299 60: q BINPUT 2
300 62: R REDUCE
301 63: q BINPUT 3
302 65: K BININT1 1
303 67: J BININT -1
304 72: K BININT1 255
305 74: J BININT -255
306 79: J BININT -256
307 84: M BININT2 65535
308 87: J BININT -65535
309 92: J BININT -65536
310 97: J BININT 2147483647
311 102: J BININT -2147483647
312 107: J BININT -2147483648
313 112: ( MARK
314 113: X BINUNICODE 'abc'
315 121: q BINPUT 4
316 123: h BINGET 4
317 125: c GLOBAL 'copy_reg _reconstructor'
318 150: q BINPUT 5
319 152: ( MARK
320 153: c GLOBAL '__main__ C'
321 165: q BINPUT 6
322 167: c GLOBAL '__builtin__ object'
323 187: q BINPUT 7
324 189: N NONE
325 190: t TUPLE (MARK at 152)
326 191: q BINPUT 8
327 193: R REDUCE
328 194: q BINPUT 9
329 196: } EMPTY_DICT
330 197: q BINPUT 10
331 199: ( MARK
332 200: X BINUNICODE 'foo'
333 208: q BINPUT 11
334 210: K BININT1 1
335 212: X BINUNICODE 'bar'
336 220: q BINPUT 12
337 222: K BININT1 2
338 224: u SETITEMS (MARK at 199)
339 225: b BUILD
340 226: h BINGET 9
341 228: t TUPLE (MARK at 112)
342 229: q BINPUT 13
343 231: h BINGET 13
344 233: K BININT1 5
345 235: e APPENDS (MARK at 3)
346 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000347highest protocol among opcodes = 1
348"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000349
Guido van Rossum98297ee2007-11-06 21:34:58 +0000350DATA2 = (
351 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200352 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000353 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
354 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
355 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
356 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
357 b'bcq\x04h\x04c__main__\nC\nq\x05'
358 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
359 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
360 b'\nK\x05e.'
361)
Tim Petersfc273752003-03-02 04:54:24 +0000362
Guido van Rossum98297ee2007-11-06 21:34:58 +0000363# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000364DATA2_DIS = """\
365 0: \x80 PROTO 2
366 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000367 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000368 5: ( MARK
369 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000370 8: K BININT1 1
371 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200372 19: c GLOBAL '__builtin__ complex'
373 40: q BINPUT 1
374 42: G BINFLOAT 3.0
375 51: G BINFLOAT 0.0
376 60: \x86 TUPLE2
377 61: q BINPUT 2
378 63: R REDUCE
379 64: q BINPUT 3
380 66: K BININT1 1
381 68: J BININT -1
382 73: K BININT1 255
383 75: J BININT -255
384 80: J BININT -256
385 85: M BININT2 65535
386 88: J BININT -65535
387 93: J BININT -65536
388 98: J BININT 2147483647
389 103: J BININT -2147483647
390 108: J BININT -2147483648
391 113: ( MARK
392 114: X BINUNICODE 'abc'
393 122: q BINPUT 4
394 124: h BINGET 4
395 126: c GLOBAL '__main__ C'
396 138: q BINPUT 5
397 140: ) EMPTY_TUPLE
398 141: \x81 NEWOBJ
399 142: q BINPUT 6
400 144: } EMPTY_DICT
401 145: q BINPUT 7
402 147: ( MARK
403 148: X BINUNICODE 'foo'
404 156: q BINPUT 8
405 158: K BININT1 1
406 160: X BINUNICODE 'bar'
407 168: q BINPUT 9
408 170: K BININT1 2
409 172: u SETITEMS (MARK at 147)
410 173: b BUILD
411 174: h BINGET 6
412 176: t TUPLE (MARK at 113)
413 177: q BINPUT 10
414 179: h BINGET 10
415 181: K BININT1 5
416 183: e APPENDS (MARK at 5)
417 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000418highest protocol among opcodes = 2
419"""
420
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300421DATA3 = (
422 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
423 b'builtins\ncomplex\nq\x01G'
424 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
425 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
426 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
427 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
428 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
429 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
430 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
431 b'e.'
432)
433
434# Disassembly of DATA3
435DATA3_DIS = """\
436 0: \x80 PROTO 3
437 2: ] EMPTY_LIST
438 3: q BINPUT 0
439 5: ( MARK
440 6: K BININT1 0
441 8: K BININT1 1
442 10: G BINFLOAT 2.0
443 19: c GLOBAL 'builtins complex'
444 37: q BINPUT 1
445 39: G BINFLOAT 3.0
446 48: G BINFLOAT 0.0
447 57: \x86 TUPLE2
448 58: q BINPUT 2
449 60: R REDUCE
450 61: q BINPUT 3
451 63: K BININT1 1
452 65: J BININT -1
453 70: K BININT1 255
454 72: J BININT -255
455 77: J BININT -256
456 82: M BININT2 65535
457 85: J BININT -65535
458 90: J BININT -65536
459 95: J BININT 2147483647
460 100: J BININT -2147483647
461 105: J BININT -2147483648
462 110: ( MARK
463 111: X BINUNICODE 'abc'
464 119: q BINPUT 4
465 121: h BINGET 4
466 123: c GLOBAL '__main__ C'
467 135: q BINPUT 5
468 137: ) EMPTY_TUPLE
469 138: \x81 NEWOBJ
470 139: q BINPUT 6
471 141: } EMPTY_DICT
472 142: q BINPUT 7
473 144: ( MARK
474 145: X BINUNICODE 'bar'
475 153: q BINPUT 8
476 155: K BININT1 2
477 157: X BINUNICODE 'foo'
478 165: q BINPUT 9
479 167: K BININT1 1
480 169: u SETITEMS (MARK at 144)
481 170: b BUILD
482 171: h BINGET 6
483 173: t TUPLE (MARK at 110)
484 174: q BINPUT 10
485 176: h BINGET 10
486 178: K BININT1 5
487 180: e APPENDS (MARK at 5)
488 181: . STOP
489highest protocol among opcodes = 2
490"""
491
492DATA4 = (
493 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
494 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
495 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
496 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
497 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
498 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
499 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
500 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
501 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
502)
503
504# Disassembly of DATA4
505DATA4_DIS = """\
506 0: \x80 PROTO 4
507 2: \x95 FRAME 168
508 11: ] EMPTY_LIST
509 12: \x94 MEMOIZE
510 13: ( MARK
511 14: K BININT1 0
512 16: K BININT1 1
513 18: G BINFLOAT 2.0
514 27: \x8c SHORT_BINUNICODE 'builtins'
515 37: \x94 MEMOIZE
516 38: \x8c SHORT_BINUNICODE 'complex'
517 47: \x94 MEMOIZE
518 48: \x93 STACK_GLOBAL
519 49: \x94 MEMOIZE
520 50: G BINFLOAT 3.0
521 59: G BINFLOAT 0.0
522 68: \x86 TUPLE2
523 69: \x94 MEMOIZE
524 70: R REDUCE
525 71: \x94 MEMOIZE
526 72: K BININT1 1
527 74: J BININT -1
528 79: K BININT1 255
529 81: J BININT -255
530 86: J BININT -256
531 91: M BININT2 65535
532 94: J BININT -65535
533 99: J BININT -65536
534 104: J BININT 2147483647
535 109: J BININT -2147483647
536 114: J BININT -2147483648
537 119: ( MARK
538 120: \x8c SHORT_BINUNICODE 'abc'
539 125: \x94 MEMOIZE
540 126: h BINGET 6
541 128: \x8c SHORT_BINUNICODE '__main__'
542 138: \x94 MEMOIZE
543 139: \x8c SHORT_BINUNICODE 'C'
544 142: \x94 MEMOIZE
545 143: \x93 STACK_GLOBAL
546 144: \x94 MEMOIZE
547 145: ) EMPTY_TUPLE
548 146: \x81 NEWOBJ
549 147: \x94 MEMOIZE
550 148: } EMPTY_DICT
551 149: \x94 MEMOIZE
552 150: ( MARK
553 151: \x8c SHORT_BINUNICODE 'bar'
554 156: \x94 MEMOIZE
555 157: K BININT1 2
556 159: \x8c SHORT_BINUNICODE 'foo'
557 164: \x94 MEMOIZE
558 165: K BININT1 1
559 167: u SETITEMS (MARK at 150)
560 168: b BUILD
561 169: h BINGET 10
562 171: t TUPLE (MARK at 119)
563 172: \x94 MEMOIZE
564 173: h BINGET 14
565 175: K BININT1 5
566 177: e APPENDS (MARK at 13)
567 178: . STOP
568highest protocol among opcodes = 4
569"""
570
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000571# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300572DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000573
574# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300575DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000576
577# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300578DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
579 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
580 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
581 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
582 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
583 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000584
585# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300586DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000587
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100588python2_exceptions_without_args = (
589 ArithmeticError,
590 AssertionError,
591 AttributeError,
592 BaseException,
593 BufferError,
594 BytesWarning,
595 DeprecationWarning,
596 EOFError,
597 EnvironmentError,
598 Exception,
599 FloatingPointError,
600 FutureWarning,
601 GeneratorExit,
602 IOError,
603 ImportError,
604 ImportWarning,
605 IndentationError,
606 IndexError,
607 KeyError,
608 KeyboardInterrupt,
609 LookupError,
610 MemoryError,
611 NameError,
612 NotImplementedError,
613 OSError,
614 OverflowError,
615 PendingDeprecationWarning,
616 ReferenceError,
617 RuntimeError,
618 RuntimeWarning,
619 # StandardError is gone in Python 3, we map it to Exception
620 StopIteration,
621 SyntaxError,
622 SyntaxWarning,
623 SystemError,
624 SystemExit,
625 TabError,
626 TypeError,
627 UnboundLocalError,
628 UnicodeError,
629 UnicodeWarning,
630 UserWarning,
631 ValueError,
632 Warning,
633 ZeroDivisionError,
634)
635
636exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
637
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100638# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300639DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
640 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
641 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100642
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000643
Jeremy Hylton66426532001-10-15 21:38:56 +0000644def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000645 c = C()
646 c.foo = 1
647 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000648 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000649 # Append some integer test cases at cPickle.c's internal size
650 # cutoffs.
651 uint1max = 0xff
652 uint2max = 0xffff
653 int4max = 0x7fffffff
654 x.extend([1, -1,
655 uint1max, -uint1max, -uint1max-1,
656 uint2max, -uint2max, -uint2max-1,
657 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000658 y = ('abc', 'abc', c, c)
659 x.append(y)
660 x.append(y)
661 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000662 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000663
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100664
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300665class AbstractUnpickleTests(unittest.TestCase):
666 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100667
Jeremy Hylton66426532001-10-15 21:38:56 +0000668 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000669
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100670 def assert_is_copy(self, obj, objcopy, msg=None):
671 """Utility method to verify if two objects are copies of each others.
672 """
673 if msg is None:
674 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
675 self.assertEqual(obj, objcopy, msg=msg)
676 self.assertIs(type(obj), type(objcopy), msg=msg)
677 if hasattr(obj, '__dict__'):
678 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
679 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
680 if hasattr(obj, '__slots__'):
681 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
682 for slot in obj.__slots__:
683 self.assertEqual(
684 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
685 self.assertEqual(getattr(obj, slot, None),
686 getattr(objcopy, slot, None), msg=msg)
687
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200688 def check_unpickling_error(self, errors, data):
689 with self.subTest(data=data), \
690 self.assertRaises(errors):
691 try:
692 self.loads(data)
693 except BaseException as exc:
694 if support.verbose > 1:
695 print('%-32r - %s: %s' %
696 (data, exc.__class__.__name__, exc))
697 raise
698
Guido van Rossum98297ee2007-11-06 21:34:58 +0000699 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100700 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000701
702 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100703 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000704
705 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100706 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000707
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300708 def test_load_from_data3(self):
709 self.assert_is_copy(self._testdata, self.loads(DATA3))
710
711 def test_load_from_data4(self):
712 self.assert_is_copy(self._testdata, self.loads(DATA4))
713
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000714 def test_load_classic_instance(self):
715 # See issue5180. Test loading 2.x pickles that
716 # contain an instance of old style class.
717 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
718 xname = X.__name__.encode('ascii')
719 # Protocol 0 (text mode pickle):
720 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200721 0: ( MARK
722 1: i INST '__main__ X' (MARK at 0)
723 13: p PUT 0
724 16: ( MARK
725 17: d DICT (MARK at 16)
726 18: p PUT 1
727 21: b BUILD
728 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000729 """
730 pickle0 = (b"(i__main__\n"
731 b"X\n"
732 b"p0\n"
733 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100734 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000735
736 # Protocol 1 (binary mode pickle)
737 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200738 0: ( MARK
739 1: c GLOBAL '__main__ X'
740 13: q BINPUT 0
741 15: o OBJ (MARK at 0)
742 16: q BINPUT 1
743 18: } EMPTY_DICT
744 19: q BINPUT 2
745 21: b BUILD
746 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000747 """
748 pickle1 = (b'(c__main__\n'
749 b'X\n'
750 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100751 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000752
753 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
754 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200755 0: \x80 PROTO 2
756 2: ( MARK
757 3: c GLOBAL '__main__ X'
758 15: q BINPUT 0
759 17: o OBJ (MARK at 2)
760 18: q BINPUT 1
761 20: } EMPTY_DICT
762 21: q BINPUT 2
763 23: b BUILD
764 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000765 """
766 pickle2 = (b'\x80\x02(c__main__\n'
767 b'X\n'
768 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100769 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000770
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300771 def test_maxint64(self):
772 maxint64 = (1 << 63) - 1
773 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
774 got = self.loads(data)
775 self.assert_is_copy(maxint64, got)
776
777 # Try too with a bogus literal.
778 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200779 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300780
781 def test_unpickle_from_2x(self):
782 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300783 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300784 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300785 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300786 self.assertEqual(type(loaded), type(range(0)))
787 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300788 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300789 self.assertEqual(type(loaded), SimpleCookie)
790 self.assertEqual(list(loaded.keys()), ["key"])
791 self.assertEqual(loaded["key"].value, "value")
792
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300793 # Exception objects without arguments pickled from 2.x with protocol 2
794 for exc in python2_exceptions_without_args:
795 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300796 loaded = self.loads(data)
797 self.assertIs(type(loaded), exc)
798
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300799 # StandardError is mapped to Exception, test that separately
800 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300801 self.assertIs(type(loaded), Exception)
802
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300803 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300804 self.assertIs(type(loaded), UnicodeEncodeError)
805 self.assertEqual(loaded.object, "foo")
806 self.assertEqual(loaded.encoding, "ascii")
807 self.assertEqual(loaded.start, 0)
808 self.assertEqual(loaded.end, 1)
809 self.assertEqual(loaded.reason, "bad")
810
811 def test_load_python2_str_as_bytes(self):
812 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
813 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
814 encoding="bytes"), b'a\x00\xa0')
815 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
816 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
817 encoding="bytes"), b'a\x00\xa0')
818 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
819 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
820 encoding="bytes"), b'a\x00\xa0')
821
822 def test_load_python2_unicode_as_str(self):
823 # From Python 2: pickle.dumps(u'π', protocol=0)
824 self.assertEqual(self.loads(b'V\\u03c0\n.',
825 encoding='bytes'), 'π')
826 # From Python 2: pickle.dumps(u'π', protocol=1)
827 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
828 encoding="bytes"), 'π')
829 # From Python 2: pickle.dumps(u'π', protocol=2)
830 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
831 encoding="bytes"), 'π')
832
833 def test_load_long_python2_str_as_bytes(self):
834 # From Python 2: pickle.dumps('x' * 300, protocol=1)
835 self.assertEqual(self.loads(pickle.BINSTRING +
836 struct.pack("<I", 300) +
837 b'x' * 300 + pickle.STOP,
838 encoding='bytes'), b'x' * 300)
839
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300840 def test_constants(self):
841 self.assertIsNone(self.loads(b'N.'))
842 self.assertIs(self.loads(b'\x88.'), True)
843 self.assertIs(self.loads(b'\x89.'), False)
844 self.assertIs(self.loads(b'I01\n.'), True)
845 self.assertIs(self.loads(b'I00\n.'), False)
846
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300847 def test_empty_bytestring(self):
848 # issue 11286
849 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
850 self.assertEqual(empty, '')
851
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300852 def test_short_binbytes(self):
853 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
854 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
855
856 def test_binbytes(self):
857 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
858 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
859
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300860 @requires_32b
861 def test_negative_32b_binbytes(self):
862 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
863 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200864 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
865 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300866
867 @requires_32b
868 def test_negative_32b_binunicode(self):
869 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
870 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200871 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
872 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300873
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300874 def test_short_binunicode(self):
875 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
876 self.assertEqual(self.loads(dumped), '\u20ac\x00')
877
878 def test_misc_get(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200879 self.check_unpickling_error(KeyError, b'g0\np0')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300880 self.assert_is_copy([(100,), (100,)],
881 self.loads(b'((Kdtp0\nh\x00l.))'))
882
Serhiy Storchakae0606192015-09-29 22:10:07 +0300883 def test_binbytes8(self):
884 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
885 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
886
887 def test_binunicode8(self):
888 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
889 self.assertEqual(self.loads(dumped), '\u20ac\x00')
890
891 @requires_32b
892 def test_large_32b_binbytes8(self):
893 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200894 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
895 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +0300896
897 @requires_32b
898 def test_large_32b_binunicode8(self):
899 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200900 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
901 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +0300902
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300903 def test_get(self):
904 pickled = b'((lp100000\ng100000\nt.'
905 unpickled = self.loads(pickled)
906 self.assertEqual(unpickled, ([],)*2)
907 self.assertIs(unpickled[0], unpickled[1])
908
909 def test_binget(self):
910 pickled = b'(]q\xffh\xfft.'
911 unpickled = self.loads(pickled)
912 self.assertEqual(unpickled, ([],)*2)
913 self.assertIs(unpickled[0], unpickled[1])
914
915 def test_long_binget(self):
916 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
917 unpickled = self.loads(pickled)
918 self.assertEqual(unpickled, ([],)*2)
919 self.assertIs(unpickled[0], unpickled[1])
920
921 def test_dup(self):
922 pickled = b'((l2t.'
923 unpickled = self.loads(pickled)
924 self.assertEqual(unpickled, ([],)*2)
925 self.assertIs(unpickled[0], unpickled[1])
926
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300927 def test_negative_put(self):
928 # Issue #12847
929 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200930 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300931
932 @requires_32b
933 def test_negative_32b_binput(self):
934 # Issue #12847
935 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200936 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300937
938 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200939 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300940
941 def test_badly_quoted_string(self):
942 # Issue #17710
943 badpickles = [b"S'\n.",
944 b'S"\n.',
945 b'S\' \n.',
946 b'S" \n.',
947 b'S\'"\n.',
948 b'S"\'\n.',
949 b"S' ' \n.",
950 b'S" " \n.',
951 b"S ''\n.",
952 b'S ""\n.',
953 b'S \n.',
954 b'S\n.',
955 b'S.']
956 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200957 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300958
959 def test_correctly_quoted_string(self):
960 goodpickles = [(b"S''\n.", ''),
961 (b'S""\n.', ''),
962 (b'S"\\n"\n.', '\n'),
963 (b"S'\\n'\n.", '\n')]
964 for p, expected in goodpickles:
965 self.assertEqual(self.loads(p), expected)
966
967 def test_frame_readline(self):
968 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
969 # 0: \x80 PROTO 4
970 # 2: \x95 FRAME 5
971 # 11: I INT 42
972 # 15: . STOP
973 self.assertEqual(self.loads(pickled), 42)
974
975 def test_compat_unpickle(self):
976 # xrange(1, 7)
977 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
978 unpickled = self.loads(pickled)
979 self.assertIs(type(unpickled), range)
980 self.assertEqual(unpickled, range(1, 7))
981 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
982 # reduce
983 pickled = b'\x80\x02c__builtin__\nreduce\n.'
984 self.assertIs(self.loads(pickled), functools.reduce)
985 # whichdb.whichdb
986 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
987 self.assertIs(self.loads(pickled), dbm.whichdb)
988 # Exception(), StandardError()
989 for name in (b'Exception', b'StandardError'):
990 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
991 unpickled = self.loads(pickled)
992 self.assertIs(type(unpickled), Exception)
993 self.assertEqual(str(unpickled), 'ugh')
994 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
995 for name in (b'UserDict', b'IterableUserDict'):
996 pickled = (b'\x80\x02(cUserDict\n' + name +
997 b'\no}U\x04data}K\x01K\x02ssb.')
998 unpickled = self.loads(pickled)
999 self.assertIs(type(unpickled), collections.UserDict)
1000 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1001
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001002 def test_bad_stack(self):
1003 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001004 b'.', # STOP
1005 b'0', # POP
1006 b'1', # POP_MARK
1007 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001008 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001009 b'R', # REDUCE
1010 b')R',
1011 b'a', # APPEND
1012 b'Na',
1013 b'b', # BUILD
1014 b'Nb',
1015 b'd', # DICT
1016 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001017 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001018 b'ibuiltins\nlist\n', # INST
1019 b'l', # LIST
1020 b'o', # OBJ
1021 b'(o',
1022 b'p1\n', # PUT
1023 b'q\x00', # BINPUT
1024 b'r\x00\x00\x00\x00', # LONG_BINPUT
1025 b's', # SETITEM
1026 b'Ns',
1027 b'NNs',
1028 b't', # TUPLE
1029 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001030 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001031 b'}(Nu',
1032 b'\x81', # NEWOBJ
1033 b')\x81',
1034 b'\x85', # TUPLE1
1035 b'\x86', # TUPLE2
1036 b'N\x86',
1037 b'\x87', # TUPLE3
1038 b'N\x87',
1039 b'NN\x87',
1040 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001041 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001042 b'\x91', # FROZENSET
1043 b'\x92', # NEWOBJ_EX
1044 b')}\x92',
1045 b'\x93', # STACK_GLOBAL
1046 b'Vlist\n\x93',
1047 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001048 ]
1049 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001050 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001051
1052 def test_bad_mark(self):
1053 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001054 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001055 b'N(2', # DUP
1056 b'cbuiltins\nlist\n)(R', # REDUCE
1057 b'cbuiltins\nlist\n()R',
1058 b']N(a', # APPEND
1059 # BUILD
1060 b'cbuiltins\nValueError\n)R}(b',
1061 b'cbuiltins\nValueError\n)R(}b',
1062 b'(Nd', # DICT
1063 b'N(p1\n', # PUT
1064 b'N(q\x00', # BINPUT
1065 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1066 b'}NN(s', # SETITEM
1067 b'}N(Ns',
1068 b'}(NNs',
1069 b'}((u', # SETITEMS
1070 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1071 b'cbuiltins\nlist\n()\x81',
1072 b'N(\x85', # TUPLE1
1073 b'NN(\x86', # TUPLE2
1074 b'N(N\x86',
1075 b'NNN(\x87', # TUPLE3
1076 b'NN(N\x87',
1077 b'N(NN\x87',
1078 b']((\x90', # ADDITEMS
1079 # NEWOBJ_EX
1080 b'cbuiltins\nlist\n)}(\x92',
1081 b'cbuiltins\nlist\n)(}\x92',
1082 b'cbuiltins\nlist\n()}\x92',
1083 # STACK_GLOBAL
1084 b'Vbuiltins\n(Vlist\n\x93',
1085 b'Vbuiltins\nVlist\n(\x93',
1086 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001087 ]
1088 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001089 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001090
1091 def test_truncated_data(self):
1092 self.check_unpickling_error(EOFError, b'')
1093 self.check_unpickling_error(EOFError, b'N')
1094 badpickles = [
1095 b'B', # BINBYTES
1096 b'B\x03\x00\x00',
1097 b'B\x03\x00\x00\x00',
1098 b'B\x03\x00\x00\x00ab',
1099 b'C', # SHORT_BINBYTES
1100 b'C\x03',
1101 b'C\x03ab',
1102 b'F', # FLOAT
1103 b'F0.0',
1104 b'F0.00',
1105 b'G', # BINFLOAT
1106 b'G\x00\x00\x00\x00\x00\x00\x00',
1107 b'I', # INT
1108 b'I0',
1109 b'J', # BININT
1110 b'J\x00\x00\x00',
1111 b'K', # BININT1
1112 b'L', # LONG
1113 b'L0',
1114 b'L10',
1115 b'L0L',
1116 b'L10L',
1117 b'M', # BININT2
1118 b'M\x00',
1119 # b'P', # PERSID
1120 # b'Pabc',
1121 b'S', # STRING
1122 b"S'abc'",
1123 b'T', # BINSTRING
1124 b'T\x03\x00\x00',
1125 b'T\x03\x00\x00\x00',
1126 b'T\x03\x00\x00\x00ab',
1127 b'U', # SHORT_BINSTRING
1128 b'U\x03',
1129 b'U\x03ab',
1130 b'V', # UNICODE
1131 b'Vabc',
1132 b'X', # BINUNICODE
1133 b'X\x03\x00\x00',
1134 b'X\x03\x00\x00\x00',
1135 b'X\x03\x00\x00\x00ab',
1136 b'(c', # GLOBAL
1137 b'(cbuiltins',
1138 b'(cbuiltins\n',
1139 b'(cbuiltins\nlist',
1140 b'Ng', # GET
1141 b'Ng0',
1142 b'(i', # INST
1143 b'(ibuiltins',
1144 b'(ibuiltins\n',
1145 b'(ibuiltins\nlist',
1146 b'Nh', # BINGET
1147 b'Nj', # LONG_BINGET
1148 b'Nj\x00\x00\x00',
1149 b'Np', # PUT
1150 b'Np0',
1151 b'Nq', # BINPUT
1152 b'Nr', # LONG_BINPUT
1153 b'Nr\x00\x00\x00',
1154 b'\x80', # PROTO
1155 b'\x82', # EXT1
1156 b'\x83', # EXT2
1157 b'\x84\x01',
1158 b'\x84', # EXT4
1159 b'\x84\x01\x00\x00',
1160 b'\x8a', # LONG1
1161 b'\x8b', # LONG4
1162 b'\x8b\x00\x00\x00',
1163 b'\x8c', # SHORT_BINUNICODE
1164 b'\x8c\x03',
1165 b'\x8c\x03ab',
1166 b'\x8d', # BINUNICODE8
1167 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1168 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1169 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1170 b'\x8e', # BINBYTES8
1171 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1172 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1173 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
1174 b'\x95', # FRAME
1175 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1176 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1177 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1178 ]
1179 for p in badpickles:
1180 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001181
tjb9004371c0a2019-02-18 23:30:51 +08001182 @reap_threads
1183 def test_unpickle_module_race(self):
1184 # https://bugs.python.org/issue34572
1185 locker_module = dedent("""
1186 import threading
1187 barrier = threading.Barrier(2)
1188 """)
1189 locking_import_module = dedent("""
1190 import locker
1191 locker.barrier.wait()
1192 class ToBeUnpickled(object):
1193 pass
1194 """)
1195
1196 os.mkdir(TESTFN)
1197 self.addCleanup(shutil.rmtree, TESTFN)
1198 sys.path.insert(0, TESTFN)
1199 self.addCleanup(sys.path.remove, TESTFN)
1200 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1201 f.write(locker_module.encode('utf-8'))
1202 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1203 f.write(locking_import_module.encode('utf-8'))
1204 self.addCleanup(forget, "locker")
1205 self.addCleanup(forget, "locking_import")
1206
1207 import locker
1208
1209 pickle_bytes = (
1210 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1211
1212 # Then try to unpickle two of these simultaneously
1213 # One of them will cause the module import, and we want it to block
1214 # until the other one either:
1215 # - fails (before the patch for this issue)
1216 # - blocks on the import lock for the module, as it should
1217 results = []
1218 barrier = threading.Barrier(3)
1219 def t():
1220 # This ensures the threads have all started
1221 # presumably barrier release is faster than thread startup
1222 barrier.wait()
1223 results.append(pickle.loads(pickle_bytes))
1224
1225 t1 = threading.Thread(target=t)
1226 t2 = threading.Thread(target=t)
1227 t1.start()
1228 t2.start()
1229
1230 barrier.wait()
1231 # could have delay here
1232 locker.barrier.wait()
1233
1234 t1.join()
1235 t2.join()
1236
1237 from locking_import import ToBeUnpickled
1238 self.assertEqual(
1239 [type(x) for x in results],
1240 [ToBeUnpickled] * 2)
1241
1242
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001243
1244class AbstractPickleTests(unittest.TestCase):
1245 # Subclass must define self.dumps, self.loads.
1246
1247 optimized = False
1248
1249 _testdata = AbstractUnpickleTests._testdata
1250
1251 def setUp(self):
1252 pass
1253
1254 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1255
1256 def test_misc(self):
1257 # test various datatypes not tested by testdata
1258 for proto in protocols:
1259 x = myint(4)
1260 s = self.dumps(x, proto)
1261 y = self.loads(s)
1262 self.assert_is_copy(x, y)
1263
1264 x = (1, ())
1265 s = self.dumps(x, proto)
1266 y = self.loads(s)
1267 self.assert_is_copy(x, y)
1268
1269 x = initarg(1, x)
1270 s = self.dumps(x, proto)
1271 y = self.loads(s)
1272 self.assert_is_copy(x, y)
1273
1274 # XXX test __reduce__ protocol?
1275
1276 def test_roundtrip_equality(self):
1277 expected = self._testdata
1278 for proto in protocols:
1279 s = self.dumps(expected, proto)
1280 got = self.loads(s)
1281 self.assert_is_copy(expected, got)
1282
Tim Peters70b02d72003-02-02 17:26:40 +00001283 # There are gratuitous differences between pickles produced by
1284 # pickle and cPickle, largely because cPickle starts PUT indices at
1285 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1286 # there's a comment with an exclamation point there whose meaning
1287 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1288 # of 1.
1289 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001290 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001291 from pickletools import dis
1292
1293 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1294 s = self.dumps(self._testdata, proto)
1295 filelike = StringIO()
1296 dis(s, out=filelike)
1297 got = filelike.getvalue()
1298 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001299
1300 def test_recursive_list(self):
1301 l = []
1302 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001303 for proto in protocols:
1304 s = self.dumps(l, proto)
1305 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001306 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001307 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001308 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001309
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001310 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001311 t = ([],)
1312 t[0].append(t)
1313 for proto in protocols:
1314 s = self.dumps(t, proto)
1315 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001316 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001317 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001318 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001319 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001320 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001321
Jeremy Hylton66426532001-10-15 21:38:56 +00001322 def test_recursive_dict(self):
1323 d = {}
1324 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001325 for proto in protocols:
1326 s = self.dumps(d, proto)
1327 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001328 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001329 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001330 self.assertIs(x[1], x)
1331
1332 def test_recursive_dict_key(self):
1333 d = {}
1334 k = K(d)
1335 d[k] = 1
1336 for proto in protocols:
1337 s = self.dumps(d, proto)
1338 x = self.loads(s)
1339 self.assertIsInstance(x, dict)
1340 self.assertEqual(len(x.keys()), 1)
1341 self.assertIsInstance(list(x.keys())[0], K)
1342 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001343
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001344 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001345 y = set()
1346 k = K(y)
1347 y.add(k)
1348 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001349 s = self.dumps(y, proto)
1350 x = self.loads(s)
1351 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001352 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001353 self.assertIsInstance(list(x)[0], K)
1354 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001355
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001356 def test_recursive_list_subclass(self):
1357 y = MyList()
1358 y.append(y)
1359 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001360 s = self.dumps(y, proto)
1361 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001362 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001363 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001364 self.assertIs(x[0], x)
1365
1366 def test_recursive_dict_subclass(self):
1367 d = MyDict()
1368 d[1] = d
1369 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1370 s = self.dumps(d, proto)
1371 x = self.loads(s)
1372 self.assertIsInstance(x, MyDict)
1373 self.assertEqual(list(x.keys()), [1])
1374 self.assertIs(x[1], x)
1375
1376 def test_recursive_dict_subclass_key(self):
1377 d = MyDict()
1378 k = K(d)
1379 d[k] = 1
1380 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1381 s = self.dumps(d, proto)
1382 x = self.loads(s)
1383 self.assertIsInstance(x, MyDict)
1384 self.assertEqual(len(list(x.keys())), 1)
1385 self.assertIsInstance(list(x.keys())[0], K)
1386 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001387
Jeremy Hylton66426532001-10-15 21:38:56 +00001388 def test_recursive_inst(self):
1389 i = C()
1390 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001391 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001392 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001393 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001394 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001395 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001396 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001397
1398 def test_recursive_multi(self):
1399 l = []
1400 d = {1:l}
1401 i = C()
1402 i.attr = d
1403 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001404 for proto in protocols:
1405 s = self.dumps(l, proto)
1406 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001407 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001408 self.assertEqual(len(x), 1)
1409 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001410 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001411 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001412
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001413 def check_recursive_collection_and_inst(self, factory):
1414 h = H()
1415 y = factory([h])
1416 h.attr = y
1417 for proto in protocols:
1418 s = self.dumps(y, proto)
1419 x = self.loads(s)
1420 self.assertIsInstance(x, type(y))
1421 self.assertEqual(len(x), 1)
1422 self.assertIsInstance(list(x)[0], H)
1423 self.assertIs(list(x)[0].attr, x)
1424
1425 def test_recursive_list_and_inst(self):
1426 self.check_recursive_collection_and_inst(list)
1427
1428 def test_recursive_tuple_and_inst(self):
1429 self.check_recursive_collection_and_inst(tuple)
1430
1431 def test_recursive_dict_and_inst(self):
1432 self.check_recursive_collection_and_inst(dict.fromkeys)
1433
1434 def test_recursive_set_and_inst(self):
1435 self.check_recursive_collection_and_inst(set)
1436
1437 def test_recursive_frozenset_and_inst(self):
1438 self.check_recursive_collection_and_inst(frozenset)
1439
1440 def test_recursive_list_subclass_and_inst(self):
1441 self.check_recursive_collection_and_inst(MyList)
1442
1443 def test_recursive_tuple_subclass_and_inst(self):
1444 self.check_recursive_collection_and_inst(MyTuple)
1445
1446 def test_recursive_dict_subclass_and_inst(self):
1447 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1448
1449 def test_recursive_set_subclass_and_inst(self):
1450 self.check_recursive_collection_and_inst(MySet)
1451
1452 def test_recursive_frozenset_subclass_and_inst(self):
1453 self.check_recursive_collection_and_inst(MyFrozenSet)
1454
Walter Dörwald9b775532007-06-08 14:30:53 +00001455 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001456 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001457 '<\\>', '<\\\U00012345>',
1458 # surrogates
1459 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001460 for proto in protocols:
1461 for u in endcases:
1462 p = self.dumps(u, proto)
1463 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001464 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001465
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001466 def test_unicode_high_plane(self):
1467 t = '\U00012345'
1468 for proto in protocols:
1469 p = self.dumps(t, proto)
1470 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001471 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001472
Guido van Rossumf4169812008-03-17 22:56:06 +00001473 def test_bytes(self):
1474 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001475 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001476 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001477 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001478 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001479 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001480 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001481 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001482 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001483 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001484
Jeremy Hylton66426532001-10-15 21:38:56 +00001485 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001486 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001487 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001488 while n:
1489 for expected in (-n, n):
1490 s = self.dumps(expected, proto)
1491 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001492 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001493 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001494
Tim Petersee1a53c2003-02-02 02:57:53 +00001495 def test_long(self):
1496 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001497 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001498 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001499 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001500 for npos in nbase-1, nbase, nbase+1:
1501 for n in npos, -npos:
1502 pickle = self.dumps(n, proto)
1503 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001504 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001505 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1506 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001507 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001508 nbase += nbase << 1000000
1509 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001510 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001511 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001512 # assert_is_copy is very expensive here as it precomputes
1513 # a failure message by computing the repr() of n and got,
1514 # we just do the check ourselves.
1515 self.assertIs(type(got), int)
1516 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001517
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001518 def test_float(self):
1519 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1520 3.14, 263.44582062374053, 6.022e23, 1e30]
1521 test_values = test_values + [-x for x in test_values]
1522 for proto in protocols:
1523 for value in test_values:
1524 pickle = self.dumps(value, proto)
1525 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001526 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001527
Thomas Wouters477c8d52006-05-27 19:21:47 +00001528 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1529 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001530 # make sure that floats are formatted locale independent with proto 0
1531 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001532
Jeremy Hylton66426532001-10-15 21:38:56 +00001533 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001534 for proto in protocols:
1535 inst = AAA()
1536 dumped = self.dumps(inst, proto)
1537 loaded = self.loads(dumped)
1538 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001539
1540 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001541 for proto in protocols:
1542 inst = initarg(1, 2)
1543 dumped = self.dumps(inst, proto)
1544 loaded = self.loads(dumped)
1545 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001546
Guido van Rossum04a86612001-12-19 16:58:54 +00001547 def test_metaclass(self):
1548 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001549 for proto in protocols:
1550 s = self.dumps(a, proto)
1551 b = self.loads(s)
1552 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001553
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001554 def test_dynamic_class(self):
1555 a = create_dynamic_class("my_dynamic_class", (object,))
1556 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1557 for proto in protocols:
1558 s = self.dumps(a, proto)
1559 b = self.loads(s)
1560 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001561 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001562
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001563 def test_structseq(self):
1564 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001565 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001566
1567 t = time.localtime()
1568 for proto in protocols:
1569 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001570 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001571 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001572 t = os.stat(os.curdir)
1573 s = self.dumps(t, proto)
1574 u = self.loads(s)
1575 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001576 if hasattr(os, "statvfs"):
1577 t = os.statvfs(os.curdir)
1578 s = self.dumps(t, proto)
1579 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001580 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001581
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001582 def test_ellipsis(self):
1583 for proto in protocols:
1584 s = self.dumps(..., proto)
1585 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001586 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001587
1588 def test_notimplemented(self):
1589 for proto in protocols:
1590 s = self.dumps(NotImplemented, proto)
1591 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001592 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001593
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001594 def test_singleton_types(self):
1595 # Issue #6477: Test that types of built-in singletons can be pickled.
1596 singletons = [None, ..., NotImplemented]
1597 for singleton in singletons:
1598 for proto in protocols:
1599 s = self.dumps(type(singleton), proto)
1600 u = self.loads(s)
1601 self.assertIs(type(singleton), u)
1602
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001603 # Tests for protocol 2
1604
Tim Peters4190fb82003-02-02 16:09:05 +00001605 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001606 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001607 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001608 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001609 proto_header = pickle.PROTO + bytes([proto])
1610 self.assertTrue(pickled.startswith(proto_header))
1611 else:
1612 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001613
1614 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001615 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001616 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001617 try:
1618 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001619 except ValueError as err:
1620 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001621 else:
1622 self.fail("expected bad protocol number to raise ValueError")
1623
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001624 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001625 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001626 for proto in protocols:
1627 s = self.dumps(x, proto)
1628 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001629 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001630 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001631
1632 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001633 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001634 for proto in protocols:
1635 s = self.dumps(x, proto)
1636 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001637 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001638 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001639
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001640 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001641 # Map (proto, len(tuple)) to expected opcode.
1642 expected_opcode = {(0, 0): pickle.TUPLE,
1643 (0, 1): pickle.TUPLE,
1644 (0, 2): pickle.TUPLE,
1645 (0, 3): pickle.TUPLE,
1646 (0, 4): pickle.TUPLE,
1647
1648 (1, 0): pickle.EMPTY_TUPLE,
1649 (1, 1): pickle.TUPLE,
1650 (1, 2): pickle.TUPLE,
1651 (1, 3): pickle.TUPLE,
1652 (1, 4): pickle.TUPLE,
1653
1654 (2, 0): pickle.EMPTY_TUPLE,
1655 (2, 1): pickle.TUPLE1,
1656 (2, 2): pickle.TUPLE2,
1657 (2, 3): pickle.TUPLE3,
1658 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001659
1660 (3, 0): pickle.EMPTY_TUPLE,
1661 (3, 1): pickle.TUPLE1,
1662 (3, 2): pickle.TUPLE2,
1663 (3, 3): pickle.TUPLE3,
1664 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001665 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001666 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001667 b = (1,)
1668 c = (1, 2)
1669 d = (1, 2, 3)
1670 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001671 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001672 for x in a, b, c, d, e:
1673 s = self.dumps(x, proto)
1674 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001675 self.assert_is_copy(x, y)
1676 expected = expected_opcode[min(proto, 3), len(x)]
1677 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001678
Guido van Rossum7d97d312003-01-28 04:25:27 +00001679 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001680 # Map (proto, singleton) to expected opcode.
1681 expected_opcode = {(0, None): pickle.NONE,
1682 (1, None): pickle.NONE,
1683 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001684 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001685
1686 (0, True): pickle.INT,
1687 (1, True): pickle.INT,
1688 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001689 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001690
1691 (0, False): pickle.INT,
1692 (1, False): pickle.INT,
1693 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001694 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001695 }
Tim Peters4190fb82003-02-02 16:09:05 +00001696 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001697 for x in None, False, True:
1698 s = self.dumps(x, proto)
1699 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001700 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001701 expected = expected_opcode[min(proto, 3), x]
1702 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001703
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001704 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001705 x = MyTuple([1, 2, 3])
1706 x.foo = 42
1707 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001708 for proto in protocols:
1709 s = self.dumps(x, proto)
1710 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001711 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001712
1713 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001714 x = MyList([1, 2, 3])
1715 x.foo = 42
1716 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001717 for proto in protocols:
1718 s = self.dumps(x, proto)
1719 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001720 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001721
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001722 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001723 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001724 for C in myclasses:
1725 B = C.__base__
1726 x = C(C.sample)
1727 x.foo = 42
1728 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001729 y = self.loads(s)
1730 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001731 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001732 self.assertEqual(B(x), B(y), detail)
1733 self.assertEqual(x.__dict__, y.__dict__, detail)
1734
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001735 def test_newobj_proxies(self):
1736 # NEWOBJ should use the __class__ rather than the raw type
1737 classes = myclasses[:]
1738 # Cannot create weakproxies to these classes
1739 for c in (MyInt, MyTuple):
1740 classes.remove(c)
1741 for proto in protocols:
1742 for C in classes:
1743 B = C.__base__
1744 x = C(C.sample)
1745 x.foo = 42
1746 p = weakref.proxy(x)
1747 s = self.dumps(p, proto)
1748 y = self.loads(s)
1749 self.assertEqual(type(y), type(x)) # rather than type(p)
1750 detail = (proto, C, B, x, y, type(y))
1751 self.assertEqual(B(x), B(y), detail)
1752 self.assertEqual(x.__dict__, y.__dict__, detail)
1753
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001754 def test_newobj_not_class(self):
1755 # Issue 24552
1756 global SimpleNewObj
1757 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001758 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001759 b = self.dumps(o, 4)
1760 try:
1761 SimpleNewObj = 42
1762 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1763 finally:
1764 SimpleNewObj = save
1765
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001766 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001767 # an object of that type. Check that the resulting pickle uses opcode
1768 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001769
Tim Peters22e71712003-02-03 22:27:38 +00001770 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001771 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001772 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001773 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001774 x = MyList([1, 2, 3])
1775 x.foo = 42
1776 x.bar = "hello"
1777
Tim Peters22e71712003-02-03 22:27:38 +00001778 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001779 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001780 self.assertIn(__name__.encode("utf-8"), s1)
1781 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001782 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001783
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001784 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001785 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001786
Tim Peters22e71712003-02-03 22:27:38 +00001787 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001788 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001789 self.assertNotIn(__name__.encode("utf-8"), s2)
1790 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001791 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001792
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001793 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001794 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001795 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001796 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001797
1798 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001799 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1800 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001801
1802 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001803 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1804 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1805 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001806
1807 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001808 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1809 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
1810 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
1811
Tim Peters8d2613a2003-02-11 16:40:16 +00001812 def test_list_chunking(self):
1813 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00001814 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001815 for proto in protocols:
1816 s = self.dumps(x, proto)
1817 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001818 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001819 num_appends = count_opcode(pickle.APPENDS, s)
1820 self.assertEqual(num_appends, proto > 0)
1821
1822 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001823 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001824 for proto in protocols:
1825 s = self.dumps(x, proto)
1826 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001827 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001828 num_appends = count_opcode(pickle.APPENDS, s)
1829 if proto == 0:
1830 self.assertEqual(num_appends, 0)
1831 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001832 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00001833
1834 def test_dict_chunking(self):
1835 n = 10 # too small to chunk
1836 x = dict.fromkeys(range(n))
1837 for proto in protocols:
1838 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00001839 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00001840 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001841 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001842 num_setitems = count_opcode(pickle.SETITEMS, s)
1843 self.assertEqual(num_setitems, proto > 0)
1844
1845 n = 2500 # expect at least two chunks when proto > 0
1846 x = dict.fromkeys(range(n))
1847 for proto in protocols:
1848 s = self.dumps(x, proto)
1849 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001850 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001851 num_setitems = count_opcode(pickle.SETITEMS, s)
1852 if proto == 0:
1853 self.assertEqual(num_setitems, 0)
1854 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001855 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001856
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001857 def test_set_chunking(self):
1858 n = 10 # too small to chunk
1859 x = set(range(n))
1860 for proto in protocols:
1861 s = self.dumps(x, proto)
1862 y = self.loads(s)
1863 self.assert_is_copy(x, y)
1864 num_additems = count_opcode(pickle.ADDITEMS, s)
1865 if proto < 4:
1866 self.assertEqual(num_additems, 0)
1867 else:
1868 self.assertEqual(num_additems, 1)
1869
1870 n = 2500 # expect at least two chunks when proto >= 4
1871 x = set(range(n))
1872 for proto in protocols:
1873 s = self.dumps(x, proto)
1874 y = self.loads(s)
1875 self.assert_is_copy(x, y)
1876 num_additems = count_opcode(pickle.ADDITEMS, s)
1877 if proto < 4:
1878 self.assertEqual(num_additems, 0)
1879 else:
1880 self.assertGreaterEqual(num_additems, 2)
1881
Tim Peterse9ef2032003-02-13 18:42:00 +00001882 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001883 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00001884 x.abc = 666
1885 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001886 with self.subTest(proto=proto):
1887 s = self.dumps(x, proto)
1888 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02001889 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001890 else:
1891 self.assertIn(b'M\xce\xfa', s) # BININT2
1892 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
1893 2 <= proto)
1894 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
1895 y = self.loads(s) # will raise TypeError if __init__ called
1896 self.assert_is_copy(x, y)
1897
1898 def test_complex_newobj(self):
1899 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
1900 x.abc = 666
1901 for proto in protocols:
1902 with self.subTest(proto=proto):
1903 s = self.dumps(x, proto)
1904 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02001905 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001906 elif proto < 2:
1907 self.assertIn(b'M\xce\xfa', s) # BININT2
1908 elif proto < 4:
1909 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
1910 else:
1911 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
1912 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
1913 2 <= proto)
1914 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
1915 y = self.loads(s) # will raise TypeError if __init__ called
1916 self.assert_is_copy(x, y)
1917
1918 def test_complex_newobj_ex(self):
1919 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
1920 x.abc = 666
1921 for proto in protocols:
1922 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001923 s = self.dumps(x, proto)
1924 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02001925 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001926 elif proto < 2:
1927 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03001928 elif proto < 4:
1929 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001930 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001931 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
1932 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
1933 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
1934 4 <= proto)
1935 y = self.loads(s) # will raise TypeError if __init__ called
1936 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00001937
Tim Peters42f08ac2003-02-11 22:43:24 +00001938 def test_newobj_list_slots(self):
1939 x = SlotList([1, 2, 3])
1940 x.foo = 42
1941 x.bar = "hello"
1942 s = self.dumps(x, 2)
1943 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001944 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00001945
Guido van Rossum2a30b212003-02-18 22:41:24 +00001946 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00001947 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001948 x = REX_one()
1949 self.assertEqual(x._reduce_called, 0)
1950 s = self.dumps(x, proto)
1951 self.assertEqual(x._reduce_called, 1)
1952 y = self.loads(s)
1953 self.assertEqual(y._reduce_called, 0)
1954
1955 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00001956 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001957 x = REX_two()
1958 self.assertEqual(x._proto, None)
1959 s = self.dumps(x, proto)
1960 self.assertEqual(x._proto, proto)
1961 y = self.loads(s)
1962 self.assertEqual(y._proto, None)
1963
1964 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00001965 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001966 x = REX_three()
1967 self.assertEqual(x._proto, None)
1968 s = self.dumps(x, proto)
1969 self.assertEqual(x._proto, proto)
1970 y = self.loads(s)
1971 self.assertEqual(y._proto, None)
1972
Guido van Rossumd8faa362007-04-27 19:54:29 +00001973 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00001974 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001975 x = REX_four()
1976 self.assertEqual(x._proto, None)
1977 s = self.dumps(x, proto)
1978 self.assertEqual(x._proto, proto)
1979 y = self.loads(s)
1980 self.assertEqual(y._proto, proto)
1981
1982 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00001983 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001984 x = REX_five()
1985 self.assertEqual(x._reduce_called, 0)
1986 s = self.dumps(x, proto)
1987 self.assertEqual(x._reduce_called, 1)
1988 y = self.loads(s)
1989 self.assertEqual(y._reduce_called, 1)
1990
Brett Cannon31f59292011-02-21 19:29:56 +00001991 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001992 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001993 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001994 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001995 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001996 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001997
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001998 def test_reduce_bad_iterator(self):
1999 # Issue4176: crash when 4th and 5th items of __reduce__()
2000 # are not iterators
2001 class C(object):
2002 def __reduce__(self):
2003 # 4th item is not an iterator
2004 return list, (), None, [], None
2005 class D(object):
2006 def __reduce__(self):
2007 # 5th item is not an iterator
2008 return dict, (), None, None, []
2009
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002010 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002011 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002012 try:
2013 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002014 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002015 pass
2016 try:
2017 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002018 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002019 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002020
Collin Winter771d8342009-04-16 03:18:06 +00002021 def test_many_puts_and_gets(self):
2022 # Test that internal data structures correctly deal with lots of
2023 # puts/gets.
2024 keys = ("aaa" + str(i) for i in range(100))
2025 large_dict = dict((k, [4, 5, 6]) for k in keys)
2026 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2027
2028 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002029 with self.subTest(proto=proto):
2030 dumped = self.dumps(obj, proto)
2031 loaded = self.loads(dumped)
2032 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002033
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002034 def test_attribute_name_interning(self):
2035 # Test that attribute names of pickled objects are interned when
2036 # unpickling.
2037 for proto in protocols:
2038 x = C()
2039 x.foo = 42
2040 x.bar = "hello"
2041 s = self.dumps(x, proto)
2042 y = self.loads(s)
2043 x_keys = sorted(x.__dict__)
2044 y_keys = sorted(y.__dict__)
2045 for x_key, y_key in zip(x_keys, y_keys):
2046 self.assertIs(x_key, y_key)
2047
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002048 def test_pickle_to_2x(self):
2049 # Pickle non-trivial data with protocol 2, expecting that it yields
2050 # the same result as Python 2.x did.
2051 # NOTE: this test is a bit too strong since we can produce different
2052 # bytecode that 2.x will still understand.
2053 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002054 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002055 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002056 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002057
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002058 def test_large_pickles(self):
2059 # Test the correctness of internal buffering routines when handling
2060 # large data.
2061 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002062 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002063 dumped = self.dumps(data, proto)
2064 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002065 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002066 self.assertEqual(loaded, data)
2067
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002068 def test_int_pickling_efficiency(self):
2069 # Test compacity of int representation (see issue #12744)
2070 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002071 with self.subTest(proto=proto):
2072 pickles = [self.dumps(2**n, proto) for n in range(70)]
2073 sizes = list(map(len, pickles))
2074 # the size function is monotonic
2075 self.assertEqual(sorted(sizes), sizes)
2076 if proto >= 2:
2077 for p in pickles:
2078 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002079
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002080 def _check_pickling_with_opcode(self, obj, opcode, proto):
2081 pickled = self.dumps(obj, proto)
2082 self.assertTrue(opcode_in_pickle(opcode, pickled))
2083 unpickled = self.loads(pickled)
2084 self.assertEqual(obj, unpickled)
2085
2086 def test_appends_on_non_lists(self):
2087 # Issue #17720
2088 obj = REX_six([1, 2, 3])
2089 for proto in protocols:
2090 if proto == 0:
2091 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2092 else:
2093 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2094
2095 def test_setitems_on_non_dicts(self):
2096 obj = REX_seven({1: -1, 2: -2, 3: -3})
2097 for proto in protocols:
2098 if proto == 0:
2099 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2100 else:
2101 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2102
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002103 # Exercise framing (proto >= 4) for significant workloads
2104
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002105 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002106 FRAME_SIZE_TARGET = 64 * 1024
2107
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002108 def check_frame_opcodes(self, pickled):
2109 """
2110 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002111
2112 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2113 framed by default and are therefore considered a frame by themselves in
2114 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002115 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002116 frame_end = frameless_start = None
2117 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8', 'BINUNICODE8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002118 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002119 if frame_end is not None:
2120 self.assertLessEqual(pos, frame_end)
2121 if pos == frame_end:
2122 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002123
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002124 if frame_end is not None: # framed
2125 self.assertNotEqual(op.name, 'FRAME')
2126 if op.name in frameless_opcodes:
2127 # Only short bytes and str objects should be written
2128 # in a frame
2129 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2130
2131 else: # not framed
2132 if (op.name == 'FRAME' or
2133 (op.name in frameless_opcodes and
2134 len(arg) > self.FRAME_SIZE_TARGET)):
2135 # Frame or large bytes or str object
2136 if frameless_start is not None:
2137 # Only short data should be written outside of a frame
2138 self.assertLess(pos - frameless_start,
2139 self.FRAME_SIZE_MIN)
2140 frameless_start = None
2141 elif frameless_start is None and op.name != 'PROTO':
2142 frameless_start = pos
2143
2144 if op.name == 'FRAME':
2145 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2146 frame_end = pos + 9 + arg
2147
2148 pos = len(pickled)
2149 if frame_end is not None:
2150 self.assertEqual(frame_end, pos)
2151 elif frameless_start is not None:
2152 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002153
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002154 def test_framing_many_objects(self):
2155 obj = list(range(10**5))
2156 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2157 with self.subTest(proto=proto):
2158 pickled = self.dumps(obj, proto)
2159 unpickled = self.loads(pickled)
2160 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002161 bytes_per_frame = (len(pickled) /
2162 count_opcode(pickle.FRAME, pickled))
2163 self.assertGreater(bytes_per_frame,
2164 self.FRAME_SIZE_TARGET / 2)
2165 self.assertLessEqual(bytes_per_frame,
2166 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002167 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002168
2169 def test_framing_large_objects(self):
2170 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002171 small_items = [[i] for i in range(10)]
2172 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002173 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002174 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002175 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002176 if not fast:
2177 # fast=False by default.
2178 # This covers in-memory pickling with pickle.dumps().
2179 pickled = self.dumps(obj, proto)
2180 else:
2181 # Pickler is required when fast=True.
2182 if not hasattr(self, 'pickler'):
2183 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002184 buf = io.BytesIO()
2185 pickler = self.pickler(buf, protocol=proto)
2186 pickler.fast = fast
2187 pickler.dump(obj)
2188 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002189 unpickled = self.loads(pickled)
2190 # More informative error message in case of failure.
2191 self.assertEqual([len(x) for x in obj],
2192 [len(x) for x in unpickled])
2193 # Perform full equality check if the lengths match.
2194 self.assertEqual(obj, unpickled)
2195 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002196 # A single frame for small objects between
2197 # first two large objects.
2198 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002199 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002200
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002201 def test_optional_frames(self):
2202 if pickle.HIGHEST_PROTOCOL < 4:
2203 return
2204
2205 def remove_frames(pickled, keep_frame=None):
2206 """Remove frame opcodes from the given pickle."""
2207 frame_starts = []
2208 # 1 byte for the opcode and 8 for the argument
2209 frame_opcode_size = 9
2210 for opcode, _, pos in pickletools.genops(pickled):
2211 if opcode.name == 'FRAME':
2212 frame_starts.append(pos)
2213
2214 newpickle = bytearray()
2215 last_frame_end = 0
2216 for i, pos in enumerate(frame_starts):
2217 if keep_frame and keep_frame(i):
2218 continue
2219 newpickle += pickled[last_frame_end:pos]
2220 last_frame_end = pos + frame_opcode_size
2221 newpickle += pickled[last_frame_end:]
2222 return newpickle
2223
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002224 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002225 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002226 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002227 # (dict keys)
2228 obj = {i: bytes([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002229
2230 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2231 pickled = self.dumps(obj, proto)
2232
2233 frameless_pickle = remove_frames(pickled)
2234 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2235 self.assertEqual(obj, self.loads(frameless_pickle))
2236
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002237 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002238 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2239 count_opcode(pickle.FRAME, pickled))
2240 self.assertEqual(obj, self.loads(some_frames_pickle))
2241
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002242 def test_framed_write_sizes_with_delayed_writer(self):
2243 class ChunkAccumulator:
2244 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002245 def __init__(self):
2246 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002247 def write(self, chunk):
2248 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002249 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002250 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002251
2252 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002253 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2254 for i in range(int(1e4))]
2255 # Add a large unique ASCII string
2256 objects.append('0123456789abcdef' *
2257 (self.FRAME_SIZE_TARGET // 16 + 1))
2258
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002259 # Protocol 4 packs groups of small objects into frames and issues
2260 # calls to write only once or twice per frame:
2261 # The C pickler issues one call to write per-frame (header and
2262 # contents) while Python pickler issues two calls to write: one for
2263 # the frame header and one for the frame binary contents.
2264 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002265 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002266
2267 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002268 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002269 # be released otherwise this delayed access would not be possible.
2270 pickled = writer.concatenate_chunks()
2271 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002272 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002273 self.assertGreater(len(writer.chunks), 1)
2274
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002275 # memoryviews should own the memory.
2276 del objects
2277 support.gc_collect()
2278 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002279
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002280 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002281 # There should be at least one call to write per frame
2282 self.assertGreaterEqual(len(writer.chunks), n_frames)
2283
2284 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002285 # one per-frame header, one per frame for the actual contents,
2286 # and two for the header.
2287 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002288
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002289 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002290 large_sizes = [s for s in chunk_sizes
2291 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002292 medium_sizes = [s for s in chunk_sizes
2293 if 9 < s < self.FRAME_SIZE_TARGET]
2294 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002295
2296 # Large chunks should not be too large:
2297 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002298 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2299 chunk_sizes)
2300 # There shouldn't bee too many small chunks: the protocol header,
2301 # the frame headers and the large string headers are written
2302 # in small chunks.
2303 self.assertLessEqual(len(small_sizes),
2304 len(large_sizes) + len(medium_sizes) + 3,
2305 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002306
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002307 def test_nested_names(self):
2308 global Nested
2309 class Nested:
2310 class A:
2311 class B:
2312 class C:
2313 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002314 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002315 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2316 with self.subTest(proto=proto, obj=obj):
2317 unpickled = self.loads(self.dumps(obj, proto))
2318 self.assertIs(obj, unpickled)
2319
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002320 def test_recursive_nested_names(self):
2321 global Recursive
2322 class Recursive:
2323 pass
2324 Recursive.mod = sys.modules[Recursive.__module__]
2325 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2326 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2327 with self.subTest(proto=proto):
2328 unpickled = self.loads(self.dumps(Recursive, proto))
2329 self.assertIs(unpickled, Recursive)
2330 del Recursive.mod # break reference loop
2331
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002332 def test_py_methods(self):
2333 global PyMethodsTest
2334 class PyMethodsTest:
2335 @staticmethod
2336 def cheese():
2337 return "cheese"
2338 @classmethod
2339 def wine(cls):
2340 assert cls is PyMethodsTest
2341 return "wine"
2342 def biscuits(self):
2343 assert isinstance(self, PyMethodsTest)
2344 return "biscuits"
2345 class Nested:
2346 "Nested class"
2347 @staticmethod
2348 def ketchup():
2349 return "ketchup"
2350 @classmethod
2351 def maple(cls):
2352 assert cls is PyMethodsTest.Nested
2353 return "maple"
2354 def pie(self):
2355 assert isinstance(self, PyMethodsTest.Nested)
2356 return "pie"
2357
2358 py_methods = (
2359 PyMethodsTest.cheese,
2360 PyMethodsTest.wine,
2361 PyMethodsTest().biscuits,
2362 PyMethodsTest.Nested.ketchup,
2363 PyMethodsTest.Nested.maple,
2364 PyMethodsTest.Nested().pie
2365 )
2366 py_unbound_methods = (
2367 (PyMethodsTest.biscuits, PyMethodsTest),
2368 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2369 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002370 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002371 for method in py_methods:
2372 with self.subTest(proto=proto, method=method):
2373 unpickled = self.loads(self.dumps(method, proto))
2374 self.assertEqual(method(), unpickled())
2375 for method, cls in py_unbound_methods:
2376 obj = cls()
2377 with self.subTest(proto=proto, method=method):
2378 unpickled = self.loads(self.dumps(method, proto))
2379 self.assertEqual(method(obj), unpickled(obj))
2380
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002381 def test_c_methods(self):
2382 global Subclass
2383 class Subclass(tuple):
2384 class Nested(str):
2385 pass
2386
2387 c_methods = (
2388 # bound built-in method
2389 ("abcd".index, ("c",)),
2390 # unbound built-in method
2391 (str.index, ("abcd", "c")),
2392 # bound "slot" method
2393 ([1, 2, 3].__len__, ()),
2394 # unbound "slot" method
2395 (list.__len__, ([1, 2, 3],)),
2396 # bound "coexist" method
2397 ({1, 2}.__contains__, (2,)),
2398 # unbound "coexist" method
2399 (set.__contains__, ({1, 2}, 2)),
2400 # built-in class method
2401 (dict.fromkeys, (("a", 1), ("b", 2))),
2402 # built-in static method
2403 (bytearray.maketrans, (b"abc", b"xyz")),
2404 # subclass methods
2405 (Subclass([1,2,2]).count, (2,)),
2406 (Subclass.count, (Subclass([1,2,2]), 2)),
2407 (Subclass.Nested("sweet").count, ("e",)),
2408 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2409 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002410 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002411 for method, args in c_methods:
2412 with self.subTest(proto=proto, method=method):
2413 unpickled = self.loads(self.dumps(method, proto))
2414 self.assertEqual(method(*args), unpickled(*args))
2415
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002416 def test_compat_pickle(self):
2417 tests = [
2418 (range(1, 7), '__builtin__', 'xrange'),
2419 (map(int, '123'), 'itertools', 'imap'),
2420 (functools.reduce, '__builtin__', 'reduce'),
2421 (dbm.whichdb, 'whichdb', 'whichdb'),
2422 (Exception(), 'exceptions', 'Exception'),
2423 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2424 (collections.UserList(), 'UserList', 'UserList'),
2425 (collections.defaultdict(), 'collections', 'defaultdict'),
2426 ]
2427 for val, mod, name in tests:
2428 for proto in range(3):
2429 with self.subTest(type=type(val), proto=proto):
2430 pickled = self.dumps(val, proto)
2431 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2432 self.assertIs(type(self.loads(pickled)), type(val))
2433
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002434 def test_local_lookup_error(self):
2435 # Test that whichmodule() errors out cleanly when looking up
2436 # an assumed globally-reachable object fails.
2437 def f():
2438 pass
2439 # Since the function is local, lookup will fail
2440 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2441 with self.assertRaises((AttributeError, pickle.PicklingError)):
2442 pickletools.dis(self.dumps(f, proto))
2443 # Same without a __module__ attribute (exercises a different path
2444 # in _pickle.c).
2445 del f.__module__
2446 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2447 with self.assertRaises((AttributeError, pickle.PicklingError)):
2448 pickletools.dis(self.dumps(f, proto))
2449 # Yet a different path.
2450 f.__name__ = f.__qualname__
2451 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2452 with self.assertRaises((AttributeError, pickle.PicklingError)):
2453 pickletools.dis(self.dumps(f, proto))
2454
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002455
2456class BigmemPickleTests(unittest.TestCase):
2457
Victor Stinner8c663fd2017-11-08 14:44:44 -08002458 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002459
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002460 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002461 def test_huge_long_32b(self, size):
2462 data = 1 << (8 * size)
2463 try:
2464 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002465 if proto < 2:
2466 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002467 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002468 with self.assertRaises((ValueError, OverflowError)):
2469 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002470 finally:
2471 data = None
2472
Victor Stinner8c663fd2017-11-08 14:44:44 -08002473 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002474 # (older protocols don't have a dedicated opcode for bytes and are
2475 # too inefficient)
2476
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002477 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002478 def test_huge_bytes_32b(self, size):
2479 data = b"abcd" * (size // 4)
2480 try:
2481 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002482 if proto < 3:
2483 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002484 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002485 try:
2486 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002487 header = (pickle.BINBYTES +
2488 struct.pack("<I", len(data)))
2489 data_start = pickled.index(data)
2490 self.assertEqual(
2491 header,
2492 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002493 finally:
2494 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002495 finally:
2496 data = None
2497
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002498 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002499 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002500 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002501 try:
2502 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002503 if proto < 3:
2504 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002505 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002506 if proto == 3:
2507 # Protocol 3 does not support large bytes objects.
2508 # Verify that we do not crash when processing one.
2509 with self.assertRaises((ValueError, OverflowError)):
2510 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002511 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002512 try:
2513 pickled = self.dumps(data, protocol=proto)
2514 header = (pickle.BINBYTES8 +
2515 struct.pack("<Q", len(data)))
2516 data_start = pickled.index(data)
2517 self.assertEqual(
2518 header,
2519 pickled[data_start-len(header):data_start])
2520 finally:
2521 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002522 finally:
2523 data = None
2524
2525 # All protocols use 1-byte per printable ASCII character; we add another
2526 # byte because the encoded form has to be copied into the internal buffer.
2527
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002528 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002529 def test_huge_str_32b(self, size):
2530 data = "abcd" * (size // 4)
2531 try:
2532 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002533 if proto == 0:
2534 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002535 with self.subTest(proto=proto):
2536 try:
2537 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002538 header = (pickle.BINUNICODE +
2539 struct.pack("<I", len(data)))
2540 data_start = pickled.index(b'abcd')
2541 self.assertEqual(
2542 header,
2543 pickled[data_start-len(header):data_start])
2544 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2545 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002546 finally:
2547 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002548 finally:
2549 data = None
2550
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002551 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2552 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2553 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002554
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002555 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002556 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002557 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002558 try:
2559 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002560 if proto == 0:
2561 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002562 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002563 if proto < 4:
2564 with self.assertRaises((ValueError, OverflowError)):
2565 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002566 continue
2567 try:
2568 pickled = self.dumps(data, protocol=proto)
2569 header = (pickle.BINUNICODE8 +
2570 struct.pack("<Q", len(data)))
2571 data_start = pickled.index(b'abcd')
2572 self.assertEqual(
2573 header,
2574 pickled[data_start-len(header):data_start])
2575 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2576 pickled.index(b"abcd")), len(data))
2577 finally:
2578 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002579 finally:
2580 data = None
2581
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002582
Guido van Rossum2a30b212003-02-18 22:41:24 +00002583# Test classes for reduce_ex
2584
2585class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002586 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002587 _reduce_called = 0
2588 def __reduce__(self):
2589 self._reduce_called = 1
2590 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002591
2592class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002593 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002594 _proto = None
2595 def __reduce_ex__(self, proto):
2596 self._proto = proto
2597 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002598
2599class REX_three(object):
2600 _proto = None
2601 def __reduce_ex__(self, proto):
2602 self._proto = proto
2603 return REX_two, ()
2604 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002605 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002606
Guido van Rossumd8faa362007-04-27 19:54:29 +00002607class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002608 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002609 _proto = None
2610 def __reduce_ex__(self, proto):
2611 self._proto = proto
2612 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002613
2614class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002615 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002616 _reduce_called = 0
2617 def __reduce__(self):
2618 self._reduce_called = 1
2619 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002620
2621class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002622 """This class is used to check the 4th argument (list iterator) of
2623 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002624 """
2625 def __init__(self, items=None):
2626 self.items = items if items is not None else []
2627 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02002628 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002629 def append(self, item):
2630 self.items.append(item)
2631 def __reduce__(self):
2632 return type(self), (), None, iter(self.items), None
2633
2634class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002635 """This class is used to check the 5th argument (dict iterator) of
2636 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002637 """
2638 def __init__(self, table=None):
2639 self.table = table if table is not None else {}
2640 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02002641 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002642 def __setitem__(self, key, value):
2643 self.table[key] = value
2644 def __reduce__(self):
2645 return type(self), (), None, None, iter(self.table.items())
2646
Guido van Rossumd8faa362007-04-27 19:54:29 +00002647
Guido van Rossum2a30b212003-02-18 22:41:24 +00002648# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00002649
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002650class MyInt(int):
2651 sample = 1
2652
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002653class MyFloat(float):
2654 sample = 1.0
2655
2656class MyComplex(complex):
2657 sample = 1.0 + 0.0j
2658
2659class MyStr(str):
2660 sample = "hello"
2661
Guido van Rossumef87d6e2007-05-02 19:09:54 +00002662class MyUnicode(str):
2663 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002664
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002665class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002666 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002667
2668class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002669 sample = [1, 2, 3]
2670
2671class MyDict(dict):
2672 sample = {"a": 1, "b": 2}
2673
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002674class MySet(set):
2675 sample = {"a", "b"}
2676
2677class MyFrozenSet(frozenset):
2678 sample = frozenset({"a", "b"})
2679
Mark Dickinson5c2db372009-12-05 20:28:34 +00002680myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00002681 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002682 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002683 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002684
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002685
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00002686class SlotList(MyList):
2687 __slots__ = ["foo"]
2688
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002689class SimpleNewObj(int):
2690 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00002691 # raise an error, to make sure this isn't called
2692 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002693 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002694 return int(self) == int(other) and self.__dict__ == other.__dict__
2695
2696class ComplexNewObj(SimpleNewObj):
2697 def __getnewargs__(self):
2698 return ('%X' % self, 16)
2699
2700class ComplexNewObjEx(SimpleNewObj):
2701 def __getnewargs_ex__(self):
2702 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00002703
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002704class BadGetattr:
2705 def __getattr__(self, key):
2706 self.foo
2707
Collin Winter771d8342009-04-16 03:18:06 +00002708
Jeremy Hylton66426532001-10-15 21:38:56 +00002709class AbstractPickleModuleTests(unittest.TestCase):
2710
2711 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00002712 import os
Walter Dörwald11b41f62007-06-20 12:46:31 +00002713 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00002714 try:
2715 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02002716 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00002717 finally:
2718 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00002719
2720 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00002721 import os
Walter Dörwald11b41f62007-06-20 12:46:31 +00002722 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00002723 try:
2724 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02002725 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00002726 finally:
2727 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002728
Collin Winter771d8342009-04-16 03:18:06 +00002729 def test_load_from_and_dump_to_file(self):
2730 stream = io.BytesIO()
2731 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02002732 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00002733 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02002734 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00002735 self.assertEqual(unpickled, data)
2736
Tim Petersc0c93702003-02-13 19:30:57 +00002737 def test_highest_protocol(self):
2738 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002739 self.assertEqual(pickle.HIGHEST_PROTOCOL, 4)
Tim Petersc0c93702003-02-13 19:30:57 +00002740
Martin v. Löwis544f1192004-07-27 05:22:33 +00002741 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00002742 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00002743 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02002744 self.dump(123, f, -1)
2745 self.dump(123, file=f, protocol=-1)
2746 self.dumps(123, -1)
2747 self.dumps(123, protocol=-1)
2748 self.Pickler(f, -1)
2749 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00002750
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002751 def test_bad_init(self):
2752 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002753 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02002754 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002755 def __init__(self): pass
2756
Serhiy Storchaka65452562017-11-15 14:01:08 +02002757 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002758 def __init__(self): pass
2759
2760 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
2761 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
2762
2763
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002764class AbstractPersistentPicklerTests(unittest.TestCase):
2765
2766 # This class defines persistent_id() and persistent_load()
2767 # functions that should be used by the pickler. All even integers
2768 # are pickled using persistent ids.
2769
2770 def persistent_id(self, object):
2771 if isinstance(object, int) and object % 2 == 0:
2772 self.id_count += 1
2773 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002774 elif object == "test_false_value":
2775 self.false_count += 1
2776 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002777 else:
2778 return None
2779
2780 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002781 if not oid:
2782 self.load_false_count += 1
2783 return "test_false_value"
2784 else:
2785 self.load_count += 1
2786 object = int(oid)
2787 assert object % 2 == 0
2788 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002789
2790 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002791 L = list(range(10)) + ["test_false_value"]
2792 for proto in protocols:
2793 self.id_count = 0
2794 self.false_count = 0
2795 self.load_false_count = 0
2796 self.load_count = 0
2797 self.assertEqual(self.loads(self.dumps(L, proto)), L)
2798 self.assertEqual(self.id_count, 5)
2799 self.assertEqual(self.false_count, 1)
2800 self.assertEqual(self.load_count, 5)
2801 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00002802
Collin Winter771d8342009-04-16 03:18:06 +00002803
Serhiy Storchakadec25af2016-07-17 11:24:17 +03002804class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
2805
2806 def persistent_id(self, obj):
2807 return obj
2808
2809 def persistent_load(self, pid):
2810 return pid
2811
2812 def _check_return_correct_type(self, obj, proto):
2813 unpickled = self.loads(self.dumps(obj, proto))
2814 self.assertIsInstance(unpickled, type(obj))
2815 self.assertEqual(unpickled, obj)
2816
2817 def test_return_correct_type(self):
2818 for proto in protocols:
2819 # Protocol 0 supports only ASCII strings.
2820 if proto == 0:
2821 self._check_return_correct_type("abc", 0)
2822 else:
2823 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
2824 self._check_return_correct_type(obj, proto)
2825
2826 def test_protocol0_is_ascii_only(self):
2827 non_ascii_str = "\N{EMPTY SET}"
2828 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
2829 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
2830 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
2831
2832
Collin Winter771d8342009-04-16 03:18:06 +00002833class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
2834
2835 pickler_class = None
2836 unpickler_class = None
2837
2838 def setUp(self):
2839 assert self.pickler_class
2840 assert self.unpickler_class
2841
2842 def test_clear_pickler_memo(self):
2843 # To test whether clear_memo() has any effect, we pickle an object,
2844 # then pickle it again without clearing the memo; the two serialized
2845 # forms should be different. If we clear_memo() and then pickle the
2846 # object again, the third serialized form should be identical to the
2847 # first one we obtained.
2848 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03002849 for proto in protocols:
2850 f = io.BytesIO()
2851 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00002852
Serhiy Storchakac8695292018-04-04 00:11:27 +03002853 pickler.dump(data)
2854 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00002855
Serhiy Storchakac8695292018-04-04 00:11:27 +03002856 # Reset BytesIO object.
2857 f.seek(0)
2858 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00002859
Serhiy Storchakac8695292018-04-04 00:11:27 +03002860 pickler.dump(data)
2861 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00002862
Serhiy Storchakac8695292018-04-04 00:11:27 +03002863 # Reset the Pickler and BytesIO objects.
2864 pickler.clear_memo()
2865 f.seek(0)
2866 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00002867
Serhiy Storchakac8695292018-04-04 00:11:27 +03002868 pickler.dump(data)
2869 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00002870
Serhiy Storchakac8695292018-04-04 00:11:27 +03002871 self.assertNotEqual(first_pickled, second_pickled)
2872 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00002873
2874 def test_priming_pickler_memo(self):
2875 # Verify that we can set the Pickler's memo attribute.
2876 data = ["abcdefg", "abcdefg", 44]
2877 f = io.BytesIO()
2878 pickler = self.pickler_class(f)
2879
2880 pickler.dump(data)
2881 first_pickled = f.getvalue()
2882
2883 f = io.BytesIO()
2884 primed = self.pickler_class(f)
2885 primed.memo = pickler.memo
2886
2887 primed.dump(data)
2888 primed_pickled = f.getvalue()
2889
2890 self.assertNotEqual(first_pickled, primed_pickled)
2891
2892 def test_priming_unpickler_memo(self):
2893 # Verify that we can set the Unpickler's memo attribute.
2894 data = ["abcdefg", "abcdefg", 44]
2895 f = io.BytesIO()
2896 pickler = self.pickler_class(f)
2897
2898 pickler.dump(data)
2899 first_pickled = f.getvalue()
2900
2901 f = io.BytesIO()
2902 primed = self.pickler_class(f)
2903 primed.memo = pickler.memo
2904
2905 primed.dump(data)
2906 primed_pickled = f.getvalue()
2907
2908 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
2909 unpickled_data1 = unpickler.load()
2910
2911 self.assertEqual(unpickled_data1, data)
2912
2913 primed = self.unpickler_class(io.BytesIO(primed_pickled))
2914 primed.memo = unpickler.memo
2915 unpickled_data2 = primed.load()
2916
2917 primed.memo.clear()
2918
2919 self.assertEqual(unpickled_data2, data)
2920 self.assertTrue(unpickled_data2 is unpickled_data1)
2921
2922 def test_reusing_unpickler_objects(self):
2923 data1 = ["abcdefg", "abcdefg", 44]
2924 f = io.BytesIO()
2925 pickler = self.pickler_class(f)
2926 pickler.dump(data1)
2927 pickled1 = f.getvalue()
2928
2929 data2 = ["abcdefg", 44, 44]
2930 f = io.BytesIO()
2931 pickler = self.pickler_class(f)
2932 pickler.dump(data2)
2933 pickled2 = f.getvalue()
2934
2935 f = io.BytesIO()
2936 f.write(pickled1)
2937 f.seek(0)
2938 unpickler = self.unpickler_class(f)
2939 self.assertEqual(unpickler.load(), data1)
2940
2941 f.seek(0)
2942 f.truncate()
2943 f.write(pickled2)
2944 f.seek(0)
2945 self.assertEqual(unpickler.load(), data2)
2946
Antoine Pitrou04248a82010-10-12 20:51:21 +00002947 def _check_multiple_unpicklings(self, ioclass):
2948 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002949 with self.subTest(proto=proto):
2950 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
2951 f = ioclass()
2952 pickler = self.pickler_class(f, protocol=proto)
2953 pickler.dump(data1)
2954 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00002955
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002956 N = 5
2957 f = ioclass(pickled * N)
2958 unpickler = self.unpickler_class(f)
2959 for i in range(N):
2960 if f.seekable():
2961 pos = f.tell()
2962 self.assertEqual(unpickler.load(), data1)
2963 if f.seekable():
2964 self.assertEqual(f.tell(), pos + len(pickled))
2965 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002966
2967 def test_multiple_unpicklings_seekable(self):
2968 self._check_multiple_unpicklings(io.BytesIO)
2969
2970 def test_multiple_unpicklings_unseekable(self):
2971 self._check_multiple_unpicklings(UnseekableIO)
2972
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02002973 def test_unpickling_buffering_readline(self):
2974 # Issue #12687: the unpickler's buffering logic could fail with
2975 # text mode opcodes.
2976 data = list(range(10))
2977 for proto in protocols:
2978 for buf_size in range(1, 11):
2979 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
2980 pickler = self.pickler_class(f, protocol=proto)
2981 pickler.dump(data)
2982 f.seek(0)
2983 unpickler = self.unpickler_class(f)
2984 self.assertEqual(unpickler.load(), data)
2985
Collin Winter771d8342009-04-16 03:18:06 +00002986
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01002987# Tests for dispatch_table attribute
2988
2989REDUCE_A = 'reduce_A'
2990
2991class AAA(object):
2992 def __reduce__(self):
2993 return str, (REDUCE_A,)
2994
2995class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02002996 def __init__(self):
2997 # Add an instance attribute to enable state-saving routines at pickling
2998 # time.
2999 self.a = "some attribute"
3000
3001 def __setstate__(self, state):
3002 self.a = "BBB.__setstate__"
3003
3004
3005def setstate_bbb(obj, state):
3006 """Custom state setter for BBB objects
3007
3008 Such callable may be created by other persons than the ones who created the
3009 BBB class. If passed as the state_setter item of a custom reducer, this
3010 allows for custom state setting behavior of BBB objects. One can think of
3011 it as the analogous of list_setitems or dict_setitems but for foreign
3012 classes/functions.
3013 """
3014 obj.a = "custom state_setter"
3015
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003016
Pierre Glaser289f1f82019-05-08 23:08:25 +02003017
3018class AbstractCustomPicklerClass:
3019 """Pickler implementing a reducing hook using reducer_override."""
3020 def reducer_override(self, obj):
3021 obj_name = getattr(obj, "__name__", None)
3022
3023 if obj_name == 'f':
3024 # asking the pickler to save f as 5
3025 return int, (5, )
3026
3027 if obj_name == 'MyClass':
3028 return str, ('some str',)
3029
3030 elif obj_name == 'g':
3031 # in this case, the callback returns an invalid result (not a 2-5
3032 # tuple or a string), the pickler should raise a proper error.
3033 return False
3034
3035 elif obj_name == 'h':
3036 # Simulate a case when the reducer fails. The error should
3037 # be propagated to the original ``dump`` call.
3038 raise ValueError('The reducer just failed')
3039
3040 return NotImplemented
3041
3042class AbstractHookTests(unittest.TestCase):
3043 def test_pickler_hook(self):
3044 # test the ability of a custom, user-defined CPickler subclass to
3045 # override the default reducing routines of any type using the method
3046 # reducer_override
3047
3048 def f():
3049 pass
3050
3051 def g():
3052 pass
3053
3054 def h():
3055 pass
3056
3057 class MyClass:
3058 pass
3059
3060 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3061 with self.subTest(proto=proto):
3062 bio = io.BytesIO()
3063 p = self.pickler_class(bio, proto)
3064
3065 p.dump([f, MyClass, math.log])
3066 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3067
3068 self.assertEqual(new_f, 5)
3069 self.assertEqual(some_str, 'some str')
3070 # math.log does not have its usual reducer overriden, so the
3071 # custom reduction callback should silently direct the pickler
3072 # to the default pickling by attribute, by returning
3073 # NotImplemented
3074 self.assertIs(math_log, math.log)
3075
3076 with self.assertRaises(pickle.PicklingError):
3077 p.dump(g)
3078
3079 with self.assertRaisesRegex(
3080 ValueError, 'The reducer just failed'):
3081 p.dump(h)
3082
3083
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003084class AbstractDispatchTableTests(unittest.TestCase):
3085
3086 def test_default_dispatch_table(self):
3087 # No dispatch_table attribute by default
3088 f = io.BytesIO()
3089 p = self.pickler_class(f, 0)
3090 with self.assertRaises(AttributeError):
3091 p.dispatch_table
3092 self.assertFalse(hasattr(p, 'dispatch_table'))
3093
3094 def test_class_dispatch_table(self):
3095 # A dispatch_table attribute can be specified class-wide
3096 dt = self.get_dispatch_table()
3097
3098 class MyPickler(self.pickler_class):
3099 dispatch_table = dt
3100
3101 def dumps(obj, protocol=None):
3102 f = io.BytesIO()
3103 p = MyPickler(f, protocol)
3104 self.assertEqual(p.dispatch_table, dt)
3105 p.dump(obj)
3106 return f.getvalue()
3107
3108 self._test_dispatch_table(dumps, dt)
3109
3110 def test_instance_dispatch_table(self):
3111 # A dispatch_table attribute can also be specified instance-wide
3112 dt = self.get_dispatch_table()
3113
3114 def dumps(obj, protocol=None):
3115 f = io.BytesIO()
3116 p = self.pickler_class(f, protocol)
3117 p.dispatch_table = dt
3118 self.assertEqual(p.dispatch_table, dt)
3119 p.dump(obj)
3120 return f.getvalue()
3121
3122 self._test_dispatch_table(dumps, dt)
3123
3124 def _test_dispatch_table(self, dumps, dispatch_table):
3125 def custom_load_dump(obj):
3126 return pickle.loads(dumps(obj, 0))
3127
3128 def default_load_dump(obj):
3129 return pickle.loads(pickle.dumps(obj, 0))
3130
3131 # pickling complex numbers using protocol 0 relies on copyreg
3132 # so check pickling a complex number still works
3133 z = 1 + 2j
3134 self.assertEqual(custom_load_dump(z), z)
3135 self.assertEqual(default_load_dump(z), z)
3136
3137 # modify pickling of complex
3138 REDUCE_1 = 'reduce_1'
3139 def reduce_1(obj):
3140 return str, (REDUCE_1,)
3141 dispatch_table[complex] = reduce_1
3142 self.assertEqual(custom_load_dump(z), REDUCE_1)
3143 self.assertEqual(default_load_dump(z), z)
3144
3145 # check picklability of AAA and BBB
3146 a = AAA()
3147 b = BBB()
3148 self.assertEqual(custom_load_dump(a), REDUCE_A)
3149 self.assertIsInstance(custom_load_dump(b), BBB)
3150 self.assertEqual(default_load_dump(a), REDUCE_A)
3151 self.assertIsInstance(default_load_dump(b), BBB)
3152
3153 # modify pickling of BBB
3154 dispatch_table[BBB] = reduce_1
3155 self.assertEqual(custom_load_dump(a), REDUCE_A)
3156 self.assertEqual(custom_load_dump(b), REDUCE_1)
3157 self.assertEqual(default_load_dump(a), REDUCE_A)
3158 self.assertIsInstance(default_load_dump(b), BBB)
3159
3160 # revert pickling of BBB and modify pickling of AAA
3161 REDUCE_2 = 'reduce_2'
3162 def reduce_2(obj):
3163 return str, (REDUCE_2,)
3164 dispatch_table[AAA] = reduce_2
3165 del dispatch_table[BBB]
3166 self.assertEqual(custom_load_dump(a), REDUCE_2)
3167 self.assertIsInstance(custom_load_dump(b), BBB)
3168 self.assertEqual(default_load_dump(a), REDUCE_A)
3169 self.assertIsInstance(default_load_dump(b), BBB)
3170
Pierre Glaser65d98d02019-05-08 21:40:25 +02003171 # End-to-end testing of save_reduce with the state_setter keyword
3172 # argument. This is a dispatch_table test as the primary goal of
3173 # state_setter is to tweak objects reduction behavior.
3174 # In particular, state_setter is useful when the default __setstate__
3175 # behavior is not flexible enough.
3176
3177 # No custom reducer for b has been registered for now, so
3178 # BBB.__setstate__ should be used at unpickling time
3179 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3180
3181 def reduce_bbb(obj):
3182 return BBB, (), obj.__dict__, None, None, setstate_bbb
3183
3184 dispatch_table[BBB] = reduce_bbb
3185
3186 # The custom reducer reduce_bbb includes a state setter, that should
3187 # have priority over BBB.__setstate__
3188 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3189
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003190
Guido van Rossum98297ee2007-11-06 21:34:58 +00003191if __name__ == "__main__":
3192 # Print some stuff that can be used to rewrite DATA{0,1,2}
3193 from pickletools import dis
3194 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003195 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003196 p = pickle.dumps(x, i)
3197 print("DATA{0} = (".format(i))
3198 for j in range(0, len(p), 20):
3199 b = bytes(p[j:j+20])
3200 print(" {0!r}".format(b))
3201 print(")")
3202 print()
3203 print("# Disassembly of DATA{0}".format(i))
3204 print("DATA{0}_DIS = \"\"\"\\".format(i))
3205 dis(p)
3206 print("\"\"\"")
3207 print()