blob: 953fd5c5a278ba49f6ccbd9346daf7b78a1dbfcf [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):
Claudiu Popa6f03b232019-11-24 20:15:08 +01001022 self.check_unpickling_error(pickle.UnpicklingError, b'g0\np0')
1023 self.check_unpickling_error(pickle.UnpicklingError, b'jens:')
1024 self.check_unpickling_error(pickle.UnpicklingError, b'hens:')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001025 self.assert_is_copy([(100,), (100,)],
1026 self.loads(b'((Kdtp0\nh\x00l.))'))
1027
Serhiy Storchakae0606192015-09-29 22:10:07 +03001028 def test_binbytes8(self):
1029 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1030 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1031
1032 def test_binunicode8(self):
1033 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1034 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1035
Antoine Pitrou91f43802019-05-26 17:10:09 +02001036 def test_bytearray8(self):
1037 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1038 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1039
Serhiy Storchakae0606192015-09-29 22:10:07 +03001040 @requires_32b
1041 def test_large_32b_binbytes8(self):
1042 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001043 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1044 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001045
1046 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001047 def test_large_32b_bytearray8(self):
1048 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1049 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1050 dumped)
1051
1052 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001053 def test_large_32b_binunicode8(self):
1054 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001055 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1056 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001057
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001058 def test_get(self):
1059 pickled = b'((lp100000\ng100000\nt.'
1060 unpickled = self.loads(pickled)
1061 self.assertEqual(unpickled, ([],)*2)
1062 self.assertIs(unpickled[0], unpickled[1])
1063
1064 def test_binget(self):
1065 pickled = b'(]q\xffh\xfft.'
1066 unpickled = self.loads(pickled)
1067 self.assertEqual(unpickled, ([],)*2)
1068 self.assertIs(unpickled[0], unpickled[1])
1069
1070 def test_long_binget(self):
1071 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1072 unpickled = self.loads(pickled)
1073 self.assertEqual(unpickled, ([],)*2)
1074 self.assertIs(unpickled[0], unpickled[1])
1075
1076 def test_dup(self):
1077 pickled = b'((l2t.'
1078 unpickled = self.loads(pickled)
1079 self.assertEqual(unpickled, ([],)*2)
1080 self.assertIs(unpickled[0], unpickled[1])
1081
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001082 def test_negative_put(self):
1083 # Issue #12847
1084 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001085 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001086
1087 @requires_32b
1088 def test_negative_32b_binput(self):
1089 # Issue #12847
1090 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001091 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001092
1093 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001094 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001095
1096 def test_badly_quoted_string(self):
1097 # Issue #17710
1098 badpickles = [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 \n.',
1109 b'S\n.',
1110 b'S.']
1111 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001112 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001113
1114 def test_correctly_quoted_string(self):
1115 goodpickles = [(b"S''\n.", ''),
1116 (b'S""\n.', ''),
1117 (b'S"\\n"\n.', '\n'),
1118 (b"S'\\n'\n.", '\n')]
1119 for p, expected in goodpickles:
1120 self.assertEqual(self.loads(p), expected)
1121
1122 def test_frame_readline(self):
1123 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1124 # 0: \x80 PROTO 4
1125 # 2: \x95 FRAME 5
1126 # 11: I INT 42
1127 # 15: . STOP
1128 self.assertEqual(self.loads(pickled), 42)
1129
1130 def test_compat_unpickle(self):
1131 # xrange(1, 7)
1132 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1133 unpickled = self.loads(pickled)
1134 self.assertIs(type(unpickled), range)
1135 self.assertEqual(unpickled, range(1, 7))
1136 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1137 # reduce
1138 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1139 self.assertIs(self.loads(pickled), functools.reduce)
1140 # whichdb.whichdb
1141 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1142 self.assertIs(self.loads(pickled), dbm.whichdb)
1143 # Exception(), StandardError()
1144 for name in (b'Exception', b'StandardError'):
1145 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1146 unpickled = self.loads(pickled)
1147 self.assertIs(type(unpickled), Exception)
1148 self.assertEqual(str(unpickled), 'ugh')
1149 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1150 for name in (b'UserDict', b'IterableUserDict'):
1151 pickled = (b'\x80\x02(cUserDict\n' + name +
1152 b'\no}U\x04data}K\x01K\x02ssb.')
1153 unpickled = self.loads(pickled)
1154 self.assertIs(type(unpickled), collections.UserDict)
1155 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1156
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001157 def test_bad_stack(self):
1158 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001159 b'.', # STOP
1160 b'0', # POP
1161 b'1', # POP_MARK
1162 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001163 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001164 b'R', # REDUCE
1165 b')R',
1166 b'a', # APPEND
1167 b'Na',
1168 b'b', # BUILD
1169 b'Nb',
1170 b'd', # DICT
1171 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001172 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001173 b'ibuiltins\nlist\n', # INST
1174 b'l', # LIST
1175 b'o', # OBJ
1176 b'(o',
1177 b'p1\n', # PUT
1178 b'q\x00', # BINPUT
1179 b'r\x00\x00\x00\x00', # LONG_BINPUT
1180 b's', # SETITEM
1181 b'Ns',
1182 b'NNs',
1183 b't', # TUPLE
1184 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001185 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001186 b'}(Nu',
1187 b'\x81', # NEWOBJ
1188 b')\x81',
1189 b'\x85', # TUPLE1
1190 b'\x86', # TUPLE2
1191 b'N\x86',
1192 b'\x87', # TUPLE3
1193 b'N\x87',
1194 b'NN\x87',
1195 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001196 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001197 b'\x91', # FROZENSET
1198 b'\x92', # NEWOBJ_EX
1199 b')}\x92',
1200 b'\x93', # STACK_GLOBAL
1201 b'Vlist\n\x93',
1202 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001203 ]
1204 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001205 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001206
1207 def test_bad_mark(self):
1208 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001209 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001210 b'N(2', # DUP
1211 b'cbuiltins\nlist\n)(R', # REDUCE
1212 b'cbuiltins\nlist\n()R',
1213 b']N(a', # APPEND
1214 # BUILD
1215 b'cbuiltins\nValueError\n)R}(b',
1216 b'cbuiltins\nValueError\n)R(}b',
1217 b'(Nd', # DICT
1218 b'N(p1\n', # PUT
1219 b'N(q\x00', # BINPUT
1220 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1221 b'}NN(s', # SETITEM
1222 b'}N(Ns',
1223 b'}(NNs',
1224 b'}((u', # SETITEMS
1225 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1226 b'cbuiltins\nlist\n()\x81',
1227 b'N(\x85', # TUPLE1
1228 b'NN(\x86', # TUPLE2
1229 b'N(N\x86',
1230 b'NNN(\x87', # TUPLE3
1231 b'NN(N\x87',
1232 b'N(NN\x87',
1233 b']((\x90', # ADDITEMS
1234 # NEWOBJ_EX
1235 b'cbuiltins\nlist\n)}(\x92',
1236 b'cbuiltins\nlist\n)(}\x92',
1237 b'cbuiltins\nlist\n()}\x92',
1238 # STACK_GLOBAL
1239 b'Vbuiltins\n(Vlist\n\x93',
1240 b'Vbuiltins\nVlist\n(\x93',
1241 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001242 ]
1243 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001244 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001245
1246 def test_truncated_data(self):
1247 self.check_unpickling_error(EOFError, b'')
1248 self.check_unpickling_error(EOFError, b'N')
1249 badpickles = [
1250 b'B', # BINBYTES
1251 b'B\x03\x00\x00',
1252 b'B\x03\x00\x00\x00',
1253 b'B\x03\x00\x00\x00ab',
1254 b'C', # SHORT_BINBYTES
1255 b'C\x03',
1256 b'C\x03ab',
1257 b'F', # FLOAT
1258 b'F0.0',
1259 b'F0.00',
1260 b'G', # BINFLOAT
1261 b'G\x00\x00\x00\x00\x00\x00\x00',
1262 b'I', # INT
1263 b'I0',
1264 b'J', # BININT
1265 b'J\x00\x00\x00',
1266 b'K', # BININT1
1267 b'L', # LONG
1268 b'L0',
1269 b'L10',
1270 b'L0L',
1271 b'L10L',
1272 b'M', # BININT2
1273 b'M\x00',
1274 # b'P', # PERSID
1275 # b'Pabc',
1276 b'S', # STRING
1277 b"S'abc'",
1278 b'T', # BINSTRING
1279 b'T\x03\x00\x00',
1280 b'T\x03\x00\x00\x00',
1281 b'T\x03\x00\x00\x00ab',
1282 b'U', # SHORT_BINSTRING
1283 b'U\x03',
1284 b'U\x03ab',
1285 b'V', # UNICODE
1286 b'Vabc',
1287 b'X', # BINUNICODE
1288 b'X\x03\x00\x00',
1289 b'X\x03\x00\x00\x00',
1290 b'X\x03\x00\x00\x00ab',
1291 b'(c', # GLOBAL
1292 b'(cbuiltins',
1293 b'(cbuiltins\n',
1294 b'(cbuiltins\nlist',
1295 b'Ng', # GET
1296 b'Ng0',
1297 b'(i', # INST
1298 b'(ibuiltins',
1299 b'(ibuiltins\n',
1300 b'(ibuiltins\nlist',
1301 b'Nh', # BINGET
1302 b'Nj', # LONG_BINGET
1303 b'Nj\x00\x00\x00',
1304 b'Np', # PUT
1305 b'Np0',
1306 b'Nq', # BINPUT
1307 b'Nr', # LONG_BINPUT
1308 b'Nr\x00\x00\x00',
1309 b'\x80', # PROTO
1310 b'\x82', # EXT1
1311 b'\x83', # EXT2
1312 b'\x84\x01',
1313 b'\x84', # EXT4
1314 b'\x84\x01\x00\x00',
1315 b'\x8a', # LONG1
1316 b'\x8b', # LONG4
1317 b'\x8b\x00\x00\x00',
1318 b'\x8c', # SHORT_BINUNICODE
1319 b'\x8c\x03',
1320 b'\x8c\x03ab',
1321 b'\x8d', # BINUNICODE8
1322 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1323 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1324 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1325 b'\x8e', # BINBYTES8
1326 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1327 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1328 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001329 b'\x96', # BYTEARRAY8
1330 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1331 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1332 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001333 b'\x95', # FRAME
1334 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1335 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1336 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1337 ]
1338 for p in badpickles:
1339 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001340
tjb9004371c0a2019-02-18 23:30:51 +08001341 @reap_threads
1342 def test_unpickle_module_race(self):
1343 # https://bugs.python.org/issue34572
1344 locker_module = dedent("""
1345 import threading
1346 barrier = threading.Barrier(2)
1347 """)
1348 locking_import_module = dedent("""
1349 import locker
1350 locker.barrier.wait()
1351 class ToBeUnpickled(object):
1352 pass
1353 """)
1354
1355 os.mkdir(TESTFN)
1356 self.addCleanup(shutil.rmtree, TESTFN)
1357 sys.path.insert(0, TESTFN)
1358 self.addCleanup(sys.path.remove, TESTFN)
1359 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1360 f.write(locker_module.encode('utf-8'))
1361 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1362 f.write(locking_import_module.encode('utf-8'))
1363 self.addCleanup(forget, "locker")
1364 self.addCleanup(forget, "locking_import")
1365
1366 import locker
1367
1368 pickle_bytes = (
1369 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1370
1371 # Then try to unpickle two of these simultaneously
1372 # One of them will cause the module import, and we want it to block
1373 # until the other one either:
1374 # - fails (before the patch for this issue)
1375 # - blocks on the import lock for the module, as it should
1376 results = []
1377 barrier = threading.Barrier(3)
1378 def t():
1379 # This ensures the threads have all started
1380 # presumably barrier release is faster than thread startup
1381 barrier.wait()
1382 results.append(pickle.loads(pickle_bytes))
1383
1384 t1 = threading.Thread(target=t)
1385 t2 = threading.Thread(target=t)
1386 t1.start()
1387 t2.start()
1388
1389 barrier.wait()
1390 # could have delay here
1391 locker.barrier.wait()
1392
1393 t1.join()
1394 t2.join()
1395
1396 from locking_import import ToBeUnpickled
1397 self.assertEqual(
1398 [type(x) for x in results],
1399 [ToBeUnpickled] * 2)
1400
1401
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001402
1403class AbstractPickleTests(unittest.TestCase):
1404 # Subclass must define self.dumps, self.loads.
1405
1406 optimized = False
1407
1408 _testdata = AbstractUnpickleTests._testdata
1409
1410 def setUp(self):
1411 pass
1412
1413 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1414
1415 def test_misc(self):
1416 # test various datatypes not tested by testdata
1417 for proto in protocols:
1418 x = myint(4)
1419 s = self.dumps(x, proto)
1420 y = self.loads(s)
1421 self.assert_is_copy(x, y)
1422
1423 x = (1, ())
1424 s = self.dumps(x, proto)
1425 y = self.loads(s)
1426 self.assert_is_copy(x, y)
1427
1428 x = initarg(1, x)
1429 s = self.dumps(x, proto)
1430 y = self.loads(s)
1431 self.assert_is_copy(x, y)
1432
1433 # XXX test __reduce__ protocol?
1434
1435 def test_roundtrip_equality(self):
1436 expected = self._testdata
1437 for proto in protocols:
1438 s = self.dumps(expected, proto)
1439 got = self.loads(s)
1440 self.assert_is_copy(expected, got)
1441
Tim Peters70b02d72003-02-02 17:26:40 +00001442 # There are gratuitous differences between pickles produced by
1443 # pickle and cPickle, largely because cPickle starts PUT indices at
1444 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1445 # there's a comment with an exclamation point there whose meaning
1446 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1447 # of 1.
1448 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001449 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001450 from pickletools import dis
1451
1452 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1453 s = self.dumps(self._testdata, proto)
1454 filelike = StringIO()
1455 dis(s, out=filelike)
1456 got = filelike.getvalue()
1457 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001458
1459 def test_recursive_list(self):
1460 l = []
1461 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001462 for proto in protocols:
1463 s = self.dumps(l, proto)
1464 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001465 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001466 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001467 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001468
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001469 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001470 t = ([],)
1471 t[0].append(t)
1472 for proto in protocols:
1473 s = self.dumps(t, proto)
1474 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001475 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001476 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001477 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001478 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001479 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001480
Jeremy Hylton66426532001-10-15 21:38:56 +00001481 def test_recursive_dict(self):
1482 d = {}
1483 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001484 for proto in protocols:
1485 s = self.dumps(d, proto)
1486 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001487 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001488 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001489 self.assertIs(x[1], x)
1490
1491 def test_recursive_dict_key(self):
1492 d = {}
1493 k = K(d)
1494 d[k] = 1
1495 for proto in protocols:
1496 s = self.dumps(d, proto)
1497 x = self.loads(s)
1498 self.assertIsInstance(x, dict)
1499 self.assertEqual(len(x.keys()), 1)
1500 self.assertIsInstance(list(x.keys())[0], K)
1501 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001502
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001503 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001504 y = set()
1505 k = K(y)
1506 y.add(k)
1507 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001508 s = self.dumps(y, proto)
1509 x = self.loads(s)
1510 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001511 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001512 self.assertIsInstance(list(x)[0], K)
1513 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001514
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001515 def test_recursive_list_subclass(self):
1516 y = MyList()
1517 y.append(y)
1518 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001519 s = self.dumps(y, proto)
1520 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001521 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001522 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001523 self.assertIs(x[0], x)
1524
1525 def test_recursive_dict_subclass(self):
1526 d = MyDict()
1527 d[1] = d
1528 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1529 s = self.dumps(d, proto)
1530 x = self.loads(s)
1531 self.assertIsInstance(x, MyDict)
1532 self.assertEqual(list(x.keys()), [1])
1533 self.assertIs(x[1], x)
1534
1535 def test_recursive_dict_subclass_key(self):
1536 d = MyDict()
1537 k = K(d)
1538 d[k] = 1
1539 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1540 s = self.dumps(d, proto)
1541 x = self.loads(s)
1542 self.assertIsInstance(x, MyDict)
1543 self.assertEqual(len(list(x.keys())), 1)
1544 self.assertIsInstance(list(x.keys())[0], K)
1545 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001546
Jeremy Hylton66426532001-10-15 21:38:56 +00001547 def test_recursive_inst(self):
1548 i = C()
1549 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001550 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001551 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001552 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001553 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001554 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001555 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001556
1557 def test_recursive_multi(self):
1558 l = []
1559 d = {1:l}
1560 i = C()
1561 i.attr = d
1562 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001563 for proto in protocols:
1564 s = self.dumps(l, proto)
1565 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001566 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001567 self.assertEqual(len(x), 1)
1568 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001569 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001570 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001571
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001572 def check_recursive_collection_and_inst(self, factory):
1573 h = H()
1574 y = factory([h])
1575 h.attr = y
1576 for proto in protocols:
1577 s = self.dumps(y, proto)
1578 x = self.loads(s)
1579 self.assertIsInstance(x, type(y))
1580 self.assertEqual(len(x), 1)
1581 self.assertIsInstance(list(x)[0], H)
1582 self.assertIs(list(x)[0].attr, x)
1583
1584 def test_recursive_list_and_inst(self):
1585 self.check_recursive_collection_and_inst(list)
1586
1587 def test_recursive_tuple_and_inst(self):
1588 self.check_recursive_collection_and_inst(tuple)
1589
1590 def test_recursive_dict_and_inst(self):
1591 self.check_recursive_collection_and_inst(dict.fromkeys)
1592
1593 def test_recursive_set_and_inst(self):
1594 self.check_recursive_collection_and_inst(set)
1595
1596 def test_recursive_frozenset_and_inst(self):
1597 self.check_recursive_collection_and_inst(frozenset)
1598
1599 def test_recursive_list_subclass_and_inst(self):
1600 self.check_recursive_collection_and_inst(MyList)
1601
1602 def test_recursive_tuple_subclass_and_inst(self):
1603 self.check_recursive_collection_and_inst(MyTuple)
1604
1605 def test_recursive_dict_subclass_and_inst(self):
1606 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1607
1608 def test_recursive_set_subclass_and_inst(self):
1609 self.check_recursive_collection_and_inst(MySet)
1610
1611 def test_recursive_frozenset_subclass_and_inst(self):
1612 self.check_recursive_collection_and_inst(MyFrozenSet)
1613
Walter Dörwald9b775532007-06-08 14:30:53 +00001614 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001615 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001616 '<\\>', '<\\\U00012345>',
1617 # surrogates
1618 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001619 for proto in protocols:
1620 for u in endcases:
1621 p = self.dumps(u, proto)
1622 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001623 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001624
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001625 def test_unicode_high_plane(self):
1626 t = '\U00012345'
1627 for proto in protocols:
1628 p = self.dumps(t, proto)
1629 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001630 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001631
Guido van Rossumf4169812008-03-17 22:56:06 +00001632 def test_bytes(self):
1633 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001634 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001635 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001636 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001637 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001638 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001639 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001640 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001641 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001642 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001643
Antoine Pitrou91f43802019-05-26 17:10:09 +02001644 def test_bytearray(self):
1645 for proto in protocols:
1646 for s in b'', b'xyz', b'xyz'*100:
1647 b = bytearray(s)
1648 p = self.dumps(b, proto)
1649 bb = self.loads(p)
1650 self.assertIsNot(bb, b)
1651 self.assert_is_copy(b, bb)
1652 if proto <= 3:
1653 # bytearray is serialized using a global reference
1654 self.assertIn(b'bytearray', p)
1655 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1656 elif proto == 4:
1657 self.assertIn(b'bytearray', p)
1658 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1659 elif proto == 5:
1660 self.assertNotIn(b'bytearray', p)
1661 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1662
Jeremy Hylton66426532001-10-15 21:38:56 +00001663 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001664 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001665 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001666 while n:
1667 for expected in (-n, n):
1668 s = self.dumps(expected, proto)
1669 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001670 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001671 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001672
Tim Petersee1a53c2003-02-02 02:57:53 +00001673 def test_long(self):
1674 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001675 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001676 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001677 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001678 for npos in nbase-1, nbase, nbase+1:
1679 for n in npos, -npos:
1680 pickle = self.dumps(n, proto)
1681 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001682 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001683 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1684 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001685 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001686 nbase += nbase << 1000000
1687 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001688 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001689 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001690 # assert_is_copy is very expensive here as it precomputes
1691 # a failure message by computing the repr() of n and got,
1692 # we just do the check ourselves.
1693 self.assertIs(type(got), int)
1694 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001695
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001696 def test_float(self):
1697 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1698 3.14, 263.44582062374053, 6.022e23, 1e30]
1699 test_values = test_values + [-x for x in test_values]
1700 for proto in protocols:
1701 for value in test_values:
1702 pickle = self.dumps(value, proto)
1703 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001704 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001705
Thomas Wouters477c8d52006-05-27 19:21:47 +00001706 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1707 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001708 # make sure that floats are formatted locale independent with proto 0
1709 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001710
Jeremy Hylton66426532001-10-15 21:38:56 +00001711 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001712 for proto in protocols:
1713 inst = AAA()
1714 dumped = self.dumps(inst, proto)
1715 loaded = self.loads(dumped)
1716 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001717
1718 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001719 for proto in protocols:
1720 inst = initarg(1, 2)
1721 dumped = self.dumps(inst, proto)
1722 loaded = self.loads(dumped)
1723 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001724
Guido van Rossum04a86612001-12-19 16:58:54 +00001725 def test_metaclass(self):
1726 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001727 for proto in protocols:
1728 s = self.dumps(a, proto)
1729 b = self.loads(s)
1730 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001731
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001732 def test_dynamic_class(self):
1733 a = create_dynamic_class("my_dynamic_class", (object,))
1734 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1735 for proto in protocols:
1736 s = self.dumps(a, proto)
1737 b = self.loads(s)
1738 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001739 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001740
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001741 def test_structseq(self):
1742 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001743 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001744
1745 t = time.localtime()
1746 for proto in protocols:
1747 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001748 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001749 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001750 t = os.stat(os.curdir)
1751 s = self.dumps(t, proto)
1752 u = self.loads(s)
1753 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001754 if hasattr(os, "statvfs"):
1755 t = os.statvfs(os.curdir)
1756 s = self.dumps(t, proto)
1757 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001758 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001759
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001760 def test_ellipsis(self):
1761 for proto in protocols:
1762 s = self.dumps(..., proto)
1763 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001764 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001765
1766 def test_notimplemented(self):
1767 for proto in protocols:
1768 s = self.dumps(NotImplemented, proto)
1769 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001770 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001771
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001772 def test_singleton_types(self):
1773 # Issue #6477: Test that types of built-in singletons can be pickled.
1774 singletons = [None, ..., NotImplemented]
1775 for singleton in singletons:
1776 for proto in protocols:
1777 s = self.dumps(type(singleton), proto)
1778 u = self.loads(s)
1779 self.assertIs(type(singleton), u)
1780
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001781 # Tests for protocol 2
1782
Tim Peters4190fb82003-02-02 16:09:05 +00001783 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001784 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001785 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001786 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001787 proto_header = pickle.PROTO + bytes([proto])
1788 self.assertTrue(pickled.startswith(proto_header))
1789 else:
1790 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001791
1792 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001793 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001794 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001795 try:
1796 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001797 except ValueError as err:
1798 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001799 else:
1800 self.fail("expected bad protocol number to raise ValueError")
1801
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001802 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001803 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001804 for proto in protocols:
1805 s = self.dumps(x, proto)
1806 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001807 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001808 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001809
1810 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001811 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001812 for proto in protocols:
1813 s = self.dumps(x, proto)
1814 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001815 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001816 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001817
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001818 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001819 # Map (proto, len(tuple)) to expected opcode.
1820 expected_opcode = {(0, 0): pickle.TUPLE,
1821 (0, 1): pickle.TUPLE,
1822 (0, 2): pickle.TUPLE,
1823 (0, 3): pickle.TUPLE,
1824 (0, 4): pickle.TUPLE,
1825
1826 (1, 0): pickle.EMPTY_TUPLE,
1827 (1, 1): pickle.TUPLE,
1828 (1, 2): pickle.TUPLE,
1829 (1, 3): pickle.TUPLE,
1830 (1, 4): pickle.TUPLE,
1831
1832 (2, 0): pickle.EMPTY_TUPLE,
1833 (2, 1): pickle.TUPLE1,
1834 (2, 2): pickle.TUPLE2,
1835 (2, 3): pickle.TUPLE3,
1836 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001837
1838 (3, 0): pickle.EMPTY_TUPLE,
1839 (3, 1): pickle.TUPLE1,
1840 (3, 2): pickle.TUPLE2,
1841 (3, 3): pickle.TUPLE3,
1842 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001843 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001844 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001845 b = (1,)
1846 c = (1, 2)
1847 d = (1, 2, 3)
1848 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001849 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001850 for x in a, b, c, d, e:
1851 s = self.dumps(x, proto)
1852 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001853 self.assert_is_copy(x, y)
1854 expected = expected_opcode[min(proto, 3), len(x)]
1855 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001856
Guido van Rossum7d97d312003-01-28 04:25:27 +00001857 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001858 # Map (proto, singleton) to expected opcode.
1859 expected_opcode = {(0, None): pickle.NONE,
1860 (1, None): pickle.NONE,
1861 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001862 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001863
1864 (0, True): pickle.INT,
1865 (1, True): pickle.INT,
1866 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001867 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001868
1869 (0, False): pickle.INT,
1870 (1, False): pickle.INT,
1871 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001872 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001873 }
Tim Peters4190fb82003-02-02 16:09:05 +00001874 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001875 for x in None, False, True:
1876 s = self.dumps(x, proto)
1877 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001878 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001879 expected = expected_opcode[min(proto, 3), x]
1880 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001881
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001882 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001883 x = MyTuple([1, 2, 3])
1884 x.foo = 42
1885 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001886 for proto in protocols:
1887 s = self.dumps(x, proto)
1888 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001889 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001890
1891 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001892 x = MyList([1, 2, 3])
1893 x.foo = 42
1894 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001895 for proto in protocols:
1896 s = self.dumps(x, proto)
1897 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001898 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001899
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001900 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001901 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001902 for C in myclasses:
1903 B = C.__base__
1904 x = C(C.sample)
1905 x.foo = 42
1906 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001907 y = self.loads(s)
1908 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001909 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001910 self.assertEqual(B(x), B(y), detail)
1911 self.assertEqual(x.__dict__, y.__dict__, detail)
1912
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001913 def test_newobj_proxies(self):
1914 # NEWOBJ should use the __class__ rather than the raw type
1915 classes = myclasses[:]
1916 # Cannot create weakproxies to these classes
1917 for c in (MyInt, MyTuple):
1918 classes.remove(c)
1919 for proto in protocols:
1920 for C in classes:
1921 B = C.__base__
1922 x = C(C.sample)
1923 x.foo = 42
1924 p = weakref.proxy(x)
1925 s = self.dumps(p, proto)
1926 y = self.loads(s)
1927 self.assertEqual(type(y), type(x)) # rather than type(p)
1928 detail = (proto, C, B, x, y, type(y))
1929 self.assertEqual(B(x), B(y), detail)
1930 self.assertEqual(x.__dict__, y.__dict__, detail)
1931
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001932 def test_newobj_not_class(self):
1933 # Issue 24552
1934 global SimpleNewObj
1935 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001936 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001937 b = self.dumps(o, 4)
1938 try:
1939 SimpleNewObj = 42
1940 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1941 finally:
1942 SimpleNewObj = save
1943
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001944 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001945 # an object of that type. Check that the resulting pickle uses opcode
1946 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001947
Tim Peters22e71712003-02-03 22:27:38 +00001948 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001949 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001950 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001951 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001952 x = MyList([1, 2, 3])
1953 x.foo = 42
1954 x.bar = "hello"
1955
Tim Peters22e71712003-02-03 22:27:38 +00001956 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001957 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001958 self.assertIn(__name__.encode("utf-8"), s1)
1959 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001960 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001961
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001962 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001963 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001964
Tim Peters22e71712003-02-03 22:27:38 +00001965 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001966 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001967 self.assertNotIn(__name__.encode("utf-8"), s2)
1968 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001969 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001970
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001971 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001972 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001973 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001974 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001975
1976 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001977 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1978 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001979
1980 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001981 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1982 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1983 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001984
1985 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001986 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1987 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
1988 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
1989
Tim Peters8d2613a2003-02-11 16:40:16 +00001990 def test_list_chunking(self):
1991 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00001992 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001993 for proto in protocols:
1994 s = self.dumps(x, proto)
1995 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001996 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001997 num_appends = count_opcode(pickle.APPENDS, s)
1998 self.assertEqual(num_appends, proto > 0)
1999
2000 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002001 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002002 for proto in protocols:
2003 s = self.dumps(x, proto)
2004 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002005 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002006 num_appends = count_opcode(pickle.APPENDS, s)
2007 if proto == 0:
2008 self.assertEqual(num_appends, 0)
2009 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002010 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002011
2012 def test_dict_chunking(self):
2013 n = 10 # too small to chunk
2014 x = dict.fromkeys(range(n))
2015 for proto in protocols:
2016 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002017 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002018 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002019 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002020 num_setitems = count_opcode(pickle.SETITEMS, s)
2021 self.assertEqual(num_setitems, proto > 0)
2022
2023 n = 2500 # expect at least two chunks when proto > 0
2024 x = dict.fromkeys(range(n))
2025 for proto in protocols:
2026 s = self.dumps(x, proto)
2027 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002028 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002029 num_setitems = count_opcode(pickle.SETITEMS, s)
2030 if proto == 0:
2031 self.assertEqual(num_setitems, 0)
2032 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002033 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002034
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002035 def test_set_chunking(self):
2036 n = 10 # too small to chunk
2037 x = set(range(n))
2038 for proto in protocols:
2039 s = self.dumps(x, proto)
2040 y = self.loads(s)
2041 self.assert_is_copy(x, y)
2042 num_additems = count_opcode(pickle.ADDITEMS, s)
2043 if proto < 4:
2044 self.assertEqual(num_additems, 0)
2045 else:
2046 self.assertEqual(num_additems, 1)
2047
2048 n = 2500 # expect at least two chunks when proto >= 4
2049 x = set(range(n))
2050 for proto in protocols:
2051 s = self.dumps(x, proto)
2052 y = self.loads(s)
2053 self.assert_is_copy(x, y)
2054 num_additems = count_opcode(pickle.ADDITEMS, s)
2055 if proto < 4:
2056 self.assertEqual(num_additems, 0)
2057 else:
2058 self.assertGreaterEqual(num_additems, 2)
2059
Tim Peterse9ef2032003-02-13 18:42:00 +00002060 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002061 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002062 x.abc = 666
2063 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002064 with self.subTest(proto=proto):
2065 s = self.dumps(x, proto)
2066 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002067 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002068 else:
2069 self.assertIn(b'M\xce\xfa', s) # BININT2
2070 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2071 2 <= proto)
2072 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2073 y = self.loads(s) # will raise TypeError if __init__ called
2074 self.assert_is_copy(x, y)
2075
2076 def test_complex_newobj(self):
2077 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2078 x.abc = 666
2079 for proto in protocols:
2080 with self.subTest(proto=proto):
2081 s = self.dumps(x, proto)
2082 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002083 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002084 elif proto < 2:
2085 self.assertIn(b'M\xce\xfa', s) # BININT2
2086 elif proto < 4:
2087 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2088 else:
2089 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2090 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2091 2 <= proto)
2092 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2093 y = self.loads(s) # will raise TypeError if __init__ called
2094 self.assert_is_copy(x, y)
2095
2096 def test_complex_newobj_ex(self):
2097 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2098 x.abc = 666
2099 for proto in protocols:
2100 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002101 s = self.dumps(x, proto)
2102 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002103 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002104 elif proto < 2:
2105 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002106 elif proto < 4:
2107 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002108 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002109 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2110 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2111 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2112 4 <= proto)
2113 y = self.loads(s) # will raise TypeError if __init__ called
2114 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002115
Tim Peters42f08ac2003-02-11 22:43:24 +00002116 def test_newobj_list_slots(self):
2117 x = SlotList([1, 2, 3])
2118 x.foo = 42
2119 x.bar = "hello"
2120 s = self.dumps(x, 2)
2121 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002122 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002123
Guido van Rossum2a30b212003-02-18 22:41:24 +00002124 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002125 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002126 x = REX_one()
2127 self.assertEqual(x._reduce_called, 0)
2128 s = self.dumps(x, proto)
2129 self.assertEqual(x._reduce_called, 1)
2130 y = self.loads(s)
2131 self.assertEqual(y._reduce_called, 0)
2132
2133 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002134 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002135 x = REX_two()
2136 self.assertEqual(x._proto, None)
2137 s = self.dumps(x, proto)
2138 self.assertEqual(x._proto, proto)
2139 y = self.loads(s)
2140 self.assertEqual(y._proto, None)
2141
2142 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002143 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002144 x = REX_three()
2145 self.assertEqual(x._proto, None)
2146 s = self.dumps(x, proto)
2147 self.assertEqual(x._proto, proto)
2148 y = self.loads(s)
2149 self.assertEqual(y._proto, None)
2150
Guido van Rossumd8faa362007-04-27 19:54:29 +00002151 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002152 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002153 x = REX_four()
2154 self.assertEqual(x._proto, None)
2155 s = self.dumps(x, proto)
2156 self.assertEqual(x._proto, proto)
2157 y = self.loads(s)
2158 self.assertEqual(y._proto, proto)
2159
2160 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002161 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002162 x = REX_five()
2163 self.assertEqual(x._reduce_called, 0)
2164 s = self.dumps(x, proto)
2165 self.assertEqual(x._reduce_called, 1)
2166 y = self.loads(s)
2167 self.assertEqual(y._reduce_called, 1)
2168
Brett Cannon31f59292011-02-21 19:29:56 +00002169 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002170 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002171 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002172 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002173 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002174 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002175
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002176 def test_reduce_bad_iterator(self):
2177 # Issue4176: crash when 4th and 5th items of __reduce__()
2178 # are not iterators
2179 class C(object):
2180 def __reduce__(self):
2181 # 4th item is not an iterator
2182 return list, (), None, [], None
2183 class D(object):
2184 def __reduce__(self):
2185 # 5th item is not an iterator
2186 return dict, (), None, None, []
2187
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002188 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002189 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002190 try:
2191 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002192 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002193 pass
2194 try:
2195 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002196 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002197 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002198
Collin Winter771d8342009-04-16 03:18:06 +00002199 def test_many_puts_and_gets(self):
2200 # Test that internal data structures correctly deal with lots of
2201 # puts/gets.
2202 keys = ("aaa" + str(i) for i in range(100))
2203 large_dict = dict((k, [4, 5, 6]) for k in keys)
2204 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2205
2206 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002207 with self.subTest(proto=proto):
2208 dumped = self.dumps(obj, proto)
2209 loaded = self.loads(dumped)
2210 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002211
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002212 def test_attribute_name_interning(self):
2213 # Test that attribute names of pickled objects are interned when
2214 # unpickling.
2215 for proto in protocols:
2216 x = C()
2217 x.foo = 42
2218 x.bar = "hello"
2219 s = self.dumps(x, proto)
2220 y = self.loads(s)
2221 x_keys = sorted(x.__dict__)
2222 y_keys = sorted(y.__dict__)
2223 for x_key, y_key in zip(x_keys, y_keys):
2224 self.assertIs(x_key, y_key)
2225
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002226 def test_pickle_to_2x(self):
2227 # Pickle non-trivial data with protocol 2, expecting that it yields
2228 # the same result as Python 2.x did.
2229 # NOTE: this test is a bit too strong since we can produce different
2230 # bytecode that 2.x will still understand.
2231 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002232 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002233 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002234 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002235
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002236 def test_large_pickles(self):
2237 # Test the correctness of internal buffering routines when handling
2238 # large data.
2239 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002240 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002241 dumped = self.dumps(data, proto)
2242 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002243 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002244 self.assertEqual(loaded, data)
2245
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002246 def test_int_pickling_efficiency(self):
2247 # Test compacity of int representation (see issue #12744)
2248 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002249 with self.subTest(proto=proto):
2250 pickles = [self.dumps(2**n, proto) for n in range(70)]
2251 sizes = list(map(len, pickles))
2252 # the size function is monotonic
2253 self.assertEqual(sorted(sizes), sizes)
2254 if proto >= 2:
2255 for p in pickles:
2256 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002257
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002258 def _check_pickling_with_opcode(self, obj, opcode, proto):
2259 pickled = self.dumps(obj, proto)
2260 self.assertTrue(opcode_in_pickle(opcode, pickled))
2261 unpickled = self.loads(pickled)
2262 self.assertEqual(obj, unpickled)
2263
2264 def test_appends_on_non_lists(self):
2265 # Issue #17720
2266 obj = REX_six([1, 2, 3])
2267 for proto in protocols:
2268 if proto == 0:
2269 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2270 else:
2271 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2272
2273 def test_setitems_on_non_dicts(self):
2274 obj = REX_seven({1: -1, 2: -2, 3: -3})
2275 for proto in protocols:
2276 if proto == 0:
2277 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2278 else:
2279 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2280
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002281 # Exercise framing (proto >= 4) for significant workloads
2282
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002283 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002284 FRAME_SIZE_TARGET = 64 * 1024
2285
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002286 def check_frame_opcodes(self, pickled):
2287 """
2288 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002289
2290 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2291 framed by default and are therefore considered a frame by themselves in
2292 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002293 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002294 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002295 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2296 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002297 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002298 if frame_end is not None:
2299 self.assertLessEqual(pos, frame_end)
2300 if pos == frame_end:
2301 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002302
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002303 if frame_end is not None: # framed
2304 self.assertNotEqual(op.name, 'FRAME')
2305 if op.name in frameless_opcodes:
2306 # Only short bytes and str objects should be written
2307 # in a frame
2308 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2309
2310 else: # not framed
2311 if (op.name == 'FRAME' or
2312 (op.name in frameless_opcodes and
2313 len(arg) > self.FRAME_SIZE_TARGET)):
2314 # Frame or large bytes or str object
2315 if frameless_start is not None:
2316 # Only short data should be written outside of a frame
2317 self.assertLess(pos - frameless_start,
2318 self.FRAME_SIZE_MIN)
2319 frameless_start = None
2320 elif frameless_start is None and op.name != 'PROTO':
2321 frameless_start = pos
2322
2323 if op.name == 'FRAME':
2324 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2325 frame_end = pos + 9 + arg
2326
2327 pos = len(pickled)
2328 if frame_end is not None:
2329 self.assertEqual(frame_end, pos)
2330 elif frameless_start is not None:
2331 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002332
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002333 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002334 def test_framing_many_objects(self):
2335 obj = list(range(10**5))
2336 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2337 with self.subTest(proto=proto):
2338 pickled = self.dumps(obj, proto)
2339 unpickled = self.loads(pickled)
2340 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002341 bytes_per_frame = (len(pickled) /
2342 count_opcode(pickle.FRAME, pickled))
2343 self.assertGreater(bytes_per_frame,
2344 self.FRAME_SIZE_TARGET / 2)
2345 self.assertLessEqual(bytes_per_frame,
2346 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002347 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002348
2349 def test_framing_large_objects(self):
2350 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002351 small_items = [[i] for i in range(10)]
2352 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002353 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002354 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002355 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002356 if not fast:
2357 # fast=False by default.
2358 # This covers in-memory pickling with pickle.dumps().
2359 pickled = self.dumps(obj, proto)
2360 else:
2361 # Pickler is required when fast=True.
2362 if not hasattr(self, 'pickler'):
2363 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002364 buf = io.BytesIO()
2365 pickler = self.pickler(buf, protocol=proto)
2366 pickler.fast = fast
2367 pickler.dump(obj)
2368 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002369 unpickled = self.loads(pickled)
2370 # More informative error message in case of failure.
2371 self.assertEqual([len(x) for x in obj],
2372 [len(x) for x in unpickled])
2373 # Perform full equality check if the lengths match.
2374 self.assertEqual(obj, unpickled)
2375 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002376 # A single frame for small objects between
2377 # first two large objects.
2378 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002379 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002380
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002381 def test_optional_frames(self):
2382 if pickle.HIGHEST_PROTOCOL < 4:
2383 return
2384
2385 def remove_frames(pickled, keep_frame=None):
2386 """Remove frame opcodes from the given pickle."""
2387 frame_starts = []
2388 # 1 byte for the opcode and 8 for the argument
2389 frame_opcode_size = 9
2390 for opcode, _, pos in pickletools.genops(pickled):
2391 if opcode.name == 'FRAME':
2392 frame_starts.append(pos)
2393
2394 newpickle = bytearray()
2395 last_frame_end = 0
2396 for i, pos in enumerate(frame_starts):
2397 if keep_frame and keep_frame(i):
2398 continue
2399 newpickle += pickled[last_frame_end:pos]
2400 last_frame_end = pos + frame_opcode_size
2401 newpickle += pickled[last_frame_end:]
2402 return newpickle
2403
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002404 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002405 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002406 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002407 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002408 for bytes_type in (bytes, bytearray):
2409 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002410
Antoine Pitrou91f43802019-05-26 17:10:09 +02002411 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2412 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002413
Antoine Pitrou91f43802019-05-26 17:10:09 +02002414 frameless_pickle = remove_frames(pickled)
2415 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2416 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002417
Antoine Pitrou91f43802019-05-26 17:10:09 +02002418 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2419 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2420 count_opcode(pickle.FRAME, pickled))
2421 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002422
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002423 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002424 def test_framed_write_sizes_with_delayed_writer(self):
2425 class ChunkAccumulator:
2426 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002427 def __init__(self):
2428 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002429 def write(self, chunk):
2430 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002431 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002432 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002433
2434 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002435 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2436 for i in range(int(1e4))]
2437 # Add a large unique ASCII string
2438 objects.append('0123456789abcdef' *
2439 (self.FRAME_SIZE_TARGET // 16 + 1))
2440
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002441 # Protocol 4 packs groups of small objects into frames and issues
2442 # calls to write only once or twice per frame:
2443 # The C pickler issues one call to write per-frame (header and
2444 # contents) while Python pickler issues two calls to write: one for
2445 # the frame header and one for the frame binary contents.
2446 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002447 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002448
2449 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002450 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002451 # be released otherwise this delayed access would not be possible.
2452 pickled = writer.concatenate_chunks()
2453 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002454 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002455 self.assertGreater(len(writer.chunks), 1)
2456
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002457 # memoryviews should own the memory.
2458 del objects
2459 support.gc_collect()
2460 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002461
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002462 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002463 # There should be at least one call to write per frame
2464 self.assertGreaterEqual(len(writer.chunks), n_frames)
2465
2466 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002467 # one per-frame header, one per frame for the actual contents,
2468 # and two for the header.
2469 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002470
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002471 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002472 large_sizes = [s for s in chunk_sizes
2473 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002474 medium_sizes = [s for s in chunk_sizes
2475 if 9 < s < self.FRAME_SIZE_TARGET]
2476 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002477
2478 # Large chunks should not be too large:
2479 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002480 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2481 chunk_sizes)
2482 # There shouldn't bee too many small chunks: the protocol header,
2483 # the frame headers and the large string headers are written
2484 # in small chunks.
2485 self.assertLessEqual(len(small_sizes),
2486 len(large_sizes) + len(medium_sizes) + 3,
2487 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002488
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002489 def test_nested_names(self):
2490 global Nested
2491 class Nested:
2492 class A:
2493 class B:
2494 class C:
2495 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002496 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002497 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2498 with self.subTest(proto=proto, obj=obj):
2499 unpickled = self.loads(self.dumps(obj, proto))
2500 self.assertIs(obj, unpickled)
2501
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002502 def test_recursive_nested_names(self):
2503 global Recursive
2504 class Recursive:
2505 pass
2506 Recursive.mod = sys.modules[Recursive.__module__]
2507 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2508 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2509 with self.subTest(proto=proto):
2510 unpickled = self.loads(self.dumps(Recursive, proto))
2511 self.assertIs(unpickled, Recursive)
2512 del Recursive.mod # break reference loop
2513
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002514 def test_py_methods(self):
2515 global PyMethodsTest
2516 class PyMethodsTest:
2517 @staticmethod
2518 def cheese():
2519 return "cheese"
2520 @classmethod
2521 def wine(cls):
2522 assert cls is PyMethodsTest
2523 return "wine"
2524 def biscuits(self):
2525 assert isinstance(self, PyMethodsTest)
2526 return "biscuits"
2527 class Nested:
2528 "Nested class"
2529 @staticmethod
2530 def ketchup():
2531 return "ketchup"
2532 @classmethod
2533 def maple(cls):
2534 assert cls is PyMethodsTest.Nested
2535 return "maple"
2536 def pie(self):
2537 assert isinstance(self, PyMethodsTest.Nested)
2538 return "pie"
2539
2540 py_methods = (
2541 PyMethodsTest.cheese,
2542 PyMethodsTest.wine,
2543 PyMethodsTest().biscuits,
2544 PyMethodsTest.Nested.ketchup,
2545 PyMethodsTest.Nested.maple,
2546 PyMethodsTest.Nested().pie
2547 )
2548 py_unbound_methods = (
2549 (PyMethodsTest.biscuits, PyMethodsTest),
2550 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2551 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002552 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002553 for method in py_methods:
2554 with self.subTest(proto=proto, method=method):
2555 unpickled = self.loads(self.dumps(method, proto))
2556 self.assertEqual(method(), unpickled())
2557 for method, cls in py_unbound_methods:
2558 obj = cls()
2559 with self.subTest(proto=proto, method=method):
2560 unpickled = self.loads(self.dumps(method, proto))
2561 self.assertEqual(method(obj), unpickled(obj))
2562
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002563 def test_c_methods(self):
2564 global Subclass
2565 class Subclass(tuple):
2566 class Nested(str):
2567 pass
2568
2569 c_methods = (
2570 # bound built-in method
2571 ("abcd".index, ("c",)),
2572 # unbound built-in method
2573 (str.index, ("abcd", "c")),
2574 # bound "slot" method
2575 ([1, 2, 3].__len__, ()),
2576 # unbound "slot" method
2577 (list.__len__, ([1, 2, 3],)),
2578 # bound "coexist" method
2579 ({1, 2}.__contains__, (2,)),
2580 # unbound "coexist" method
2581 (set.__contains__, ({1, 2}, 2)),
2582 # built-in class method
2583 (dict.fromkeys, (("a", 1), ("b", 2))),
2584 # built-in static method
2585 (bytearray.maketrans, (b"abc", b"xyz")),
2586 # subclass methods
2587 (Subclass([1,2,2]).count, (2,)),
2588 (Subclass.count, (Subclass([1,2,2]), 2)),
2589 (Subclass.Nested("sweet").count, ("e",)),
2590 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2591 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002592 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002593 for method, args in c_methods:
2594 with self.subTest(proto=proto, method=method):
2595 unpickled = self.loads(self.dumps(method, proto))
2596 self.assertEqual(method(*args), unpickled(*args))
2597
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002598 def test_compat_pickle(self):
2599 tests = [
2600 (range(1, 7), '__builtin__', 'xrange'),
2601 (map(int, '123'), 'itertools', 'imap'),
2602 (functools.reduce, '__builtin__', 'reduce'),
2603 (dbm.whichdb, 'whichdb', 'whichdb'),
2604 (Exception(), 'exceptions', 'Exception'),
2605 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2606 (collections.UserList(), 'UserList', 'UserList'),
2607 (collections.defaultdict(), 'collections', 'defaultdict'),
2608 ]
2609 for val, mod, name in tests:
2610 for proto in range(3):
2611 with self.subTest(type=type(val), proto=proto):
2612 pickled = self.dumps(val, proto)
2613 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2614 self.assertIs(type(self.loads(pickled)), type(val))
2615
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002616 def test_local_lookup_error(self):
2617 # Test that whichmodule() errors out cleanly when looking up
2618 # an assumed globally-reachable object fails.
2619 def f():
2620 pass
2621 # Since the function is local, lookup will fail
2622 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2623 with self.assertRaises((AttributeError, pickle.PicklingError)):
2624 pickletools.dis(self.dumps(f, proto))
2625 # Same without a __module__ attribute (exercises a different path
2626 # in _pickle.c).
2627 del f.__module__
2628 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2629 with self.assertRaises((AttributeError, pickle.PicklingError)):
2630 pickletools.dis(self.dumps(f, proto))
2631 # Yet a different path.
2632 f.__name__ = f.__qualname__
2633 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2634 with self.assertRaises((AttributeError, pickle.PicklingError)):
2635 pickletools.dis(self.dumps(f, proto))
2636
Antoine Pitrou91f43802019-05-26 17:10:09 +02002637 #
2638 # PEP 574 tests below
2639 #
2640
2641 def buffer_like_objects(self):
2642 # Yield buffer-like objects with the bytestring "abcdef" in them
2643 bytestring = b"abcdefgh"
2644 yield ZeroCopyBytes(bytestring)
2645 yield ZeroCopyBytearray(bytestring)
2646 if _testbuffer is not None:
2647 items = list(bytestring)
2648 value = int.from_bytes(bytestring, byteorder='little')
2649 for flags in (0, _testbuffer.ND_WRITABLE):
2650 # 1-D, contiguous
2651 yield PicklableNDArray(items, format='B', shape=(8,),
2652 flags=flags)
2653 # 2-D, C-contiguous
2654 yield PicklableNDArray(items, format='B', shape=(4, 2),
2655 strides=(2, 1), flags=flags)
2656 # 2-D, Fortran-contiguous
2657 yield PicklableNDArray(items, format='B',
2658 shape=(4, 2), strides=(1, 4),
2659 flags=flags)
2660
2661 def test_in_band_buffers(self):
2662 # Test in-band buffers (PEP 574)
2663 for obj in self.buffer_like_objects():
2664 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2665 data = self.dumps(obj, proto)
2666 if obj.c_contiguous and proto >= 5:
2667 # The raw memory bytes are serialized in physical order
2668 self.assertIn(b"abcdefgh", data)
2669 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2670 if proto >= 5:
2671 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2672 1 if obj.readonly else 0)
2673 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2674 0 if obj.readonly else 1)
2675 # Return a true value from buffer_callback should have
2676 # the same effect
2677 def buffer_callback(obj):
2678 return True
2679 data2 = self.dumps(obj, proto,
2680 buffer_callback=buffer_callback)
2681 self.assertEqual(data2, data)
2682
2683 new = self.loads(data)
2684 # It's a copy
2685 self.assertIsNot(new, obj)
2686 self.assertIs(type(new), type(obj))
2687 self.assertEqual(new, obj)
2688
2689 # XXX Unfortunately cannot test non-contiguous array
2690 # (see comment in PicklableNDArray.__reduce_ex__)
2691
2692 def test_oob_buffers(self):
2693 # Test out-of-band buffers (PEP 574)
2694 for obj in self.buffer_like_objects():
2695 for proto in range(0, 5):
2696 # Need protocol >= 5 for buffer_callback
2697 with self.assertRaises(ValueError):
2698 self.dumps(obj, proto,
2699 buffer_callback=[].append)
2700 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2701 buffers = []
2702 buffer_callback = lambda pb: buffers.append(pb.raw())
2703 data = self.dumps(obj, proto,
2704 buffer_callback=buffer_callback)
2705 self.assertNotIn(b"abcdefgh", data)
2706 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2707 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2708 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2709 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2710 1 if obj.readonly else 0)
2711
2712 if obj.c_contiguous:
2713 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2714 # Need buffers argument to unpickle properly
2715 with self.assertRaises(pickle.UnpicklingError):
2716 self.loads(data)
2717
2718 new = self.loads(data, buffers=buffers)
2719 if obj.zero_copy_reconstruct:
2720 # Zero-copy achieved
2721 self.assertIs(new, obj)
2722 else:
2723 self.assertIs(type(new), type(obj))
2724 self.assertEqual(new, obj)
2725 # Non-sequence buffers accepted too
2726 new = self.loads(data, buffers=iter(buffers))
2727 if obj.zero_copy_reconstruct:
2728 # Zero-copy achieved
2729 self.assertIs(new, obj)
2730 else:
2731 self.assertIs(type(new), type(obj))
2732 self.assertEqual(new, obj)
2733
2734 def test_oob_buffers_writable_to_readonly(self):
2735 # Test reconstructing readonly object from writable buffer
2736 obj = ZeroCopyBytes(b"foobar")
2737 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2738 buffers = []
2739 buffer_callback = buffers.append
2740 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2741
2742 buffers = map(bytearray, buffers)
2743 new = self.loads(data, buffers=buffers)
2744 self.assertIs(type(new), type(obj))
2745 self.assertEqual(new, obj)
2746
2747 def test_picklebuffer_error(self):
2748 # PickleBuffer forbidden with protocol < 5
2749 pb = pickle.PickleBuffer(b"foobar")
2750 for proto in range(0, 5):
2751 with self.assertRaises(pickle.PickleError):
2752 self.dumps(pb, proto)
2753
2754 def test_buffer_callback_error(self):
2755 def buffer_callback(buffers):
2756 1/0
2757 pb = pickle.PickleBuffer(b"foobar")
2758 with self.assertRaises(ZeroDivisionError):
2759 self.dumps(pb, 5, buffer_callback=buffer_callback)
2760
2761 def test_buffers_error(self):
2762 pb = pickle.PickleBuffer(b"foobar")
2763 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2764 data = self.dumps(pb, proto, buffer_callback=[].append)
2765 # Non iterable buffers
2766 with self.assertRaises(TypeError):
2767 self.loads(data, buffers=object())
2768 # Buffer iterable exhausts too early
2769 with self.assertRaises(pickle.UnpicklingError):
2770 self.loads(data, buffers=[])
2771
Markus Mohrhard898318b2019-07-26 00:00:34 +08002772 def test_inband_accept_default_buffers_argument(self):
2773 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2774 data_pickled = self.dumps(1, proto, buffer_callback=None)
2775 data = self.loads(data_pickled, buffers=None)
2776
Antoine Pitrou91f43802019-05-26 17:10:09 +02002777 @unittest.skipIf(np is None, "Test needs Numpy")
2778 def test_buffers_numpy(self):
2779 def check_no_copy(x, y):
2780 np.testing.assert_equal(x, y)
2781 self.assertEqual(x.ctypes.data, y.ctypes.data)
2782
2783 def check_copy(x, y):
2784 np.testing.assert_equal(x, y)
2785 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2786
2787 def check_array(arr):
2788 # In-band
2789 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2790 data = self.dumps(arr, proto)
2791 new = self.loads(data)
2792 check_copy(arr, new)
2793 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2794 buffer_callback = lambda _: True
2795 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2796 new = self.loads(data)
2797 check_copy(arr, new)
2798 # Out-of-band
2799 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2800 buffers = []
2801 buffer_callback = buffers.append
2802 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2803 new = self.loads(data, buffers=buffers)
2804 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2805 check_no_copy(arr, new)
2806 else:
2807 check_copy(arr, new)
2808
2809 # 1-D
2810 arr = np.arange(6)
2811 check_array(arr)
2812 # 1-D, non-contiguous
2813 check_array(arr[::2])
2814 # 2-D, C-contiguous
2815 arr = np.arange(12).reshape((3, 4))
2816 check_array(arr)
2817 # 2-D, F-contiguous
2818 check_array(arr.T)
2819 # 2-D, non-contiguous
2820 check_array(arr[::2])
2821
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002822
2823class BigmemPickleTests(unittest.TestCase):
2824
Victor Stinner8c663fd2017-11-08 14:44:44 -08002825 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002826
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002827 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002828 def test_huge_long_32b(self, size):
2829 data = 1 << (8 * size)
2830 try:
2831 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002832 if proto < 2:
2833 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002834 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002835 with self.assertRaises((ValueError, OverflowError)):
2836 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002837 finally:
2838 data = None
2839
Victor Stinner8c663fd2017-11-08 14:44:44 -08002840 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002841 # (older protocols don't have a dedicated opcode for bytes and are
2842 # too inefficient)
2843
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002844 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002845 def test_huge_bytes_32b(self, size):
2846 data = b"abcd" * (size // 4)
2847 try:
2848 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002849 if proto < 3:
2850 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002851 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002852 try:
2853 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002854 header = (pickle.BINBYTES +
2855 struct.pack("<I", len(data)))
2856 data_start = pickled.index(data)
2857 self.assertEqual(
2858 header,
2859 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002860 finally:
2861 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002862 finally:
2863 data = None
2864
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002865 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002866 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002867 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002868 try:
2869 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002870 if proto < 3:
2871 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002872 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002873 if proto == 3:
2874 # Protocol 3 does not support large bytes objects.
2875 # Verify that we do not crash when processing one.
2876 with self.assertRaises((ValueError, OverflowError)):
2877 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002878 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002879 try:
2880 pickled = self.dumps(data, protocol=proto)
2881 header = (pickle.BINBYTES8 +
2882 struct.pack("<Q", len(data)))
2883 data_start = pickled.index(data)
2884 self.assertEqual(
2885 header,
2886 pickled[data_start-len(header):data_start])
2887 finally:
2888 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002889 finally:
2890 data = None
2891
2892 # All protocols use 1-byte per printable ASCII character; we add another
2893 # byte because the encoded form has to be copied into the internal buffer.
2894
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002895 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002896 def test_huge_str_32b(self, size):
2897 data = "abcd" * (size // 4)
2898 try:
2899 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002900 if proto == 0:
2901 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002902 with self.subTest(proto=proto):
2903 try:
2904 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002905 header = (pickle.BINUNICODE +
2906 struct.pack("<I", len(data)))
2907 data_start = pickled.index(b'abcd')
2908 self.assertEqual(
2909 header,
2910 pickled[data_start-len(header):data_start])
2911 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2912 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002913 finally:
2914 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002915 finally:
2916 data = None
2917
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002918 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2919 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2920 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002921
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002922 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002923 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002924 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002925 try:
2926 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002927 if proto == 0:
2928 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002929 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002930 if proto < 4:
2931 with self.assertRaises((ValueError, OverflowError)):
2932 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002933 continue
2934 try:
2935 pickled = self.dumps(data, protocol=proto)
2936 header = (pickle.BINUNICODE8 +
2937 struct.pack("<Q", len(data)))
2938 data_start = pickled.index(b'abcd')
2939 self.assertEqual(
2940 header,
2941 pickled[data_start-len(header):data_start])
2942 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2943 pickled.index(b"abcd")), len(data))
2944 finally:
2945 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002946 finally:
2947 data = None
2948
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002949
Guido van Rossum2a30b212003-02-18 22:41:24 +00002950# Test classes for reduce_ex
2951
2952class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002953 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002954 _reduce_called = 0
2955 def __reduce__(self):
2956 self._reduce_called = 1
2957 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002958
2959class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002960 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002961 _proto = None
2962 def __reduce_ex__(self, proto):
2963 self._proto = proto
2964 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002965
2966class REX_three(object):
2967 _proto = None
2968 def __reduce_ex__(self, proto):
2969 self._proto = proto
2970 return REX_two, ()
2971 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002972 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002973
Guido van Rossumd8faa362007-04-27 19:54:29 +00002974class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002975 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002976 _proto = None
2977 def __reduce_ex__(self, proto):
2978 self._proto = proto
2979 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002980
2981class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002982 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002983 _reduce_called = 0
2984 def __reduce__(self):
2985 self._reduce_called = 1
2986 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002987
2988class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002989 """This class is used to check the 4th argument (list iterator) of
2990 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002991 """
2992 def __init__(self, items=None):
2993 self.items = items if items is not None else []
2994 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02002995 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002996 def append(self, item):
2997 self.items.append(item)
2998 def __reduce__(self):
2999 return type(self), (), None, iter(self.items), None
3000
3001class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003002 """This class is used to check the 5th argument (dict iterator) of
3003 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003004 """
3005 def __init__(self, table=None):
3006 self.table = table if table is not None else {}
3007 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003008 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003009 def __setitem__(self, key, value):
3010 self.table[key] = value
3011 def __reduce__(self):
3012 return type(self), (), None, None, iter(self.table.items())
3013
Guido van Rossumd8faa362007-04-27 19:54:29 +00003014
Guido van Rossum2a30b212003-02-18 22:41:24 +00003015# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003016
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003017class MyInt(int):
3018 sample = 1
3019
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003020class MyFloat(float):
3021 sample = 1.0
3022
3023class MyComplex(complex):
3024 sample = 1.0 + 0.0j
3025
3026class MyStr(str):
3027 sample = "hello"
3028
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003029class MyUnicode(str):
3030 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003031
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003032class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003033 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003034
3035class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003036 sample = [1, 2, 3]
3037
3038class MyDict(dict):
3039 sample = {"a": 1, "b": 2}
3040
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003041class MySet(set):
3042 sample = {"a", "b"}
3043
3044class MyFrozenSet(frozenset):
3045 sample = frozenset({"a", "b"})
3046
Mark Dickinson5c2db372009-12-05 20:28:34 +00003047myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003048 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003049 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003050 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003051
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003052
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003053class SlotList(MyList):
3054 __slots__ = ["foo"]
3055
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003056class SimpleNewObj(int):
3057 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003058 # raise an error, to make sure this isn't called
3059 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003060 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003061 return int(self) == int(other) and self.__dict__ == other.__dict__
3062
3063class ComplexNewObj(SimpleNewObj):
3064 def __getnewargs__(self):
3065 return ('%X' % self, 16)
3066
3067class ComplexNewObjEx(SimpleNewObj):
3068 def __getnewargs_ex__(self):
3069 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003070
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003071class BadGetattr:
3072 def __getattr__(self, key):
3073 self.foo
3074
Collin Winter771d8342009-04-16 03:18:06 +00003075
Jeremy Hylton66426532001-10-15 21:38:56 +00003076class AbstractPickleModuleTests(unittest.TestCase):
3077
3078 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003079 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003080 try:
3081 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003082 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003083 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003084 support.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003085
3086 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003087 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003088 try:
3089 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003090 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003091 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003092 support.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003093
Collin Winter771d8342009-04-16 03:18:06 +00003094 def test_load_from_and_dump_to_file(self):
3095 stream = io.BytesIO()
3096 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003097 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003098 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003099 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003100 self.assertEqual(unpickled, data)
3101
Tim Petersc0c93702003-02-13 19:30:57 +00003102 def test_highest_protocol(self):
3103 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003104 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003105
Martin v. Löwis544f1192004-07-27 05:22:33 +00003106 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003107 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003108 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003109 self.dump(123, f, -1)
3110 self.dump(123, file=f, protocol=-1)
3111 self.dumps(123, -1)
3112 self.dumps(123, protocol=-1)
3113 self.Pickler(f, -1)
3114 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003115
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003116 def test_dump_text_file(self):
3117 f = open(TESTFN, "w")
3118 try:
3119 for proto in protocols:
3120 self.assertRaises(TypeError, self.dump, 123, f, proto)
3121 finally:
3122 f.close()
3123 support.unlink(TESTFN)
3124
3125 def test_incomplete_input(self):
3126 s = io.BytesIO(b"X''.")
3127 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3128
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003129 def test_bad_init(self):
3130 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003131 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003132 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003133 def __init__(self): pass
3134
Serhiy Storchaka65452562017-11-15 14:01:08 +02003135 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003136 def __init__(self): pass
3137
3138 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3139 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3140
Antoine Pitrou91f43802019-05-26 17:10:09 +02003141 def check_dumps_loads_oob_buffers(self, dumps, loads):
3142 # No need to do the full gamut of tests here, just enough to
3143 # check that dumps() and loads() redirect their arguments
3144 # to the underlying Pickler and Unpickler, respectively.
3145 obj = ZeroCopyBytes(b"foo")
3146
3147 for proto in range(0, 5):
3148 # Need protocol >= 5 for buffer_callback
3149 with self.assertRaises(ValueError):
3150 dumps(obj, protocol=proto,
3151 buffer_callback=[].append)
3152 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3153 buffers = []
3154 buffer_callback = buffers.append
3155 data = dumps(obj, protocol=proto,
3156 buffer_callback=buffer_callback)
3157 self.assertNotIn(b"foo", data)
3158 self.assertEqual(bytes(buffers[0]), b"foo")
3159 # Need buffers argument to unpickle properly
3160 with self.assertRaises(pickle.UnpicklingError):
3161 loads(data)
3162 new = loads(data, buffers=buffers)
3163 self.assertIs(new, obj)
3164
3165 def test_dumps_loads_oob_buffers(self):
3166 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3167 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3168
3169 def test_dump_load_oob_buffers(self):
3170 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3171 def dumps(obj, **kwargs):
3172 f = io.BytesIO()
3173 self.dump(obj, f, **kwargs)
3174 return f.getvalue()
3175
3176 def loads(data, **kwargs):
3177 f = io.BytesIO(data)
3178 return self.load(f, **kwargs)
3179
3180 self.check_dumps_loads_oob_buffers(dumps, loads)
3181
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003182
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003183class AbstractPersistentPicklerTests(unittest.TestCase):
3184
3185 # This class defines persistent_id() and persistent_load()
3186 # functions that should be used by the pickler. All even integers
3187 # are pickled using persistent ids.
3188
3189 def persistent_id(self, object):
3190 if isinstance(object, int) and object % 2 == 0:
3191 self.id_count += 1
3192 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003193 elif object == "test_false_value":
3194 self.false_count += 1
3195 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003196 else:
3197 return None
3198
3199 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003200 if not oid:
3201 self.load_false_count += 1
3202 return "test_false_value"
3203 else:
3204 self.load_count += 1
3205 object = int(oid)
3206 assert object % 2 == 0
3207 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003208
3209 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003210 L = list(range(10)) + ["test_false_value"]
3211 for proto in protocols:
3212 self.id_count = 0
3213 self.false_count = 0
3214 self.load_false_count = 0
3215 self.load_count = 0
3216 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3217 self.assertEqual(self.id_count, 5)
3218 self.assertEqual(self.false_count, 1)
3219 self.assertEqual(self.load_count, 5)
3220 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003221
Collin Winter771d8342009-04-16 03:18:06 +00003222
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003223class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3224
3225 def persistent_id(self, obj):
3226 return obj
3227
3228 def persistent_load(self, pid):
3229 return pid
3230
3231 def _check_return_correct_type(self, obj, proto):
3232 unpickled = self.loads(self.dumps(obj, proto))
3233 self.assertIsInstance(unpickled, type(obj))
3234 self.assertEqual(unpickled, obj)
3235
3236 def test_return_correct_type(self):
3237 for proto in protocols:
3238 # Protocol 0 supports only ASCII strings.
3239 if proto == 0:
3240 self._check_return_correct_type("abc", 0)
3241 else:
3242 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3243 self._check_return_correct_type(obj, proto)
3244
3245 def test_protocol0_is_ascii_only(self):
3246 non_ascii_str = "\N{EMPTY SET}"
3247 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3248 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3249 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3250
3251
Collin Winter771d8342009-04-16 03:18:06 +00003252class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3253
3254 pickler_class = None
3255 unpickler_class = None
3256
3257 def setUp(self):
3258 assert self.pickler_class
3259 assert self.unpickler_class
3260
3261 def test_clear_pickler_memo(self):
3262 # To test whether clear_memo() has any effect, we pickle an object,
3263 # then pickle it again without clearing the memo; the two serialized
3264 # forms should be different. If we clear_memo() and then pickle the
3265 # object again, the third serialized form should be identical to the
3266 # first one we obtained.
3267 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003268 for proto in protocols:
3269 f = io.BytesIO()
3270 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003271
Serhiy Storchakac8695292018-04-04 00:11:27 +03003272 pickler.dump(data)
3273 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003274
Serhiy Storchakac8695292018-04-04 00:11:27 +03003275 # Reset BytesIO object.
3276 f.seek(0)
3277 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003278
Serhiy Storchakac8695292018-04-04 00:11:27 +03003279 pickler.dump(data)
3280 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003281
Serhiy Storchakac8695292018-04-04 00:11:27 +03003282 # Reset the Pickler and BytesIO objects.
3283 pickler.clear_memo()
3284 f.seek(0)
3285 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003286
Serhiy Storchakac8695292018-04-04 00:11:27 +03003287 pickler.dump(data)
3288 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003289
Serhiy Storchakac8695292018-04-04 00:11:27 +03003290 self.assertNotEqual(first_pickled, second_pickled)
3291 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003292
3293 def test_priming_pickler_memo(self):
3294 # Verify that we can set the Pickler's memo attribute.
3295 data = ["abcdefg", "abcdefg", 44]
3296 f = io.BytesIO()
3297 pickler = self.pickler_class(f)
3298
3299 pickler.dump(data)
3300 first_pickled = f.getvalue()
3301
3302 f = io.BytesIO()
3303 primed = self.pickler_class(f)
3304 primed.memo = pickler.memo
3305
3306 primed.dump(data)
3307 primed_pickled = f.getvalue()
3308
3309 self.assertNotEqual(first_pickled, primed_pickled)
3310
3311 def test_priming_unpickler_memo(self):
3312 # Verify that we can set the Unpickler's memo attribute.
3313 data = ["abcdefg", "abcdefg", 44]
3314 f = io.BytesIO()
3315 pickler = self.pickler_class(f)
3316
3317 pickler.dump(data)
3318 first_pickled = f.getvalue()
3319
3320 f = io.BytesIO()
3321 primed = self.pickler_class(f)
3322 primed.memo = pickler.memo
3323
3324 primed.dump(data)
3325 primed_pickled = f.getvalue()
3326
3327 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3328 unpickled_data1 = unpickler.load()
3329
3330 self.assertEqual(unpickled_data1, data)
3331
3332 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3333 primed.memo = unpickler.memo
3334 unpickled_data2 = primed.load()
3335
3336 primed.memo.clear()
3337
3338 self.assertEqual(unpickled_data2, data)
3339 self.assertTrue(unpickled_data2 is unpickled_data1)
3340
3341 def test_reusing_unpickler_objects(self):
3342 data1 = ["abcdefg", "abcdefg", 44]
3343 f = io.BytesIO()
3344 pickler = self.pickler_class(f)
3345 pickler.dump(data1)
3346 pickled1 = f.getvalue()
3347
3348 data2 = ["abcdefg", 44, 44]
3349 f = io.BytesIO()
3350 pickler = self.pickler_class(f)
3351 pickler.dump(data2)
3352 pickled2 = f.getvalue()
3353
3354 f = io.BytesIO()
3355 f.write(pickled1)
3356 f.seek(0)
3357 unpickler = self.unpickler_class(f)
3358 self.assertEqual(unpickler.load(), data1)
3359
3360 f.seek(0)
3361 f.truncate()
3362 f.write(pickled2)
3363 f.seek(0)
3364 self.assertEqual(unpickler.load(), data2)
3365
Antoine Pitrou04248a82010-10-12 20:51:21 +00003366 def _check_multiple_unpicklings(self, ioclass):
3367 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003368 with self.subTest(proto=proto):
3369 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3370 f = ioclass()
3371 pickler = self.pickler_class(f, protocol=proto)
3372 pickler.dump(data1)
3373 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003374
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003375 N = 5
3376 f = ioclass(pickled * N)
3377 unpickler = self.unpickler_class(f)
3378 for i in range(N):
3379 if f.seekable():
3380 pos = f.tell()
3381 self.assertEqual(unpickler.load(), data1)
3382 if f.seekable():
3383 self.assertEqual(f.tell(), pos + len(pickled))
3384 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003385
3386 def test_multiple_unpicklings_seekable(self):
3387 self._check_multiple_unpicklings(io.BytesIO)
3388
3389 def test_multiple_unpicklings_unseekable(self):
3390 self._check_multiple_unpicklings(UnseekableIO)
3391
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003392 def test_unpickling_buffering_readline(self):
3393 # Issue #12687: the unpickler's buffering logic could fail with
3394 # text mode opcodes.
3395 data = list(range(10))
3396 for proto in protocols:
3397 for buf_size in range(1, 11):
3398 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3399 pickler = self.pickler_class(f, protocol=proto)
3400 pickler.dump(data)
3401 f.seek(0)
3402 unpickler = self.unpickler_class(f)
3403 self.assertEqual(unpickler.load(), data)
3404
Collin Winter771d8342009-04-16 03:18:06 +00003405
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003406# Tests for dispatch_table attribute
3407
3408REDUCE_A = 'reduce_A'
3409
3410class AAA(object):
3411 def __reduce__(self):
3412 return str, (REDUCE_A,)
3413
3414class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003415 def __init__(self):
3416 # Add an instance attribute to enable state-saving routines at pickling
3417 # time.
3418 self.a = "some attribute"
3419
3420 def __setstate__(self, state):
3421 self.a = "BBB.__setstate__"
3422
3423
3424def setstate_bbb(obj, state):
3425 """Custom state setter for BBB objects
3426
3427 Such callable may be created by other persons than the ones who created the
3428 BBB class. If passed as the state_setter item of a custom reducer, this
3429 allows for custom state setting behavior of BBB objects. One can think of
3430 it as the analogous of list_setitems or dict_setitems but for foreign
3431 classes/functions.
3432 """
3433 obj.a = "custom state_setter"
3434
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003435
Pierre Glaser289f1f82019-05-08 23:08:25 +02003436
3437class AbstractCustomPicklerClass:
3438 """Pickler implementing a reducing hook using reducer_override."""
3439 def reducer_override(self, obj):
3440 obj_name = getattr(obj, "__name__", None)
3441
3442 if obj_name == 'f':
3443 # asking the pickler to save f as 5
3444 return int, (5, )
3445
3446 if obj_name == 'MyClass':
3447 return str, ('some str',)
3448
3449 elif obj_name == 'g':
3450 # in this case, the callback returns an invalid result (not a 2-5
3451 # tuple or a string), the pickler should raise a proper error.
3452 return False
3453
3454 elif obj_name == 'h':
3455 # Simulate a case when the reducer fails. The error should
3456 # be propagated to the original ``dump`` call.
3457 raise ValueError('The reducer just failed')
3458
3459 return NotImplemented
3460
3461class AbstractHookTests(unittest.TestCase):
3462 def test_pickler_hook(self):
3463 # test the ability of a custom, user-defined CPickler subclass to
3464 # override the default reducing routines of any type using the method
3465 # reducer_override
3466
3467 def f():
3468 pass
3469
3470 def g():
3471 pass
3472
3473 def h():
3474 pass
3475
3476 class MyClass:
3477 pass
3478
3479 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3480 with self.subTest(proto=proto):
3481 bio = io.BytesIO()
3482 p = self.pickler_class(bio, proto)
3483
3484 p.dump([f, MyClass, math.log])
3485 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3486
3487 self.assertEqual(new_f, 5)
3488 self.assertEqual(some_str, 'some str')
3489 # math.log does not have its usual reducer overriden, so the
3490 # custom reduction callback should silently direct the pickler
3491 # to the default pickling by attribute, by returning
3492 # NotImplemented
3493 self.assertIs(math_log, math.log)
3494
3495 with self.assertRaises(pickle.PicklingError):
3496 p.dump(g)
3497
3498 with self.assertRaisesRegex(
3499 ValueError, 'The reducer just failed'):
3500 p.dump(h)
3501
3502
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003503class AbstractDispatchTableTests(unittest.TestCase):
3504
3505 def test_default_dispatch_table(self):
3506 # No dispatch_table attribute by default
3507 f = io.BytesIO()
3508 p = self.pickler_class(f, 0)
3509 with self.assertRaises(AttributeError):
3510 p.dispatch_table
3511 self.assertFalse(hasattr(p, 'dispatch_table'))
3512
3513 def test_class_dispatch_table(self):
3514 # A dispatch_table attribute can be specified class-wide
3515 dt = self.get_dispatch_table()
3516
3517 class MyPickler(self.pickler_class):
3518 dispatch_table = dt
3519
3520 def dumps(obj, protocol=None):
3521 f = io.BytesIO()
3522 p = MyPickler(f, protocol)
3523 self.assertEqual(p.dispatch_table, dt)
3524 p.dump(obj)
3525 return f.getvalue()
3526
3527 self._test_dispatch_table(dumps, dt)
3528
3529 def test_instance_dispatch_table(self):
3530 # A dispatch_table attribute can also be specified instance-wide
3531 dt = self.get_dispatch_table()
3532
3533 def dumps(obj, protocol=None):
3534 f = io.BytesIO()
3535 p = self.pickler_class(f, protocol)
3536 p.dispatch_table = dt
3537 self.assertEqual(p.dispatch_table, dt)
3538 p.dump(obj)
3539 return f.getvalue()
3540
3541 self._test_dispatch_table(dumps, dt)
3542
3543 def _test_dispatch_table(self, dumps, dispatch_table):
3544 def custom_load_dump(obj):
3545 return pickle.loads(dumps(obj, 0))
3546
3547 def default_load_dump(obj):
3548 return pickle.loads(pickle.dumps(obj, 0))
3549
3550 # pickling complex numbers using protocol 0 relies on copyreg
3551 # so check pickling a complex number still works
3552 z = 1 + 2j
3553 self.assertEqual(custom_load_dump(z), z)
3554 self.assertEqual(default_load_dump(z), z)
3555
3556 # modify pickling of complex
3557 REDUCE_1 = 'reduce_1'
3558 def reduce_1(obj):
3559 return str, (REDUCE_1,)
3560 dispatch_table[complex] = reduce_1
3561 self.assertEqual(custom_load_dump(z), REDUCE_1)
3562 self.assertEqual(default_load_dump(z), z)
3563
3564 # check picklability of AAA and BBB
3565 a = AAA()
3566 b = BBB()
3567 self.assertEqual(custom_load_dump(a), REDUCE_A)
3568 self.assertIsInstance(custom_load_dump(b), BBB)
3569 self.assertEqual(default_load_dump(a), REDUCE_A)
3570 self.assertIsInstance(default_load_dump(b), BBB)
3571
3572 # modify pickling of BBB
3573 dispatch_table[BBB] = reduce_1
3574 self.assertEqual(custom_load_dump(a), REDUCE_A)
3575 self.assertEqual(custom_load_dump(b), REDUCE_1)
3576 self.assertEqual(default_load_dump(a), REDUCE_A)
3577 self.assertIsInstance(default_load_dump(b), BBB)
3578
3579 # revert pickling of BBB and modify pickling of AAA
3580 REDUCE_2 = 'reduce_2'
3581 def reduce_2(obj):
3582 return str, (REDUCE_2,)
3583 dispatch_table[AAA] = reduce_2
3584 del dispatch_table[BBB]
3585 self.assertEqual(custom_load_dump(a), REDUCE_2)
3586 self.assertIsInstance(custom_load_dump(b), BBB)
3587 self.assertEqual(default_load_dump(a), REDUCE_A)
3588 self.assertIsInstance(default_load_dump(b), BBB)
3589
Pierre Glaser65d98d02019-05-08 21:40:25 +02003590 # End-to-end testing of save_reduce with the state_setter keyword
3591 # argument. This is a dispatch_table test as the primary goal of
3592 # state_setter is to tweak objects reduction behavior.
3593 # In particular, state_setter is useful when the default __setstate__
3594 # behavior is not flexible enough.
3595
3596 # No custom reducer for b has been registered for now, so
3597 # BBB.__setstate__ should be used at unpickling time
3598 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3599
3600 def reduce_bbb(obj):
3601 return BBB, (), obj.__dict__, None, None, setstate_bbb
3602
3603 dispatch_table[BBB] = reduce_bbb
3604
3605 # The custom reducer reduce_bbb includes a state setter, that should
3606 # have priority over BBB.__setstate__
3607 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3608
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003609
Guido van Rossum98297ee2007-11-06 21:34:58 +00003610if __name__ == "__main__":
3611 # Print some stuff that can be used to rewrite DATA{0,1,2}
3612 from pickletools import dis
3613 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003614 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003615 p = pickle.dumps(x, i)
3616 print("DATA{0} = (".format(i))
3617 for j in range(0, len(p), 20):
3618 b = bytes(p[j:j+20])
3619 print(" {0!r}".format(b))
3620 print(")")
3621 print()
3622 print("# Disassembly of DATA{0}".format(i))
3623 print("DATA{0}_DIS = \"\"\"\\".format(i))
3624 dis(p)
3625 print("\"\"\"")
3626 print()