blob: 5d402a4711bff6b16e8fdfe7d9fd51a1121b9315 [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
Antoine Pitrou91f43802019-05-26 17:10:09 +020019try:
20 import _testbuffer
21except ImportError:
22 _testbuffer = None
23
24try:
25 import numpy as np
26except ImportError:
27 np = None
28
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020029from test import support
Antoine Pitrou82be19f2011-08-29 23:09:33 +020030from test.support import (
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020031 TestFailed, TESTFN, run_with_locale, no_tracing,
tjb9004371c0a2019-02-18 23:30:51 +080032 _2G, _4G, bigmemtest, reap_threads, forget,
Antoine Pitrou82be19f2011-08-29 23:09:33 +020033 )
Tim Peterse089c682001-04-10 03:41:41 +000034
Guido van Rossum98297ee2007-11-06 21:34:58 +000035from pickle import bytes_types
36
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030037requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
38 "test is only meaningful on 32-bit builds")
39
Tim Petersee1a53c2003-02-02 02:57:53 +000040# Tests that try a number of pickle protocols should have a
41# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000042# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000043protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000044
Tim Peters22e71712003-02-03 22:27:38 +000045
46# Return True if opcode code appears in the pickle, else False.
47def opcode_in_pickle(code, pickle):
48 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000049 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000050 return True
51 return False
52
Tim Peters8d2613a2003-02-11 16:40:16 +000053# Return the number of times opcode code appears in pickle.
54def count_opcode(code, pickle):
55 n = 0
56 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000057 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000058 n += 1
59 return n
60
Antoine Pitrou04248a82010-10-12 20:51:21 +000061
62class UnseekableIO(io.BytesIO):
63 def peek(self, *args):
64 raise NotImplementedError
65
66 def seekable(self):
67 return False
68
69 def seek(self, *args):
70 raise io.UnsupportedOperation
71
72 def tell(self):
73 raise io.UnsupportedOperation
74
75
Tim Peters3e667d52003-02-04 21:47:44 +000076# We can't very well test the extension registry without putting known stuff
77# in it, but we have to be careful to restore its original state. Code
78# should do this:
79#
80# e = ExtensionSaver(extension_code)
81# try:
82# fiddle w/ the extension registry's stuff for extension_code
83# finally:
84# e.restore()
85
86class ExtensionSaver:
87 # Remember current registration for code (if any), and remove it (if
88 # there is one).
89 def __init__(self, code):
90 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000091 if code in copyreg._inverted_registry:
92 self.pair = copyreg._inverted_registry[code]
93 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000094 else:
95 self.pair = None
96
97 # Restore previous registration for code.
98 def restore(self):
99 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000100 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000101 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000102 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000103 pair = self.pair
104 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000105 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000106
Jeremy Hylton66426532001-10-15 21:38:56 +0000107class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000108 def __eq__(self, other):
109 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000110
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000111class D(C):
112 def __init__(self, arg):
113 pass
114
115class E(C):
116 def __getinitargs__(self):
117 return ()
118
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100119class H(object):
120 pass
121
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200122# Hashable mutable key
123class K(object):
124 def __init__(self, value):
125 self.value = value
126
127 def __reduce__(self):
128 # Shouldn't support the recursion itself
129 return K, (self.value,)
130
Jeremy Hylton66426532001-10-15 21:38:56 +0000131import __main__
132__main__.C = C
133C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000134__main__.D = D
135D.__module__ = "__main__"
136__main__.E = E
137E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100138__main__.H = H
139H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200140__main__.K = K
141K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000142
143class myint(int):
144 def __init__(self, x):
145 self.str = str(x)
146
147class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000148
Jeremy Hylton66426532001-10-15 21:38:56 +0000149 def __init__(self, a, b):
150 self.a = a
151 self.b = b
152
153 def __getinitargs__(self):
154 return self.a, self.b
155
Guido van Rossum04a86612001-12-19 16:58:54 +0000156class metaclass(type):
157 pass
158
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000159class use_metaclass(object, metaclass=metaclass):
160 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000161
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200162class pickling_metaclass(type):
163 def __eq__(self, other):
164 return (type(self) == type(other) and
165 self.reduce_args == other.reduce_args)
166
167 def __reduce__(self):
168 return (create_dynamic_class, self.reduce_args)
169
170def create_dynamic_class(name, bases):
171 result = pickling_metaclass(name, bases, dict())
172 result.reduce_args = (name, bases)
173 return result
174
Antoine Pitrou91f43802019-05-26 17:10:09 +0200175
176class ZeroCopyBytes(bytes):
177 readonly = True
178 c_contiguous = True
179 f_contiguous = True
180 zero_copy_reconstruct = True
181
182 def __reduce_ex__(self, protocol):
183 if protocol >= 5:
184 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
185 else:
186 return type(self)._reconstruct, (bytes(self),)
187
188 def __repr__(self):
189 return "{}({!r})".format(self.__class__.__name__, bytes(self))
190
191 __str__ = __repr__
192
193 @classmethod
194 def _reconstruct(cls, obj):
195 with memoryview(obj) as m:
196 obj = m.obj
197 if type(obj) is cls:
198 # Zero-copy
199 return obj
200 else:
201 return cls(obj)
202
203
204class ZeroCopyBytearray(bytearray):
205 readonly = False
206 c_contiguous = True
207 f_contiguous = True
208 zero_copy_reconstruct = True
209
210 def __reduce_ex__(self, protocol):
211 if protocol >= 5:
212 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
213 else:
214 return type(self)._reconstruct, (bytes(self),)
215
216 def __repr__(self):
217 return "{}({!r})".format(self.__class__.__name__, bytes(self))
218
219 __str__ = __repr__
220
221 @classmethod
222 def _reconstruct(cls, obj):
223 with memoryview(obj) as m:
224 obj = m.obj
225 if type(obj) is cls:
226 # Zero-copy
227 return obj
228 else:
229 return cls(obj)
230
231
232if _testbuffer is not None:
233
234 class PicklableNDArray:
235 # A not-really-zero-copy picklable ndarray, as the ndarray()
236 # constructor doesn't allow for it
237
238 zero_copy_reconstruct = False
239
240 def __init__(self, *args, **kwargs):
241 self.array = _testbuffer.ndarray(*args, **kwargs)
242
243 def __getitem__(self, idx):
244 cls = type(self)
245 new = cls.__new__(cls)
246 new.array = self.array[idx]
247 return new
248
249 @property
250 def readonly(self):
251 return self.array.readonly
252
253 @property
254 def c_contiguous(self):
255 return self.array.c_contiguous
256
257 @property
258 def f_contiguous(self):
259 return self.array.f_contiguous
260
261 def __eq__(self, other):
262 if not isinstance(other, PicklableNDArray):
263 return NotImplemented
264 return (other.array.format == self.array.format and
265 other.array.shape == self.array.shape and
266 other.array.strides == self.array.strides and
267 other.array.readonly == self.array.readonly and
268 other.array.tobytes() == self.array.tobytes())
269
270 def __ne__(self, other):
271 if not isinstance(other, PicklableNDArray):
272 return NotImplemented
273 return not (self == other)
274
275 def __repr__(self):
276 return (f"{type(self)}(shape={self.array.shape},"
277 f"strides={self.array.strides}, "
278 f"bytes={self.array.tobytes()})")
279
280 def __reduce_ex__(self, protocol):
281 if not self.array.contiguous:
282 raise NotImplementedError("Reconstructing a non-contiguous "
283 "ndarray does not seem possible")
284 ndarray_kwargs = {"shape": self.array.shape,
285 "strides": self.array.strides,
286 "format": self.array.format,
287 "flags": (0 if self.readonly
288 else _testbuffer.ND_WRITABLE)}
289 pb = pickle.PickleBuffer(self.array)
290 if protocol >= 5:
291 return (type(self)._reconstruct,
292 (pb, ndarray_kwargs))
293 else:
294 # Need to serialize the bytes in physical order
295 with pb.raw() as m:
296 return (type(self)._reconstruct,
297 (m.tobytes(), ndarray_kwargs))
298
299 @classmethod
300 def _reconstruct(cls, obj, kwargs):
301 with memoryview(obj) as m:
302 # For some reason, ndarray() wants a list of integers...
303 # XXX This only works if format == 'B'
304 items = list(m.tobytes())
305 return cls(items, **kwargs)
306
307
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300308# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000309# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000310
Guido van Rossum98297ee2007-11-06 21:34:58 +0000311DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200312 b'(lp0\nL0L\naL1L\naF2.0\n'
313 b'ac__builtin__\ncomple'
314 b'x\np1\n(F3.0\nF0.0\ntp2\n'
315 b'Rp3\naL1L\naL-1L\naL255'
316 b'L\naL-255L\naL-256L\naL'
317 b'65535L\naL-65535L\naL-'
318 b'65536L\naL2147483647L'
319 b'\naL-2147483647L\naL-2'
320 b'147483648L\na(Vabc\np4'
321 b'\ng4\nccopy_reg\n_recon'
322 b'structor\np5\n(c__main'
323 b'__\nC\np6\nc__builtin__'
324 b'\nobject\np7\nNtp8\nRp9\n'
325 b'(dp10\nVfoo\np11\nL1L\ns'
326 b'Vbar\np12\nL2L\nsbg9\ntp'
327 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000328)
Tim Peterse9358162001-01-22 22:05:20 +0000329
Guido van Rossum98297ee2007-11-06 21:34:58 +0000330# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000331DATA0_DIS = """\
332 0: ( MARK
333 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000334 2: p PUT 0
335 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000336 9: a APPEND
337 10: L LONG 1
338 14: a APPEND
339 15: F FLOAT 2.0
340 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200341 21: c GLOBAL '__builtin__ complex'
342 42: p PUT 1
343 45: ( MARK
344 46: F FLOAT 3.0
345 51: F FLOAT 0.0
346 56: t TUPLE (MARK at 45)
347 57: p PUT 2
348 60: R REDUCE
349 61: p PUT 3
350 64: a APPEND
351 65: L LONG 1
352 69: a APPEND
353 70: L LONG -1
354 75: a APPEND
355 76: L LONG 255
356 82: a APPEND
357 83: L LONG -255
358 90: a APPEND
359 91: L LONG -256
360 98: a APPEND
361 99: L LONG 65535
362 107: a APPEND
363 108: L LONG -65535
364 117: a APPEND
365 118: L LONG -65536
366 127: a APPEND
367 128: L LONG 2147483647
368 141: a APPEND
369 142: L LONG -2147483647
370 156: a APPEND
371 157: L LONG -2147483648
372 171: a APPEND
373 172: ( MARK
374 173: V UNICODE 'abc'
375 178: p PUT 4
376 181: g GET 4
377 184: c GLOBAL 'copy_reg _reconstructor'
378 209: p PUT 5
379 212: ( MARK
380 213: c GLOBAL '__main__ C'
381 225: p PUT 6
382 228: c GLOBAL '__builtin__ object'
383 248: p PUT 7
384 251: N NONE
385 252: t TUPLE (MARK at 212)
386 253: p PUT 8
387 256: R REDUCE
388 257: p PUT 9
389 260: ( MARK
390 261: d DICT (MARK at 260)
391 262: p PUT 10
392 266: V UNICODE 'foo'
393 271: p PUT 11
394 275: L LONG 1
395 279: s SETITEM
396 280: V UNICODE 'bar'
397 285: p PUT 12
398 289: L LONG 2
399 293: s SETITEM
400 294: b BUILD
401 295: g GET 9
402 298: t TUPLE (MARK at 172)
403 299: p PUT 13
404 303: a APPEND
405 304: g GET 13
406 308: a APPEND
407 309: L LONG 5
408 313: a APPEND
409 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000410highest protocol among opcodes = 0
411"""
412
Guido van Rossum98297ee2007-11-06 21:34:58 +0000413DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200414 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
415 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000416 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
417 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
418 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
419 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200420 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000421 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200422 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000423 b'object\nq\x07Ntq\x08Rq\t}q\n('
424 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
425 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
426)
Tim Peters70b02d72003-02-02 17:26:40 +0000427
Guido van Rossum98297ee2007-11-06 21:34:58 +0000428# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000429DATA1_DIS = """\
430 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000431 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000432 3: ( MARK
433 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000434 6: K BININT1 1
435 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200436 17: c GLOBAL '__builtin__ complex'
437 38: q BINPUT 1
438 40: ( MARK
439 41: G BINFLOAT 3.0
440 50: G BINFLOAT 0.0
441 59: t TUPLE (MARK at 40)
442 60: q BINPUT 2
443 62: R REDUCE
444 63: q BINPUT 3
445 65: K BININT1 1
446 67: J BININT -1
447 72: K BININT1 255
448 74: J BININT -255
449 79: J BININT -256
450 84: M BININT2 65535
451 87: J BININT -65535
452 92: J BININT -65536
453 97: J BININT 2147483647
454 102: J BININT -2147483647
455 107: J BININT -2147483648
456 112: ( MARK
457 113: X BINUNICODE 'abc'
458 121: q BINPUT 4
459 123: h BINGET 4
460 125: c GLOBAL 'copy_reg _reconstructor'
461 150: q BINPUT 5
462 152: ( MARK
463 153: c GLOBAL '__main__ C'
464 165: q BINPUT 6
465 167: c GLOBAL '__builtin__ object'
466 187: q BINPUT 7
467 189: N NONE
468 190: t TUPLE (MARK at 152)
469 191: q BINPUT 8
470 193: R REDUCE
471 194: q BINPUT 9
472 196: } EMPTY_DICT
473 197: q BINPUT 10
474 199: ( MARK
475 200: X BINUNICODE 'foo'
476 208: q BINPUT 11
477 210: K BININT1 1
478 212: X BINUNICODE 'bar'
479 220: q BINPUT 12
480 222: K BININT1 2
481 224: u SETITEMS (MARK at 199)
482 225: b BUILD
483 226: h BINGET 9
484 228: t TUPLE (MARK at 112)
485 229: q BINPUT 13
486 231: h BINGET 13
487 233: K BININT1 5
488 235: e APPENDS (MARK at 3)
489 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000490highest protocol among opcodes = 1
491"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000492
Guido van Rossum98297ee2007-11-06 21:34:58 +0000493DATA2 = (
494 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200495 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000496 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
497 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
498 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
499 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
500 b'bcq\x04h\x04c__main__\nC\nq\x05'
501 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
502 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
503 b'\nK\x05e.'
504)
Tim Petersfc273752003-03-02 04:54:24 +0000505
Guido van Rossum98297ee2007-11-06 21:34:58 +0000506# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000507DATA2_DIS = """\
508 0: \x80 PROTO 2
509 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000510 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000511 5: ( MARK
512 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000513 8: K BININT1 1
514 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200515 19: c GLOBAL '__builtin__ complex'
516 40: q BINPUT 1
517 42: G BINFLOAT 3.0
518 51: G BINFLOAT 0.0
519 60: \x86 TUPLE2
520 61: q BINPUT 2
521 63: R REDUCE
522 64: q BINPUT 3
523 66: K BININT1 1
524 68: J BININT -1
525 73: K BININT1 255
526 75: J BININT -255
527 80: J BININT -256
528 85: M BININT2 65535
529 88: J BININT -65535
530 93: J BININT -65536
531 98: J BININT 2147483647
532 103: J BININT -2147483647
533 108: J BININT -2147483648
534 113: ( MARK
535 114: X BINUNICODE 'abc'
536 122: q BINPUT 4
537 124: h BINGET 4
538 126: c GLOBAL '__main__ C'
539 138: q BINPUT 5
540 140: ) EMPTY_TUPLE
541 141: \x81 NEWOBJ
542 142: q BINPUT 6
543 144: } EMPTY_DICT
544 145: q BINPUT 7
545 147: ( MARK
546 148: X BINUNICODE 'foo'
547 156: q BINPUT 8
548 158: K BININT1 1
549 160: X BINUNICODE 'bar'
550 168: q BINPUT 9
551 170: K BININT1 2
552 172: u SETITEMS (MARK at 147)
553 173: b BUILD
554 174: h BINGET 6
555 176: t TUPLE (MARK at 113)
556 177: q BINPUT 10
557 179: h BINGET 10
558 181: K BININT1 5
559 183: e APPENDS (MARK at 5)
560 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000561highest protocol among opcodes = 2
562"""
563
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300564DATA3 = (
565 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
566 b'builtins\ncomplex\nq\x01G'
567 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
568 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
569 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
570 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
571 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
572 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
573 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
574 b'e.'
575)
576
577# Disassembly of DATA3
578DATA3_DIS = """\
579 0: \x80 PROTO 3
580 2: ] EMPTY_LIST
581 3: q BINPUT 0
582 5: ( MARK
583 6: K BININT1 0
584 8: K BININT1 1
585 10: G BINFLOAT 2.0
586 19: c GLOBAL 'builtins complex'
587 37: q BINPUT 1
588 39: G BINFLOAT 3.0
589 48: G BINFLOAT 0.0
590 57: \x86 TUPLE2
591 58: q BINPUT 2
592 60: R REDUCE
593 61: q BINPUT 3
594 63: K BININT1 1
595 65: J BININT -1
596 70: K BININT1 255
597 72: J BININT -255
598 77: J BININT -256
599 82: M BININT2 65535
600 85: J BININT -65535
601 90: J BININT -65536
602 95: J BININT 2147483647
603 100: J BININT -2147483647
604 105: J BININT -2147483648
605 110: ( MARK
606 111: X BINUNICODE 'abc'
607 119: q BINPUT 4
608 121: h BINGET 4
609 123: c GLOBAL '__main__ C'
610 135: q BINPUT 5
611 137: ) EMPTY_TUPLE
612 138: \x81 NEWOBJ
613 139: q BINPUT 6
614 141: } EMPTY_DICT
615 142: q BINPUT 7
616 144: ( MARK
617 145: X BINUNICODE 'bar'
618 153: q BINPUT 8
619 155: K BININT1 2
620 157: X BINUNICODE 'foo'
621 165: q BINPUT 9
622 167: K BININT1 1
623 169: u SETITEMS (MARK at 144)
624 170: b BUILD
625 171: h BINGET 6
626 173: t TUPLE (MARK at 110)
627 174: q BINPUT 10
628 176: h BINGET 10
629 178: K BININT1 5
630 180: e APPENDS (MARK at 5)
631 181: . STOP
632highest protocol among opcodes = 2
633"""
634
635DATA4 = (
636 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
637 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
638 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
639 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
640 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
641 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
642 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
643 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
644 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
645)
646
647# Disassembly of DATA4
648DATA4_DIS = """\
649 0: \x80 PROTO 4
650 2: \x95 FRAME 168
651 11: ] EMPTY_LIST
652 12: \x94 MEMOIZE
653 13: ( MARK
654 14: K BININT1 0
655 16: K BININT1 1
656 18: G BINFLOAT 2.0
657 27: \x8c SHORT_BINUNICODE 'builtins'
658 37: \x94 MEMOIZE
659 38: \x8c SHORT_BINUNICODE 'complex'
660 47: \x94 MEMOIZE
661 48: \x93 STACK_GLOBAL
662 49: \x94 MEMOIZE
663 50: G BINFLOAT 3.0
664 59: G BINFLOAT 0.0
665 68: \x86 TUPLE2
666 69: \x94 MEMOIZE
667 70: R REDUCE
668 71: \x94 MEMOIZE
669 72: K BININT1 1
670 74: J BININT -1
671 79: K BININT1 255
672 81: J BININT -255
673 86: J BININT -256
674 91: M BININT2 65535
675 94: J BININT -65535
676 99: J BININT -65536
677 104: J BININT 2147483647
678 109: J BININT -2147483647
679 114: J BININT -2147483648
680 119: ( MARK
681 120: \x8c SHORT_BINUNICODE 'abc'
682 125: \x94 MEMOIZE
683 126: h BINGET 6
684 128: \x8c SHORT_BINUNICODE '__main__'
685 138: \x94 MEMOIZE
686 139: \x8c SHORT_BINUNICODE 'C'
687 142: \x94 MEMOIZE
688 143: \x93 STACK_GLOBAL
689 144: \x94 MEMOIZE
690 145: ) EMPTY_TUPLE
691 146: \x81 NEWOBJ
692 147: \x94 MEMOIZE
693 148: } EMPTY_DICT
694 149: \x94 MEMOIZE
695 150: ( MARK
696 151: \x8c SHORT_BINUNICODE 'bar'
697 156: \x94 MEMOIZE
698 157: K BININT1 2
699 159: \x8c SHORT_BINUNICODE 'foo'
700 164: \x94 MEMOIZE
701 165: K BININT1 1
702 167: u SETITEMS (MARK at 150)
703 168: b BUILD
704 169: h BINGET 10
705 171: t TUPLE (MARK at 119)
706 172: \x94 MEMOIZE
707 173: h BINGET 14
708 175: K BININT1 5
709 177: e APPENDS (MARK at 13)
710 178: . STOP
711highest protocol among opcodes = 4
712"""
713
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000714# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300715DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000716
717# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300718DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000719
720# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300721DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
722 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
723 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
724 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
725 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
726 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000727
728# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300729DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000730
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100731python2_exceptions_without_args = (
732 ArithmeticError,
733 AssertionError,
734 AttributeError,
735 BaseException,
736 BufferError,
737 BytesWarning,
738 DeprecationWarning,
739 EOFError,
740 EnvironmentError,
741 Exception,
742 FloatingPointError,
743 FutureWarning,
744 GeneratorExit,
745 IOError,
746 ImportError,
747 ImportWarning,
748 IndentationError,
749 IndexError,
750 KeyError,
751 KeyboardInterrupt,
752 LookupError,
753 MemoryError,
754 NameError,
755 NotImplementedError,
756 OSError,
757 OverflowError,
758 PendingDeprecationWarning,
759 ReferenceError,
760 RuntimeError,
761 RuntimeWarning,
762 # StandardError is gone in Python 3, we map it to Exception
763 StopIteration,
764 SyntaxError,
765 SyntaxWarning,
766 SystemError,
767 SystemExit,
768 TabError,
769 TypeError,
770 UnboundLocalError,
771 UnicodeError,
772 UnicodeWarning,
773 UserWarning,
774 ValueError,
775 Warning,
776 ZeroDivisionError,
777)
778
779exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
780
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100781# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300782DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
783 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
784 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100785
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000786
Jeremy Hylton66426532001-10-15 21:38:56 +0000787def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000788 c = C()
789 c.foo = 1
790 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000791 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000792 # Append some integer test cases at cPickle.c's internal size
793 # cutoffs.
794 uint1max = 0xff
795 uint2max = 0xffff
796 int4max = 0x7fffffff
797 x.extend([1, -1,
798 uint1max, -uint1max, -uint1max-1,
799 uint2max, -uint2max, -uint2max-1,
800 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000801 y = ('abc', 'abc', c, c)
802 x.append(y)
803 x.append(y)
804 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000805 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000806
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100807
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300808class AbstractUnpickleTests(unittest.TestCase):
809 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100810
Jeremy Hylton66426532001-10-15 21:38:56 +0000811 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000812
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100813 def assert_is_copy(self, obj, objcopy, msg=None):
814 """Utility method to verify if two objects are copies of each others.
815 """
816 if msg is None:
817 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
818 self.assertEqual(obj, objcopy, msg=msg)
819 self.assertIs(type(obj), type(objcopy), msg=msg)
820 if hasattr(obj, '__dict__'):
821 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
822 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
823 if hasattr(obj, '__slots__'):
824 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
825 for slot in obj.__slots__:
826 self.assertEqual(
827 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
828 self.assertEqual(getattr(obj, slot, None),
829 getattr(objcopy, slot, None), msg=msg)
830
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200831 def check_unpickling_error(self, errors, data):
832 with self.subTest(data=data), \
833 self.assertRaises(errors):
834 try:
835 self.loads(data)
836 except BaseException as exc:
837 if support.verbose > 1:
838 print('%-32r - %s: %s' %
839 (data, exc.__class__.__name__, exc))
840 raise
841
Guido van Rossum98297ee2007-11-06 21:34:58 +0000842 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100843 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000844
845 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100846 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000847
848 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100849 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000850
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300851 def test_load_from_data3(self):
852 self.assert_is_copy(self._testdata, self.loads(DATA3))
853
854 def test_load_from_data4(self):
855 self.assert_is_copy(self._testdata, self.loads(DATA4))
856
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000857 def test_load_classic_instance(self):
858 # See issue5180. Test loading 2.x pickles that
859 # contain an instance of old style class.
860 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
861 xname = X.__name__.encode('ascii')
862 # Protocol 0 (text mode pickle):
863 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200864 0: ( MARK
865 1: i INST '__main__ X' (MARK at 0)
866 13: p PUT 0
867 16: ( MARK
868 17: d DICT (MARK at 16)
869 18: p PUT 1
870 21: b BUILD
871 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000872 """
873 pickle0 = (b"(i__main__\n"
874 b"X\n"
875 b"p0\n"
876 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100877 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000878
879 # Protocol 1 (binary mode pickle)
880 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200881 0: ( MARK
882 1: c GLOBAL '__main__ X'
883 13: q BINPUT 0
884 15: o OBJ (MARK at 0)
885 16: q BINPUT 1
886 18: } EMPTY_DICT
887 19: q BINPUT 2
888 21: b BUILD
889 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000890 """
891 pickle1 = (b'(c__main__\n'
892 b'X\n'
893 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100894 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000895
896 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
897 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200898 0: \x80 PROTO 2
899 2: ( MARK
900 3: c GLOBAL '__main__ X'
901 15: q BINPUT 0
902 17: o OBJ (MARK at 2)
903 18: q BINPUT 1
904 20: } EMPTY_DICT
905 21: q BINPUT 2
906 23: b BUILD
907 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000908 """
909 pickle2 = (b'\x80\x02(c__main__\n'
910 b'X\n'
911 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100912 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000913
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300914 def test_maxint64(self):
915 maxint64 = (1 << 63) - 1
916 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
917 got = self.loads(data)
918 self.assert_is_copy(maxint64, got)
919
920 # Try too with a bogus literal.
921 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200922 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300923
924 def test_unpickle_from_2x(self):
925 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300926 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300927 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300928 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300929 self.assertEqual(type(loaded), type(range(0)))
930 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300931 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300932 self.assertEqual(type(loaded), SimpleCookie)
933 self.assertEqual(list(loaded.keys()), ["key"])
934 self.assertEqual(loaded["key"].value, "value")
935
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300936 # Exception objects without arguments pickled from 2.x with protocol 2
937 for exc in python2_exceptions_without_args:
938 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300939 loaded = self.loads(data)
940 self.assertIs(type(loaded), exc)
941
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300942 # StandardError is mapped to Exception, test that separately
943 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300944 self.assertIs(type(loaded), Exception)
945
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300946 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300947 self.assertIs(type(loaded), UnicodeEncodeError)
948 self.assertEqual(loaded.object, "foo")
949 self.assertEqual(loaded.encoding, "ascii")
950 self.assertEqual(loaded.start, 0)
951 self.assertEqual(loaded.end, 1)
952 self.assertEqual(loaded.reason, "bad")
953
954 def test_load_python2_str_as_bytes(self):
955 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
956 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
957 encoding="bytes"), b'a\x00\xa0')
958 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
959 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
960 encoding="bytes"), b'a\x00\xa0')
961 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
962 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
963 encoding="bytes"), b'a\x00\xa0')
964
965 def test_load_python2_unicode_as_str(self):
966 # From Python 2: pickle.dumps(u'π', protocol=0)
967 self.assertEqual(self.loads(b'V\\u03c0\n.',
968 encoding='bytes'), 'π')
969 # From Python 2: pickle.dumps(u'π', protocol=1)
970 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
971 encoding="bytes"), 'π')
972 # From Python 2: pickle.dumps(u'π', protocol=2)
973 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
974 encoding="bytes"), 'π')
975
976 def test_load_long_python2_str_as_bytes(self):
977 # From Python 2: pickle.dumps('x' * 300, protocol=1)
978 self.assertEqual(self.loads(pickle.BINSTRING +
979 struct.pack("<I", 300) +
980 b'x' * 300 + pickle.STOP,
981 encoding='bytes'), b'x' * 300)
982
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300983 def test_constants(self):
984 self.assertIsNone(self.loads(b'N.'))
985 self.assertIs(self.loads(b'\x88.'), True)
986 self.assertIs(self.loads(b'\x89.'), False)
987 self.assertIs(self.loads(b'I01\n.'), True)
988 self.assertIs(self.loads(b'I00\n.'), False)
989
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300990 def test_empty_bytestring(self):
991 # issue 11286
992 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
993 self.assertEqual(empty, '')
994
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300995 def test_short_binbytes(self):
996 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
997 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
998
999 def test_binbytes(self):
1000 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1001 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1002
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001003 @requires_32b
1004 def test_negative_32b_binbytes(self):
1005 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1006 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001007 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1008 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001009
1010 @requires_32b
1011 def test_negative_32b_binunicode(self):
1012 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1013 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001014 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1015 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001016
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001017 def test_short_binunicode(self):
1018 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1019 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1020
1021 def test_misc_get(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001022 self.check_unpickling_error(KeyError, b'g0\np0')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001023 self.assert_is_copy([(100,), (100,)],
1024 self.loads(b'((Kdtp0\nh\x00l.))'))
1025
Serhiy Storchakae0606192015-09-29 22:10:07 +03001026 def test_binbytes8(self):
1027 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1028 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1029
1030 def test_binunicode8(self):
1031 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1032 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1033
Antoine Pitrou91f43802019-05-26 17:10:09 +02001034 def test_bytearray8(self):
1035 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1036 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1037
Serhiy Storchakae0606192015-09-29 22:10:07 +03001038 @requires_32b
1039 def test_large_32b_binbytes8(self):
1040 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001041 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1042 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001043
1044 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001045 def test_large_32b_bytearray8(self):
1046 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1047 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1048 dumped)
1049
1050 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001051 def test_large_32b_binunicode8(self):
1052 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001053 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1054 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001055
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001056 def test_get(self):
1057 pickled = b'((lp100000\ng100000\nt.'
1058 unpickled = self.loads(pickled)
1059 self.assertEqual(unpickled, ([],)*2)
1060 self.assertIs(unpickled[0], unpickled[1])
1061
1062 def test_binget(self):
1063 pickled = b'(]q\xffh\xfft.'
1064 unpickled = self.loads(pickled)
1065 self.assertEqual(unpickled, ([],)*2)
1066 self.assertIs(unpickled[0], unpickled[1])
1067
1068 def test_long_binget(self):
1069 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1070 unpickled = self.loads(pickled)
1071 self.assertEqual(unpickled, ([],)*2)
1072 self.assertIs(unpickled[0], unpickled[1])
1073
1074 def test_dup(self):
1075 pickled = b'((l2t.'
1076 unpickled = self.loads(pickled)
1077 self.assertEqual(unpickled, ([],)*2)
1078 self.assertIs(unpickled[0], unpickled[1])
1079
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001080 def test_negative_put(self):
1081 # Issue #12847
1082 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001083 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001084
1085 @requires_32b
1086 def test_negative_32b_binput(self):
1087 # Issue #12847
1088 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001089 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001090
1091 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001092 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001093
1094 def test_badly_quoted_string(self):
1095 # Issue #17710
1096 badpickles = [b"S'\n.",
1097 b'S"\n.',
1098 b'S\' \n.',
1099 b'S" \n.',
1100 b'S\'"\n.',
1101 b'S"\'\n.',
1102 b"S' ' \n.",
1103 b'S" " \n.',
1104 b"S ''\n.",
1105 b'S ""\n.',
1106 b'S \n.',
1107 b'S\n.',
1108 b'S.']
1109 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001110 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001111
1112 def test_correctly_quoted_string(self):
1113 goodpickles = [(b"S''\n.", ''),
1114 (b'S""\n.', ''),
1115 (b'S"\\n"\n.', '\n'),
1116 (b"S'\\n'\n.", '\n')]
1117 for p, expected in goodpickles:
1118 self.assertEqual(self.loads(p), expected)
1119
1120 def test_frame_readline(self):
1121 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1122 # 0: \x80 PROTO 4
1123 # 2: \x95 FRAME 5
1124 # 11: I INT 42
1125 # 15: . STOP
1126 self.assertEqual(self.loads(pickled), 42)
1127
1128 def test_compat_unpickle(self):
1129 # xrange(1, 7)
1130 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1131 unpickled = self.loads(pickled)
1132 self.assertIs(type(unpickled), range)
1133 self.assertEqual(unpickled, range(1, 7))
1134 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1135 # reduce
1136 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1137 self.assertIs(self.loads(pickled), functools.reduce)
1138 # whichdb.whichdb
1139 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1140 self.assertIs(self.loads(pickled), dbm.whichdb)
1141 # Exception(), StandardError()
1142 for name in (b'Exception', b'StandardError'):
1143 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1144 unpickled = self.loads(pickled)
1145 self.assertIs(type(unpickled), Exception)
1146 self.assertEqual(str(unpickled), 'ugh')
1147 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1148 for name in (b'UserDict', b'IterableUserDict'):
1149 pickled = (b'\x80\x02(cUserDict\n' + name +
1150 b'\no}U\x04data}K\x01K\x02ssb.')
1151 unpickled = self.loads(pickled)
1152 self.assertIs(type(unpickled), collections.UserDict)
1153 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1154
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001155 def test_bad_stack(self):
1156 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001157 b'.', # STOP
1158 b'0', # POP
1159 b'1', # POP_MARK
1160 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001161 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001162 b'R', # REDUCE
1163 b')R',
1164 b'a', # APPEND
1165 b'Na',
1166 b'b', # BUILD
1167 b'Nb',
1168 b'd', # DICT
1169 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001170 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001171 b'ibuiltins\nlist\n', # INST
1172 b'l', # LIST
1173 b'o', # OBJ
1174 b'(o',
1175 b'p1\n', # PUT
1176 b'q\x00', # BINPUT
1177 b'r\x00\x00\x00\x00', # LONG_BINPUT
1178 b's', # SETITEM
1179 b'Ns',
1180 b'NNs',
1181 b't', # TUPLE
1182 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001183 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001184 b'}(Nu',
1185 b'\x81', # NEWOBJ
1186 b')\x81',
1187 b'\x85', # TUPLE1
1188 b'\x86', # TUPLE2
1189 b'N\x86',
1190 b'\x87', # TUPLE3
1191 b'N\x87',
1192 b'NN\x87',
1193 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001194 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001195 b'\x91', # FROZENSET
1196 b'\x92', # NEWOBJ_EX
1197 b')}\x92',
1198 b'\x93', # STACK_GLOBAL
1199 b'Vlist\n\x93',
1200 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001201 ]
1202 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001203 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001204
1205 def test_bad_mark(self):
1206 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001207 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001208 b'N(2', # DUP
1209 b'cbuiltins\nlist\n)(R', # REDUCE
1210 b'cbuiltins\nlist\n()R',
1211 b']N(a', # APPEND
1212 # BUILD
1213 b'cbuiltins\nValueError\n)R}(b',
1214 b'cbuiltins\nValueError\n)R(}b',
1215 b'(Nd', # DICT
1216 b'N(p1\n', # PUT
1217 b'N(q\x00', # BINPUT
1218 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1219 b'}NN(s', # SETITEM
1220 b'}N(Ns',
1221 b'}(NNs',
1222 b'}((u', # SETITEMS
1223 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1224 b'cbuiltins\nlist\n()\x81',
1225 b'N(\x85', # TUPLE1
1226 b'NN(\x86', # TUPLE2
1227 b'N(N\x86',
1228 b'NNN(\x87', # TUPLE3
1229 b'NN(N\x87',
1230 b'N(NN\x87',
1231 b']((\x90', # ADDITEMS
1232 # NEWOBJ_EX
1233 b'cbuiltins\nlist\n)}(\x92',
1234 b'cbuiltins\nlist\n)(}\x92',
1235 b'cbuiltins\nlist\n()}\x92',
1236 # STACK_GLOBAL
1237 b'Vbuiltins\n(Vlist\n\x93',
1238 b'Vbuiltins\nVlist\n(\x93',
1239 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001240 ]
1241 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001242 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001243
1244 def test_truncated_data(self):
1245 self.check_unpickling_error(EOFError, b'')
1246 self.check_unpickling_error(EOFError, b'N')
1247 badpickles = [
1248 b'B', # BINBYTES
1249 b'B\x03\x00\x00',
1250 b'B\x03\x00\x00\x00',
1251 b'B\x03\x00\x00\x00ab',
1252 b'C', # SHORT_BINBYTES
1253 b'C\x03',
1254 b'C\x03ab',
1255 b'F', # FLOAT
1256 b'F0.0',
1257 b'F0.00',
1258 b'G', # BINFLOAT
1259 b'G\x00\x00\x00\x00\x00\x00\x00',
1260 b'I', # INT
1261 b'I0',
1262 b'J', # BININT
1263 b'J\x00\x00\x00',
1264 b'K', # BININT1
1265 b'L', # LONG
1266 b'L0',
1267 b'L10',
1268 b'L0L',
1269 b'L10L',
1270 b'M', # BININT2
1271 b'M\x00',
1272 # b'P', # PERSID
1273 # b'Pabc',
1274 b'S', # STRING
1275 b"S'abc'",
1276 b'T', # BINSTRING
1277 b'T\x03\x00\x00',
1278 b'T\x03\x00\x00\x00',
1279 b'T\x03\x00\x00\x00ab',
1280 b'U', # SHORT_BINSTRING
1281 b'U\x03',
1282 b'U\x03ab',
1283 b'V', # UNICODE
1284 b'Vabc',
1285 b'X', # BINUNICODE
1286 b'X\x03\x00\x00',
1287 b'X\x03\x00\x00\x00',
1288 b'X\x03\x00\x00\x00ab',
1289 b'(c', # GLOBAL
1290 b'(cbuiltins',
1291 b'(cbuiltins\n',
1292 b'(cbuiltins\nlist',
1293 b'Ng', # GET
1294 b'Ng0',
1295 b'(i', # INST
1296 b'(ibuiltins',
1297 b'(ibuiltins\n',
1298 b'(ibuiltins\nlist',
1299 b'Nh', # BINGET
1300 b'Nj', # LONG_BINGET
1301 b'Nj\x00\x00\x00',
1302 b'Np', # PUT
1303 b'Np0',
1304 b'Nq', # BINPUT
1305 b'Nr', # LONG_BINPUT
1306 b'Nr\x00\x00\x00',
1307 b'\x80', # PROTO
1308 b'\x82', # EXT1
1309 b'\x83', # EXT2
1310 b'\x84\x01',
1311 b'\x84', # EXT4
1312 b'\x84\x01\x00\x00',
1313 b'\x8a', # LONG1
1314 b'\x8b', # LONG4
1315 b'\x8b\x00\x00\x00',
1316 b'\x8c', # SHORT_BINUNICODE
1317 b'\x8c\x03',
1318 b'\x8c\x03ab',
1319 b'\x8d', # BINUNICODE8
1320 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1321 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1322 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1323 b'\x8e', # BINBYTES8
1324 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1325 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1326 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001327 b'\x96', # BYTEARRAY8
1328 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1329 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1330 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001331 b'\x95', # FRAME
1332 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1333 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1334 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1335 ]
1336 for p in badpickles:
1337 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001338
tjb9004371c0a2019-02-18 23:30:51 +08001339 @reap_threads
1340 def test_unpickle_module_race(self):
1341 # https://bugs.python.org/issue34572
1342 locker_module = dedent("""
1343 import threading
1344 barrier = threading.Barrier(2)
1345 """)
1346 locking_import_module = dedent("""
1347 import locker
1348 locker.barrier.wait()
1349 class ToBeUnpickled(object):
1350 pass
1351 """)
1352
1353 os.mkdir(TESTFN)
1354 self.addCleanup(shutil.rmtree, TESTFN)
1355 sys.path.insert(0, TESTFN)
1356 self.addCleanup(sys.path.remove, TESTFN)
1357 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1358 f.write(locker_module.encode('utf-8'))
1359 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1360 f.write(locking_import_module.encode('utf-8'))
1361 self.addCleanup(forget, "locker")
1362 self.addCleanup(forget, "locking_import")
1363
1364 import locker
1365
1366 pickle_bytes = (
1367 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1368
1369 # Then try to unpickle two of these simultaneously
1370 # One of them will cause the module import, and we want it to block
1371 # until the other one either:
1372 # - fails (before the patch for this issue)
1373 # - blocks on the import lock for the module, as it should
1374 results = []
1375 barrier = threading.Barrier(3)
1376 def t():
1377 # This ensures the threads have all started
1378 # presumably barrier release is faster than thread startup
1379 barrier.wait()
1380 results.append(pickle.loads(pickle_bytes))
1381
1382 t1 = threading.Thread(target=t)
1383 t2 = threading.Thread(target=t)
1384 t1.start()
1385 t2.start()
1386
1387 barrier.wait()
1388 # could have delay here
1389 locker.barrier.wait()
1390
1391 t1.join()
1392 t2.join()
1393
1394 from locking_import import ToBeUnpickled
1395 self.assertEqual(
1396 [type(x) for x in results],
1397 [ToBeUnpickled] * 2)
1398
1399
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001400
1401class AbstractPickleTests(unittest.TestCase):
1402 # Subclass must define self.dumps, self.loads.
1403
1404 optimized = False
1405
1406 _testdata = AbstractUnpickleTests._testdata
1407
1408 def setUp(self):
1409 pass
1410
1411 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1412
1413 def test_misc(self):
1414 # test various datatypes not tested by testdata
1415 for proto in protocols:
1416 x = myint(4)
1417 s = self.dumps(x, proto)
1418 y = self.loads(s)
1419 self.assert_is_copy(x, y)
1420
1421 x = (1, ())
1422 s = self.dumps(x, proto)
1423 y = self.loads(s)
1424 self.assert_is_copy(x, y)
1425
1426 x = initarg(1, x)
1427 s = self.dumps(x, proto)
1428 y = self.loads(s)
1429 self.assert_is_copy(x, y)
1430
1431 # XXX test __reduce__ protocol?
1432
1433 def test_roundtrip_equality(self):
1434 expected = self._testdata
1435 for proto in protocols:
1436 s = self.dumps(expected, proto)
1437 got = self.loads(s)
1438 self.assert_is_copy(expected, got)
1439
Tim Peters70b02d72003-02-02 17:26:40 +00001440 # There are gratuitous differences between pickles produced by
1441 # pickle and cPickle, largely because cPickle starts PUT indices at
1442 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1443 # there's a comment with an exclamation point there whose meaning
1444 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1445 # of 1.
1446 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001447 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001448 from pickletools import dis
1449
1450 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1451 s = self.dumps(self._testdata, proto)
1452 filelike = StringIO()
1453 dis(s, out=filelike)
1454 got = filelike.getvalue()
1455 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001456
1457 def test_recursive_list(self):
1458 l = []
1459 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001460 for proto in protocols:
1461 s = self.dumps(l, proto)
1462 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001463 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001464 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001465 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001466
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001467 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001468 t = ([],)
1469 t[0].append(t)
1470 for proto in protocols:
1471 s = self.dumps(t, proto)
1472 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001473 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001474 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001475 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001476 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001477 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001478
Jeremy Hylton66426532001-10-15 21:38:56 +00001479 def test_recursive_dict(self):
1480 d = {}
1481 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001482 for proto in protocols:
1483 s = self.dumps(d, proto)
1484 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001485 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001486 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001487 self.assertIs(x[1], x)
1488
1489 def test_recursive_dict_key(self):
1490 d = {}
1491 k = K(d)
1492 d[k] = 1
1493 for proto in protocols:
1494 s = self.dumps(d, proto)
1495 x = self.loads(s)
1496 self.assertIsInstance(x, dict)
1497 self.assertEqual(len(x.keys()), 1)
1498 self.assertIsInstance(list(x.keys())[0], K)
1499 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001500
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001501 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001502 y = set()
1503 k = K(y)
1504 y.add(k)
1505 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001506 s = self.dumps(y, proto)
1507 x = self.loads(s)
1508 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001509 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001510 self.assertIsInstance(list(x)[0], K)
1511 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001512
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001513 def test_recursive_list_subclass(self):
1514 y = MyList()
1515 y.append(y)
1516 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001517 s = self.dumps(y, proto)
1518 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001519 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001520 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001521 self.assertIs(x[0], x)
1522
1523 def test_recursive_dict_subclass(self):
1524 d = MyDict()
1525 d[1] = d
1526 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1527 s = self.dumps(d, proto)
1528 x = self.loads(s)
1529 self.assertIsInstance(x, MyDict)
1530 self.assertEqual(list(x.keys()), [1])
1531 self.assertIs(x[1], x)
1532
1533 def test_recursive_dict_subclass_key(self):
1534 d = MyDict()
1535 k = K(d)
1536 d[k] = 1
1537 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1538 s = self.dumps(d, proto)
1539 x = self.loads(s)
1540 self.assertIsInstance(x, MyDict)
1541 self.assertEqual(len(list(x.keys())), 1)
1542 self.assertIsInstance(list(x.keys())[0], K)
1543 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001544
Jeremy Hylton66426532001-10-15 21:38:56 +00001545 def test_recursive_inst(self):
1546 i = C()
1547 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001548 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001549 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001550 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001551 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001552 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001553 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001554
1555 def test_recursive_multi(self):
1556 l = []
1557 d = {1:l}
1558 i = C()
1559 i.attr = d
1560 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001561 for proto in protocols:
1562 s = self.dumps(l, proto)
1563 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001564 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001565 self.assertEqual(len(x), 1)
1566 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001567 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001568 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001569
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001570 def check_recursive_collection_and_inst(self, factory):
1571 h = H()
1572 y = factory([h])
1573 h.attr = y
1574 for proto in protocols:
1575 s = self.dumps(y, proto)
1576 x = self.loads(s)
1577 self.assertIsInstance(x, type(y))
1578 self.assertEqual(len(x), 1)
1579 self.assertIsInstance(list(x)[0], H)
1580 self.assertIs(list(x)[0].attr, x)
1581
1582 def test_recursive_list_and_inst(self):
1583 self.check_recursive_collection_and_inst(list)
1584
1585 def test_recursive_tuple_and_inst(self):
1586 self.check_recursive_collection_and_inst(tuple)
1587
1588 def test_recursive_dict_and_inst(self):
1589 self.check_recursive_collection_and_inst(dict.fromkeys)
1590
1591 def test_recursive_set_and_inst(self):
1592 self.check_recursive_collection_and_inst(set)
1593
1594 def test_recursive_frozenset_and_inst(self):
1595 self.check_recursive_collection_and_inst(frozenset)
1596
1597 def test_recursive_list_subclass_and_inst(self):
1598 self.check_recursive_collection_and_inst(MyList)
1599
1600 def test_recursive_tuple_subclass_and_inst(self):
1601 self.check_recursive_collection_and_inst(MyTuple)
1602
1603 def test_recursive_dict_subclass_and_inst(self):
1604 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1605
1606 def test_recursive_set_subclass_and_inst(self):
1607 self.check_recursive_collection_and_inst(MySet)
1608
1609 def test_recursive_frozenset_subclass_and_inst(self):
1610 self.check_recursive_collection_and_inst(MyFrozenSet)
1611
Walter Dörwald9b775532007-06-08 14:30:53 +00001612 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001613 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001614 '<\\>', '<\\\U00012345>',
1615 # surrogates
1616 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001617 for proto in protocols:
1618 for u in endcases:
1619 p = self.dumps(u, proto)
1620 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001621 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001622
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001623 def test_unicode_high_plane(self):
1624 t = '\U00012345'
1625 for proto in protocols:
1626 p = self.dumps(t, proto)
1627 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001628 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001629
Guido van Rossumf4169812008-03-17 22:56:06 +00001630 def test_bytes(self):
1631 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001632 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001633 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001634 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001635 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001636 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001637 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001638 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001639 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001640 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001641
Antoine Pitrou91f43802019-05-26 17:10:09 +02001642 def test_bytearray(self):
1643 for proto in protocols:
1644 for s in b'', b'xyz', b'xyz'*100:
1645 b = bytearray(s)
1646 p = self.dumps(b, proto)
1647 bb = self.loads(p)
1648 self.assertIsNot(bb, b)
1649 self.assert_is_copy(b, bb)
1650 if proto <= 3:
1651 # bytearray is serialized using a global reference
1652 self.assertIn(b'bytearray', p)
1653 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1654 elif proto == 4:
1655 self.assertIn(b'bytearray', p)
1656 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1657 elif proto == 5:
1658 self.assertNotIn(b'bytearray', p)
1659 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1660
Jeremy Hylton66426532001-10-15 21:38:56 +00001661 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001662 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001663 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001664 while n:
1665 for expected in (-n, n):
1666 s = self.dumps(expected, proto)
1667 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001668 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001669 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001670
Tim Petersee1a53c2003-02-02 02:57:53 +00001671 def test_long(self):
1672 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001673 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001674 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001675 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001676 for npos in nbase-1, nbase, nbase+1:
1677 for n in npos, -npos:
1678 pickle = self.dumps(n, proto)
1679 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001680 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001681 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1682 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001683 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001684 nbase += nbase << 1000000
1685 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001686 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001687 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001688 # assert_is_copy is very expensive here as it precomputes
1689 # a failure message by computing the repr() of n and got,
1690 # we just do the check ourselves.
1691 self.assertIs(type(got), int)
1692 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001693
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001694 def test_float(self):
1695 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1696 3.14, 263.44582062374053, 6.022e23, 1e30]
1697 test_values = test_values + [-x for x in test_values]
1698 for proto in protocols:
1699 for value in test_values:
1700 pickle = self.dumps(value, proto)
1701 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001702 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001703
Thomas Wouters477c8d52006-05-27 19:21:47 +00001704 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1705 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001706 # make sure that floats are formatted locale independent with proto 0
1707 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001708
Jeremy Hylton66426532001-10-15 21:38:56 +00001709 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001710 for proto in protocols:
1711 inst = AAA()
1712 dumped = self.dumps(inst, proto)
1713 loaded = self.loads(dumped)
1714 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001715
1716 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001717 for proto in protocols:
1718 inst = initarg(1, 2)
1719 dumped = self.dumps(inst, proto)
1720 loaded = self.loads(dumped)
1721 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001722
Guido van Rossum04a86612001-12-19 16:58:54 +00001723 def test_metaclass(self):
1724 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001725 for proto in protocols:
1726 s = self.dumps(a, proto)
1727 b = self.loads(s)
1728 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001729
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001730 def test_dynamic_class(self):
1731 a = create_dynamic_class("my_dynamic_class", (object,))
1732 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1733 for proto in protocols:
1734 s = self.dumps(a, proto)
1735 b = self.loads(s)
1736 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001737 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001738
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001739 def test_structseq(self):
1740 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001741 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001742
1743 t = time.localtime()
1744 for proto in protocols:
1745 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001746 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001747 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001748 t = os.stat(os.curdir)
1749 s = self.dumps(t, proto)
1750 u = self.loads(s)
1751 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001752 if hasattr(os, "statvfs"):
1753 t = os.statvfs(os.curdir)
1754 s = self.dumps(t, proto)
1755 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001756 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001757
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001758 def test_ellipsis(self):
1759 for proto in protocols:
1760 s = self.dumps(..., proto)
1761 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001762 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001763
1764 def test_notimplemented(self):
1765 for proto in protocols:
1766 s = self.dumps(NotImplemented, proto)
1767 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001768 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001769
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001770 def test_singleton_types(self):
1771 # Issue #6477: Test that types of built-in singletons can be pickled.
1772 singletons = [None, ..., NotImplemented]
1773 for singleton in singletons:
1774 for proto in protocols:
1775 s = self.dumps(type(singleton), proto)
1776 u = self.loads(s)
1777 self.assertIs(type(singleton), u)
1778
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001779 # Tests for protocol 2
1780
Tim Peters4190fb82003-02-02 16:09:05 +00001781 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001782 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001783 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001784 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001785 proto_header = pickle.PROTO + bytes([proto])
1786 self.assertTrue(pickled.startswith(proto_header))
1787 else:
1788 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001789
1790 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001791 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001792 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001793 try:
1794 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001795 except ValueError as err:
1796 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001797 else:
1798 self.fail("expected bad protocol number to raise ValueError")
1799
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001800 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001801 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001802 for proto in protocols:
1803 s = self.dumps(x, proto)
1804 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001805 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001806 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001807
1808 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001809 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001810 for proto in protocols:
1811 s = self.dumps(x, proto)
1812 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001813 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001814 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001815
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001816 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001817 # Map (proto, len(tuple)) to expected opcode.
1818 expected_opcode = {(0, 0): pickle.TUPLE,
1819 (0, 1): pickle.TUPLE,
1820 (0, 2): pickle.TUPLE,
1821 (0, 3): pickle.TUPLE,
1822 (0, 4): pickle.TUPLE,
1823
1824 (1, 0): pickle.EMPTY_TUPLE,
1825 (1, 1): pickle.TUPLE,
1826 (1, 2): pickle.TUPLE,
1827 (1, 3): pickle.TUPLE,
1828 (1, 4): pickle.TUPLE,
1829
1830 (2, 0): pickle.EMPTY_TUPLE,
1831 (2, 1): pickle.TUPLE1,
1832 (2, 2): pickle.TUPLE2,
1833 (2, 3): pickle.TUPLE3,
1834 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001835
1836 (3, 0): pickle.EMPTY_TUPLE,
1837 (3, 1): pickle.TUPLE1,
1838 (3, 2): pickle.TUPLE2,
1839 (3, 3): pickle.TUPLE3,
1840 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001841 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001842 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001843 b = (1,)
1844 c = (1, 2)
1845 d = (1, 2, 3)
1846 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001847 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001848 for x in a, b, c, d, e:
1849 s = self.dumps(x, proto)
1850 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001851 self.assert_is_copy(x, y)
1852 expected = expected_opcode[min(proto, 3), len(x)]
1853 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001854
Guido van Rossum7d97d312003-01-28 04:25:27 +00001855 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001856 # Map (proto, singleton) to expected opcode.
1857 expected_opcode = {(0, None): pickle.NONE,
1858 (1, None): pickle.NONE,
1859 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001860 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001861
1862 (0, True): pickle.INT,
1863 (1, True): pickle.INT,
1864 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001865 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001866
1867 (0, False): pickle.INT,
1868 (1, False): pickle.INT,
1869 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001870 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001871 }
Tim Peters4190fb82003-02-02 16:09:05 +00001872 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001873 for x in None, False, True:
1874 s = self.dumps(x, proto)
1875 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001876 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001877 expected = expected_opcode[min(proto, 3), x]
1878 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001879
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001880 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001881 x = MyTuple([1, 2, 3])
1882 x.foo = 42
1883 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001884 for proto in protocols:
1885 s = self.dumps(x, proto)
1886 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001887 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001888
1889 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001890 x = MyList([1, 2, 3])
1891 x.foo = 42
1892 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001893 for proto in protocols:
1894 s = self.dumps(x, proto)
1895 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001896 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001897
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001898 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001899 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001900 for C in myclasses:
1901 B = C.__base__
1902 x = C(C.sample)
1903 x.foo = 42
1904 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001905 y = self.loads(s)
1906 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001907 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001908 self.assertEqual(B(x), B(y), detail)
1909 self.assertEqual(x.__dict__, y.__dict__, detail)
1910
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001911 def test_newobj_proxies(self):
1912 # NEWOBJ should use the __class__ rather than the raw type
1913 classes = myclasses[:]
1914 # Cannot create weakproxies to these classes
1915 for c in (MyInt, MyTuple):
1916 classes.remove(c)
1917 for proto in protocols:
1918 for C in classes:
1919 B = C.__base__
1920 x = C(C.sample)
1921 x.foo = 42
1922 p = weakref.proxy(x)
1923 s = self.dumps(p, proto)
1924 y = self.loads(s)
1925 self.assertEqual(type(y), type(x)) # rather than type(p)
1926 detail = (proto, C, B, x, y, type(y))
1927 self.assertEqual(B(x), B(y), detail)
1928 self.assertEqual(x.__dict__, y.__dict__, detail)
1929
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001930 def test_newobj_not_class(self):
1931 # Issue 24552
1932 global SimpleNewObj
1933 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001934 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001935 b = self.dumps(o, 4)
1936 try:
1937 SimpleNewObj = 42
1938 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1939 finally:
1940 SimpleNewObj = save
1941
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001942 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001943 # an object of that type. Check that the resulting pickle uses opcode
1944 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001945
Tim Peters22e71712003-02-03 22:27:38 +00001946 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001947 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001948 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001949 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001950 x = MyList([1, 2, 3])
1951 x.foo = 42
1952 x.bar = "hello"
1953
Tim Peters22e71712003-02-03 22:27:38 +00001954 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001955 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001956 self.assertIn(__name__.encode("utf-8"), s1)
1957 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001958 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001959
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001960 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001961 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001962
Tim Peters22e71712003-02-03 22:27:38 +00001963 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001964 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001965 self.assertNotIn(__name__.encode("utf-8"), s2)
1966 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001967 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001968
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001969 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001970 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001971 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001972 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001973
1974 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001975 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1976 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001977
1978 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001979 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1980 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1981 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001982
1983 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001984 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1985 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
1986 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
1987
Tim Peters8d2613a2003-02-11 16:40:16 +00001988 def test_list_chunking(self):
1989 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00001990 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001991 for proto in protocols:
1992 s = self.dumps(x, proto)
1993 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001994 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001995 num_appends = count_opcode(pickle.APPENDS, s)
1996 self.assertEqual(num_appends, proto > 0)
1997
1998 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001999 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002000 for proto in protocols:
2001 s = self.dumps(x, proto)
2002 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002003 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002004 num_appends = count_opcode(pickle.APPENDS, s)
2005 if proto == 0:
2006 self.assertEqual(num_appends, 0)
2007 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002008 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002009
2010 def test_dict_chunking(self):
2011 n = 10 # too small to chunk
2012 x = dict.fromkeys(range(n))
2013 for proto in protocols:
2014 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002015 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002016 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002017 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002018 num_setitems = count_opcode(pickle.SETITEMS, s)
2019 self.assertEqual(num_setitems, proto > 0)
2020
2021 n = 2500 # expect at least two chunks when proto > 0
2022 x = dict.fromkeys(range(n))
2023 for proto in protocols:
2024 s = self.dumps(x, proto)
2025 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002026 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002027 num_setitems = count_opcode(pickle.SETITEMS, s)
2028 if proto == 0:
2029 self.assertEqual(num_setitems, 0)
2030 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002031 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002032
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002033 def test_set_chunking(self):
2034 n = 10 # too small to chunk
2035 x = set(range(n))
2036 for proto in protocols:
2037 s = self.dumps(x, proto)
2038 y = self.loads(s)
2039 self.assert_is_copy(x, y)
2040 num_additems = count_opcode(pickle.ADDITEMS, s)
2041 if proto < 4:
2042 self.assertEqual(num_additems, 0)
2043 else:
2044 self.assertEqual(num_additems, 1)
2045
2046 n = 2500 # expect at least two chunks when proto >= 4
2047 x = set(range(n))
2048 for proto in protocols:
2049 s = self.dumps(x, proto)
2050 y = self.loads(s)
2051 self.assert_is_copy(x, y)
2052 num_additems = count_opcode(pickle.ADDITEMS, s)
2053 if proto < 4:
2054 self.assertEqual(num_additems, 0)
2055 else:
2056 self.assertGreaterEqual(num_additems, 2)
2057
Tim Peterse9ef2032003-02-13 18:42:00 +00002058 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002059 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002060 x.abc = 666
2061 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002062 with self.subTest(proto=proto):
2063 s = self.dumps(x, proto)
2064 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002065 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002066 else:
2067 self.assertIn(b'M\xce\xfa', s) # BININT2
2068 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2069 2 <= proto)
2070 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2071 y = self.loads(s) # will raise TypeError if __init__ called
2072 self.assert_is_copy(x, y)
2073
2074 def test_complex_newobj(self):
2075 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2076 x.abc = 666
2077 for proto in protocols:
2078 with self.subTest(proto=proto):
2079 s = self.dumps(x, proto)
2080 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002081 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002082 elif proto < 2:
2083 self.assertIn(b'M\xce\xfa', s) # BININT2
2084 elif proto < 4:
2085 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2086 else:
2087 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2088 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2089 2 <= proto)
2090 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2091 y = self.loads(s) # will raise TypeError if __init__ called
2092 self.assert_is_copy(x, y)
2093
2094 def test_complex_newobj_ex(self):
2095 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2096 x.abc = 666
2097 for proto in protocols:
2098 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002099 s = self.dumps(x, proto)
2100 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002101 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002102 elif proto < 2:
2103 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002104 elif proto < 4:
2105 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002106 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002107 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2108 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2109 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2110 4 <= proto)
2111 y = self.loads(s) # will raise TypeError if __init__ called
2112 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002113
Tim Peters42f08ac2003-02-11 22:43:24 +00002114 def test_newobj_list_slots(self):
2115 x = SlotList([1, 2, 3])
2116 x.foo = 42
2117 x.bar = "hello"
2118 s = self.dumps(x, 2)
2119 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002120 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002121
Guido van Rossum2a30b212003-02-18 22:41:24 +00002122 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002123 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002124 x = REX_one()
2125 self.assertEqual(x._reduce_called, 0)
2126 s = self.dumps(x, proto)
2127 self.assertEqual(x._reduce_called, 1)
2128 y = self.loads(s)
2129 self.assertEqual(y._reduce_called, 0)
2130
2131 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002132 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002133 x = REX_two()
2134 self.assertEqual(x._proto, None)
2135 s = self.dumps(x, proto)
2136 self.assertEqual(x._proto, proto)
2137 y = self.loads(s)
2138 self.assertEqual(y._proto, None)
2139
2140 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002141 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002142 x = REX_three()
2143 self.assertEqual(x._proto, None)
2144 s = self.dumps(x, proto)
2145 self.assertEqual(x._proto, proto)
2146 y = self.loads(s)
2147 self.assertEqual(y._proto, None)
2148
Guido van Rossumd8faa362007-04-27 19:54:29 +00002149 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002150 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002151 x = REX_four()
2152 self.assertEqual(x._proto, None)
2153 s = self.dumps(x, proto)
2154 self.assertEqual(x._proto, proto)
2155 y = self.loads(s)
2156 self.assertEqual(y._proto, proto)
2157
2158 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002159 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002160 x = REX_five()
2161 self.assertEqual(x._reduce_called, 0)
2162 s = self.dumps(x, proto)
2163 self.assertEqual(x._reduce_called, 1)
2164 y = self.loads(s)
2165 self.assertEqual(y._reduce_called, 1)
2166
Brett Cannon31f59292011-02-21 19:29:56 +00002167 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002168 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002169 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002170 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002171 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002172 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002173
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002174 def test_reduce_bad_iterator(self):
2175 # Issue4176: crash when 4th and 5th items of __reduce__()
2176 # are not iterators
2177 class C(object):
2178 def __reduce__(self):
2179 # 4th item is not an iterator
2180 return list, (), None, [], None
2181 class D(object):
2182 def __reduce__(self):
2183 # 5th item is not an iterator
2184 return dict, (), None, None, []
2185
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002186 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002187 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002188 try:
2189 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002190 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002191 pass
2192 try:
2193 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002194 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002195 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002196
Collin Winter771d8342009-04-16 03:18:06 +00002197 def test_many_puts_and_gets(self):
2198 # Test that internal data structures correctly deal with lots of
2199 # puts/gets.
2200 keys = ("aaa" + str(i) for i in range(100))
2201 large_dict = dict((k, [4, 5, 6]) for k in keys)
2202 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2203
2204 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002205 with self.subTest(proto=proto):
2206 dumped = self.dumps(obj, proto)
2207 loaded = self.loads(dumped)
2208 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002209
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002210 def test_attribute_name_interning(self):
2211 # Test that attribute names of pickled objects are interned when
2212 # unpickling.
2213 for proto in protocols:
2214 x = C()
2215 x.foo = 42
2216 x.bar = "hello"
2217 s = self.dumps(x, proto)
2218 y = self.loads(s)
2219 x_keys = sorted(x.__dict__)
2220 y_keys = sorted(y.__dict__)
2221 for x_key, y_key in zip(x_keys, y_keys):
2222 self.assertIs(x_key, y_key)
2223
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002224 def test_pickle_to_2x(self):
2225 # Pickle non-trivial data with protocol 2, expecting that it yields
2226 # the same result as Python 2.x did.
2227 # NOTE: this test is a bit too strong since we can produce different
2228 # bytecode that 2.x will still understand.
2229 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002230 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002231 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002232 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002233
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002234 def test_large_pickles(self):
2235 # Test the correctness of internal buffering routines when handling
2236 # large data.
2237 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002238 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002239 dumped = self.dumps(data, proto)
2240 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002241 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002242 self.assertEqual(loaded, data)
2243
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002244 def test_int_pickling_efficiency(self):
2245 # Test compacity of int representation (see issue #12744)
2246 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002247 with self.subTest(proto=proto):
2248 pickles = [self.dumps(2**n, proto) for n in range(70)]
2249 sizes = list(map(len, pickles))
2250 # the size function is monotonic
2251 self.assertEqual(sorted(sizes), sizes)
2252 if proto >= 2:
2253 for p in pickles:
2254 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002255
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002256 def _check_pickling_with_opcode(self, obj, opcode, proto):
2257 pickled = self.dumps(obj, proto)
2258 self.assertTrue(opcode_in_pickle(opcode, pickled))
2259 unpickled = self.loads(pickled)
2260 self.assertEqual(obj, unpickled)
2261
2262 def test_appends_on_non_lists(self):
2263 # Issue #17720
2264 obj = REX_six([1, 2, 3])
2265 for proto in protocols:
2266 if proto == 0:
2267 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2268 else:
2269 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2270
2271 def test_setitems_on_non_dicts(self):
2272 obj = REX_seven({1: -1, 2: -2, 3: -3})
2273 for proto in protocols:
2274 if proto == 0:
2275 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2276 else:
2277 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2278
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002279 # Exercise framing (proto >= 4) for significant workloads
2280
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002281 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002282 FRAME_SIZE_TARGET = 64 * 1024
2283
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002284 @support.skip_if_pgo_task
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002285 def check_frame_opcodes(self, pickled):
2286 """
2287 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002288
2289 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2290 framed by default and are therefore considered a frame by themselves in
2291 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002292 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002293 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002294 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2295 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002296 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002297 if frame_end is not None:
2298 self.assertLessEqual(pos, frame_end)
2299 if pos == frame_end:
2300 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002301
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002302 if frame_end is not None: # framed
2303 self.assertNotEqual(op.name, 'FRAME')
2304 if op.name in frameless_opcodes:
2305 # Only short bytes and str objects should be written
2306 # in a frame
2307 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2308
2309 else: # not framed
2310 if (op.name == 'FRAME' or
2311 (op.name in frameless_opcodes and
2312 len(arg) > self.FRAME_SIZE_TARGET)):
2313 # Frame or large bytes or str object
2314 if frameless_start is not None:
2315 # Only short data should be written outside of a frame
2316 self.assertLess(pos - frameless_start,
2317 self.FRAME_SIZE_MIN)
2318 frameless_start = None
2319 elif frameless_start is None and op.name != 'PROTO':
2320 frameless_start = pos
2321
2322 if op.name == 'FRAME':
2323 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2324 frame_end = pos + 9 + arg
2325
2326 pos = len(pickled)
2327 if frame_end is not None:
2328 self.assertEqual(frame_end, pos)
2329 elif frameless_start is not None:
2330 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002331
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002332 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002333 def test_framing_many_objects(self):
2334 obj = list(range(10**5))
2335 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2336 with self.subTest(proto=proto):
2337 pickled = self.dumps(obj, proto)
2338 unpickled = self.loads(pickled)
2339 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002340 bytes_per_frame = (len(pickled) /
2341 count_opcode(pickle.FRAME, pickled))
2342 self.assertGreater(bytes_per_frame,
2343 self.FRAME_SIZE_TARGET / 2)
2344 self.assertLessEqual(bytes_per_frame,
2345 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002346 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002347
2348 def test_framing_large_objects(self):
2349 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002350 small_items = [[i] for i in range(10)]
2351 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002352 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002353 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002354 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002355 if not fast:
2356 # fast=False by default.
2357 # This covers in-memory pickling with pickle.dumps().
2358 pickled = self.dumps(obj, proto)
2359 else:
2360 # Pickler is required when fast=True.
2361 if not hasattr(self, 'pickler'):
2362 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002363 buf = io.BytesIO()
2364 pickler = self.pickler(buf, protocol=proto)
2365 pickler.fast = fast
2366 pickler.dump(obj)
2367 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002368 unpickled = self.loads(pickled)
2369 # More informative error message in case of failure.
2370 self.assertEqual([len(x) for x in obj],
2371 [len(x) for x in unpickled])
2372 # Perform full equality check if the lengths match.
2373 self.assertEqual(obj, unpickled)
2374 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002375 # A single frame for small objects between
2376 # first two large objects.
2377 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002378 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002379
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002380 def test_optional_frames(self):
2381 if pickle.HIGHEST_PROTOCOL < 4:
2382 return
2383
2384 def remove_frames(pickled, keep_frame=None):
2385 """Remove frame opcodes from the given pickle."""
2386 frame_starts = []
2387 # 1 byte for the opcode and 8 for the argument
2388 frame_opcode_size = 9
2389 for opcode, _, pos in pickletools.genops(pickled):
2390 if opcode.name == 'FRAME':
2391 frame_starts.append(pos)
2392
2393 newpickle = bytearray()
2394 last_frame_end = 0
2395 for i, pos in enumerate(frame_starts):
2396 if keep_frame and keep_frame(i):
2397 continue
2398 newpickle += pickled[last_frame_end:pos]
2399 last_frame_end = pos + frame_opcode_size
2400 newpickle += pickled[last_frame_end:]
2401 return newpickle
2402
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002403 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002404 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002405 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002406 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002407 for bytes_type in (bytes, bytearray):
2408 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002409
Antoine Pitrou91f43802019-05-26 17:10:09 +02002410 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2411 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002412
Antoine Pitrou91f43802019-05-26 17:10:09 +02002413 frameless_pickle = remove_frames(pickled)
2414 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2415 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002416
Antoine Pitrou91f43802019-05-26 17:10:09 +02002417 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2418 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2419 count_opcode(pickle.FRAME, pickled))
2420 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002421
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002422 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002423 def test_framed_write_sizes_with_delayed_writer(self):
2424 class ChunkAccumulator:
2425 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002426 def __init__(self):
2427 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002428 def write(self, chunk):
2429 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002430 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002431 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002432
2433 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002434 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2435 for i in range(int(1e4))]
2436 # Add a large unique ASCII string
2437 objects.append('0123456789abcdef' *
2438 (self.FRAME_SIZE_TARGET // 16 + 1))
2439
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002440 # Protocol 4 packs groups of small objects into frames and issues
2441 # calls to write only once or twice per frame:
2442 # The C pickler issues one call to write per-frame (header and
2443 # contents) while Python pickler issues two calls to write: one for
2444 # the frame header and one for the frame binary contents.
2445 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002446 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002447
2448 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002449 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002450 # be released otherwise this delayed access would not be possible.
2451 pickled = writer.concatenate_chunks()
2452 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002453 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002454 self.assertGreater(len(writer.chunks), 1)
2455
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002456 # memoryviews should own the memory.
2457 del objects
2458 support.gc_collect()
2459 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002460
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002461 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002462 # There should be at least one call to write per frame
2463 self.assertGreaterEqual(len(writer.chunks), n_frames)
2464
2465 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002466 # one per-frame header, one per frame for the actual contents,
2467 # and two for the header.
2468 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002469
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002470 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002471 large_sizes = [s for s in chunk_sizes
2472 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002473 medium_sizes = [s for s in chunk_sizes
2474 if 9 < s < self.FRAME_SIZE_TARGET]
2475 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002476
2477 # Large chunks should not be too large:
2478 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002479 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2480 chunk_sizes)
2481 # There shouldn't bee too many small chunks: the protocol header,
2482 # the frame headers and the large string headers are written
2483 # in small chunks.
2484 self.assertLessEqual(len(small_sizes),
2485 len(large_sizes) + len(medium_sizes) + 3,
2486 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002487
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002488 def test_nested_names(self):
2489 global Nested
2490 class Nested:
2491 class A:
2492 class B:
2493 class C:
2494 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002495 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002496 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2497 with self.subTest(proto=proto, obj=obj):
2498 unpickled = self.loads(self.dumps(obj, proto))
2499 self.assertIs(obj, unpickled)
2500
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002501 def test_recursive_nested_names(self):
2502 global Recursive
2503 class Recursive:
2504 pass
2505 Recursive.mod = sys.modules[Recursive.__module__]
2506 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2507 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2508 with self.subTest(proto=proto):
2509 unpickled = self.loads(self.dumps(Recursive, proto))
2510 self.assertIs(unpickled, Recursive)
2511 del Recursive.mod # break reference loop
2512
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002513 def test_py_methods(self):
2514 global PyMethodsTest
2515 class PyMethodsTest:
2516 @staticmethod
2517 def cheese():
2518 return "cheese"
2519 @classmethod
2520 def wine(cls):
2521 assert cls is PyMethodsTest
2522 return "wine"
2523 def biscuits(self):
2524 assert isinstance(self, PyMethodsTest)
2525 return "biscuits"
2526 class Nested:
2527 "Nested class"
2528 @staticmethod
2529 def ketchup():
2530 return "ketchup"
2531 @classmethod
2532 def maple(cls):
2533 assert cls is PyMethodsTest.Nested
2534 return "maple"
2535 def pie(self):
2536 assert isinstance(self, PyMethodsTest.Nested)
2537 return "pie"
2538
2539 py_methods = (
2540 PyMethodsTest.cheese,
2541 PyMethodsTest.wine,
2542 PyMethodsTest().biscuits,
2543 PyMethodsTest.Nested.ketchup,
2544 PyMethodsTest.Nested.maple,
2545 PyMethodsTest.Nested().pie
2546 )
2547 py_unbound_methods = (
2548 (PyMethodsTest.biscuits, PyMethodsTest),
2549 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2550 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002551 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002552 for method in py_methods:
2553 with self.subTest(proto=proto, method=method):
2554 unpickled = self.loads(self.dumps(method, proto))
2555 self.assertEqual(method(), unpickled())
2556 for method, cls in py_unbound_methods:
2557 obj = cls()
2558 with self.subTest(proto=proto, method=method):
2559 unpickled = self.loads(self.dumps(method, proto))
2560 self.assertEqual(method(obj), unpickled(obj))
2561
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002562 def test_c_methods(self):
2563 global Subclass
2564 class Subclass(tuple):
2565 class Nested(str):
2566 pass
2567
2568 c_methods = (
2569 # bound built-in method
2570 ("abcd".index, ("c",)),
2571 # unbound built-in method
2572 (str.index, ("abcd", "c")),
2573 # bound "slot" method
2574 ([1, 2, 3].__len__, ()),
2575 # unbound "slot" method
2576 (list.__len__, ([1, 2, 3],)),
2577 # bound "coexist" method
2578 ({1, 2}.__contains__, (2,)),
2579 # unbound "coexist" method
2580 (set.__contains__, ({1, 2}, 2)),
2581 # built-in class method
2582 (dict.fromkeys, (("a", 1), ("b", 2))),
2583 # built-in static method
2584 (bytearray.maketrans, (b"abc", b"xyz")),
2585 # subclass methods
2586 (Subclass([1,2,2]).count, (2,)),
2587 (Subclass.count, (Subclass([1,2,2]), 2)),
2588 (Subclass.Nested("sweet").count, ("e",)),
2589 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2590 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002591 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002592 for method, args in c_methods:
2593 with self.subTest(proto=proto, method=method):
2594 unpickled = self.loads(self.dumps(method, proto))
2595 self.assertEqual(method(*args), unpickled(*args))
2596
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002597 def test_compat_pickle(self):
2598 tests = [
2599 (range(1, 7), '__builtin__', 'xrange'),
2600 (map(int, '123'), 'itertools', 'imap'),
2601 (functools.reduce, '__builtin__', 'reduce'),
2602 (dbm.whichdb, 'whichdb', 'whichdb'),
2603 (Exception(), 'exceptions', 'Exception'),
2604 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2605 (collections.UserList(), 'UserList', 'UserList'),
2606 (collections.defaultdict(), 'collections', 'defaultdict'),
2607 ]
2608 for val, mod, name in tests:
2609 for proto in range(3):
2610 with self.subTest(type=type(val), proto=proto):
2611 pickled = self.dumps(val, proto)
2612 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2613 self.assertIs(type(self.loads(pickled)), type(val))
2614
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002615 def test_local_lookup_error(self):
2616 # Test that whichmodule() errors out cleanly when looking up
2617 # an assumed globally-reachable object fails.
2618 def f():
2619 pass
2620 # Since the function is local, lookup will fail
2621 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2622 with self.assertRaises((AttributeError, pickle.PicklingError)):
2623 pickletools.dis(self.dumps(f, proto))
2624 # Same without a __module__ attribute (exercises a different path
2625 # in _pickle.c).
2626 del f.__module__
2627 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2628 with self.assertRaises((AttributeError, pickle.PicklingError)):
2629 pickletools.dis(self.dumps(f, proto))
2630 # Yet a different path.
2631 f.__name__ = f.__qualname__
2632 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2633 with self.assertRaises((AttributeError, pickle.PicklingError)):
2634 pickletools.dis(self.dumps(f, proto))
2635
Antoine Pitrou91f43802019-05-26 17:10:09 +02002636 #
2637 # PEP 574 tests below
2638 #
2639
2640 def buffer_like_objects(self):
2641 # Yield buffer-like objects with the bytestring "abcdef" in them
2642 bytestring = b"abcdefgh"
2643 yield ZeroCopyBytes(bytestring)
2644 yield ZeroCopyBytearray(bytestring)
2645 if _testbuffer is not None:
2646 items = list(bytestring)
2647 value = int.from_bytes(bytestring, byteorder='little')
2648 for flags in (0, _testbuffer.ND_WRITABLE):
2649 # 1-D, contiguous
2650 yield PicklableNDArray(items, format='B', shape=(8,),
2651 flags=flags)
2652 # 2-D, C-contiguous
2653 yield PicklableNDArray(items, format='B', shape=(4, 2),
2654 strides=(2, 1), flags=flags)
2655 # 2-D, Fortran-contiguous
2656 yield PicklableNDArray(items, format='B',
2657 shape=(4, 2), strides=(1, 4),
2658 flags=flags)
2659
2660 def test_in_band_buffers(self):
2661 # Test in-band buffers (PEP 574)
2662 for obj in self.buffer_like_objects():
2663 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2664 data = self.dumps(obj, proto)
2665 if obj.c_contiguous and proto >= 5:
2666 # The raw memory bytes are serialized in physical order
2667 self.assertIn(b"abcdefgh", data)
2668 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2669 if proto >= 5:
2670 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2671 1 if obj.readonly else 0)
2672 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2673 0 if obj.readonly else 1)
2674 # Return a true value from buffer_callback should have
2675 # the same effect
2676 def buffer_callback(obj):
2677 return True
2678 data2 = self.dumps(obj, proto,
2679 buffer_callback=buffer_callback)
2680 self.assertEqual(data2, data)
2681
2682 new = self.loads(data)
2683 # It's a copy
2684 self.assertIsNot(new, obj)
2685 self.assertIs(type(new), type(obj))
2686 self.assertEqual(new, obj)
2687
2688 # XXX Unfortunately cannot test non-contiguous array
2689 # (see comment in PicklableNDArray.__reduce_ex__)
2690
2691 def test_oob_buffers(self):
2692 # Test out-of-band buffers (PEP 574)
2693 for obj in self.buffer_like_objects():
2694 for proto in range(0, 5):
2695 # Need protocol >= 5 for buffer_callback
2696 with self.assertRaises(ValueError):
2697 self.dumps(obj, proto,
2698 buffer_callback=[].append)
2699 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2700 buffers = []
2701 buffer_callback = lambda pb: buffers.append(pb.raw())
2702 data = self.dumps(obj, proto,
2703 buffer_callback=buffer_callback)
2704 self.assertNotIn(b"abcdefgh", data)
2705 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2706 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2707 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2708 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2709 1 if obj.readonly else 0)
2710
2711 if obj.c_contiguous:
2712 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2713 # Need buffers argument to unpickle properly
2714 with self.assertRaises(pickle.UnpicklingError):
2715 self.loads(data)
2716
2717 new = self.loads(data, buffers=buffers)
2718 if obj.zero_copy_reconstruct:
2719 # Zero-copy achieved
2720 self.assertIs(new, obj)
2721 else:
2722 self.assertIs(type(new), type(obj))
2723 self.assertEqual(new, obj)
2724 # Non-sequence buffers accepted too
2725 new = self.loads(data, buffers=iter(buffers))
2726 if obj.zero_copy_reconstruct:
2727 # Zero-copy achieved
2728 self.assertIs(new, obj)
2729 else:
2730 self.assertIs(type(new), type(obj))
2731 self.assertEqual(new, obj)
2732
2733 def test_oob_buffers_writable_to_readonly(self):
2734 # Test reconstructing readonly object from writable buffer
2735 obj = ZeroCopyBytes(b"foobar")
2736 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2737 buffers = []
2738 buffer_callback = buffers.append
2739 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2740
2741 buffers = map(bytearray, buffers)
2742 new = self.loads(data, buffers=buffers)
2743 self.assertIs(type(new), type(obj))
2744 self.assertEqual(new, obj)
2745
2746 def test_picklebuffer_error(self):
2747 # PickleBuffer forbidden with protocol < 5
2748 pb = pickle.PickleBuffer(b"foobar")
2749 for proto in range(0, 5):
2750 with self.assertRaises(pickle.PickleError):
2751 self.dumps(pb, proto)
2752
2753 def test_buffer_callback_error(self):
2754 def buffer_callback(buffers):
2755 1/0
2756 pb = pickle.PickleBuffer(b"foobar")
2757 with self.assertRaises(ZeroDivisionError):
2758 self.dumps(pb, 5, buffer_callback=buffer_callback)
2759
2760 def test_buffers_error(self):
2761 pb = pickle.PickleBuffer(b"foobar")
2762 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2763 data = self.dumps(pb, proto, buffer_callback=[].append)
2764 # Non iterable buffers
2765 with self.assertRaises(TypeError):
2766 self.loads(data, buffers=object())
2767 # Buffer iterable exhausts too early
2768 with self.assertRaises(pickle.UnpicklingError):
2769 self.loads(data, buffers=[])
2770
Markus Mohrhard898318b2019-07-26 00:00:34 +08002771 def test_inband_accept_default_buffers_argument(self):
2772 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2773 data_pickled = self.dumps(1, proto, buffer_callback=None)
2774 data = self.loads(data_pickled, buffers=None)
2775
Antoine Pitrou91f43802019-05-26 17:10:09 +02002776 @unittest.skipIf(np is None, "Test needs Numpy")
2777 def test_buffers_numpy(self):
2778 def check_no_copy(x, y):
2779 np.testing.assert_equal(x, y)
2780 self.assertEqual(x.ctypes.data, y.ctypes.data)
2781
2782 def check_copy(x, y):
2783 np.testing.assert_equal(x, y)
2784 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2785
2786 def check_array(arr):
2787 # In-band
2788 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2789 data = self.dumps(arr, proto)
2790 new = self.loads(data)
2791 check_copy(arr, new)
2792 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2793 buffer_callback = lambda _: True
2794 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2795 new = self.loads(data)
2796 check_copy(arr, new)
2797 # Out-of-band
2798 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2799 buffers = []
2800 buffer_callback = buffers.append
2801 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2802 new = self.loads(data, buffers=buffers)
2803 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2804 check_no_copy(arr, new)
2805 else:
2806 check_copy(arr, new)
2807
2808 # 1-D
2809 arr = np.arange(6)
2810 check_array(arr)
2811 # 1-D, non-contiguous
2812 check_array(arr[::2])
2813 # 2-D, C-contiguous
2814 arr = np.arange(12).reshape((3, 4))
2815 check_array(arr)
2816 # 2-D, F-contiguous
2817 check_array(arr.T)
2818 # 2-D, non-contiguous
2819 check_array(arr[::2])
2820
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002821
2822class BigmemPickleTests(unittest.TestCase):
2823
Victor Stinner8c663fd2017-11-08 14:44:44 -08002824 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002825
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002826 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002827 def test_huge_long_32b(self, size):
2828 data = 1 << (8 * size)
2829 try:
2830 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002831 if proto < 2:
2832 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002833 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002834 with self.assertRaises((ValueError, OverflowError)):
2835 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002836 finally:
2837 data = None
2838
Victor Stinner8c663fd2017-11-08 14:44:44 -08002839 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002840 # (older protocols don't have a dedicated opcode for bytes and are
2841 # too inefficient)
2842
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002843 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002844 def test_huge_bytes_32b(self, size):
2845 data = b"abcd" * (size // 4)
2846 try:
2847 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002848 if proto < 3:
2849 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002850 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002851 try:
2852 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002853 header = (pickle.BINBYTES +
2854 struct.pack("<I", len(data)))
2855 data_start = pickled.index(data)
2856 self.assertEqual(
2857 header,
2858 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002859 finally:
2860 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002861 finally:
2862 data = None
2863
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002864 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002865 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002866 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002867 try:
2868 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002869 if proto < 3:
2870 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002871 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002872 if proto == 3:
2873 # Protocol 3 does not support large bytes objects.
2874 # Verify that we do not crash when processing one.
2875 with self.assertRaises((ValueError, OverflowError)):
2876 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002877 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002878 try:
2879 pickled = self.dumps(data, protocol=proto)
2880 header = (pickle.BINBYTES8 +
2881 struct.pack("<Q", len(data)))
2882 data_start = pickled.index(data)
2883 self.assertEqual(
2884 header,
2885 pickled[data_start-len(header):data_start])
2886 finally:
2887 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002888 finally:
2889 data = None
2890
2891 # All protocols use 1-byte per printable ASCII character; we add another
2892 # byte because the encoded form has to be copied into the internal buffer.
2893
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002894 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002895 def test_huge_str_32b(self, size):
2896 data = "abcd" * (size // 4)
2897 try:
2898 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002899 if proto == 0:
2900 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002901 with self.subTest(proto=proto):
2902 try:
2903 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002904 header = (pickle.BINUNICODE +
2905 struct.pack("<I", len(data)))
2906 data_start = pickled.index(b'abcd')
2907 self.assertEqual(
2908 header,
2909 pickled[data_start-len(header):data_start])
2910 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2911 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002912 finally:
2913 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002914 finally:
2915 data = None
2916
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002917 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2918 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2919 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002920
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002921 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002922 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002923 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002924 try:
2925 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002926 if proto == 0:
2927 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002928 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002929 if proto < 4:
2930 with self.assertRaises((ValueError, OverflowError)):
2931 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002932 continue
2933 try:
2934 pickled = self.dumps(data, protocol=proto)
2935 header = (pickle.BINUNICODE8 +
2936 struct.pack("<Q", len(data)))
2937 data_start = pickled.index(b'abcd')
2938 self.assertEqual(
2939 header,
2940 pickled[data_start-len(header):data_start])
2941 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2942 pickled.index(b"abcd")), len(data))
2943 finally:
2944 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002945 finally:
2946 data = None
2947
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002948
Guido van Rossum2a30b212003-02-18 22:41:24 +00002949# Test classes for reduce_ex
2950
2951class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002952 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002953 _reduce_called = 0
2954 def __reduce__(self):
2955 self._reduce_called = 1
2956 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002957
2958class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002959 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002960 _proto = None
2961 def __reduce_ex__(self, proto):
2962 self._proto = proto
2963 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002964
2965class REX_three(object):
2966 _proto = None
2967 def __reduce_ex__(self, proto):
2968 self._proto = proto
2969 return REX_two, ()
2970 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002971 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002972
Guido van Rossumd8faa362007-04-27 19:54:29 +00002973class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002974 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002975 _proto = None
2976 def __reduce_ex__(self, proto):
2977 self._proto = proto
2978 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002979
2980class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002981 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002982 _reduce_called = 0
2983 def __reduce__(self):
2984 self._reduce_called = 1
2985 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002986
2987class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002988 """This class is used to check the 4th argument (list iterator) of
2989 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002990 """
2991 def __init__(self, items=None):
2992 self.items = items if items is not None else []
2993 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02002994 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002995 def append(self, item):
2996 self.items.append(item)
2997 def __reduce__(self):
2998 return type(self), (), None, iter(self.items), None
2999
3000class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003001 """This class is used to check the 5th argument (dict iterator) of
3002 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003003 """
3004 def __init__(self, table=None):
3005 self.table = table if table is not None else {}
3006 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003007 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003008 def __setitem__(self, key, value):
3009 self.table[key] = value
3010 def __reduce__(self):
3011 return type(self), (), None, None, iter(self.table.items())
3012
Guido van Rossumd8faa362007-04-27 19:54:29 +00003013
Guido van Rossum2a30b212003-02-18 22:41:24 +00003014# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003015
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003016class MyInt(int):
3017 sample = 1
3018
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003019class MyFloat(float):
3020 sample = 1.0
3021
3022class MyComplex(complex):
3023 sample = 1.0 + 0.0j
3024
3025class MyStr(str):
3026 sample = "hello"
3027
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003028class MyUnicode(str):
3029 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003030
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003031class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003032 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003033
3034class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003035 sample = [1, 2, 3]
3036
3037class MyDict(dict):
3038 sample = {"a": 1, "b": 2}
3039
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003040class MySet(set):
3041 sample = {"a", "b"}
3042
3043class MyFrozenSet(frozenset):
3044 sample = frozenset({"a", "b"})
3045
Mark Dickinson5c2db372009-12-05 20:28:34 +00003046myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003047 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003048 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003049 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003050
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003051
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003052class SlotList(MyList):
3053 __slots__ = ["foo"]
3054
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003055class SimpleNewObj(int):
3056 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003057 # raise an error, to make sure this isn't called
3058 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003059 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003060 return int(self) == int(other) and self.__dict__ == other.__dict__
3061
3062class ComplexNewObj(SimpleNewObj):
3063 def __getnewargs__(self):
3064 return ('%X' % self, 16)
3065
3066class ComplexNewObjEx(SimpleNewObj):
3067 def __getnewargs_ex__(self):
3068 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003069
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003070class BadGetattr:
3071 def __getattr__(self, key):
3072 self.foo
3073
Collin Winter771d8342009-04-16 03:18:06 +00003074
Jeremy Hylton66426532001-10-15 21:38:56 +00003075class AbstractPickleModuleTests(unittest.TestCase):
3076
3077 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003078 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003079 try:
3080 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003081 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003082 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003083 support.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003084
3085 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003086 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003087 try:
3088 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003089 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003090 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003091 support.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003092
Collin Winter771d8342009-04-16 03:18:06 +00003093 def test_load_from_and_dump_to_file(self):
3094 stream = io.BytesIO()
3095 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003096 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003097 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003098 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003099 self.assertEqual(unpickled, data)
3100
Tim Petersc0c93702003-02-13 19:30:57 +00003101 def test_highest_protocol(self):
3102 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003103 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003104
Martin v. Löwis544f1192004-07-27 05:22:33 +00003105 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003106 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003107 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003108 self.dump(123, f, -1)
3109 self.dump(123, file=f, protocol=-1)
3110 self.dumps(123, -1)
3111 self.dumps(123, protocol=-1)
3112 self.Pickler(f, -1)
3113 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003114
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003115 def test_dump_text_file(self):
3116 f = open(TESTFN, "w")
3117 try:
3118 for proto in protocols:
3119 self.assertRaises(TypeError, self.dump, 123, f, proto)
3120 finally:
3121 f.close()
3122 support.unlink(TESTFN)
3123
3124 def test_incomplete_input(self):
3125 s = io.BytesIO(b"X''.")
3126 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3127
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003128 def test_bad_init(self):
3129 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003130 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003131 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003132 def __init__(self): pass
3133
Serhiy Storchaka65452562017-11-15 14:01:08 +02003134 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003135 def __init__(self): pass
3136
3137 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3138 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3139
Antoine Pitrou91f43802019-05-26 17:10:09 +02003140 def check_dumps_loads_oob_buffers(self, dumps, loads):
3141 # No need to do the full gamut of tests here, just enough to
3142 # check that dumps() and loads() redirect their arguments
3143 # to the underlying Pickler and Unpickler, respectively.
3144 obj = ZeroCopyBytes(b"foo")
3145
3146 for proto in range(0, 5):
3147 # Need protocol >= 5 for buffer_callback
3148 with self.assertRaises(ValueError):
3149 dumps(obj, protocol=proto,
3150 buffer_callback=[].append)
3151 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3152 buffers = []
3153 buffer_callback = buffers.append
3154 data = dumps(obj, protocol=proto,
3155 buffer_callback=buffer_callback)
3156 self.assertNotIn(b"foo", data)
3157 self.assertEqual(bytes(buffers[0]), b"foo")
3158 # Need buffers argument to unpickle properly
3159 with self.assertRaises(pickle.UnpicklingError):
3160 loads(data)
3161 new = loads(data, buffers=buffers)
3162 self.assertIs(new, obj)
3163
3164 def test_dumps_loads_oob_buffers(self):
3165 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3166 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3167
3168 def test_dump_load_oob_buffers(self):
3169 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3170 def dumps(obj, **kwargs):
3171 f = io.BytesIO()
3172 self.dump(obj, f, **kwargs)
3173 return f.getvalue()
3174
3175 def loads(data, **kwargs):
3176 f = io.BytesIO(data)
3177 return self.load(f, **kwargs)
3178
3179 self.check_dumps_loads_oob_buffers(dumps, loads)
3180
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003181
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003182class AbstractPersistentPicklerTests(unittest.TestCase):
3183
3184 # This class defines persistent_id() and persistent_load()
3185 # functions that should be used by the pickler. All even integers
3186 # are pickled using persistent ids.
3187
3188 def persistent_id(self, object):
3189 if isinstance(object, int) and object % 2 == 0:
3190 self.id_count += 1
3191 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003192 elif object == "test_false_value":
3193 self.false_count += 1
3194 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003195 else:
3196 return None
3197
3198 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003199 if not oid:
3200 self.load_false_count += 1
3201 return "test_false_value"
3202 else:
3203 self.load_count += 1
3204 object = int(oid)
3205 assert object % 2 == 0
3206 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003207
3208 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003209 L = list(range(10)) + ["test_false_value"]
3210 for proto in protocols:
3211 self.id_count = 0
3212 self.false_count = 0
3213 self.load_false_count = 0
3214 self.load_count = 0
3215 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3216 self.assertEqual(self.id_count, 5)
3217 self.assertEqual(self.false_count, 1)
3218 self.assertEqual(self.load_count, 5)
3219 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003220
Collin Winter771d8342009-04-16 03:18:06 +00003221
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003222class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3223
3224 def persistent_id(self, obj):
3225 return obj
3226
3227 def persistent_load(self, pid):
3228 return pid
3229
3230 def _check_return_correct_type(self, obj, proto):
3231 unpickled = self.loads(self.dumps(obj, proto))
3232 self.assertIsInstance(unpickled, type(obj))
3233 self.assertEqual(unpickled, obj)
3234
3235 def test_return_correct_type(self):
3236 for proto in protocols:
3237 # Protocol 0 supports only ASCII strings.
3238 if proto == 0:
3239 self._check_return_correct_type("abc", 0)
3240 else:
3241 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3242 self._check_return_correct_type(obj, proto)
3243
3244 def test_protocol0_is_ascii_only(self):
3245 non_ascii_str = "\N{EMPTY SET}"
3246 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3247 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3248 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3249
3250
Collin Winter771d8342009-04-16 03:18:06 +00003251class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3252
3253 pickler_class = None
3254 unpickler_class = None
3255
3256 def setUp(self):
3257 assert self.pickler_class
3258 assert self.unpickler_class
3259
3260 def test_clear_pickler_memo(self):
3261 # To test whether clear_memo() has any effect, we pickle an object,
3262 # then pickle it again without clearing the memo; the two serialized
3263 # forms should be different. If we clear_memo() and then pickle the
3264 # object again, the third serialized form should be identical to the
3265 # first one we obtained.
3266 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003267 for proto in protocols:
3268 f = io.BytesIO()
3269 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003270
Serhiy Storchakac8695292018-04-04 00:11:27 +03003271 pickler.dump(data)
3272 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003273
Serhiy Storchakac8695292018-04-04 00:11:27 +03003274 # Reset BytesIO object.
3275 f.seek(0)
3276 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003277
Serhiy Storchakac8695292018-04-04 00:11:27 +03003278 pickler.dump(data)
3279 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003280
Serhiy Storchakac8695292018-04-04 00:11:27 +03003281 # Reset the Pickler and BytesIO objects.
3282 pickler.clear_memo()
3283 f.seek(0)
3284 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003285
Serhiy Storchakac8695292018-04-04 00:11:27 +03003286 pickler.dump(data)
3287 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003288
Serhiy Storchakac8695292018-04-04 00:11:27 +03003289 self.assertNotEqual(first_pickled, second_pickled)
3290 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003291
3292 def test_priming_pickler_memo(self):
3293 # Verify that we can set the Pickler's memo attribute.
3294 data = ["abcdefg", "abcdefg", 44]
3295 f = io.BytesIO()
3296 pickler = self.pickler_class(f)
3297
3298 pickler.dump(data)
3299 first_pickled = f.getvalue()
3300
3301 f = io.BytesIO()
3302 primed = self.pickler_class(f)
3303 primed.memo = pickler.memo
3304
3305 primed.dump(data)
3306 primed_pickled = f.getvalue()
3307
3308 self.assertNotEqual(first_pickled, primed_pickled)
3309
3310 def test_priming_unpickler_memo(self):
3311 # Verify that we can set the Unpickler's memo attribute.
3312 data = ["abcdefg", "abcdefg", 44]
3313 f = io.BytesIO()
3314 pickler = self.pickler_class(f)
3315
3316 pickler.dump(data)
3317 first_pickled = f.getvalue()
3318
3319 f = io.BytesIO()
3320 primed = self.pickler_class(f)
3321 primed.memo = pickler.memo
3322
3323 primed.dump(data)
3324 primed_pickled = f.getvalue()
3325
3326 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3327 unpickled_data1 = unpickler.load()
3328
3329 self.assertEqual(unpickled_data1, data)
3330
3331 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3332 primed.memo = unpickler.memo
3333 unpickled_data2 = primed.load()
3334
3335 primed.memo.clear()
3336
3337 self.assertEqual(unpickled_data2, data)
3338 self.assertTrue(unpickled_data2 is unpickled_data1)
3339
3340 def test_reusing_unpickler_objects(self):
3341 data1 = ["abcdefg", "abcdefg", 44]
3342 f = io.BytesIO()
3343 pickler = self.pickler_class(f)
3344 pickler.dump(data1)
3345 pickled1 = f.getvalue()
3346
3347 data2 = ["abcdefg", 44, 44]
3348 f = io.BytesIO()
3349 pickler = self.pickler_class(f)
3350 pickler.dump(data2)
3351 pickled2 = f.getvalue()
3352
3353 f = io.BytesIO()
3354 f.write(pickled1)
3355 f.seek(0)
3356 unpickler = self.unpickler_class(f)
3357 self.assertEqual(unpickler.load(), data1)
3358
3359 f.seek(0)
3360 f.truncate()
3361 f.write(pickled2)
3362 f.seek(0)
3363 self.assertEqual(unpickler.load(), data2)
3364
Antoine Pitrou04248a82010-10-12 20:51:21 +00003365 def _check_multiple_unpicklings(self, ioclass):
3366 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003367 with self.subTest(proto=proto):
3368 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3369 f = ioclass()
3370 pickler = self.pickler_class(f, protocol=proto)
3371 pickler.dump(data1)
3372 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003373
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003374 N = 5
3375 f = ioclass(pickled * N)
3376 unpickler = self.unpickler_class(f)
3377 for i in range(N):
3378 if f.seekable():
3379 pos = f.tell()
3380 self.assertEqual(unpickler.load(), data1)
3381 if f.seekable():
3382 self.assertEqual(f.tell(), pos + len(pickled))
3383 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003384
3385 def test_multiple_unpicklings_seekable(self):
3386 self._check_multiple_unpicklings(io.BytesIO)
3387
3388 def test_multiple_unpicklings_unseekable(self):
3389 self._check_multiple_unpicklings(UnseekableIO)
3390
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003391 def test_unpickling_buffering_readline(self):
3392 # Issue #12687: the unpickler's buffering logic could fail with
3393 # text mode opcodes.
3394 data = list(range(10))
3395 for proto in protocols:
3396 for buf_size in range(1, 11):
3397 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3398 pickler = self.pickler_class(f, protocol=proto)
3399 pickler.dump(data)
3400 f.seek(0)
3401 unpickler = self.unpickler_class(f)
3402 self.assertEqual(unpickler.load(), data)
3403
Collin Winter771d8342009-04-16 03:18:06 +00003404
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003405# Tests for dispatch_table attribute
3406
3407REDUCE_A = 'reduce_A'
3408
3409class AAA(object):
3410 def __reduce__(self):
3411 return str, (REDUCE_A,)
3412
3413class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003414 def __init__(self):
3415 # Add an instance attribute to enable state-saving routines at pickling
3416 # time.
3417 self.a = "some attribute"
3418
3419 def __setstate__(self, state):
3420 self.a = "BBB.__setstate__"
3421
3422
3423def setstate_bbb(obj, state):
3424 """Custom state setter for BBB objects
3425
3426 Such callable may be created by other persons than the ones who created the
3427 BBB class. If passed as the state_setter item of a custom reducer, this
3428 allows for custom state setting behavior of BBB objects. One can think of
3429 it as the analogous of list_setitems or dict_setitems but for foreign
3430 classes/functions.
3431 """
3432 obj.a = "custom state_setter"
3433
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003434
Pierre Glaser289f1f82019-05-08 23:08:25 +02003435
3436class AbstractCustomPicklerClass:
3437 """Pickler implementing a reducing hook using reducer_override."""
3438 def reducer_override(self, obj):
3439 obj_name = getattr(obj, "__name__", None)
3440
3441 if obj_name == 'f':
3442 # asking the pickler to save f as 5
3443 return int, (5, )
3444
3445 if obj_name == 'MyClass':
3446 return str, ('some str',)
3447
3448 elif obj_name == 'g':
3449 # in this case, the callback returns an invalid result (not a 2-5
3450 # tuple or a string), the pickler should raise a proper error.
3451 return False
3452
3453 elif obj_name == 'h':
3454 # Simulate a case when the reducer fails. The error should
3455 # be propagated to the original ``dump`` call.
3456 raise ValueError('The reducer just failed')
3457
3458 return NotImplemented
3459
3460class AbstractHookTests(unittest.TestCase):
3461 def test_pickler_hook(self):
3462 # test the ability of a custom, user-defined CPickler subclass to
3463 # override the default reducing routines of any type using the method
3464 # reducer_override
3465
3466 def f():
3467 pass
3468
3469 def g():
3470 pass
3471
3472 def h():
3473 pass
3474
3475 class MyClass:
3476 pass
3477
3478 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3479 with self.subTest(proto=proto):
3480 bio = io.BytesIO()
3481 p = self.pickler_class(bio, proto)
3482
3483 p.dump([f, MyClass, math.log])
3484 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3485
3486 self.assertEqual(new_f, 5)
3487 self.assertEqual(some_str, 'some str')
3488 # math.log does not have its usual reducer overriden, so the
3489 # custom reduction callback should silently direct the pickler
3490 # to the default pickling by attribute, by returning
3491 # NotImplemented
3492 self.assertIs(math_log, math.log)
3493
3494 with self.assertRaises(pickle.PicklingError):
3495 p.dump(g)
3496
3497 with self.assertRaisesRegex(
3498 ValueError, 'The reducer just failed'):
3499 p.dump(h)
3500
3501
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003502class AbstractDispatchTableTests(unittest.TestCase):
3503
3504 def test_default_dispatch_table(self):
3505 # No dispatch_table attribute by default
3506 f = io.BytesIO()
3507 p = self.pickler_class(f, 0)
3508 with self.assertRaises(AttributeError):
3509 p.dispatch_table
3510 self.assertFalse(hasattr(p, 'dispatch_table'))
3511
3512 def test_class_dispatch_table(self):
3513 # A dispatch_table attribute can be specified class-wide
3514 dt = self.get_dispatch_table()
3515
3516 class MyPickler(self.pickler_class):
3517 dispatch_table = dt
3518
3519 def dumps(obj, protocol=None):
3520 f = io.BytesIO()
3521 p = MyPickler(f, protocol)
3522 self.assertEqual(p.dispatch_table, dt)
3523 p.dump(obj)
3524 return f.getvalue()
3525
3526 self._test_dispatch_table(dumps, dt)
3527
3528 def test_instance_dispatch_table(self):
3529 # A dispatch_table attribute can also be specified instance-wide
3530 dt = self.get_dispatch_table()
3531
3532 def dumps(obj, protocol=None):
3533 f = io.BytesIO()
3534 p = self.pickler_class(f, protocol)
3535 p.dispatch_table = dt
3536 self.assertEqual(p.dispatch_table, dt)
3537 p.dump(obj)
3538 return f.getvalue()
3539
3540 self._test_dispatch_table(dumps, dt)
3541
3542 def _test_dispatch_table(self, dumps, dispatch_table):
3543 def custom_load_dump(obj):
3544 return pickle.loads(dumps(obj, 0))
3545
3546 def default_load_dump(obj):
3547 return pickle.loads(pickle.dumps(obj, 0))
3548
3549 # pickling complex numbers using protocol 0 relies on copyreg
3550 # so check pickling a complex number still works
3551 z = 1 + 2j
3552 self.assertEqual(custom_load_dump(z), z)
3553 self.assertEqual(default_load_dump(z), z)
3554
3555 # modify pickling of complex
3556 REDUCE_1 = 'reduce_1'
3557 def reduce_1(obj):
3558 return str, (REDUCE_1,)
3559 dispatch_table[complex] = reduce_1
3560 self.assertEqual(custom_load_dump(z), REDUCE_1)
3561 self.assertEqual(default_load_dump(z), z)
3562
3563 # check picklability of AAA and BBB
3564 a = AAA()
3565 b = BBB()
3566 self.assertEqual(custom_load_dump(a), REDUCE_A)
3567 self.assertIsInstance(custom_load_dump(b), BBB)
3568 self.assertEqual(default_load_dump(a), REDUCE_A)
3569 self.assertIsInstance(default_load_dump(b), BBB)
3570
3571 # modify pickling of BBB
3572 dispatch_table[BBB] = reduce_1
3573 self.assertEqual(custom_load_dump(a), REDUCE_A)
3574 self.assertEqual(custom_load_dump(b), REDUCE_1)
3575 self.assertEqual(default_load_dump(a), REDUCE_A)
3576 self.assertIsInstance(default_load_dump(b), BBB)
3577
3578 # revert pickling of BBB and modify pickling of AAA
3579 REDUCE_2 = 'reduce_2'
3580 def reduce_2(obj):
3581 return str, (REDUCE_2,)
3582 dispatch_table[AAA] = reduce_2
3583 del dispatch_table[BBB]
3584 self.assertEqual(custom_load_dump(a), REDUCE_2)
3585 self.assertIsInstance(custom_load_dump(b), BBB)
3586 self.assertEqual(default_load_dump(a), REDUCE_A)
3587 self.assertIsInstance(default_load_dump(b), BBB)
3588
Pierre Glaser65d98d02019-05-08 21:40:25 +02003589 # End-to-end testing of save_reduce with the state_setter keyword
3590 # argument. This is a dispatch_table test as the primary goal of
3591 # state_setter is to tweak objects reduction behavior.
3592 # In particular, state_setter is useful when the default __setstate__
3593 # behavior is not flexible enough.
3594
3595 # No custom reducer for b has been registered for now, so
3596 # BBB.__setstate__ should be used at unpickling time
3597 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3598
3599 def reduce_bbb(obj):
3600 return BBB, (), obj.__dict__, None, None, setstate_bbb
3601
3602 dispatch_table[BBB] = reduce_bbb
3603
3604 # The custom reducer reduce_bbb includes a state setter, that should
3605 # have priority over BBB.__setstate__
3606 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3607
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003608
Guido van Rossum98297ee2007-11-06 21:34:58 +00003609if __name__ == "__main__":
3610 # Print some stuff that can be used to rewrite DATA{0,1,2}
3611 from pickletools import dis
3612 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003613 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003614 p = pickle.dumps(x, i)
3615 print("DATA{0} = (".format(i))
3616 for j in range(0, len(p), 20):
3617 b = bytes(p[j:j+20])
3618 print(" {0!r}".format(b))
3619 print(")")
3620 print()
3621 print("# Disassembly of DATA{0}".format(i))
3622 print("DATA{0}_DIS = \"\"\"\\".format(i))
3623 dis(p)
3624 print("\"\"\"")
3625 print()