blob: 6ef4c8989f55bfb4d73c28381e53b22a96aa3fdb [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
Antoine Pitrou9f378722020-02-23 23:33:53 +010076class MinimalIO(object):
77 """
78 A file-like object that doesn't support readinto().
79 """
80 def __init__(self, *args):
81 self._bio = io.BytesIO(*args)
82 self.getvalue = self._bio.getvalue
83 self.read = self._bio.read
84 self.readline = self._bio.readline
85 self.write = self._bio.write
86
87
Tim Peters3e667d52003-02-04 21:47:44 +000088# We can't very well test the extension registry without putting known stuff
89# in it, but we have to be careful to restore its original state. Code
90# should do this:
91#
92# e = ExtensionSaver(extension_code)
93# try:
94# fiddle w/ the extension registry's stuff for extension_code
95# finally:
96# e.restore()
97
98class ExtensionSaver:
99 # Remember current registration for code (if any), and remove it (if
100 # there is one).
101 def __init__(self, code):
102 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000103 if code in copyreg._inverted_registry:
104 self.pair = copyreg._inverted_registry[code]
105 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000106 else:
107 self.pair = None
108
109 # Restore previous registration for code.
110 def restore(self):
111 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000112 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000113 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000114 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000115 pair = self.pair
116 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000117 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000118
Jeremy Hylton66426532001-10-15 21:38:56 +0000119class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000120 def __eq__(self, other):
121 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000122
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000123class D(C):
124 def __init__(self, arg):
125 pass
126
127class E(C):
128 def __getinitargs__(self):
129 return ()
130
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100131class H(object):
132 pass
133
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200134# Hashable mutable key
135class K(object):
136 def __init__(self, value):
137 self.value = value
138
139 def __reduce__(self):
140 # Shouldn't support the recursion itself
141 return K, (self.value,)
142
Jeremy Hylton66426532001-10-15 21:38:56 +0000143import __main__
144__main__.C = C
145C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000146__main__.D = D
147D.__module__ = "__main__"
148__main__.E = E
149E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100150__main__.H = H
151H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200152__main__.K = K
153K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000154
155class myint(int):
156 def __init__(self, x):
157 self.str = str(x)
158
159class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000160
Jeremy Hylton66426532001-10-15 21:38:56 +0000161 def __init__(self, a, b):
162 self.a = a
163 self.b = b
164
165 def __getinitargs__(self):
166 return self.a, self.b
167
Guido van Rossum04a86612001-12-19 16:58:54 +0000168class metaclass(type):
169 pass
170
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000171class use_metaclass(object, metaclass=metaclass):
172 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000173
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200174class pickling_metaclass(type):
175 def __eq__(self, other):
176 return (type(self) == type(other) and
177 self.reduce_args == other.reduce_args)
178
179 def __reduce__(self):
180 return (create_dynamic_class, self.reduce_args)
181
182def create_dynamic_class(name, bases):
183 result = pickling_metaclass(name, bases, dict())
184 result.reduce_args = (name, bases)
185 return result
186
Antoine Pitrou91f43802019-05-26 17:10:09 +0200187
188class ZeroCopyBytes(bytes):
189 readonly = True
190 c_contiguous = True
191 f_contiguous = True
192 zero_copy_reconstruct = True
193
194 def __reduce_ex__(self, protocol):
195 if protocol >= 5:
196 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
197 else:
198 return type(self)._reconstruct, (bytes(self),)
199
200 def __repr__(self):
201 return "{}({!r})".format(self.__class__.__name__, bytes(self))
202
203 __str__ = __repr__
204
205 @classmethod
206 def _reconstruct(cls, obj):
207 with memoryview(obj) as m:
208 obj = m.obj
209 if type(obj) is cls:
210 # Zero-copy
211 return obj
212 else:
213 return cls(obj)
214
215
216class ZeroCopyBytearray(bytearray):
217 readonly = False
218 c_contiguous = True
219 f_contiguous = True
220 zero_copy_reconstruct = True
221
222 def __reduce_ex__(self, protocol):
223 if protocol >= 5:
224 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
225 else:
226 return type(self)._reconstruct, (bytes(self),)
227
228 def __repr__(self):
229 return "{}({!r})".format(self.__class__.__name__, bytes(self))
230
231 __str__ = __repr__
232
233 @classmethod
234 def _reconstruct(cls, obj):
235 with memoryview(obj) as m:
236 obj = m.obj
237 if type(obj) is cls:
238 # Zero-copy
239 return obj
240 else:
241 return cls(obj)
242
243
244if _testbuffer is not None:
245
246 class PicklableNDArray:
247 # A not-really-zero-copy picklable ndarray, as the ndarray()
248 # constructor doesn't allow for it
249
250 zero_copy_reconstruct = False
251
252 def __init__(self, *args, **kwargs):
253 self.array = _testbuffer.ndarray(*args, **kwargs)
254
255 def __getitem__(self, idx):
256 cls = type(self)
257 new = cls.__new__(cls)
258 new.array = self.array[idx]
259 return new
260
261 @property
262 def readonly(self):
263 return self.array.readonly
264
265 @property
266 def c_contiguous(self):
267 return self.array.c_contiguous
268
269 @property
270 def f_contiguous(self):
271 return self.array.f_contiguous
272
273 def __eq__(self, other):
274 if not isinstance(other, PicklableNDArray):
275 return NotImplemented
276 return (other.array.format == self.array.format and
277 other.array.shape == self.array.shape and
278 other.array.strides == self.array.strides and
279 other.array.readonly == self.array.readonly and
280 other.array.tobytes() == self.array.tobytes())
281
282 def __ne__(self, other):
283 if not isinstance(other, PicklableNDArray):
284 return NotImplemented
285 return not (self == other)
286
287 def __repr__(self):
288 return (f"{type(self)}(shape={self.array.shape},"
289 f"strides={self.array.strides}, "
290 f"bytes={self.array.tobytes()})")
291
292 def __reduce_ex__(self, protocol):
293 if not self.array.contiguous:
294 raise NotImplementedError("Reconstructing a non-contiguous "
295 "ndarray does not seem possible")
296 ndarray_kwargs = {"shape": self.array.shape,
297 "strides": self.array.strides,
298 "format": self.array.format,
299 "flags": (0 if self.readonly
300 else _testbuffer.ND_WRITABLE)}
301 pb = pickle.PickleBuffer(self.array)
302 if protocol >= 5:
303 return (type(self)._reconstruct,
304 (pb, ndarray_kwargs))
305 else:
306 # Need to serialize the bytes in physical order
307 with pb.raw() as m:
308 return (type(self)._reconstruct,
309 (m.tobytes(), ndarray_kwargs))
310
311 @classmethod
312 def _reconstruct(cls, obj, kwargs):
313 with memoryview(obj) as m:
314 # For some reason, ndarray() wants a list of integers...
315 # XXX This only works if format == 'B'
316 items = list(m.tobytes())
317 return cls(items, **kwargs)
318
319
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300320# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000321# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000322
Guido van Rossum98297ee2007-11-06 21:34:58 +0000323DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200324 b'(lp0\nL0L\naL1L\naF2.0\n'
325 b'ac__builtin__\ncomple'
326 b'x\np1\n(F3.0\nF0.0\ntp2\n'
327 b'Rp3\naL1L\naL-1L\naL255'
328 b'L\naL-255L\naL-256L\naL'
329 b'65535L\naL-65535L\naL-'
330 b'65536L\naL2147483647L'
331 b'\naL-2147483647L\naL-2'
332 b'147483648L\na(Vabc\np4'
333 b'\ng4\nccopy_reg\n_recon'
334 b'structor\np5\n(c__main'
335 b'__\nC\np6\nc__builtin__'
336 b'\nobject\np7\nNtp8\nRp9\n'
337 b'(dp10\nVfoo\np11\nL1L\ns'
338 b'Vbar\np12\nL2L\nsbg9\ntp'
339 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000340)
Tim Peterse9358162001-01-22 22:05:20 +0000341
Guido van Rossum98297ee2007-11-06 21:34:58 +0000342# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000343DATA0_DIS = """\
344 0: ( MARK
345 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000346 2: p PUT 0
347 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000348 9: a APPEND
349 10: L LONG 1
350 14: a APPEND
351 15: F FLOAT 2.0
352 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200353 21: c GLOBAL '__builtin__ complex'
354 42: p PUT 1
355 45: ( MARK
356 46: F FLOAT 3.0
357 51: F FLOAT 0.0
358 56: t TUPLE (MARK at 45)
359 57: p PUT 2
360 60: R REDUCE
361 61: p PUT 3
362 64: a APPEND
363 65: L LONG 1
364 69: a APPEND
365 70: L LONG -1
366 75: a APPEND
367 76: L LONG 255
368 82: a APPEND
369 83: L LONG -255
370 90: a APPEND
371 91: L LONG -256
372 98: a APPEND
373 99: L LONG 65535
374 107: a APPEND
375 108: L LONG -65535
376 117: a APPEND
377 118: L LONG -65536
378 127: a APPEND
379 128: L LONG 2147483647
380 141: a APPEND
381 142: L LONG -2147483647
382 156: a APPEND
383 157: L LONG -2147483648
384 171: a APPEND
385 172: ( MARK
386 173: V UNICODE 'abc'
387 178: p PUT 4
388 181: g GET 4
389 184: c GLOBAL 'copy_reg _reconstructor'
390 209: p PUT 5
391 212: ( MARK
392 213: c GLOBAL '__main__ C'
393 225: p PUT 6
394 228: c GLOBAL '__builtin__ object'
395 248: p PUT 7
396 251: N NONE
397 252: t TUPLE (MARK at 212)
398 253: p PUT 8
399 256: R REDUCE
400 257: p PUT 9
401 260: ( MARK
402 261: d DICT (MARK at 260)
403 262: p PUT 10
404 266: V UNICODE 'foo'
405 271: p PUT 11
406 275: L LONG 1
407 279: s SETITEM
408 280: V UNICODE 'bar'
409 285: p PUT 12
410 289: L LONG 2
411 293: s SETITEM
412 294: b BUILD
413 295: g GET 9
414 298: t TUPLE (MARK at 172)
415 299: p PUT 13
416 303: a APPEND
417 304: g GET 13
418 308: a APPEND
419 309: L LONG 5
420 313: a APPEND
421 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000422highest protocol among opcodes = 0
423"""
424
Guido van Rossum98297ee2007-11-06 21:34:58 +0000425DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200426 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
427 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000428 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
429 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
430 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
431 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200432 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000433 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200434 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000435 b'object\nq\x07Ntq\x08Rq\t}q\n('
436 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
437 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
438)
Tim Peters70b02d72003-02-02 17:26:40 +0000439
Guido van Rossum98297ee2007-11-06 21:34:58 +0000440# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000441DATA1_DIS = """\
442 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000443 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000444 3: ( MARK
445 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000446 6: K BININT1 1
447 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200448 17: c GLOBAL '__builtin__ complex'
449 38: q BINPUT 1
450 40: ( MARK
451 41: G BINFLOAT 3.0
452 50: G BINFLOAT 0.0
453 59: t TUPLE (MARK at 40)
454 60: q BINPUT 2
455 62: R REDUCE
456 63: q BINPUT 3
457 65: K BININT1 1
458 67: J BININT -1
459 72: K BININT1 255
460 74: J BININT -255
461 79: J BININT -256
462 84: M BININT2 65535
463 87: J BININT -65535
464 92: J BININT -65536
465 97: J BININT 2147483647
466 102: J BININT -2147483647
467 107: J BININT -2147483648
468 112: ( MARK
469 113: X BINUNICODE 'abc'
470 121: q BINPUT 4
471 123: h BINGET 4
472 125: c GLOBAL 'copy_reg _reconstructor'
473 150: q BINPUT 5
474 152: ( MARK
475 153: c GLOBAL '__main__ C'
476 165: q BINPUT 6
477 167: c GLOBAL '__builtin__ object'
478 187: q BINPUT 7
479 189: N NONE
480 190: t TUPLE (MARK at 152)
481 191: q BINPUT 8
482 193: R REDUCE
483 194: q BINPUT 9
484 196: } EMPTY_DICT
485 197: q BINPUT 10
486 199: ( MARK
487 200: X BINUNICODE 'foo'
488 208: q BINPUT 11
489 210: K BININT1 1
490 212: X BINUNICODE 'bar'
491 220: q BINPUT 12
492 222: K BININT1 2
493 224: u SETITEMS (MARK at 199)
494 225: b BUILD
495 226: h BINGET 9
496 228: t TUPLE (MARK at 112)
497 229: q BINPUT 13
498 231: h BINGET 13
499 233: K BININT1 5
500 235: e APPENDS (MARK at 3)
501 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000502highest protocol among opcodes = 1
503"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000504
Guido van Rossum98297ee2007-11-06 21:34:58 +0000505DATA2 = (
506 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200507 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000508 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
509 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
510 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
511 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
512 b'bcq\x04h\x04c__main__\nC\nq\x05'
513 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
514 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
515 b'\nK\x05e.'
516)
Tim Petersfc273752003-03-02 04:54:24 +0000517
Guido van Rossum98297ee2007-11-06 21:34:58 +0000518# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000519DATA2_DIS = """\
520 0: \x80 PROTO 2
521 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000522 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000523 5: ( MARK
524 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000525 8: K BININT1 1
526 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200527 19: c GLOBAL '__builtin__ complex'
528 40: q BINPUT 1
529 42: G BINFLOAT 3.0
530 51: G BINFLOAT 0.0
531 60: \x86 TUPLE2
532 61: q BINPUT 2
533 63: R REDUCE
534 64: q BINPUT 3
535 66: K BININT1 1
536 68: J BININT -1
537 73: K BININT1 255
538 75: J BININT -255
539 80: J BININT -256
540 85: M BININT2 65535
541 88: J BININT -65535
542 93: J BININT -65536
543 98: J BININT 2147483647
544 103: J BININT -2147483647
545 108: J BININT -2147483648
546 113: ( MARK
547 114: X BINUNICODE 'abc'
548 122: q BINPUT 4
549 124: h BINGET 4
550 126: c GLOBAL '__main__ C'
551 138: q BINPUT 5
552 140: ) EMPTY_TUPLE
553 141: \x81 NEWOBJ
554 142: q BINPUT 6
555 144: } EMPTY_DICT
556 145: q BINPUT 7
557 147: ( MARK
558 148: X BINUNICODE 'foo'
559 156: q BINPUT 8
560 158: K BININT1 1
561 160: X BINUNICODE 'bar'
562 168: q BINPUT 9
563 170: K BININT1 2
564 172: u SETITEMS (MARK at 147)
565 173: b BUILD
566 174: h BINGET 6
567 176: t TUPLE (MARK at 113)
568 177: q BINPUT 10
569 179: h BINGET 10
570 181: K BININT1 5
571 183: e APPENDS (MARK at 5)
572 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000573highest protocol among opcodes = 2
574"""
575
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300576DATA3 = (
577 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
578 b'builtins\ncomplex\nq\x01G'
579 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
580 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
581 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
582 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
583 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
584 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
585 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
586 b'e.'
587)
588
589# Disassembly of DATA3
590DATA3_DIS = """\
591 0: \x80 PROTO 3
592 2: ] EMPTY_LIST
593 3: q BINPUT 0
594 5: ( MARK
595 6: K BININT1 0
596 8: K BININT1 1
597 10: G BINFLOAT 2.0
598 19: c GLOBAL 'builtins complex'
599 37: q BINPUT 1
600 39: G BINFLOAT 3.0
601 48: G BINFLOAT 0.0
602 57: \x86 TUPLE2
603 58: q BINPUT 2
604 60: R REDUCE
605 61: q BINPUT 3
606 63: K BININT1 1
607 65: J BININT -1
608 70: K BININT1 255
609 72: J BININT -255
610 77: J BININT -256
611 82: M BININT2 65535
612 85: J BININT -65535
613 90: J BININT -65536
614 95: J BININT 2147483647
615 100: J BININT -2147483647
616 105: J BININT -2147483648
617 110: ( MARK
618 111: X BINUNICODE 'abc'
619 119: q BINPUT 4
620 121: h BINGET 4
621 123: c GLOBAL '__main__ C'
622 135: q BINPUT 5
623 137: ) EMPTY_TUPLE
624 138: \x81 NEWOBJ
625 139: q BINPUT 6
626 141: } EMPTY_DICT
627 142: q BINPUT 7
628 144: ( MARK
629 145: X BINUNICODE 'bar'
630 153: q BINPUT 8
631 155: K BININT1 2
632 157: X BINUNICODE 'foo'
633 165: q BINPUT 9
634 167: K BININT1 1
635 169: u SETITEMS (MARK at 144)
636 170: b BUILD
637 171: h BINGET 6
638 173: t TUPLE (MARK at 110)
639 174: q BINPUT 10
640 176: h BINGET 10
641 178: K BININT1 5
642 180: e APPENDS (MARK at 5)
643 181: . STOP
644highest protocol among opcodes = 2
645"""
646
647DATA4 = (
648 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
649 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
650 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
651 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
652 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
653 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
654 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
655 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
656 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
657)
658
659# Disassembly of DATA4
660DATA4_DIS = """\
661 0: \x80 PROTO 4
662 2: \x95 FRAME 168
663 11: ] EMPTY_LIST
664 12: \x94 MEMOIZE
665 13: ( MARK
666 14: K BININT1 0
667 16: K BININT1 1
668 18: G BINFLOAT 2.0
669 27: \x8c SHORT_BINUNICODE 'builtins'
670 37: \x94 MEMOIZE
671 38: \x8c SHORT_BINUNICODE 'complex'
672 47: \x94 MEMOIZE
673 48: \x93 STACK_GLOBAL
674 49: \x94 MEMOIZE
675 50: G BINFLOAT 3.0
676 59: G BINFLOAT 0.0
677 68: \x86 TUPLE2
678 69: \x94 MEMOIZE
679 70: R REDUCE
680 71: \x94 MEMOIZE
681 72: K BININT1 1
682 74: J BININT -1
683 79: K BININT1 255
684 81: J BININT -255
685 86: J BININT -256
686 91: M BININT2 65535
687 94: J BININT -65535
688 99: J BININT -65536
689 104: J BININT 2147483647
690 109: J BININT -2147483647
691 114: J BININT -2147483648
692 119: ( MARK
693 120: \x8c SHORT_BINUNICODE 'abc'
694 125: \x94 MEMOIZE
695 126: h BINGET 6
696 128: \x8c SHORT_BINUNICODE '__main__'
697 138: \x94 MEMOIZE
698 139: \x8c SHORT_BINUNICODE 'C'
699 142: \x94 MEMOIZE
700 143: \x93 STACK_GLOBAL
701 144: \x94 MEMOIZE
702 145: ) EMPTY_TUPLE
703 146: \x81 NEWOBJ
704 147: \x94 MEMOIZE
705 148: } EMPTY_DICT
706 149: \x94 MEMOIZE
707 150: ( MARK
708 151: \x8c SHORT_BINUNICODE 'bar'
709 156: \x94 MEMOIZE
710 157: K BININT1 2
711 159: \x8c SHORT_BINUNICODE 'foo'
712 164: \x94 MEMOIZE
713 165: K BININT1 1
714 167: u SETITEMS (MARK at 150)
715 168: b BUILD
716 169: h BINGET 10
717 171: t TUPLE (MARK at 119)
718 172: \x94 MEMOIZE
719 173: h BINGET 14
720 175: K BININT1 5
721 177: e APPENDS (MARK at 13)
722 178: . STOP
723highest protocol among opcodes = 4
724"""
725
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000726# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300727DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000728
729# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300730DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000731
732# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300733DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
734 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
735 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
736 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
737 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
738 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000739
740# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300741DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000742
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100743python2_exceptions_without_args = (
744 ArithmeticError,
745 AssertionError,
746 AttributeError,
747 BaseException,
748 BufferError,
749 BytesWarning,
750 DeprecationWarning,
751 EOFError,
752 EnvironmentError,
753 Exception,
754 FloatingPointError,
755 FutureWarning,
756 GeneratorExit,
757 IOError,
758 ImportError,
759 ImportWarning,
760 IndentationError,
761 IndexError,
762 KeyError,
763 KeyboardInterrupt,
764 LookupError,
765 MemoryError,
766 NameError,
767 NotImplementedError,
768 OSError,
769 OverflowError,
770 PendingDeprecationWarning,
771 ReferenceError,
772 RuntimeError,
773 RuntimeWarning,
774 # StandardError is gone in Python 3, we map it to Exception
775 StopIteration,
776 SyntaxError,
777 SyntaxWarning,
778 SystemError,
779 SystemExit,
780 TabError,
781 TypeError,
782 UnboundLocalError,
783 UnicodeError,
784 UnicodeWarning,
785 UserWarning,
786 ValueError,
787 Warning,
788 ZeroDivisionError,
789)
790
791exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
792
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100793# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300794DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
795 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
796 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100797
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000798
Jeremy Hylton66426532001-10-15 21:38:56 +0000799def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000800 c = C()
801 c.foo = 1
802 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000803 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000804 # Append some integer test cases at cPickle.c's internal size
805 # cutoffs.
806 uint1max = 0xff
807 uint2max = 0xffff
808 int4max = 0x7fffffff
809 x.extend([1, -1,
810 uint1max, -uint1max, -uint1max-1,
811 uint2max, -uint2max, -uint2max-1,
812 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000813 y = ('abc', 'abc', c, c)
814 x.append(y)
815 x.append(y)
816 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000817 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000818
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100819
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300820class AbstractUnpickleTests(unittest.TestCase):
821 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100822
Jeremy Hylton66426532001-10-15 21:38:56 +0000823 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000824
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100825 def assert_is_copy(self, obj, objcopy, msg=None):
826 """Utility method to verify if two objects are copies of each others.
827 """
828 if msg is None:
829 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
830 self.assertEqual(obj, objcopy, msg=msg)
831 self.assertIs(type(obj), type(objcopy), msg=msg)
832 if hasattr(obj, '__dict__'):
833 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
834 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
835 if hasattr(obj, '__slots__'):
836 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
837 for slot in obj.__slots__:
838 self.assertEqual(
839 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
840 self.assertEqual(getattr(obj, slot, None),
841 getattr(objcopy, slot, None), msg=msg)
842
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200843 def check_unpickling_error(self, errors, data):
844 with self.subTest(data=data), \
845 self.assertRaises(errors):
846 try:
847 self.loads(data)
848 except BaseException as exc:
849 if support.verbose > 1:
850 print('%-32r - %s: %s' %
851 (data, exc.__class__.__name__, exc))
852 raise
853
Guido van Rossum98297ee2007-11-06 21:34:58 +0000854 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100855 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000856
857 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100858 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000859
860 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100861 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000862
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300863 def test_load_from_data3(self):
864 self.assert_is_copy(self._testdata, self.loads(DATA3))
865
866 def test_load_from_data4(self):
867 self.assert_is_copy(self._testdata, self.loads(DATA4))
868
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000869 def test_load_classic_instance(self):
870 # See issue5180. Test loading 2.x pickles that
871 # contain an instance of old style class.
872 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
873 xname = X.__name__.encode('ascii')
874 # Protocol 0 (text mode pickle):
875 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200876 0: ( MARK
877 1: i INST '__main__ X' (MARK at 0)
878 13: p PUT 0
879 16: ( MARK
880 17: d DICT (MARK at 16)
881 18: p PUT 1
882 21: b BUILD
883 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000884 """
885 pickle0 = (b"(i__main__\n"
886 b"X\n"
887 b"p0\n"
888 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100889 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000890
891 # Protocol 1 (binary mode pickle)
892 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200893 0: ( MARK
894 1: c GLOBAL '__main__ X'
895 13: q BINPUT 0
896 15: o OBJ (MARK at 0)
897 16: q BINPUT 1
898 18: } EMPTY_DICT
899 19: q BINPUT 2
900 21: b BUILD
901 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000902 """
903 pickle1 = (b'(c__main__\n'
904 b'X\n'
905 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100906 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000907
908 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
909 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200910 0: \x80 PROTO 2
911 2: ( MARK
912 3: c GLOBAL '__main__ X'
913 15: q BINPUT 0
914 17: o OBJ (MARK at 2)
915 18: q BINPUT 1
916 20: } EMPTY_DICT
917 21: q BINPUT 2
918 23: b BUILD
919 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000920 """
921 pickle2 = (b'\x80\x02(c__main__\n'
922 b'X\n'
923 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100924 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000925
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300926 def test_maxint64(self):
927 maxint64 = (1 << 63) - 1
928 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
929 got = self.loads(data)
930 self.assert_is_copy(maxint64, got)
931
932 # Try too with a bogus literal.
933 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200934 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300935
936 def test_unpickle_from_2x(self):
937 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300938 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300939 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300940 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300941 self.assertEqual(type(loaded), type(range(0)))
942 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300943 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300944 self.assertEqual(type(loaded), SimpleCookie)
945 self.assertEqual(list(loaded.keys()), ["key"])
946 self.assertEqual(loaded["key"].value, "value")
947
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300948 # Exception objects without arguments pickled from 2.x with protocol 2
949 for exc in python2_exceptions_without_args:
950 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300951 loaded = self.loads(data)
952 self.assertIs(type(loaded), exc)
953
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300954 # StandardError is mapped to Exception, test that separately
955 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300956 self.assertIs(type(loaded), Exception)
957
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300958 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300959 self.assertIs(type(loaded), UnicodeEncodeError)
960 self.assertEqual(loaded.object, "foo")
961 self.assertEqual(loaded.encoding, "ascii")
962 self.assertEqual(loaded.start, 0)
963 self.assertEqual(loaded.end, 1)
964 self.assertEqual(loaded.reason, "bad")
965
966 def test_load_python2_str_as_bytes(self):
967 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
968 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
969 encoding="bytes"), b'a\x00\xa0')
970 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
971 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
972 encoding="bytes"), b'a\x00\xa0')
973 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
974 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
975 encoding="bytes"), b'a\x00\xa0')
976
977 def test_load_python2_unicode_as_str(self):
978 # From Python 2: pickle.dumps(u'π', protocol=0)
979 self.assertEqual(self.loads(b'V\\u03c0\n.',
980 encoding='bytes'), 'π')
981 # From Python 2: pickle.dumps(u'π', protocol=1)
982 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
983 encoding="bytes"), 'π')
984 # From Python 2: pickle.dumps(u'π', protocol=2)
985 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
986 encoding="bytes"), 'π')
987
988 def test_load_long_python2_str_as_bytes(self):
989 # From Python 2: pickle.dumps('x' * 300, protocol=1)
990 self.assertEqual(self.loads(pickle.BINSTRING +
991 struct.pack("<I", 300) +
992 b'x' * 300 + pickle.STOP,
993 encoding='bytes'), b'x' * 300)
994
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300995 def test_constants(self):
996 self.assertIsNone(self.loads(b'N.'))
997 self.assertIs(self.loads(b'\x88.'), True)
998 self.assertIs(self.loads(b'\x89.'), False)
999 self.assertIs(self.loads(b'I01\n.'), True)
1000 self.assertIs(self.loads(b'I00\n.'), False)
1001
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001002 def test_empty_bytestring(self):
1003 # issue 11286
1004 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1005 self.assertEqual(empty, '')
1006
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001007 def test_short_binbytes(self):
1008 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
1009 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1010
1011 def test_binbytes(self):
1012 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1013 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1014
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001015 @requires_32b
1016 def test_negative_32b_binbytes(self):
1017 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1018 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001019 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1020 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001021
1022 @requires_32b
1023 def test_negative_32b_binunicode(self):
1024 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1025 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001026 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1027 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001028
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001029 def test_short_binunicode(self):
1030 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1031 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1032
1033 def test_misc_get(self):
Claudiu Popa6f03b232019-11-24 20:15:08 +01001034 self.check_unpickling_error(pickle.UnpicklingError, b'g0\np0')
1035 self.check_unpickling_error(pickle.UnpicklingError, b'jens:')
1036 self.check_unpickling_error(pickle.UnpicklingError, b'hens:')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001037 self.assert_is_copy([(100,), (100,)],
1038 self.loads(b'((Kdtp0\nh\x00l.))'))
1039
Serhiy Storchakae0606192015-09-29 22:10:07 +03001040 def test_binbytes8(self):
1041 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1042 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1043
1044 def test_binunicode8(self):
1045 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1046 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1047
Antoine Pitrou91f43802019-05-26 17:10:09 +02001048 def test_bytearray8(self):
1049 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1050 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1051
Serhiy Storchakae0606192015-09-29 22:10:07 +03001052 @requires_32b
1053 def test_large_32b_binbytes8(self):
1054 dumped = b'\x80\x04\x8e\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
1058 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001059 def test_large_32b_bytearray8(self):
1060 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1061 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1062 dumped)
1063
1064 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001065 def test_large_32b_binunicode8(self):
1066 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001067 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1068 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001069
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001070 def test_get(self):
1071 pickled = b'((lp100000\ng100000\nt.'
1072 unpickled = self.loads(pickled)
1073 self.assertEqual(unpickled, ([],)*2)
1074 self.assertIs(unpickled[0], unpickled[1])
1075
1076 def test_binget(self):
1077 pickled = b'(]q\xffh\xfft.'
1078 unpickled = self.loads(pickled)
1079 self.assertEqual(unpickled, ([],)*2)
1080 self.assertIs(unpickled[0], unpickled[1])
1081
1082 def test_long_binget(self):
1083 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1084 unpickled = self.loads(pickled)
1085 self.assertEqual(unpickled, ([],)*2)
1086 self.assertIs(unpickled[0], unpickled[1])
1087
1088 def test_dup(self):
1089 pickled = b'((l2t.'
1090 unpickled = self.loads(pickled)
1091 self.assertEqual(unpickled, ([],)*2)
1092 self.assertIs(unpickled[0], unpickled[1])
1093
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001094 def test_negative_put(self):
1095 # Issue #12847
1096 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001097 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001098
1099 @requires_32b
1100 def test_negative_32b_binput(self):
1101 # Issue #12847
1102 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001103 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001104
1105 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001106 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001107
1108 def test_badly_quoted_string(self):
1109 # Issue #17710
1110 badpickles = [b"S'\n.",
1111 b'S"\n.',
1112 b'S\' \n.',
1113 b'S" \n.',
1114 b'S\'"\n.',
1115 b'S"\'\n.',
1116 b"S' ' \n.",
1117 b'S" " \n.',
1118 b"S ''\n.",
1119 b'S ""\n.',
1120 b'S \n.',
1121 b'S\n.',
1122 b'S.']
1123 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001124 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001125
1126 def test_correctly_quoted_string(self):
1127 goodpickles = [(b"S''\n.", ''),
1128 (b'S""\n.', ''),
1129 (b'S"\\n"\n.', '\n'),
1130 (b"S'\\n'\n.", '\n')]
1131 for p, expected in goodpickles:
1132 self.assertEqual(self.loads(p), expected)
1133
1134 def test_frame_readline(self):
1135 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1136 # 0: \x80 PROTO 4
1137 # 2: \x95 FRAME 5
1138 # 11: I INT 42
1139 # 15: . STOP
1140 self.assertEqual(self.loads(pickled), 42)
1141
1142 def test_compat_unpickle(self):
1143 # xrange(1, 7)
1144 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1145 unpickled = self.loads(pickled)
1146 self.assertIs(type(unpickled), range)
1147 self.assertEqual(unpickled, range(1, 7))
1148 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1149 # reduce
1150 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1151 self.assertIs(self.loads(pickled), functools.reduce)
1152 # whichdb.whichdb
1153 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1154 self.assertIs(self.loads(pickled), dbm.whichdb)
1155 # Exception(), StandardError()
1156 for name in (b'Exception', b'StandardError'):
1157 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1158 unpickled = self.loads(pickled)
1159 self.assertIs(type(unpickled), Exception)
1160 self.assertEqual(str(unpickled), 'ugh')
1161 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1162 for name in (b'UserDict', b'IterableUserDict'):
1163 pickled = (b'\x80\x02(cUserDict\n' + name +
1164 b'\no}U\x04data}K\x01K\x02ssb.')
1165 unpickled = self.loads(pickled)
1166 self.assertIs(type(unpickled), collections.UserDict)
1167 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1168
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001169 def test_bad_stack(self):
1170 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001171 b'.', # STOP
1172 b'0', # POP
1173 b'1', # POP_MARK
1174 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001175 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001176 b'R', # REDUCE
1177 b')R',
1178 b'a', # APPEND
1179 b'Na',
1180 b'b', # BUILD
1181 b'Nb',
1182 b'd', # DICT
1183 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001184 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001185 b'ibuiltins\nlist\n', # INST
1186 b'l', # LIST
1187 b'o', # OBJ
1188 b'(o',
1189 b'p1\n', # PUT
1190 b'q\x00', # BINPUT
1191 b'r\x00\x00\x00\x00', # LONG_BINPUT
1192 b's', # SETITEM
1193 b'Ns',
1194 b'NNs',
1195 b't', # TUPLE
1196 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001197 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001198 b'}(Nu',
1199 b'\x81', # NEWOBJ
1200 b')\x81',
1201 b'\x85', # TUPLE1
1202 b'\x86', # TUPLE2
1203 b'N\x86',
1204 b'\x87', # TUPLE3
1205 b'N\x87',
1206 b'NN\x87',
1207 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001208 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001209 b'\x91', # FROZENSET
1210 b'\x92', # NEWOBJ_EX
1211 b')}\x92',
1212 b'\x93', # STACK_GLOBAL
1213 b'Vlist\n\x93',
1214 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001215 ]
1216 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001217 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001218
1219 def test_bad_mark(self):
1220 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001221 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001222 b'N(2', # DUP
1223 b'cbuiltins\nlist\n)(R', # REDUCE
1224 b'cbuiltins\nlist\n()R',
1225 b']N(a', # APPEND
1226 # BUILD
1227 b'cbuiltins\nValueError\n)R}(b',
1228 b'cbuiltins\nValueError\n)R(}b',
1229 b'(Nd', # DICT
1230 b'N(p1\n', # PUT
1231 b'N(q\x00', # BINPUT
1232 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1233 b'}NN(s', # SETITEM
1234 b'}N(Ns',
1235 b'}(NNs',
1236 b'}((u', # SETITEMS
1237 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1238 b'cbuiltins\nlist\n()\x81',
1239 b'N(\x85', # TUPLE1
1240 b'NN(\x86', # TUPLE2
1241 b'N(N\x86',
1242 b'NNN(\x87', # TUPLE3
1243 b'NN(N\x87',
1244 b'N(NN\x87',
1245 b']((\x90', # ADDITEMS
1246 # NEWOBJ_EX
1247 b'cbuiltins\nlist\n)}(\x92',
1248 b'cbuiltins\nlist\n)(}\x92',
1249 b'cbuiltins\nlist\n()}\x92',
1250 # STACK_GLOBAL
1251 b'Vbuiltins\n(Vlist\n\x93',
1252 b'Vbuiltins\nVlist\n(\x93',
1253 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001254 ]
1255 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001256 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001257
1258 def test_truncated_data(self):
1259 self.check_unpickling_error(EOFError, b'')
1260 self.check_unpickling_error(EOFError, b'N')
1261 badpickles = [
1262 b'B', # BINBYTES
1263 b'B\x03\x00\x00',
1264 b'B\x03\x00\x00\x00',
1265 b'B\x03\x00\x00\x00ab',
1266 b'C', # SHORT_BINBYTES
1267 b'C\x03',
1268 b'C\x03ab',
1269 b'F', # FLOAT
1270 b'F0.0',
1271 b'F0.00',
1272 b'G', # BINFLOAT
1273 b'G\x00\x00\x00\x00\x00\x00\x00',
1274 b'I', # INT
1275 b'I0',
1276 b'J', # BININT
1277 b'J\x00\x00\x00',
1278 b'K', # BININT1
1279 b'L', # LONG
1280 b'L0',
1281 b'L10',
1282 b'L0L',
1283 b'L10L',
1284 b'M', # BININT2
1285 b'M\x00',
1286 # b'P', # PERSID
1287 # b'Pabc',
1288 b'S', # STRING
1289 b"S'abc'",
1290 b'T', # BINSTRING
1291 b'T\x03\x00\x00',
1292 b'T\x03\x00\x00\x00',
1293 b'T\x03\x00\x00\x00ab',
1294 b'U', # SHORT_BINSTRING
1295 b'U\x03',
1296 b'U\x03ab',
1297 b'V', # UNICODE
1298 b'Vabc',
1299 b'X', # BINUNICODE
1300 b'X\x03\x00\x00',
1301 b'X\x03\x00\x00\x00',
1302 b'X\x03\x00\x00\x00ab',
1303 b'(c', # GLOBAL
1304 b'(cbuiltins',
1305 b'(cbuiltins\n',
1306 b'(cbuiltins\nlist',
1307 b'Ng', # GET
1308 b'Ng0',
1309 b'(i', # INST
1310 b'(ibuiltins',
1311 b'(ibuiltins\n',
1312 b'(ibuiltins\nlist',
1313 b'Nh', # BINGET
1314 b'Nj', # LONG_BINGET
1315 b'Nj\x00\x00\x00',
1316 b'Np', # PUT
1317 b'Np0',
1318 b'Nq', # BINPUT
1319 b'Nr', # LONG_BINPUT
1320 b'Nr\x00\x00\x00',
1321 b'\x80', # PROTO
1322 b'\x82', # EXT1
1323 b'\x83', # EXT2
1324 b'\x84\x01',
1325 b'\x84', # EXT4
1326 b'\x84\x01\x00\x00',
1327 b'\x8a', # LONG1
1328 b'\x8b', # LONG4
1329 b'\x8b\x00\x00\x00',
1330 b'\x8c', # SHORT_BINUNICODE
1331 b'\x8c\x03',
1332 b'\x8c\x03ab',
1333 b'\x8d', # BINUNICODE8
1334 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1335 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1336 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1337 b'\x8e', # BINBYTES8
1338 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1339 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1340 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001341 b'\x96', # BYTEARRAY8
1342 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1343 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1344 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001345 b'\x95', # FRAME
1346 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1347 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1348 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1349 ]
1350 for p in badpickles:
1351 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001352
tjb9004371c0a2019-02-18 23:30:51 +08001353 @reap_threads
1354 def test_unpickle_module_race(self):
1355 # https://bugs.python.org/issue34572
1356 locker_module = dedent("""
1357 import threading
1358 barrier = threading.Barrier(2)
1359 """)
1360 locking_import_module = dedent("""
1361 import locker
1362 locker.barrier.wait()
1363 class ToBeUnpickled(object):
1364 pass
1365 """)
1366
1367 os.mkdir(TESTFN)
1368 self.addCleanup(shutil.rmtree, TESTFN)
1369 sys.path.insert(0, TESTFN)
1370 self.addCleanup(sys.path.remove, TESTFN)
1371 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1372 f.write(locker_module.encode('utf-8'))
1373 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1374 f.write(locking_import_module.encode('utf-8'))
1375 self.addCleanup(forget, "locker")
1376 self.addCleanup(forget, "locking_import")
1377
1378 import locker
1379
1380 pickle_bytes = (
1381 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1382
1383 # Then try to unpickle two of these simultaneously
1384 # One of them will cause the module import, and we want it to block
1385 # until the other one either:
1386 # - fails (before the patch for this issue)
1387 # - blocks on the import lock for the module, as it should
1388 results = []
1389 barrier = threading.Barrier(3)
1390 def t():
1391 # This ensures the threads have all started
1392 # presumably barrier release is faster than thread startup
1393 barrier.wait()
1394 results.append(pickle.loads(pickle_bytes))
1395
1396 t1 = threading.Thread(target=t)
1397 t2 = threading.Thread(target=t)
1398 t1.start()
1399 t2.start()
1400
1401 barrier.wait()
1402 # could have delay here
1403 locker.barrier.wait()
1404
1405 t1.join()
1406 t2.join()
1407
1408 from locking_import import ToBeUnpickled
1409 self.assertEqual(
1410 [type(x) for x in results],
1411 [ToBeUnpickled] * 2)
1412
1413
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001414
1415class AbstractPickleTests(unittest.TestCase):
1416 # Subclass must define self.dumps, self.loads.
1417
1418 optimized = False
1419
1420 _testdata = AbstractUnpickleTests._testdata
1421
1422 def setUp(self):
1423 pass
1424
1425 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1426
1427 def test_misc(self):
1428 # test various datatypes not tested by testdata
1429 for proto in protocols:
1430 x = myint(4)
1431 s = self.dumps(x, proto)
1432 y = self.loads(s)
1433 self.assert_is_copy(x, y)
1434
1435 x = (1, ())
1436 s = self.dumps(x, proto)
1437 y = self.loads(s)
1438 self.assert_is_copy(x, y)
1439
1440 x = initarg(1, x)
1441 s = self.dumps(x, proto)
1442 y = self.loads(s)
1443 self.assert_is_copy(x, y)
1444
1445 # XXX test __reduce__ protocol?
1446
1447 def test_roundtrip_equality(self):
1448 expected = self._testdata
1449 for proto in protocols:
1450 s = self.dumps(expected, proto)
1451 got = self.loads(s)
1452 self.assert_is_copy(expected, got)
1453
Tim Peters70b02d72003-02-02 17:26:40 +00001454 # There are gratuitous differences between pickles produced by
1455 # pickle and cPickle, largely because cPickle starts PUT indices at
1456 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1457 # there's a comment with an exclamation point there whose meaning
1458 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1459 # of 1.
1460 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001461 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001462 from pickletools import dis
1463
1464 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1465 s = self.dumps(self._testdata, proto)
1466 filelike = StringIO()
1467 dis(s, out=filelike)
1468 got = filelike.getvalue()
1469 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001470
1471 def test_recursive_list(self):
1472 l = []
1473 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001474 for proto in protocols:
1475 s = self.dumps(l, proto)
1476 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001477 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001478 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001479 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001480
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001481 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001482 t = ([],)
1483 t[0].append(t)
1484 for proto in protocols:
1485 s = self.dumps(t, proto)
1486 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001487 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001488 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001489 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001490 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001491 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001492
Jeremy Hylton66426532001-10-15 21:38:56 +00001493 def test_recursive_dict(self):
1494 d = {}
1495 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001496 for proto in protocols:
1497 s = self.dumps(d, proto)
1498 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001499 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001500 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001501 self.assertIs(x[1], x)
1502
1503 def test_recursive_dict_key(self):
1504 d = {}
1505 k = K(d)
1506 d[k] = 1
1507 for proto in protocols:
1508 s = self.dumps(d, proto)
1509 x = self.loads(s)
1510 self.assertIsInstance(x, dict)
1511 self.assertEqual(len(x.keys()), 1)
1512 self.assertIsInstance(list(x.keys())[0], K)
1513 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001514
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001515 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001516 y = set()
1517 k = K(y)
1518 y.add(k)
1519 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001520 s = self.dumps(y, proto)
1521 x = self.loads(s)
1522 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001523 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001524 self.assertIsInstance(list(x)[0], K)
1525 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001526
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001527 def test_recursive_list_subclass(self):
1528 y = MyList()
1529 y.append(y)
1530 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001531 s = self.dumps(y, proto)
1532 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001533 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001534 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001535 self.assertIs(x[0], x)
1536
1537 def test_recursive_dict_subclass(self):
1538 d = MyDict()
1539 d[1] = d
1540 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1541 s = self.dumps(d, proto)
1542 x = self.loads(s)
1543 self.assertIsInstance(x, MyDict)
1544 self.assertEqual(list(x.keys()), [1])
1545 self.assertIs(x[1], x)
1546
1547 def test_recursive_dict_subclass_key(self):
1548 d = MyDict()
1549 k = K(d)
1550 d[k] = 1
1551 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1552 s = self.dumps(d, proto)
1553 x = self.loads(s)
1554 self.assertIsInstance(x, MyDict)
1555 self.assertEqual(len(list(x.keys())), 1)
1556 self.assertIsInstance(list(x.keys())[0], K)
1557 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001558
Jeremy Hylton66426532001-10-15 21:38:56 +00001559 def test_recursive_inst(self):
1560 i = C()
1561 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001562 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001563 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001564 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001565 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001566 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001567 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001568
1569 def test_recursive_multi(self):
1570 l = []
1571 d = {1:l}
1572 i = C()
1573 i.attr = d
1574 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001575 for proto in protocols:
1576 s = self.dumps(l, proto)
1577 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001578 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001579 self.assertEqual(len(x), 1)
1580 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001581 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001582 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001583
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001584 def check_recursive_collection_and_inst(self, factory):
1585 h = H()
1586 y = factory([h])
1587 h.attr = y
1588 for proto in protocols:
1589 s = self.dumps(y, proto)
1590 x = self.loads(s)
1591 self.assertIsInstance(x, type(y))
1592 self.assertEqual(len(x), 1)
1593 self.assertIsInstance(list(x)[0], H)
1594 self.assertIs(list(x)[0].attr, x)
1595
1596 def test_recursive_list_and_inst(self):
1597 self.check_recursive_collection_and_inst(list)
1598
1599 def test_recursive_tuple_and_inst(self):
1600 self.check_recursive_collection_and_inst(tuple)
1601
1602 def test_recursive_dict_and_inst(self):
1603 self.check_recursive_collection_and_inst(dict.fromkeys)
1604
1605 def test_recursive_set_and_inst(self):
1606 self.check_recursive_collection_and_inst(set)
1607
1608 def test_recursive_frozenset_and_inst(self):
1609 self.check_recursive_collection_and_inst(frozenset)
1610
1611 def test_recursive_list_subclass_and_inst(self):
1612 self.check_recursive_collection_and_inst(MyList)
1613
1614 def test_recursive_tuple_subclass_and_inst(self):
1615 self.check_recursive_collection_and_inst(MyTuple)
1616
1617 def test_recursive_dict_subclass_and_inst(self):
1618 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1619
1620 def test_recursive_set_subclass_and_inst(self):
1621 self.check_recursive_collection_and_inst(MySet)
1622
1623 def test_recursive_frozenset_subclass_and_inst(self):
1624 self.check_recursive_collection_and_inst(MyFrozenSet)
1625
Walter Dörwald9b775532007-06-08 14:30:53 +00001626 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001627 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001628 '<\\>', '<\\\U00012345>',
1629 # surrogates
1630 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001631 for proto in protocols:
1632 for u in endcases:
1633 p = self.dumps(u, proto)
1634 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001635 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001636
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001637 def test_unicode_high_plane(self):
1638 t = '\U00012345'
1639 for proto in protocols:
1640 p = self.dumps(t, proto)
1641 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001642 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001643
Guido van Rossumf4169812008-03-17 22:56:06 +00001644 def test_bytes(self):
1645 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001646 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001647 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001648 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001649 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001650 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001651 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001652 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001653 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001654 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001655
Antoine Pitrou91f43802019-05-26 17:10:09 +02001656 def test_bytearray(self):
1657 for proto in protocols:
1658 for s in b'', b'xyz', b'xyz'*100:
1659 b = bytearray(s)
1660 p = self.dumps(b, proto)
1661 bb = self.loads(p)
1662 self.assertIsNot(bb, b)
1663 self.assert_is_copy(b, bb)
1664 if proto <= 3:
1665 # bytearray is serialized using a global reference
1666 self.assertIn(b'bytearray', p)
1667 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1668 elif proto == 4:
1669 self.assertIn(b'bytearray', p)
1670 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1671 elif proto == 5:
1672 self.assertNotIn(b'bytearray', p)
1673 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1674
Jeremy Hylton66426532001-10-15 21:38:56 +00001675 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001676 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001677 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001678 while n:
1679 for expected in (-n, n):
1680 s = self.dumps(expected, proto)
1681 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001682 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001683 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001684
Tim Petersee1a53c2003-02-02 02:57:53 +00001685 def test_long(self):
1686 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001687 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001688 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001689 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001690 for npos in nbase-1, nbase, nbase+1:
1691 for n in npos, -npos:
1692 pickle = self.dumps(n, proto)
1693 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001694 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001695 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1696 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001697 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001698 nbase += nbase << 1000000
1699 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001700 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001701 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001702 # assert_is_copy is very expensive here as it precomputes
1703 # a failure message by computing the repr() of n and got,
1704 # we just do the check ourselves.
1705 self.assertIs(type(got), int)
1706 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001707
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001708 def test_float(self):
1709 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1710 3.14, 263.44582062374053, 6.022e23, 1e30]
1711 test_values = test_values + [-x for x in test_values]
1712 for proto in protocols:
1713 for value in test_values:
1714 pickle = self.dumps(value, proto)
1715 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001716 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001717
Thomas Wouters477c8d52006-05-27 19:21:47 +00001718 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1719 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001720 # make sure that floats are formatted locale independent with proto 0
1721 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001722
Jeremy Hylton66426532001-10-15 21:38:56 +00001723 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001724 for proto in protocols:
1725 inst = AAA()
1726 dumped = self.dumps(inst, proto)
1727 loaded = self.loads(dumped)
1728 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001729
1730 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001731 for proto in protocols:
1732 inst = initarg(1, 2)
1733 dumped = self.dumps(inst, proto)
1734 loaded = self.loads(dumped)
1735 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001736
Guido van Rossum04a86612001-12-19 16:58:54 +00001737 def test_metaclass(self):
1738 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001739 for proto in protocols:
1740 s = self.dumps(a, proto)
1741 b = self.loads(s)
1742 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001743
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001744 def test_dynamic_class(self):
1745 a = create_dynamic_class("my_dynamic_class", (object,))
1746 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1747 for proto in protocols:
1748 s = self.dumps(a, proto)
1749 b = self.loads(s)
1750 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001751 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001752
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001753 def test_structseq(self):
1754 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001755 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001756
1757 t = time.localtime()
1758 for proto in protocols:
1759 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001760 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001761 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001762 t = os.stat(os.curdir)
1763 s = self.dumps(t, proto)
1764 u = self.loads(s)
1765 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001766 if hasattr(os, "statvfs"):
1767 t = os.statvfs(os.curdir)
1768 s = self.dumps(t, proto)
1769 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001770 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001771
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001772 def test_ellipsis(self):
1773 for proto in protocols:
1774 s = self.dumps(..., proto)
1775 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001776 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001777
1778 def test_notimplemented(self):
1779 for proto in protocols:
1780 s = self.dumps(NotImplemented, proto)
1781 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001782 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001783
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001784 def test_singleton_types(self):
1785 # Issue #6477: Test that types of built-in singletons can be pickled.
1786 singletons = [None, ..., NotImplemented]
1787 for singleton in singletons:
1788 for proto in protocols:
1789 s = self.dumps(type(singleton), proto)
1790 u = self.loads(s)
1791 self.assertIs(type(singleton), u)
1792
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001793 # Tests for protocol 2
1794
Tim Peters4190fb82003-02-02 16:09:05 +00001795 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001796 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001797 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001798 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001799 proto_header = pickle.PROTO + bytes([proto])
1800 self.assertTrue(pickled.startswith(proto_header))
1801 else:
1802 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001803
1804 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001805 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001806 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001807 try:
1808 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001809 except ValueError as err:
1810 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001811 else:
1812 self.fail("expected bad protocol number to raise ValueError")
1813
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001814 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001815 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001816 for proto in protocols:
1817 s = self.dumps(x, proto)
1818 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001819 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001820 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001821
1822 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001823 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001824 for proto in protocols:
1825 s = self.dumps(x, proto)
1826 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001827 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001828 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001829
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001830 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001831 # Map (proto, len(tuple)) to expected opcode.
1832 expected_opcode = {(0, 0): pickle.TUPLE,
1833 (0, 1): pickle.TUPLE,
1834 (0, 2): pickle.TUPLE,
1835 (0, 3): pickle.TUPLE,
1836 (0, 4): pickle.TUPLE,
1837
1838 (1, 0): pickle.EMPTY_TUPLE,
1839 (1, 1): pickle.TUPLE,
1840 (1, 2): pickle.TUPLE,
1841 (1, 3): pickle.TUPLE,
1842 (1, 4): pickle.TUPLE,
1843
1844 (2, 0): pickle.EMPTY_TUPLE,
1845 (2, 1): pickle.TUPLE1,
1846 (2, 2): pickle.TUPLE2,
1847 (2, 3): pickle.TUPLE3,
1848 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001849
1850 (3, 0): pickle.EMPTY_TUPLE,
1851 (3, 1): pickle.TUPLE1,
1852 (3, 2): pickle.TUPLE2,
1853 (3, 3): pickle.TUPLE3,
1854 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001855 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001856 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001857 b = (1,)
1858 c = (1, 2)
1859 d = (1, 2, 3)
1860 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001861 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001862 for x in a, b, c, d, e:
1863 s = self.dumps(x, proto)
1864 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001865 self.assert_is_copy(x, y)
1866 expected = expected_opcode[min(proto, 3), len(x)]
1867 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001868
Guido van Rossum7d97d312003-01-28 04:25:27 +00001869 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001870 # Map (proto, singleton) to expected opcode.
1871 expected_opcode = {(0, None): pickle.NONE,
1872 (1, None): pickle.NONE,
1873 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001874 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001875
1876 (0, True): pickle.INT,
1877 (1, True): pickle.INT,
1878 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001879 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001880
1881 (0, False): pickle.INT,
1882 (1, False): pickle.INT,
1883 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001884 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001885 }
Tim Peters4190fb82003-02-02 16:09:05 +00001886 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001887 for x in None, False, True:
1888 s = self.dumps(x, proto)
1889 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001890 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001891 expected = expected_opcode[min(proto, 3), x]
1892 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001893
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001894 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001895 x = MyTuple([1, 2, 3])
1896 x.foo = 42
1897 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001898 for proto in protocols:
1899 s = self.dumps(x, proto)
1900 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001901 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001902
1903 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001904 x = MyList([1, 2, 3])
1905 x.foo = 42
1906 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001907 for proto in protocols:
1908 s = self.dumps(x, proto)
1909 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001910 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001911
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001912 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001913 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001914 for C in myclasses:
1915 B = C.__base__
1916 x = C(C.sample)
1917 x.foo = 42
1918 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001919 y = self.loads(s)
1920 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001921 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001922 self.assertEqual(B(x), B(y), detail)
1923 self.assertEqual(x.__dict__, y.__dict__, detail)
1924
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001925 def test_newobj_proxies(self):
1926 # NEWOBJ should use the __class__ rather than the raw type
1927 classes = myclasses[:]
1928 # Cannot create weakproxies to these classes
1929 for c in (MyInt, MyTuple):
1930 classes.remove(c)
1931 for proto in protocols:
1932 for C in classes:
1933 B = C.__base__
1934 x = C(C.sample)
1935 x.foo = 42
1936 p = weakref.proxy(x)
1937 s = self.dumps(p, proto)
1938 y = self.loads(s)
1939 self.assertEqual(type(y), type(x)) # rather than type(p)
1940 detail = (proto, C, B, x, y, type(y))
1941 self.assertEqual(B(x), B(y), detail)
1942 self.assertEqual(x.__dict__, y.__dict__, detail)
1943
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001944 def test_newobj_not_class(self):
1945 # Issue 24552
1946 global SimpleNewObj
1947 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001948 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001949 b = self.dumps(o, 4)
1950 try:
1951 SimpleNewObj = 42
1952 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1953 finally:
1954 SimpleNewObj = save
1955
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001956 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001957 # an object of that type. Check that the resulting pickle uses opcode
1958 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001959
Tim Peters22e71712003-02-03 22:27:38 +00001960 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001961 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001962 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001963 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001964 x = MyList([1, 2, 3])
1965 x.foo = 42
1966 x.bar = "hello"
1967
Tim Peters22e71712003-02-03 22:27:38 +00001968 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001969 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001970 self.assertIn(__name__.encode("utf-8"), s1)
1971 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001972 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001973
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001974 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001975 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001976
Tim Peters22e71712003-02-03 22:27:38 +00001977 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001978 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001979 self.assertNotIn(__name__.encode("utf-8"), s2)
1980 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001981 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001982
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001983 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001984 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001985 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001986 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001987
1988 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001989 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1990 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001991
1992 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001993 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1994 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1995 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001996
1997 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001998 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1999 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
2000 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
2001
Tim Peters8d2613a2003-02-11 16:40:16 +00002002 def test_list_chunking(self):
2003 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002004 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002005 for proto in protocols:
2006 s = self.dumps(x, proto)
2007 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002008 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002009 num_appends = count_opcode(pickle.APPENDS, s)
2010 self.assertEqual(num_appends, proto > 0)
2011
2012 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002013 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002014 for proto in protocols:
2015 s = self.dumps(x, proto)
2016 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002017 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002018 num_appends = count_opcode(pickle.APPENDS, s)
2019 if proto == 0:
2020 self.assertEqual(num_appends, 0)
2021 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002022 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002023
2024 def test_dict_chunking(self):
2025 n = 10 # too small to chunk
2026 x = dict.fromkeys(range(n))
2027 for proto in protocols:
2028 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002029 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002030 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002031 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002032 num_setitems = count_opcode(pickle.SETITEMS, s)
2033 self.assertEqual(num_setitems, proto > 0)
2034
2035 n = 2500 # expect at least two chunks when proto > 0
2036 x = dict.fromkeys(range(n))
2037 for proto in protocols:
2038 s = self.dumps(x, proto)
2039 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002040 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002041 num_setitems = count_opcode(pickle.SETITEMS, s)
2042 if proto == 0:
2043 self.assertEqual(num_setitems, 0)
2044 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002045 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002046
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002047 def test_set_chunking(self):
2048 n = 10 # too small to chunk
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.assertEqual(num_additems, 1)
2059
2060 n = 2500 # expect at least two chunks when proto >= 4
2061 x = set(range(n))
2062 for proto in protocols:
2063 s = self.dumps(x, proto)
2064 y = self.loads(s)
2065 self.assert_is_copy(x, y)
2066 num_additems = count_opcode(pickle.ADDITEMS, s)
2067 if proto < 4:
2068 self.assertEqual(num_additems, 0)
2069 else:
2070 self.assertGreaterEqual(num_additems, 2)
2071
Tim Peterse9ef2032003-02-13 18:42:00 +00002072 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002073 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002074 x.abc = 666
2075 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002076 with self.subTest(proto=proto):
2077 s = self.dumps(x, proto)
2078 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002079 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002080 else:
2081 self.assertIn(b'M\xce\xfa', s) # BININT2
2082 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2083 2 <= proto)
2084 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2085 y = self.loads(s) # will raise TypeError if __init__ called
2086 self.assert_is_copy(x, y)
2087
2088 def test_complex_newobj(self):
2089 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2090 x.abc = 666
2091 for proto in protocols:
2092 with self.subTest(proto=proto):
2093 s = self.dumps(x, proto)
2094 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002095 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002096 elif proto < 2:
2097 self.assertIn(b'M\xce\xfa', s) # BININT2
2098 elif proto < 4:
2099 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2100 else:
2101 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2102 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2103 2 <= proto)
2104 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2105 y = self.loads(s) # will raise TypeError if __init__ called
2106 self.assert_is_copy(x, y)
2107
2108 def test_complex_newobj_ex(self):
2109 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2110 x.abc = 666
2111 for proto in protocols:
2112 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002113 s = self.dumps(x, proto)
2114 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002115 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002116 elif proto < 2:
2117 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002118 elif proto < 4:
2119 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002120 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002121 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2122 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2123 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2124 4 <= proto)
2125 y = self.loads(s) # will raise TypeError if __init__ called
2126 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002127
Tim Peters42f08ac2003-02-11 22:43:24 +00002128 def test_newobj_list_slots(self):
2129 x = SlotList([1, 2, 3])
2130 x.foo = 42
2131 x.bar = "hello"
2132 s = self.dumps(x, 2)
2133 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002134 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002135
Guido van Rossum2a30b212003-02-18 22:41:24 +00002136 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002137 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002138 x = REX_one()
2139 self.assertEqual(x._reduce_called, 0)
2140 s = self.dumps(x, proto)
2141 self.assertEqual(x._reduce_called, 1)
2142 y = self.loads(s)
2143 self.assertEqual(y._reduce_called, 0)
2144
2145 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002146 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002147 x = REX_two()
2148 self.assertEqual(x._proto, None)
2149 s = self.dumps(x, proto)
2150 self.assertEqual(x._proto, proto)
2151 y = self.loads(s)
2152 self.assertEqual(y._proto, None)
2153
2154 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002155 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002156 x = REX_three()
2157 self.assertEqual(x._proto, None)
2158 s = self.dumps(x, proto)
2159 self.assertEqual(x._proto, proto)
2160 y = self.loads(s)
2161 self.assertEqual(y._proto, None)
2162
Guido van Rossumd8faa362007-04-27 19:54:29 +00002163 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002164 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002165 x = REX_four()
2166 self.assertEqual(x._proto, None)
2167 s = self.dumps(x, proto)
2168 self.assertEqual(x._proto, proto)
2169 y = self.loads(s)
2170 self.assertEqual(y._proto, proto)
2171
2172 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002173 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002174 x = REX_five()
2175 self.assertEqual(x._reduce_called, 0)
2176 s = self.dumps(x, proto)
2177 self.assertEqual(x._reduce_called, 1)
2178 y = self.loads(s)
2179 self.assertEqual(y._reduce_called, 1)
2180
Brett Cannon31f59292011-02-21 19:29:56 +00002181 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002182 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002183 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002184 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002185 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002186 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002187
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002188 def test_reduce_bad_iterator(self):
2189 # Issue4176: crash when 4th and 5th items of __reduce__()
2190 # are not iterators
2191 class C(object):
2192 def __reduce__(self):
2193 # 4th item is not an iterator
2194 return list, (), None, [], None
2195 class D(object):
2196 def __reduce__(self):
2197 # 5th item is not an iterator
2198 return dict, (), None, None, []
2199
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002200 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002201 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002202 try:
2203 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002204 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002205 pass
2206 try:
2207 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002208 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002209 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002210
Collin Winter771d8342009-04-16 03:18:06 +00002211 def test_many_puts_and_gets(self):
2212 # Test that internal data structures correctly deal with lots of
2213 # puts/gets.
2214 keys = ("aaa" + str(i) for i in range(100))
2215 large_dict = dict((k, [4, 5, 6]) for k in keys)
2216 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2217
2218 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002219 with self.subTest(proto=proto):
2220 dumped = self.dumps(obj, proto)
2221 loaded = self.loads(dumped)
2222 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002223
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002224 def test_attribute_name_interning(self):
2225 # Test that attribute names of pickled objects are interned when
2226 # unpickling.
2227 for proto in protocols:
2228 x = C()
2229 x.foo = 42
2230 x.bar = "hello"
2231 s = self.dumps(x, proto)
2232 y = self.loads(s)
2233 x_keys = sorted(x.__dict__)
2234 y_keys = sorted(y.__dict__)
2235 for x_key, y_key in zip(x_keys, y_keys):
2236 self.assertIs(x_key, y_key)
2237
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002238 def test_pickle_to_2x(self):
2239 # Pickle non-trivial data with protocol 2, expecting that it yields
2240 # the same result as Python 2.x did.
2241 # NOTE: this test is a bit too strong since we can produce different
2242 # bytecode that 2.x will still understand.
2243 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002244 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002245 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002246 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002247
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002248 def test_large_pickles(self):
2249 # Test the correctness of internal buffering routines when handling
2250 # large data.
2251 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002252 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002253 dumped = self.dumps(data, proto)
2254 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002255 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002256 self.assertEqual(loaded, data)
2257
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002258 def test_int_pickling_efficiency(self):
2259 # Test compacity of int representation (see issue #12744)
2260 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002261 with self.subTest(proto=proto):
2262 pickles = [self.dumps(2**n, proto) for n in range(70)]
2263 sizes = list(map(len, pickles))
2264 # the size function is monotonic
2265 self.assertEqual(sorted(sizes), sizes)
2266 if proto >= 2:
2267 for p in pickles:
2268 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002269
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002270 def _check_pickling_with_opcode(self, obj, opcode, proto):
2271 pickled = self.dumps(obj, proto)
2272 self.assertTrue(opcode_in_pickle(opcode, pickled))
2273 unpickled = self.loads(pickled)
2274 self.assertEqual(obj, unpickled)
2275
2276 def test_appends_on_non_lists(self):
2277 # Issue #17720
2278 obj = REX_six([1, 2, 3])
2279 for proto in protocols:
2280 if proto == 0:
2281 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2282 else:
2283 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2284
2285 def test_setitems_on_non_dicts(self):
2286 obj = REX_seven({1: -1, 2: -2, 3: -3})
2287 for proto in protocols:
2288 if proto == 0:
2289 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2290 else:
2291 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2292
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002293 # Exercise framing (proto >= 4) for significant workloads
2294
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002295 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002296 FRAME_SIZE_TARGET = 64 * 1024
2297
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002298 def check_frame_opcodes(self, pickled):
2299 """
2300 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002301
2302 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2303 framed by default and are therefore considered a frame by themselves in
2304 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002305 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002306 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002307 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2308 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002309 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002310 if frame_end is not None:
2311 self.assertLessEqual(pos, frame_end)
2312 if pos == frame_end:
2313 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002314
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002315 if frame_end is not None: # framed
2316 self.assertNotEqual(op.name, 'FRAME')
2317 if op.name in frameless_opcodes:
2318 # Only short bytes and str objects should be written
2319 # in a frame
2320 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2321
2322 else: # not framed
2323 if (op.name == 'FRAME' or
2324 (op.name in frameless_opcodes and
2325 len(arg) > self.FRAME_SIZE_TARGET)):
2326 # Frame or large bytes or str object
2327 if frameless_start is not None:
2328 # Only short data should be written outside of a frame
2329 self.assertLess(pos - frameless_start,
2330 self.FRAME_SIZE_MIN)
2331 frameless_start = None
2332 elif frameless_start is None and op.name != 'PROTO':
2333 frameless_start = pos
2334
2335 if op.name == 'FRAME':
2336 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2337 frame_end = pos + 9 + arg
2338
2339 pos = len(pickled)
2340 if frame_end is not None:
2341 self.assertEqual(frame_end, pos)
2342 elif frameless_start is not None:
2343 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002344
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002345 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002346 def test_framing_many_objects(self):
2347 obj = list(range(10**5))
2348 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2349 with self.subTest(proto=proto):
2350 pickled = self.dumps(obj, proto)
2351 unpickled = self.loads(pickled)
2352 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002353 bytes_per_frame = (len(pickled) /
2354 count_opcode(pickle.FRAME, pickled))
2355 self.assertGreater(bytes_per_frame,
2356 self.FRAME_SIZE_TARGET / 2)
2357 self.assertLessEqual(bytes_per_frame,
2358 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002359 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002360
2361 def test_framing_large_objects(self):
2362 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002363 small_items = [[i] for i in range(10)]
2364 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002365 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002366 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002367 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002368 if not fast:
2369 # fast=False by default.
2370 # This covers in-memory pickling with pickle.dumps().
2371 pickled = self.dumps(obj, proto)
2372 else:
2373 # Pickler is required when fast=True.
2374 if not hasattr(self, 'pickler'):
2375 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002376 buf = io.BytesIO()
2377 pickler = self.pickler(buf, protocol=proto)
2378 pickler.fast = fast
2379 pickler.dump(obj)
2380 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002381 unpickled = self.loads(pickled)
2382 # More informative error message in case of failure.
2383 self.assertEqual([len(x) for x in obj],
2384 [len(x) for x in unpickled])
2385 # Perform full equality check if the lengths match.
2386 self.assertEqual(obj, unpickled)
2387 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002388 # A single frame for small objects between
2389 # first two large objects.
2390 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002391 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002392
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002393 def test_optional_frames(self):
2394 if pickle.HIGHEST_PROTOCOL < 4:
2395 return
2396
2397 def remove_frames(pickled, keep_frame=None):
2398 """Remove frame opcodes from the given pickle."""
2399 frame_starts = []
2400 # 1 byte for the opcode and 8 for the argument
2401 frame_opcode_size = 9
2402 for opcode, _, pos in pickletools.genops(pickled):
2403 if opcode.name == 'FRAME':
2404 frame_starts.append(pos)
2405
2406 newpickle = bytearray()
2407 last_frame_end = 0
2408 for i, pos in enumerate(frame_starts):
2409 if keep_frame and keep_frame(i):
2410 continue
2411 newpickle += pickled[last_frame_end:pos]
2412 last_frame_end = pos + frame_opcode_size
2413 newpickle += pickled[last_frame_end:]
2414 return newpickle
2415
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002416 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002417 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002418 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002419 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002420 for bytes_type in (bytes, bytearray):
2421 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002422
Antoine Pitrou91f43802019-05-26 17:10:09 +02002423 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2424 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002425
Antoine Pitrou91f43802019-05-26 17:10:09 +02002426 frameless_pickle = remove_frames(pickled)
2427 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2428 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002429
Antoine Pitrou91f43802019-05-26 17:10:09 +02002430 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2431 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2432 count_opcode(pickle.FRAME, pickled))
2433 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002434
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002435 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002436 def test_framed_write_sizes_with_delayed_writer(self):
2437 class ChunkAccumulator:
2438 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002439 def __init__(self):
2440 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002441 def write(self, chunk):
2442 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002443 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002444 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002445
2446 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002447 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2448 for i in range(int(1e4))]
2449 # Add a large unique ASCII string
2450 objects.append('0123456789abcdef' *
2451 (self.FRAME_SIZE_TARGET // 16 + 1))
2452
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002453 # Protocol 4 packs groups of small objects into frames and issues
2454 # calls to write only once or twice per frame:
2455 # The C pickler issues one call to write per-frame (header and
2456 # contents) while Python pickler issues two calls to write: one for
2457 # the frame header and one for the frame binary contents.
2458 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002459 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002460
2461 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002462 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002463 # be released otherwise this delayed access would not be possible.
2464 pickled = writer.concatenate_chunks()
2465 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002466 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002467 self.assertGreater(len(writer.chunks), 1)
2468
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002469 # memoryviews should own the memory.
2470 del objects
2471 support.gc_collect()
2472 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002473
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002474 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002475 # There should be at least one call to write per frame
2476 self.assertGreaterEqual(len(writer.chunks), n_frames)
2477
2478 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002479 # one per-frame header, one per frame for the actual contents,
2480 # and two for the header.
2481 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002482
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002483 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002484 large_sizes = [s for s in chunk_sizes
2485 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002486 medium_sizes = [s for s in chunk_sizes
2487 if 9 < s < self.FRAME_SIZE_TARGET]
2488 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002489
2490 # Large chunks should not be too large:
2491 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002492 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2493 chunk_sizes)
2494 # There shouldn't bee too many small chunks: the protocol header,
2495 # the frame headers and the large string headers are written
2496 # in small chunks.
2497 self.assertLessEqual(len(small_sizes),
2498 len(large_sizes) + len(medium_sizes) + 3,
2499 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002500
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002501 def test_nested_names(self):
2502 global Nested
2503 class Nested:
2504 class A:
2505 class B:
2506 class C:
2507 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002508 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002509 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2510 with self.subTest(proto=proto, obj=obj):
2511 unpickled = self.loads(self.dumps(obj, proto))
2512 self.assertIs(obj, unpickled)
2513
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002514 def test_recursive_nested_names(self):
2515 global Recursive
2516 class Recursive:
2517 pass
2518 Recursive.mod = sys.modules[Recursive.__module__]
2519 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2520 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2521 with self.subTest(proto=proto):
2522 unpickled = self.loads(self.dumps(Recursive, proto))
2523 self.assertIs(unpickled, Recursive)
2524 del Recursive.mod # break reference loop
2525
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002526 def test_py_methods(self):
2527 global PyMethodsTest
2528 class PyMethodsTest:
2529 @staticmethod
2530 def cheese():
2531 return "cheese"
2532 @classmethod
2533 def wine(cls):
2534 assert cls is PyMethodsTest
2535 return "wine"
2536 def biscuits(self):
2537 assert isinstance(self, PyMethodsTest)
2538 return "biscuits"
2539 class Nested:
2540 "Nested class"
2541 @staticmethod
2542 def ketchup():
2543 return "ketchup"
2544 @classmethod
2545 def maple(cls):
2546 assert cls is PyMethodsTest.Nested
2547 return "maple"
2548 def pie(self):
2549 assert isinstance(self, PyMethodsTest.Nested)
2550 return "pie"
2551
2552 py_methods = (
2553 PyMethodsTest.cheese,
2554 PyMethodsTest.wine,
2555 PyMethodsTest().biscuits,
2556 PyMethodsTest.Nested.ketchup,
2557 PyMethodsTest.Nested.maple,
2558 PyMethodsTest.Nested().pie
2559 )
2560 py_unbound_methods = (
2561 (PyMethodsTest.biscuits, PyMethodsTest),
2562 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2563 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002564 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002565 for method in py_methods:
2566 with self.subTest(proto=proto, method=method):
2567 unpickled = self.loads(self.dumps(method, proto))
2568 self.assertEqual(method(), unpickled())
2569 for method, cls in py_unbound_methods:
2570 obj = cls()
2571 with self.subTest(proto=proto, method=method):
2572 unpickled = self.loads(self.dumps(method, proto))
2573 self.assertEqual(method(obj), unpickled(obj))
2574
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002575 def test_c_methods(self):
2576 global Subclass
2577 class Subclass(tuple):
2578 class Nested(str):
2579 pass
2580
2581 c_methods = (
2582 # bound built-in method
2583 ("abcd".index, ("c",)),
2584 # unbound built-in method
2585 (str.index, ("abcd", "c")),
2586 # bound "slot" method
2587 ([1, 2, 3].__len__, ()),
2588 # unbound "slot" method
2589 (list.__len__, ([1, 2, 3],)),
2590 # bound "coexist" method
2591 ({1, 2}.__contains__, (2,)),
2592 # unbound "coexist" method
2593 (set.__contains__, ({1, 2}, 2)),
2594 # built-in class method
2595 (dict.fromkeys, (("a", 1), ("b", 2))),
2596 # built-in static method
2597 (bytearray.maketrans, (b"abc", b"xyz")),
2598 # subclass methods
2599 (Subclass([1,2,2]).count, (2,)),
2600 (Subclass.count, (Subclass([1,2,2]), 2)),
2601 (Subclass.Nested("sweet").count, ("e",)),
2602 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2603 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002604 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002605 for method, args in c_methods:
2606 with self.subTest(proto=proto, method=method):
2607 unpickled = self.loads(self.dumps(method, proto))
2608 self.assertEqual(method(*args), unpickled(*args))
2609
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002610 def test_compat_pickle(self):
2611 tests = [
2612 (range(1, 7), '__builtin__', 'xrange'),
2613 (map(int, '123'), 'itertools', 'imap'),
2614 (functools.reduce, '__builtin__', 'reduce'),
2615 (dbm.whichdb, 'whichdb', 'whichdb'),
2616 (Exception(), 'exceptions', 'Exception'),
2617 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2618 (collections.UserList(), 'UserList', 'UserList'),
2619 (collections.defaultdict(), 'collections', 'defaultdict'),
2620 ]
2621 for val, mod, name in tests:
2622 for proto in range(3):
2623 with self.subTest(type=type(val), proto=proto):
2624 pickled = self.dumps(val, proto)
2625 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2626 self.assertIs(type(self.loads(pickled)), type(val))
2627
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002628 def test_local_lookup_error(self):
2629 # Test that whichmodule() errors out cleanly when looking up
2630 # an assumed globally-reachable object fails.
2631 def f():
2632 pass
2633 # Since the function is local, lookup will fail
2634 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2635 with self.assertRaises((AttributeError, pickle.PicklingError)):
2636 pickletools.dis(self.dumps(f, proto))
2637 # Same without a __module__ attribute (exercises a different path
2638 # in _pickle.c).
2639 del f.__module__
2640 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2641 with self.assertRaises((AttributeError, pickle.PicklingError)):
2642 pickletools.dis(self.dumps(f, proto))
2643 # Yet a different path.
2644 f.__name__ = f.__qualname__
2645 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2646 with self.assertRaises((AttributeError, pickle.PicklingError)):
2647 pickletools.dis(self.dumps(f, proto))
2648
Antoine Pitrou91f43802019-05-26 17:10:09 +02002649 #
2650 # PEP 574 tests below
2651 #
2652
2653 def buffer_like_objects(self):
2654 # Yield buffer-like objects with the bytestring "abcdef" in them
2655 bytestring = b"abcdefgh"
2656 yield ZeroCopyBytes(bytestring)
2657 yield ZeroCopyBytearray(bytestring)
2658 if _testbuffer is not None:
2659 items = list(bytestring)
2660 value = int.from_bytes(bytestring, byteorder='little')
2661 for flags in (0, _testbuffer.ND_WRITABLE):
2662 # 1-D, contiguous
2663 yield PicklableNDArray(items, format='B', shape=(8,),
2664 flags=flags)
2665 # 2-D, C-contiguous
2666 yield PicklableNDArray(items, format='B', shape=(4, 2),
2667 strides=(2, 1), flags=flags)
2668 # 2-D, Fortran-contiguous
2669 yield PicklableNDArray(items, format='B',
2670 shape=(4, 2), strides=(1, 4),
2671 flags=flags)
2672
2673 def test_in_band_buffers(self):
2674 # Test in-band buffers (PEP 574)
2675 for obj in self.buffer_like_objects():
2676 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2677 data = self.dumps(obj, proto)
2678 if obj.c_contiguous and proto >= 5:
2679 # The raw memory bytes are serialized in physical order
2680 self.assertIn(b"abcdefgh", data)
2681 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2682 if proto >= 5:
2683 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2684 1 if obj.readonly else 0)
2685 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2686 0 if obj.readonly else 1)
2687 # Return a true value from buffer_callback should have
2688 # the same effect
2689 def buffer_callback(obj):
2690 return True
2691 data2 = self.dumps(obj, proto,
2692 buffer_callback=buffer_callback)
2693 self.assertEqual(data2, data)
2694
2695 new = self.loads(data)
2696 # It's a copy
2697 self.assertIsNot(new, obj)
2698 self.assertIs(type(new), type(obj))
2699 self.assertEqual(new, obj)
2700
2701 # XXX Unfortunately cannot test non-contiguous array
2702 # (see comment in PicklableNDArray.__reduce_ex__)
2703
2704 def test_oob_buffers(self):
2705 # Test out-of-band buffers (PEP 574)
2706 for obj in self.buffer_like_objects():
2707 for proto in range(0, 5):
2708 # Need protocol >= 5 for buffer_callback
2709 with self.assertRaises(ValueError):
2710 self.dumps(obj, proto,
2711 buffer_callback=[].append)
2712 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2713 buffers = []
2714 buffer_callback = lambda pb: buffers.append(pb.raw())
2715 data = self.dumps(obj, proto,
2716 buffer_callback=buffer_callback)
2717 self.assertNotIn(b"abcdefgh", data)
2718 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2719 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2720 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2721 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2722 1 if obj.readonly else 0)
2723
2724 if obj.c_contiguous:
2725 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2726 # Need buffers argument to unpickle properly
2727 with self.assertRaises(pickle.UnpicklingError):
2728 self.loads(data)
2729
2730 new = self.loads(data, buffers=buffers)
2731 if obj.zero_copy_reconstruct:
2732 # Zero-copy achieved
2733 self.assertIs(new, obj)
2734 else:
2735 self.assertIs(type(new), type(obj))
2736 self.assertEqual(new, obj)
2737 # Non-sequence buffers accepted too
2738 new = self.loads(data, buffers=iter(buffers))
2739 if obj.zero_copy_reconstruct:
2740 # Zero-copy achieved
2741 self.assertIs(new, obj)
2742 else:
2743 self.assertIs(type(new), type(obj))
2744 self.assertEqual(new, obj)
2745
2746 def test_oob_buffers_writable_to_readonly(self):
2747 # Test reconstructing readonly object from writable buffer
2748 obj = ZeroCopyBytes(b"foobar")
2749 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2750 buffers = []
2751 buffer_callback = buffers.append
2752 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2753
2754 buffers = map(bytearray, buffers)
2755 new = self.loads(data, buffers=buffers)
2756 self.assertIs(type(new), type(obj))
2757 self.assertEqual(new, obj)
2758
2759 def test_picklebuffer_error(self):
2760 # PickleBuffer forbidden with protocol < 5
2761 pb = pickle.PickleBuffer(b"foobar")
2762 for proto in range(0, 5):
2763 with self.assertRaises(pickle.PickleError):
2764 self.dumps(pb, proto)
2765
2766 def test_buffer_callback_error(self):
2767 def buffer_callback(buffers):
2768 1/0
2769 pb = pickle.PickleBuffer(b"foobar")
2770 with self.assertRaises(ZeroDivisionError):
2771 self.dumps(pb, 5, buffer_callback=buffer_callback)
2772
2773 def test_buffers_error(self):
2774 pb = pickle.PickleBuffer(b"foobar")
2775 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2776 data = self.dumps(pb, proto, buffer_callback=[].append)
2777 # Non iterable buffers
2778 with self.assertRaises(TypeError):
2779 self.loads(data, buffers=object())
2780 # Buffer iterable exhausts too early
2781 with self.assertRaises(pickle.UnpicklingError):
2782 self.loads(data, buffers=[])
2783
Markus Mohrhard898318b2019-07-26 00:00:34 +08002784 def test_inband_accept_default_buffers_argument(self):
2785 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2786 data_pickled = self.dumps(1, proto, buffer_callback=None)
2787 data = self.loads(data_pickled, buffers=None)
2788
Antoine Pitrou91f43802019-05-26 17:10:09 +02002789 @unittest.skipIf(np is None, "Test needs Numpy")
2790 def test_buffers_numpy(self):
2791 def check_no_copy(x, y):
2792 np.testing.assert_equal(x, y)
2793 self.assertEqual(x.ctypes.data, y.ctypes.data)
2794
2795 def check_copy(x, y):
2796 np.testing.assert_equal(x, y)
2797 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2798
2799 def check_array(arr):
2800 # In-band
2801 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2802 data = self.dumps(arr, proto)
2803 new = self.loads(data)
2804 check_copy(arr, new)
2805 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2806 buffer_callback = lambda _: True
2807 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2808 new = self.loads(data)
2809 check_copy(arr, new)
2810 # Out-of-band
2811 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2812 buffers = []
2813 buffer_callback = buffers.append
2814 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2815 new = self.loads(data, buffers=buffers)
2816 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2817 check_no_copy(arr, new)
2818 else:
2819 check_copy(arr, new)
2820
2821 # 1-D
2822 arr = np.arange(6)
2823 check_array(arr)
2824 # 1-D, non-contiguous
2825 check_array(arr[::2])
2826 # 2-D, C-contiguous
2827 arr = np.arange(12).reshape((3, 4))
2828 check_array(arr)
2829 # 2-D, F-contiguous
2830 check_array(arr.T)
2831 # 2-D, non-contiguous
2832 check_array(arr[::2])
2833
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002834
2835class BigmemPickleTests(unittest.TestCase):
2836
Victor Stinner8c663fd2017-11-08 14:44:44 -08002837 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002838
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002839 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002840 def test_huge_long_32b(self, size):
2841 data = 1 << (8 * size)
2842 try:
2843 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002844 if proto < 2:
2845 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002846 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002847 with self.assertRaises((ValueError, OverflowError)):
2848 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002849 finally:
2850 data = None
2851
Victor Stinner8c663fd2017-11-08 14:44:44 -08002852 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002853 # (older protocols don't have a dedicated opcode for bytes and are
2854 # too inefficient)
2855
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002856 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002857 def test_huge_bytes_32b(self, size):
2858 data = b"abcd" * (size // 4)
2859 try:
2860 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002861 if proto < 3:
2862 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002863 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002864 try:
2865 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002866 header = (pickle.BINBYTES +
2867 struct.pack("<I", len(data)))
2868 data_start = pickled.index(data)
2869 self.assertEqual(
2870 header,
2871 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002872 finally:
2873 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002874 finally:
2875 data = None
2876
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002877 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002878 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002879 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002880 try:
2881 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002882 if proto < 3:
2883 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002884 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002885 if proto == 3:
2886 # Protocol 3 does not support large bytes objects.
2887 # Verify that we do not crash when processing one.
2888 with self.assertRaises((ValueError, OverflowError)):
2889 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002890 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002891 try:
2892 pickled = self.dumps(data, protocol=proto)
2893 header = (pickle.BINBYTES8 +
2894 struct.pack("<Q", len(data)))
2895 data_start = pickled.index(data)
2896 self.assertEqual(
2897 header,
2898 pickled[data_start-len(header):data_start])
2899 finally:
2900 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002901 finally:
2902 data = None
2903
2904 # All protocols use 1-byte per printable ASCII character; we add another
2905 # byte because the encoded form has to be copied into the internal buffer.
2906
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002907 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002908 def test_huge_str_32b(self, size):
2909 data = "abcd" * (size // 4)
2910 try:
2911 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002912 if proto == 0:
2913 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002914 with self.subTest(proto=proto):
2915 try:
2916 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002917 header = (pickle.BINUNICODE +
2918 struct.pack("<I", len(data)))
2919 data_start = pickled.index(b'abcd')
2920 self.assertEqual(
2921 header,
2922 pickled[data_start-len(header):data_start])
2923 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2924 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002925 finally:
2926 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002927 finally:
2928 data = None
2929
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002930 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2931 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2932 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002933
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002934 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002935 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002936 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002937 try:
2938 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002939 if proto == 0:
2940 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002941 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002942 if proto < 4:
2943 with self.assertRaises((ValueError, OverflowError)):
2944 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002945 continue
2946 try:
2947 pickled = self.dumps(data, protocol=proto)
2948 header = (pickle.BINUNICODE8 +
2949 struct.pack("<Q", len(data)))
2950 data_start = pickled.index(b'abcd')
2951 self.assertEqual(
2952 header,
2953 pickled[data_start-len(header):data_start])
2954 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2955 pickled.index(b"abcd")), len(data))
2956 finally:
2957 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002958 finally:
2959 data = None
2960
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002961
Guido van Rossum2a30b212003-02-18 22:41:24 +00002962# Test classes for reduce_ex
2963
2964class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002965 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002966 _reduce_called = 0
2967 def __reduce__(self):
2968 self._reduce_called = 1
2969 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002970
2971class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002972 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002973 _proto = None
2974 def __reduce_ex__(self, proto):
2975 self._proto = proto
2976 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002977
2978class REX_three(object):
2979 _proto = None
2980 def __reduce_ex__(self, proto):
2981 self._proto = proto
2982 return REX_two, ()
2983 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002984 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002985
Guido van Rossumd8faa362007-04-27 19:54:29 +00002986class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002987 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002988 _proto = None
2989 def __reduce_ex__(self, proto):
2990 self._proto = proto
2991 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002992
2993class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002994 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002995 _reduce_called = 0
2996 def __reduce__(self):
2997 self._reduce_called = 1
2998 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002999
3000class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003001 """This class is used to check the 4th argument (list iterator) of
3002 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003003 """
3004 def __init__(self, items=None):
3005 self.items = items if items is not None else []
3006 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003007 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003008 def append(self, item):
3009 self.items.append(item)
3010 def __reduce__(self):
3011 return type(self), (), None, iter(self.items), None
3012
3013class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003014 """This class is used to check the 5th argument (dict iterator) of
3015 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003016 """
3017 def __init__(self, table=None):
3018 self.table = table if table is not None else {}
3019 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003020 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003021 def __setitem__(self, key, value):
3022 self.table[key] = value
3023 def __reduce__(self):
3024 return type(self), (), None, None, iter(self.table.items())
3025
Guido van Rossumd8faa362007-04-27 19:54:29 +00003026
Guido van Rossum2a30b212003-02-18 22:41:24 +00003027# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003028
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003029class MyInt(int):
3030 sample = 1
3031
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003032class MyFloat(float):
3033 sample = 1.0
3034
3035class MyComplex(complex):
3036 sample = 1.0 + 0.0j
3037
3038class MyStr(str):
3039 sample = "hello"
3040
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003041class MyUnicode(str):
3042 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003043
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003044class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003045 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003046
3047class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003048 sample = [1, 2, 3]
3049
3050class MyDict(dict):
3051 sample = {"a": 1, "b": 2}
3052
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003053class MySet(set):
3054 sample = {"a", "b"}
3055
3056class MyFrozenSet(frozenset):
3057 sample = frozenset({"a", "b"})
3058
Mark Dickinson5c2db372009-12-05 20:28:34 +00003059myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003060 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003061 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003062 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003063
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003064
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003065class SlotList(MyList):
3066 __slots__ = ["foo"]
3067
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003068class SimpleNewObj(int):
3069 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003070 # raise an error, to make sure this isn't called
3071 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003072 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003073 return int(self) == int(other) and self.__dict__ == other.__dict__
3074
3075class ComplexNewObj(SimpleNewObj):
3076 def __getnewargs__(self):
3077 return ('%X' % self, 16)
3078
3079class ComplexNewObjEx(SimpleNewObj):
3080 def __getnewargs_ex__(self):
3081 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003082
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003083class BadGetattr:
3084 def __getattr__(self, key):
3085 self.foo
3086
Collin Winter771d8342009-04-16 03:18:06 +00003087
Jeremy Hylton66426532001-10-15 21:38:56 +00003088class AbstractPickleModuleTests(unittest.TestCase):
3089
3090 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003091 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003092 try:
3093 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003094 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003095 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003096 support.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003097
3098 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003099 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003100 try:
3101 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003102 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003103 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003104 support.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003105
Collin Winter771d8342009-04-16 03:18:06 +00003106 def test_load_from_and_dump_to_file(self):
3107 stream = io.BytesIO()
3108 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003109 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003110 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003111 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003112 self.assertEqual(unpickled, data)
3113
Tim Petersc0c93702003-02-13 19:30:57 +00003114 def test_highest_protocol(self):
3115 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003116 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003117
Martin v. Löwis544f1192004-07-27 05:22:33 +00003118 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003119 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003120 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003121 self.dump(123, f, -1)
3122 self.dump(123, file=f, protocol=-1)
3123 self.dumps(123, -1)
3124 self.dumps(123, protocol=-1)
3125 self.Pickler(f, -1)
3126 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003127
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003128 def test_dump_text_file(self):
3129 f = open(TESTFN, "w")
3130 try:
3131 for proto in protocols:
3132 self.assertRaises(TypeError, self.dump, 123, f, proto)
3133 finally:
3134 f.close()
3135 support.unlink(TESTFN)
3136
3137 def test_incomplete_input(self):
3138 s = io.BytesIO(b"X''.")
3139 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3140
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003141 def test_bad_init(self):
3142 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003143 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003144 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003145 def __init__(self): pass
3146
Serhiy Storchaka65452562017-11-15 14:01:08 +02003147 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003148 def __init__(self): pass
3149
3150 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3151 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3152
Antoine Pitrou91f43802019-05-26 17:10:09 +02003153 def check_dumps_loads_oob_buffers(self, dumps, loads):
3154 # No need to do the full gamut of tests here, just enough to
3155 # check that dumps() and loads() redirect their arguments
3156 # to the underlying Pickler and Unpickler, respectively.
3157 obj = ZeroCopyBytes(b"foo")
3158
3159 for proto in range(0, 5):
3160 # Need protocol >= 5 for buffer_callback
3161 with self.assertRaises(ValueError):
3162 dumps(obj, protocol=proto,
3163 buffer_callback=[].append)
3164 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3165 buffers = []
3166 buffer_callback = buffers.append
3167 data = dumps(obj, protocol=proto,
3168 buffer_callback=buffer_callback)
3169 self.assertNotIn(b"foo", data)
3170 self.assertEqual(bytes(buffers[0]), b"foo")
3171 # Need buffers argument to unpickle properly
3172 with self.assertRaises(pickle.UnpicklingError):
3173 loads(data)
3174 new = loads(data, buffers=buffers)
3175 self.assertIs(new, obj)
3176
3177 def test_dumps_loads_oob_buffers(self):
3178 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3179 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3180
3181 def test_dump_load_oob_buffers(self):
3182 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3183 def dumps(obj, **kwargs):
3184 f = io.BytesIO()
3185 self.dump(obj, f, **kwargs)
3186 return f.getvalue()
3187
3188 def loads(data, **kwargs):
3189 f = io.BytesIO(data)
3190 return self.load(f, **kwargs)
3191
3192 self.check_dumps_loads_oob_buffers(dumps, loads)
3193
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003194
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003195class AbstractPersistentPicklerTests(unittest.TestCase):
3196
3197 # This class defines persistent_id() and persistent_load()
3198 # functions that should be used by the pickler. All even integers
3199 # are pickled using persistent ids.
3200
3201 def persistent_id(self, object):
3202 if isinstance(object, int) and object % 2 == 0:
3203 self.id_count += 1
3204 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003205 elif object == "test_false_value":
3206 self.false_count += 1
3207 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003208 else:
3209 return None
3210
3211 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003212 if not oid:
3213 self.load_false_count += 1
3214 return "test_false_value"
3215 else:
3216 self.load_count += 1
3217 object = int(oid)
3218 assert object % 2 == 0
3219 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003220
3221 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003222 L = list(range(10)) + ["test_false_value"]
3223 for proto in protocols:
3224 self.id_count = 0
3225 self.false_count = 0
3226 self.load_false_count = 0
3227 self.load_count = 0
3228 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3229 self.assertEqual(self.id_count, 5)
3230 self.assertEqual(self.false_count, 1)
3231 self.assertEqual(self.load_count, 5)
3232 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003233
Collin Winter771d8342009-04-16 03:18:06 +00003234
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003235class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3236
3237 def persistent_id(self, obj):
3238 return obj
3239
3240 def persistent_load(self, pid):
3241 return pid
3242
3243 def _check_return_correct_type(self, obj, proto):
3244 unpickled = self.loads(self.dumps(obj, proto))
3245 self.assertIsInstance(unpickled, type(obj))
3246 self.assertEqual(unpickled, obj)
3247
3248 def test_return_correct_type(self):
3249 for proto in protocols:
3250 # Protocol 0 supports only ASCII strings.
3251 if proto == 0:
3252 self._check_return_correct_type("abc", 0)
3253 else:
3254 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3255 self._check_return_correct_type(obj, proto)
3256
3257 def test_protocol0_is_ascii_only(self):
3258 non_ascii_str = "\N{EMPTY SET}"
3259 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3260 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3261 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3262
3263
Collin Winter771d8342009-04-16 03:18:06 +00003264class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3265
3266 pickler_class = None
3267 unpickler_class = None
3268
3269 def setUp(self):
3270 assert self.pickler_class
3271 assert self.unpickler_class
3272
3273 def test_clear_pickler_memo(self):
3274 # To test whether clear_memo() has any effect, we pickle an object,
3275 # then pickle it again without clearing the memo; the two serialized
3276 # forms should be different. If we clear_memo() and then pickle the
3277 # object again, the third serialized form should be identical to the
3278 # first one we obtained.
3279 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003280 for proto in protocols:
3281 f = io.BytesIO()
3282 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003283
Serhiy Storchakac8695292018-04-04 00:11:27 +03003284 pickler.dump(data)
3285 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003286
Serhiy Storchakac8695292018-04-04 00:11:27 +03003287 # Reset BytesIO object.
3288 f.seek(0)
3289 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003290
Serhiy Storchakac8695292018-04-04 00:11:27 +03003291 pickler.dump(data)
3292 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003293
Serhiy Storchakac8695292018-04-04 00:11:27 +03003294 # Reset the Pickler and BytesIO objects.
3295 pickler.clear_memo()
3296 f.seek(0)
3297 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003298
Serhiy Storchakac8695292018-04-04 00:11:27 +03003299 pickler.dump(data)
3300 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003301
Serhiy Storchakac8695292018-04-04 00:11:27 +03003302 self.assertNotEqual(first_pickled, second_pickled)
3303 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003304
3305 def test_priming_pickler_memo(self):
3306 # Verify that we can set the Pickler's memo attribute.
3307 data = ["abcdefg", "abcdefg", 44]
3308 f = io.BytesIO()
3309 pickler = self.pickler_class(f)
3310
3311 pickler.dump(data)
3312 first_pickled = f.getvalue()
3313
3314 f = io.BytesIO()
3315 primed = self.pickler_class(f)
3316 primed.memo = pickler.memo
3317
3318 primed.dump(data)
3319 primed_pickled = f.getvalue()
3320
3321 self.assertNotEqual(first_pickled, primed_pickled)
3322
3323 def test_priming_unpickler_memo(self):
3324 # Verify that we can set the Unpickler's memo attribute.
3325 data = ["abcdefg", "abcdefg", 44]
3326 f = io.BytesIO()
3327 pickler = self.pickler_class(f)
3328
3329 pickler.dump(data)
3330 first_pickled = f.getvalue()
3331
3332 f = io.BytesIO()
3333 primed = self.pickler_class(f)
3334 primed.memo = pickler.memo
3335
3336 primed.dump(data)
3337 primed_pickled = f.getvalue()
3338
3339 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3340 unpickled_data1 = unpickler.load()
3341
3342 self.assertEqual(unpickled_data1, data)
3343
3344 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3345 primed.memo = unpickler.memo
3346 unpickled_data2 = primed.load()
3347
3348 primed.memo.clear()
3349
3350 self.assertEqual(unpickled_data2, data)
3351 self.assertTrue(unpickled_data2 is unpickled_data1)
3352
3353 def test_reusing_unpickler_objects(self):
3354 data1 = ["abcdefg", "abcdefg", 44]
3355 f = io.BytesIO()
3356 pickler = self.pickler_class(f)
3357 pickler.dump(data1)
3358 pickled1 = f.getvalue()
3359
3360 data2 = ["abcdefg", 44, 44]
3361 f = io.BytesIO()
3362 pickler = self.pickler_class(f)
3363 pickler.dump(data2)
3364 pickled2 = f.getvalue()
3365
3366 f = io.BytesIO()
3367 f.write(pickled1)
3368 f.seek(0)
3369 unpickler = self.unpickler_class(f)
3370 self.assertEqual(unpickler.load(), data1)
3371
3372 f.seek(0)
3373 f.truncate()
3374 f.write(pickled2)
3375 f.seek(0)
3376 self.assertEqual(unpickler.load(), data2)
3377
Antoine Pitrou9f378722020-02-23 23:33:53 +01003378 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003379 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003380 with self.subTest(proto=proto):
3381 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3382 f = ioclass()
3383 pickler = self.pickler_class(f, protocol=proto)
3384 pickler.dump(data1)
3385 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003386
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003387 N = 5
3388 f = ioclass(pickled * N)
3389 unpickler = self.unpickler_class(f)
3390 for i in range(N):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003391 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003392 pos = f.tell()
3393 self.assertEqual(unpickler.load(), data1)
Antoine Pitrou9f378722020-02-23 23:33:53 +01003394 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003395 self.assertEqual(f.tell(), pos + len(pickled))
3396 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003397
3398 def test_multiple_unpicklings_seekable(self):
3399 self._check_multiple_unpicklings(io.BytesIO)
3400
3401 def test_multiple_unpicklings_unseekable(self):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003402 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3403
3404 def test_multiple_unpicklings_minimal(self):
3405 # File-like object that doesn't support peek() and readinto()
3406 # (bpo-39681)
3407 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003408
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003409 def test_unpickling_buffering_readline(self):
3410 # Issue #12687: the unpickler's buffering logic could fail with
3411 # text mode opcodes.
3412 data = list(range(10))
3413 for proto in protocols:
3414 for buf_size in range(1, 11):
3415 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3416 pickler = self.pickler_class(f, protocol=proto)
3417 pickler.dump(data)
3418 f.seek(0)
3419 unpickler = self.unpickler_class(f)
3420 self.assertEqual(unpickler.load(), data)
3421
Collin Winter771d8342009-04-16 03:18:06 +00003422
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003423# Tests for dispatch_table attribute
3424
3425REDUCE_A = 'reduce_A'
3426
3427class AAA(object):
3428 def __reduce__(self):
3429 return str, (REDUCE_A,)
3430
3431class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003432 def __init__(self):
3433 # Add an instance attribute to enable state-saving routines at pickling
3434 # time.
3435 self.a = "some attribute"
3436
3437 def __setstate__(self, state):
3438 self.a = "BBB.__setstate__"
3439
3440
3441def setstate_bbb(obj, state):
3442 """Custom state setter for BBB objects
3443
3444 Such callable may be created by other persons than the ones who created the
3445 BBB class. If passed as the state_setter item of a custom reducer, this
3446 allows for custom state setting behavior of BBB objects. One can think of
3447 it as the analogous of list_setitems or dict_setitems but for foreign
3448 classes/functions.
3449 """
3450 obj.a = "custom state_setter"
3451
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003452
Pierre Glaser289f1f82019-05-08 23:08:25 +02003453
3454class AbstractCustomPicklerClass:
3455 """Pickler implementing a reducing hook using reducer_override."""
3456 def reducer_override(self, obj):
3457 obj_name = getattr(obj, "__name__", None)
3458
3459 if obj_name == 'f':
3460 # asking the pickler to save f as 5
3461 return int, (5, )
3462
3463 if obj_name == 'MyClass':
3464 return str, ('some str',)
3465
3466 elif obj_name == 'g':
3467 # in this case, the callback returns an invalid result (not a 2-5
3468 # tuple or a string), the pickler should raise a proper error.
3469 return False
3470
3471 elif obj_name == 'h':
3472 # Simulate a case when the reducer fails. The error should
3473 # be propagated to the original ``dump`` call.
3474 raise ValueError('The reducer just failed')
3475
3476 return NotImplemented
3477
3478class AbstractHookTests(unittest.TestCase):
3479 def test_pickler_hook(self):
3480 # test the ability of a custom, user-defined CPickler subclass to
3481 # override the default reducing routines of any type using the method
3482 # reducer_override
3483
3484 def f():
3485 pass
3486
3487 def g():
3488 pass
3489
3490 def h():
3491 pass
3492
3493 class MyClass:
3494 pass
3495
3496 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3497 with self.subTest(proto=proto):
3498 bio = io.BytesIO()
3499 p = self.pickler_class(bio, proto)
3500
3501 p.dump([f, MyClass, math.log])
3502 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3503
3504 self.assertEqual(new_f, 5)
3505 self.assertEqual(some_str, 'some str')
3506 # math.log does not have its usual reducer overriden, so the
3507 # custom reduction callback should silently direct the pickler
3508 # to the default pickling by attribute, by returning
3509 # NotImplemented
3510 self.assertIs(math_log, math.log)
3511
3512 with self.assertRaises(pickle.PicklingError):
3513 p.dump(g)
3514
3515 with self.assertRaisesRegex(
3516 ValueError, 'The reducer just failed'):
3517 p.dump(h)
3518
Pierre Glaser0f2f35e2020-02-02 19:55:21 +01003519 @support.cpython_only
3520 def test_reducer_override_no_reference_cycle(self):
3521 # bpo-39492: reducer_override used to induce a spurious reference cycle
3522 # inside the Pickler object, that could prevent all serialized objects
3523 # from being garbage-collected without explicity invoking gc.collect.
3524
3525 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3526 with self.subTest(proto=proto):
3527 def f():
3528 pass
3529
3530 wr = weakref.ref(f)
3531
3532 bio = io.BytesIO()
3533 p = self.pickler_class(bio, proto)
3534 p.dump(f)
3535 new_f = pickle.loads(bio.getvalue())
3536 assert new_f == 5
3537
3538 del p
3539 del f
3540
3541 self.assertIsNone(wr())
3542
Pierre Glaser289f1f82019-05-08 23:08:25 +02003543
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003544class AbstractDispatchTableTests(unittest.TestCase):
3545
3546 def test_default_dispatch_table(self):
3547 # No dispatch_table attribute by default
3548 f = io.BytesIO()
3549 p = self.pickler_class(f, 0)
3550 with self.assertRaises(AttributeError):
3551 p.dispatch_table
3552 self.assertFalse(hasattr(p, 'dispatch_table'))
3553
3554 def test_class_dispatch_table(self):
3555 # A dispatch_table attribute can be specified class-wide
3556 dt = self.get_dispatch_table()
3557
3558 class MyPickler(self.pickler_class):
3559 dispatch_table = dt
3560
3561 def dumps(obj, protocol=None):
3562 f = io.BytesIO()
3563 p = MyPickler(f, protocol)
3564 self.assertEqual(p.dispatch_table, dt)
3565 p.dump(obj)
3566 return f.getvalue()
3567
3568 self._test_dispatch_table(dumps, dt)
3569
3570 def test_instance_dispatch_table(self):
3571 # A dispatch_table attribute can also be specified instance-wide
3572 dt = self.get_dispatch_table()
3573
3574 def dumps(obj, protocol=None):
3575 f = io.BytesIO()
3576 p = self.pickler_class(f, protocol)
3577 p.dispatch_table = dt
3578 self.assertEqual(p.dispatch_table, dt)
3579 p.dump(obj)
3580 return f.getvalue()
3581
3582 self._test_dispatch_table(dumps, dt)
3583
3584 def _test_dispatch_table(self, dumps, dispatch_table):
3585 def custom_load_dump(obj):
3586 return pickle.loads(dumps(obj, 0))
3587
3588 def default_load_dump(obj):
3589 return pickle.loads(pickle.dumps(obj, 0))
3590
3591 # pickling complex numbers using protocol 0 relies on copyreg
3592 # so check pickling a complex number still works
3593 z = 1 + 2j
3594 self.assertEqual(custom_load_dump(z), z)
3595 self.assertEqual(default_load_dump(z), z)
3596
3597 # modify pickling of complex
3598 REDUCE_1 = 'reduce_1'
3599 def reduce_1(obj):
3600 return str, (REDUCE_1,)
3601 dispatch_table[complex] = reduce_1
3602 self.assertEqual(custom_load_dump(z), REDUCE_1)
3603 self.assertEqual(default_load_dump(z), z)
3604
3605 # check picklability of AAA and BBB
3606 a = AAA()
3607 b = BBB()
3608 self.assertEqual(custom_load_dump(a), REDUCE_A)
3609 self.assertIsInstance(custom_load_dump(b), BBB)
3610 self.assertEqual(default_load_dump(a), REDUCE_A)
3611 self.assertIsInstance(default_load_dump(b), BBB)
3612
3613 # modify pickling of BBB
3614 dispatch_table[BBB] = reduce_1
3615 self.assertEqual(custom_load_dump(a), REDUCE_A)
3616 self.assertEqual(custom_load_dump(b), REDUCE_1)
3617 self.assertEqual(default_load_dump(a), REDUCE_A)
3618 self.assertIsInstance(default_load_dump(b), BBB)
3619
3620 # revert pickling of BBB and modify pickling of AAA
3621 REDUCE_2 = 'reduce_2'
3622 def reduce_2(obj):
3623 return str, (REDUCE_2,)
3624 dispatch_table[AAA] = reduce_2
3625 del dispatch_table[BBB]
3626 self.assertEqual(custom_load_dump(a), REDUCE_2)
3627 self.assertIsInstance(custom_load_dump(b), BBB)
3628 self.assertEqual(default_load_dump(a), REDUCE_A)
3629 self.assertIsInstance(default_load_dump(b), BBB)
3630
Pierre Glaser65d98d02019-05-08 21:40:25 +02003631 # End-to-end testing of save_reduce with the state_setter keyword
3632 # argument. This is a dispatch_table test as the primary goal of
3633 # state_setter is to tweak objects reduction behavior.
3634 # In particular, state_setter is useful when the default __setstate__
3635 # behavior is not flexible enough.
3636
3637 # No custom reducer for b has been registered for now, so
3638 # BBB.__setstate__ should be used at unpickling time
3639 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3640
3641 def reduce_bbb(obj):
3642 return BBB, (), obj.__dict__, None, None, setstate_bbb
3643
3644 dispatch_table[BBB] = reduce_bbb
3645
3646 # The custom reducer reduce_bbb includes a state setter, that should
3647 # have priority over BBB.__setstate__
3648 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3649
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003650
Guido van Rossum98297ee2007-11-06 21:34:58 +00003651if __name__ == "__main__":
3652 # Print some stuff that can be used to rewrite DATA{0,1,2}
3653 from pickletools import dis
3654 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003655 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003656 p = pickle.dumps(x, i)
3657 print("DATA{0} = (".format(i))
3658 for j in range(0, len(p), 20):
3659 b = bytes(p[j:j+20])
3660 print(" {0!r}".format(b))
3661 print(")")
3662 print()
3663 print("# Disassembly of DATA{0}".format(i))
3664 print("DATA{0}_DIS = \"\"\"\\".format(i))
3665 dis(p)
3666 print("\"\"\"")
3667 print()