blob: afbc2b3bf0a79c13656ff63c81dcccd4dab969ac [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
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020024from test import support
Hai Shi883bc632020-07-06 17:12:49 +080025from test.support import os_helper
Antoine Pitrou82be19f2011-08-29 23:09:33 +020026from test.support import (
Hai Shi883bc632020-07-06 17:12:49 +080027 TestFailed, run_with_locale, no_tracing,
28 _2G, _4G, bigmemtest
Antoine Pitrou82be19f2011-08-29 23:09:33 +020029 )
Hai Shi883bc632020-07-06 17:12:49 +080030from test.support.import_helper import forget
31from test.support.os_helper import TESTFN
Hai Shie80697d2020-05-28 06:10:27 +080032from test.support import threading_helper
Victor Stinner83628932020-06-17 18:07:13 +020033from test.support.warnings_helper import save_restore_warnings_filters
Tim Peterse089c682001-04-10 03:41:41 +000034
Guido van Rossum98297ee2007-11-06 21:34:58 +000035from pickle import bytes_types
36
Victor Stinner83628932020-06-17 18:07:13 +020037
38# bpo-41003: Save/restore warnings filters to leave them unchanged.
39# Ignore filters installed by numpy.
40try:
41 with save_restore_warnings_filters():
42 import numpy as np
43except ImportError:
44 np = None
45
46
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030047requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
48 "test is only meaningful on 32-bit builds")
49
Tim Petersee1a53c2003-02-02 02:57:53 +000050# Tests that try a number of pickle protocols should have a
51# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000052# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000053protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000054
Tim Peters22e71712003-02-03 22:27:38 +000055
56# Return True if opcode code appears in the pickle, else False.
57def opcode_in_pickle(code, pickle):
58 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000059 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000060 return True
61 return False
62
Tim Peters8d2613a2003-02-11 16:40:16 +000063# Return the number of times opcode code appears in pickle.
64def count_opcode(code, pickle):
65 n = 0
66 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000067 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000068 n += 1
69 return n
70
Antoine Pitrou04248a82010-10-12 20:51:21 +000071
72class UnseekableIO(io.BytesIO):
73 def peek(self, *args):
74 raise NotImplementedError
75
76 def seekable(self):
77 return False
78
79 def seek(self, *args):
80 raise io.UnsupportedOperation
81
82 def tell(self):
83 raise io.UnsupportedOperation
84
85
Antoine Pitrou9f378722020-02-23 23:33:53 +010086class MinimalIO(object):
87 """
88 A file-like object that doesn't support readinto().
89 """
90 def __init__(self, *args):
91 self._bio = io.BytesIO(*args)
92 self.getvalue = self._bio.getvalue
93 self.read = self._bio.read
94 self.readline = self._bio.readline
95 self.write = self._bio.write
96
97
Tim Peters3e667d52003-02-04 21:47:44 +000098# We can't very well test the extension registry without putting known stuff
99# in it, but we have to be careful to restore its original state. Code
100# should do this:
101#
102# e = ExtensionSaver(extension_code)
103# try:
104# fiddle w/ the extension registry's stuff for extension_code
105# finally:
106# e.restore()
107
108class ExtensionSaver:
109 # Remember current registration for code (if any), and remove it (if
110 # there is one).
111 def __init__(self, code):
112 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000113 if code in copyreg._inverted_registry:
114 self.pair = copyreg._inverted_registry[code]
115 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000116 else:
117 self.pair = None
118
119 # Restore previous registration for code.
120 def restore(self):
121 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000122 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000123 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000124 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000125 pair = self.pair
126 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000127 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000128
Jeremy Hylton66426532001-10-15 21:38:56 +0000129class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000130 def __eq__(self, other):
131 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000132
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000133class D(C):
134 def __init__(self, arg):
135 pass
136
137class E(C):
138 def __getinitargs__(self):
139 return ()
140
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100141class H(object):
142 pass
143
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200144# Hashable mutable key
145class K(object):
146 def __init__(self, value):
147 self.value = value
148
149 def __reduce__(self):
150 # Shouldn't support the recursion itself
151 return K, (self.value,)
152
Jeremy Hylton66426532001-10-15 21:38:56 +0000153import __main__
154__main__.C = C
155C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000156__main__.D = D
157D.__module__ = "__main__"
158__main__.E = E
159E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100160__main__.H = H
161H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200162__main__.K = K
163K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000164
165class myint(int):
166 def __init__(self, x):
167 self.str = str(x)
168
169class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000170
Jeremy Hylton66426532001-10-15 21:38:56 +0000171 def __init__(self, a, b):
172 self.a = a
173 self.b = b
174
175 def __getinitargs__(self):
176 return self.a, self.b
177
Guido van Rossum04a86612001-12-19 16:58:54 +0000178class metaclass(type):
179 pass
180
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000181class use_metaclass(object, metaclass=metaclass):
182 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000183
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200184class pickling_metaclass(type):
185 def __eq__(self, other):
186 return (type(self) == type(other) and
187 self.reduce_args == other.reduce_args)
188
189 def __reduce__(self):
190 return (create_dynamic_class, self.reduce_args)
191
192def create_dynamic_class(name, bases):
193 result = pickling_metaclass(name, bases, dict())
194 result.reduce_args = (name, bases)
195 return result
196
Antoine Pitrou91f43802019-05-26 17:10:09 +0200197
198class ZeroCopyBytes(bytes):
199 readonly = True
200 c_contiguous = True
201 f_contiguous = True
202 zero_copy_reconstruct = True
203
204 def __reduce_ex__(self, protocol):
205 if protocol >= 5:
206 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
207 else:
208 return type(self)._reconstruct, (bytes(self),)
209
210 def __repr__(self):
211 return "{}({!r})".format(self.__class__.__name__, bytes(self))
212
213 __str__ = __repr__
214
215 @classmethod
216 def _reconstruct(cls, obj):
217 with memoryview(obj) as m:
218 obj = m.obj
219 if type(obj) is cls:
220 # Zero-copy
221 return obj
222 else:
223 return cls(obj)
224
225
226class ZeroCopyBytearray(bytearray):
227 readonly = False
228 c_contiguous = True
229 f_contiguous = True
230 zero_copy_reconstruct = True
231
232 def __reduce_ex__(self, protocol):
233 if protocol >= 5:
234 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
235 else:
236 return type(self)._reconstruct, (bytes(self),)
237
238 def __repr__(self):
239 return "{}({!r})".format(self.__class__.__name__, bytes(self))
240
241 __str__ = __repr__
242
243 @classmethod
244 def _reconstruct(cls, obj):
245 with memoryview(obj) as m:
246 obj = m.obj
247 if type(obj) is cls:
248 # Zero-copy
249 return obj
250 else:
251 return cls(obj)
252
253
254if _testbuffer is not None:
255
256 class PicklableNDArray:
257 # A not-really-zero-copy picklable ndarray, as the ndarray()
258 # constructor doesn't allow for it
259
260 zero_copy_reconstruct = False
261
262 def __init__(self, *args, **kwargs):
263 self.array = _testbuffer.ndarray(*args, **kwargs)
264
265 def __getitem__(self, idx):
266 cls = type(self)
267 new = cls.__new__(cls)
268 new.array = self.array[idx]
269 return new
270
271 @property
272 def readonly(self):
273 return self.array.readonly
274
275 @property
276 def c_contiguous(self):
277 return self.array.c_contiguous
278
279 @property
280 def f_contiguous(self):
281 return self.array.f_contiguous
282
283 def __eq__(self, other):
284 if not isinstance(other, PicklableNDArray):
285 return NotImplemented
286 return (other.array.format == self.array.format and
287 other.array.shape == self.array.shape and
288 other.array.strides == self.array.strides and
289 other.array.readonly == self.array.readonly and
290 other.array.tobytes() == self.array.tobytes())
291
292 def __ne__(self, other):
293 if not isinstance(other, PicklableNDArray):
294 return NotImplemented
295 return not (self == other)
296
297 def __repr__(self):
298 return (f"{type(self)}(shape={self.array.shape},"
299 f"strides={self.array.strides}, "
300 f"bytes={self.array.tobytes()})")
301
302 def __reduce_ex__(self, protocol):
303 if not self.array.contiguous:
304 raise NotImplementedError("Reconstructing a non-contiguous "
305 "ndarray does not seem possible")
306 ndarray_kwargs = {"shape": self.array.shape,
307 "strides": self.array.strides,
308 "format": self.array.format,
309 "flags": (0 if self.readonly
310 else _testbuffer.ND_WRITABLE)}
311 pb = pickle.PickleBuffer(self.array)
312 if protocol >= 5:
313 return (type(self)._reconstruct,
314 (pb, ndarray_kwargs))
315 else:
316 # Need to serialize the bytes in physical order
317 with pb.raw() as m:
318 return (type(self)._reconstruct,
319 (m.tobytes(), ndarray_kwargs))
320
321 @classmethod
322 def _reconstruct(cls, obj, kwargs):
323 with memoryview(obj) as m:
324 # For some reason, ndarray() wants a list of integers...
325 # XXX This only works if format == 'B'
326 items = list(m.tobytes())
327 return cls(items, **kwargs)
328
329
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300330# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000331# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000332
Guido van Rossum98297ee2007-11-06 21:34:58 +0000333DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200334 b'(lp0\nL0L\naL1L\naF2.0\n'
335 b'ac__builtin__\ncomple'
336 b'x\np1\n(F3.0\nF0.0\ntp2\n'
337 b'Rp3\naL1L\naL-1L\naL255'
338 b'L\naL-255L\naL-256L\naL'
339 b'65535L\naL-65535L\naL-'
340 b'65536L\naL2147483647L'
341 b'\naL-2147483647L\naL-2'
342 b'147483648L\na(Vabc\np4'
343 b'\ng4\nccopy_reg\n_recon'
344 b'structor\np5\n(c__main'
345 b'__\nC\np6\nc__builtin__'
346 b'\nobject\np7\nNtp8\nRp9\n'
347 b'(dp10\nVfoo\np11\nL1L\ns'
348 b'Vbar\np12\nL2L\nsbg9\ntp'
349 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000350)
Tim Peterse9358162001-01-22 22:05:20 +0000351
Guido van Rossum98297ee2007-11-06 21:34:58 +0000352# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000353DATA0_DIS = """\
354 0: ( MARK
355 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000356 2: p PUT 0
357 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000358 9: a APPEND
359 10: L LONG 1
360 14: a APPEND
361 15: F FLOAT 2.0
362 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200363 21: c GLOBAL '__builtin__ complex'
364 42: p PUT 1
365 45: ( MARK
366 46: F FLOAT 3.0
367 51: F FLOAT 0.0
368 56: t TUPLE (MARK at 45)
369 57: p PUT 2
370 60: R REDUCE
371 61: p PUT 3
372 64: a APPEND
373 65: L LONG 1
374 69: a APPEND
375 70: L LONG -1
376 75: a APPEND
377 76: L LONG 255
378 82: a APPEND
379 83: L LONG -255
380 90: a APPEND
381 91: L LONG -256
382 98: a APPEND
383 99: L LONG 65535
384 107: a APPEND
385 108: L LONG -65535
386 117: a APPEND
387 118: L LONG -65536
388 127: a APPEND
389 128: L LONG 2147483647
390 141: a APPEND
391 142: L LONG -2147483647
392 156: a APPEND
393 157: L LONG -2147483648
394 171: a APPEND
395 172: ( MARK
396 173: V UNICODE 'abc'
397 178: p PUT 4
398 181: g GET 4
399 184: c GLOBAL 'copy_reg _reconstructor'
400 209: p PUT 5
401 212: ( MARK
402 213: c GLOBAL '__main__ C'
403 225: p PUT 6
404 228: c GLOBAL '__builtin__ object'
405 248: p PUT 7
406 251: N NONE
407 252: t TUPLE (MARK at 212)
408 253: p PUT 8
409 256: R REDUCE
410 257: p PUT 9
411 260: ( MARK
412 261: d DICT (MARK at 260)
413 262: p PUT 10
414 266: V UNICODE 'foo'
415 271: p PUT 11
416 275: L LONG 1
417 279: s SETITEM
418 280: V UNICODE 'bar'
419 285: p PUT 12
420 289: L LONG 2
421 293: s SETITEM
422 294: b BUILD
423 295: g GET 9
424 298: t TUPLE (MARK at 172)
425 299: p PUT 13
426 303: a APPEND
427 304: g GET 13
428 308: a APPEND
429 309: L LONG 5
430 313: a APPEND
431 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000432highest protocol among opcodes = 0
433"""
434
Guido van Rossum98297ee2007-11-06 21:34:58 +0000435DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200436 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
437 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000438 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
439 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
440 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
441 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200442 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000443 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200444 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000445 b'object\nq\x07Ntq\x08Rq\t}q\n('
446 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
447 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
448)
Tim Peters70b02d72003-02-02 17:26:40 +0000449
Guido van Rossum98297ee2007-11-06 21:34:58 +0000450# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000451DATA1_DIS = """\
452 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000453 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000454 3: ( MARK
455 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000456 6: K BININT1 1
457 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200458 17: c GLOBAL '__builtin__ complex'
459 38: q BINPUT 1
460 40: ( MARK
461 41: G BINFLOAT 3.0
462 50: G BINFLOAT 0.0
463 59: t TUPLE (MARK at 40)
464 60: q BINPUT 2
465 62: R REDUCE
466 63: q BINPUT 3
467 65: K BININT1 1
468 67: J BININT -1
469 72: K BININT1 255
470 74: J BININT -255
471 79: J BININT -256
472 84: M BININT2 65535
473 87: J BININT -65535
474 92: J BININT -65536
475 97: J BININT 2147483647
476 102: J BININT -2147483647
477 107: J BININT -2147483648
478 112: ( MARK
479 113: X BINUNICODE 'abc'
480 121: q BINPUT 4
481 123: h BINGET 4
482 125: c GLOBAL 'copy_reg _reconstructor'
483 150: q BINPUT 5
484 152: ( MARK
485 153: c GLOBAL '__main__ C'
486 165: q BINPUT 6
487 167: c GLOBAL '__builtin__ object'
488 187: q BINPUT 7
489 189: N NONE
490 190: t TUPLE (MARK at 152)
491 191: q BINPUT 8
492 193: R REDUCE
493 194: q BINPUT 9
494 196: } EMPTY_DICT
495 197: q BINPUT 10
496 199: ( MARK
497 200: X BINUNICODE 'foo'
498 208: q BINPUT 11
499 210: K BININT1 1
500 212: X BINUNICODE 'bar'
501 220: q BINPUT 12
502 222: K BININT1 2
503 224: u SETITEMS (MARK at 199)
504 225: b BUILD
505 226: h BINGET 9
506 228: t TUPLE (MARK at 112)
507 229: q BINPUT 13
508 231: h BINGET 13
509 233: K BININT1 5
510 235: e APPENDS (MARK at 3)
511 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000512highest protocol among opcodes = 1
513"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000514
Guido van Rossum98297ee2007-11-06 21:34:58 +0000515DATA2 = (
516 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200517 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000518 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
519 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
520 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
521 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
522 b'bcq\x04h\x04c__main__\nC\nq\x05'
523 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
524 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
525 b'\nK\x05e.'
526)
Tim Petersfc273752003-03-02 04:54:24 +0000527
Guido van Rossum98297ee2007-11-06 21:34:58 +0000528# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000529DATA2_DIS = """\
530 0: \x80 PROTO 2
531 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000532 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000533 5: ( MARK
534 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000535 8: K BININT1 1
536 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200537 19: c GLOBAL '__builtin__ complex'
538 40: q BINPUT 1
539 42: G BINFLOAT 3.0
540 51: G BINFLOAT 0.0
541 60: \x86 TUPLE2
542 61: q BINPUT 2
543 63: R REDUCE
544 64: q BINPUT 3
545 66: K BININT1 1
546 68: J BININT -1
547 73: K BININT1 255
548 75: J BININT -255
549 80: J BININT -256
550 85: M BININT2 65535
551 88: J BININT -65535
552 93: J BININT -65536
553 98: J BININT 2147483647
554 103: J BININT -2147483647
555 108: J BININT -2147483648
556 113: ( MARK
557 114: X BINUNICODE 'abc'
558 122: q BINPUT 4
559 124: h BINGET 4
560 126: c GLOBAL '__main__ C'
561 138: q BINPUT 5
562 140: ) EMPTY_TUPLE
563 141: \x81 NEWOBJ
564 142: q BINPUT 6
565 144: } EMPTY_DICT
566 145: q BINPUT 7
567 147: ( MARK
568 148: X BINUNICODE 'foo'
569 156: q BINPUT 8
570 158: K BININT1 1
571 160: X BINUNICODE 'bar'
572 168: q BINPUT 9
573 170: K BININT1 2
574 172: u SETITEMS (MARK at 147)
575 173: b BUILD
576 174: h BINGET 6
577 176: t TUPLE (MARK at 113)
578 177: q BINPUT 10
579 179: h BINGET 10
580 181: K BININT1 5
581 183: e APPENDS (MARK at 5)
582 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000583highest protocol among opcodes = 2
584"""
585
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300586DATA3 = (
587 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
588 b'builtins\ncomplex\nq\x01G'
589 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
590 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
591 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
592 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
593 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
594 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
595 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
596 b'e.'
597)
598
599# Disassembly of DATA3
600DATA3_DIS = """\
601 0: \x80 PROTO 3
602 2: ] EMPTY_LIST
603 3: q BINPUT 0
604 5: ( MARK
605 6: K BININT1 0
606 8: K BININT1 1
607 10: G BINFLOAT 2.0
608 19: c GLOBAL 'builtins complex'
609 37: q BINPUT 1
610 39: G BINFLOAT 3.0
611 48: G BINFLOAT 0.0
612 57: \x86 TUPLE2
613 58: q BINPUT 2
614 60: R REDUCE
615 61: q BINPUT 3
616 63: K BININT1 1
617 65: J BININT -1
618 70: K BININT1 255
619 72: J BININT -255
620 77: J BININT -256
621 82: M BININT2 65535
622 85: J BININT -65535
623 90: J BININT -65536
624 95: J BININT 2147483647
625 100: J BININT -2147483647
626 105: J BININT -2147483648
627 110: ( MARK
628 111: X BINUNICODE 'abc'
629 119: q BINPUT 4
630 121: h BINGET 4
631 123: c GLOBAL '__main__ C'
632 135: q BINPUT 5
633 137: ) EMPTY_TUPLE
634 138: \x81 NEWOBJ
635 139: q BINPUT 6
636 141: } EMPTY_DICT
637 142: q BINPUT 7
638 144: ( MARK
639 145: X BINUNICODE 'bar'
640 153: q BINPUT 8
641 155: K BININT1 2
642 157: X BINUNICODE 'foo'
643 165: q BINPUT 9
644 167: K BININT1 1
645 169: u SETITEMS (MARK at 144)
646 170: b BUILD
647 171: h BINGET 6
648 173: t TUPLE (MARK at 110)
649 174: q BINPUT 10
650 176: h BINGET 10
651 178: K BININT1 5
652 180: e APPENDS (MARK at 5)
653 181: . STOP
654highest protocol among opcodes = 2
655"""
656
657DATA4 = (
658 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
659 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
660 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
661 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
662 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
663 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
664 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
665 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
666 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
667)
668
669# Disassembly of DATA4
670DATA4_DIS = """\
671 0: \x80 PROTO 4
672 2: \x95 FRAME 168
673 11: ] EMPTY_LIST
674 12: \x94 MEMOIZE
675 13: ( MARK
676 14: K BININT1 0
677 16: K BININT1 1
678 18: G BINFLOAT 2.0
679 27: \x8c SHORT_BINUNICODE 'builtins'
680 37: \x94 MEMOIZE
681 38: \x8c SHORT_BINUNICODE 'complex'
682 47: \x94 MEMOIZE
683 48: \x93 STACK_GLOBAL
684 49: \x94 MEMOIZE
685 50: G BINFLOAT 3.0
686 59: G BINFLOAT 0.0
687 68: \x86 TUPLE2
688 69: \x94 MEMOIZE
689 70: R REDUCE
690 71: \x94 MEMOIZE
691 72: K BININT1 1
692 74: J BININT -1
693 79: K BININT1 255
694 81: J BININT -255
695 86: J BININT -256
696 91: M BININT2 65535
697 94: J BININT -65535
698 99: J BININT -65536
699 104: J BININT 2147483647
700 109: J BININT -2147483647
701 114: J BININT -2147483648
702 119: ( MARK
703 120: \x8c SHORT_BINUNICODE 'abc'
704 125: \x94 MEMOIZE
705 126: h BINGET 6
706 128: \x8c SHORT_BINUNICODE '__main__'
707 138: \x94 MEMOIZE
708 139: \x8c SHORT_BINUNICODE 'C'
709 142: \x94 MEMOIZE
710 143: \x93 STACK_GLOBAL
711 144: \x94 MEMOIZE
712 145: ) EMPTY_TUPLE
713 146: \x81 NEWOBJ
714 147: \x94 MEMOIZE
715 148: } EMPTY_DICT
716 149: \x94 MEMOIZE
717 150: ( MARK
718 151: \x8c SHORT_BINUNICODE 'bar'
719 156: \x94 MEMOIZE
720 157: K BININT1 2
721 159: \x8c SHORT_BINUNICODE 'foo'
722 164: \x94 MEMOIZE
723 165: K BININT1 1
724 167: u SETITEMS (MARK at 150)
725 168: b BUILD
726 169: h BINGET 10
727 171: t TUPLE (MARK at 119)
728 172: \x94 MEMOIZE
729 173: h BINGET 14
730 175: K BININT1 5
731 177: e APPENDS (MARK at 13)
732 178: . STOP
733highest protocol among opcodes = 4
734"""
735
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000736# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300737DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000738
739# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300740DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000741
742# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300743DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
744 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
745 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
746 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
747 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
748 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000749
750# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300751DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000752
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100753python2_exceptions_without_args = (
754 ArithmeticError,
755 AssertionError,
756 AttributeError,
757 BaseException,
758 BufferError,
759 BytesWarning,
760 DeprecationWarning,
761 EOFError,
762 EnvironmentError,
763 Exception,
764 FloatingPointError,
765 FutureWarning,
766 GeneratorExit,
767 IOError,
768 ImportError,
769 ImportWarning,
770 IndentationError,
771 IndexError,
772 KeyError,
773 KeyboardInterrupt,
774 LookupError,
775 MemoryError,
776 NameError,
777 NotImplementedError,
778 OSError,
779 OverflowError,
780 PendingDeprecationWarning,
781 ReferenceError,
782 RuntimeError,
783 RuntimeWarning,
784 # StandardError is gone in Python 3, we map it to Exception
785 StopIteration,
786 SyntaxError,
787 SyntaxWarning,
788 SystemError,
789 SystemExit,
790 TabError,
791 TypeError,
792 UnboundLocalError,
793 UnicodeError,
794 UnicodeWarning,
795 UserWarning,
796 ValueError,
797 Warning,
798 ZeroDivisionError,
799)
800
801exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
802
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100803# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300804DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
805 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
806 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100807
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000808
Jeremy Hylton66426532001-10-15 21:38:56 +0000809def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000810 c = C()
811 c.foo = 1
812 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000813 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000814 # Append some integer test cases at cPickle.c's internal size
815 # cutoffs.
816 uint1max = 0xff
817 uint2max = 0xffff
818 int4max = 0x7fffffff
819 x.extend([1, -1,
820 uint1max, -uint1max, -uint1max-1,
821 uint2max, -uint2max, -uint2max-1,
822 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000823 y = ('abc', 'abc', c, c)
824 x.append(y)
825 x.append(y)
826 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000827 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000828
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100829
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300830class AbstractUnpickleTests(unittest.TestCase):
831 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100832
Jeremy Hylton66426532001-10-15 21:38:56 +0000833 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000834
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100835 def assert_is_copy(self, obj, objcopy, msg=None):
836 """Utility method to verify if two objects are copies of each others.
837 """
838 if msg is None:
839 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
840 self.assertEqual(obj, objcopy, msg=msg)
841 self.assertIs(type(obj), type(objcopy), msg=msg)
842 if hasattr(obj, '__dict__'):
843 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
844 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
845 if hasattr(obj, '__slots__'):
846 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
847 for slot in obj.__slots__:
848 self.assertEqual(
849 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
850 self.assertEqual(getattr(obj, slot, None),
851 getattr(objcopy, slot, None), msg=msg)
852
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200853 def check_unpickling_error(self, errors, data):
854 with self.subTest(data=data), \
855 self.assertRaises(errors):
856 try:
857 self.loads(data)
858 except BaseException as exc:
859 if support.verbose > 1:
860 print('%-32r - %s: %s' %
861 (data, exc.__class__.__name__, exc))
862 raise
863
Guido van Rossum98297ee2007-11-06 21:34:58 +0000864 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100865 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000866
867 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100868 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000869
870 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100871 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000872
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300873 def test_load_from_data3(self):
874 self.assert_is_copy(self._testdata, self.loads(DATA3))
875
876 def test_load_from_data4(self):
877 self.assert_is_copy(self._testdata, self.loads(DATA4))
878
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000879 def test_load_classic_instance(self):
880 # See issue5180. Test loading 2.x pickles that
881 # contain an instance of old style class.
882 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
883 xname = X.__name__.encode('ascii')
884 # Protocol 0 (text mode pickle):
885 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200886 0: ( MARK
887 1: i INST '__main__ X' (MARK at 0)
888 13: p PUT 0
889 16: ( MARK
890 17: d DICT (MARK at 16)
891 18: p PUT 1
892 21: b BUILD
893 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000894 """
895 pickle0 = (b"(i__main__\n"
896 b"X\n"
897 b"p0\n"
898 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100899 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000900
901 # Protocol 1 (binary mode pickle)
902 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200903 0: ( MARK
904 1: c GLOBAL '__main__ X'
905 13: q BINPUT 0
906 15: o OBJ (MARK at 0)
907 16: q BINPUT 1
908 18: } EMPTY_DICT
909 19: q BINPUT 2
910 21: b BUILD
911 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000912 """
913 pickle1 = (b'(c__main__\n'
914 b'X\n'
915 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100916 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000917
918 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
919 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200920 0: \x80 PROTO 2
921 2: ( MARK
922 3: c GLOBAL '__main__ X'
923 15: q BINPUT 0
924 17: o OBJ (MARK at 2)
925 18: q BINPUT 1
926 20: } EMPTY_DICT
927 21: q BINPUT 2
928 23: b BUILD
929 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000930 """
931 pickle2 = (b'\x80\x02(c__main__\n'
932 b'X\n'
933 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100934 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000935
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300936 def test_maxint64(self):
937 maxint64 = (1 << 63) - 1
938 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
939 got = self.loads(data)
940 self.assert_is_copy(maxint64, got)
941
942 # Try too with a bogus literal.
943 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200944 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300945
946 def test_unpickle_from_2x(self):
947 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300948 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300949 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300950 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300951 self.assertEqual(type(loaded), type(range(0)))
952 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300953 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300954 self.assertEqual(type(loaded), SimpleCookie)
955 self.assertEqual(list(loaded.keys()), ["key"])
956 self.assertEqual(loaded["key"].value, "value")
957
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300958 # Exception objects without arguments pickled from 2.x with protocol 2
959 for exc in python2_exceptions_without_args:
960 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300961 loaded = self.loads(data)
962 self.assertIs(type(loaded), exc)
963
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300964 # StandardError is mapped to Exception, test that separately
965 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300966 self.assertIs(type(loaded), Exception)
967
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300968 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300969 self.assertIs(type(loaded), UnicodeEncodeError)
970 self.assertEqual(loaded.object, "foo")
971 self.assertEqual(loaded.encoding, "ascii")
972 self.assertEqual(loaded.start, 0)
973 self.assertEqual(loaded.end, 1)
974 self.assertEqual(loaded.reason, "bad")
975
976 def test_load_python2_str_as_bytes(self):
977 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
978 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
979 encoding="bytes"), b'a\x00\xa0')
980 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
981 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
982 encoding="bytes"), b'a\x00\xa0')
983 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
984 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
985 encoding="bytes"), b'a\x00\xa0')
986
987 def test_load_python2_unicode_as_str(self):
988 # From Python 2: pickle.dumps(u'π', protocol=0)
989 self.assertEqual(self.loads(b'V\\u03c0\n.',
990 encoding='bytes'), 'π')
991 # From Python 2: pickle.dumps(u'π', protocol=1)
992 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
993 encoding="bytes"), 'π')
994 # From Python 2: pickle.dumps(u'π', protocol=2)
995 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
996 encoding="bytes"), 'π')
997
998 def test_load_long_python2_str_as_bytes(self):
999 # From Python 2: pickle.dumps('x' * 300, protocol=1)
1000 self.assertEqual(self.loads(pickle.BINSTRING +
1001 struct.pack("<I", 300) +
1002 b'x' * 300 + pickle.STOP,
1003 encoding='bytes'), b'x' * 300)
1004
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001005 def test_constants(self):
1006 self.assertIsNone(self.loads(b'N.'))
1007 self.assertIs(self.loads(b'\x88.'), True)
1008 self.assertIs(self.loads(b'\x89.'), False)
1009 self.assertIs(self.loads(b'I01\n.'), True)
1010 self.assertIs(self.loads(b'I00\n.'), False)
1011
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001012 def test_empty_bytestring(self):
1013 # issue 11286
1014 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1015 self.assertEqual(empty, '')
1016
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001017 def test_short_binbytes(self):
1018 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
1019 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1020
1021 def test_binbytes(self):
1022 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1023 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1024
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001025 @requires_32b
1026 def test_negative_32b_binbytes(self):
1027 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1028 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001029 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1030 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001031
1032 @requires_32b
1033 def test_negative_32b_binunicode(self):
1034 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1035 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001036 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1037 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001038
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001039 def test_short_binunicode(self):
1040 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1041 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1042
1043 def test_misc_get(self):
Claudiu Popa6f03b232019-11-24 20:15:08 +01001044 self.check_unpickling_error(pickle.UnpicklingError, b'g0\np0')
1045 self.check_unpickling_error(pickle.UnpicklingError, b'jens:')
1046 self.check_unpickling_error(pickle.UnpicklingError, b'hens:')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001047 self.assert_is_copy([(100,), (100,)],
1048 self.loads(b'((Kdtp0\nh\x00l.))'))
1049
Serhiy Storchakae0606192015-09-29 22:10:07 +03001050 def test_binbytes8(self):
1051 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1052 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1053
1054 def test_binunicode8(self):
1055 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1056 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1057
Antoine Pitrou91f43802019-05-26 17:10:09 +02001058 def test_bytearray8(self):
1059 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1060 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1061
Serhiy Storchakae0606192015-09-29 22:10:07 +03001062 @requires_32b
1063 def test_large_32b_binbytes8(self):
1064 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001065 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1066 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001067
1068 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001069 def test_large_32b_bytearray8(self):
1070 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1071 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1072 dumped)
1073
1074 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001075 def test_large_32b_binunicode8(self):
1076 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001077 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1078 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001079
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001080 def test_get(self):
1081 pickled = b'((lp100000\ng100000\nt.'
1082 unpickled = self.loads(pickled)
1083 self.assertEqual(unpickled, ([],)*2)
1084 self.assertIs(unpickled[0], unpickled[1])
1085
1086 def test_binget(self):
1087 pickled = b'(]q\xffh\xfft.'
1088 unpickled = self.loads(pickled)
1089 self.assertEqual(unpickled, ([],)*2)
1090 self.assertIs(unpickled[0], unpickled[1])
1091
1092 def test_long_binget(self):
1093 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1094 unpickled = self.loads(pickled)
1095 self.assertEqual(unpickled, ([],)*2)
1096 self.assertIs(unpickled[0], unpickled[1])
1097
1098 def test_dup(self):
1099 pickled = b'((l2t.'
1100 unpickled = self.loads(pickled)
1101 self.assertEqual(unpickled, ([],)*2)
1102 self.assertIs(unpickled[0], unpickled[1])
1103
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001104 def test_negative_put(self):
1105 # Issue #12847
1106 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001107 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001108
1109 @requires_32b
1110 def test_negative_32b_binput(self):
1111 # Issue #12847
1112 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001113 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001114
1115 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001116 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001117
1118 def test_badly_quoted_string(self):
1119 # Issue #17710
1120 badpickles = [b"S'\n.",
1121 b'S"\n.',
1122 b'S\' \n.',
1123 b'S" \n.',
1124 b'S\'"\n.',
1125 b'S"\'\n.',
1126 b"S' ' \n.",
1127 b'S" " \n.',
1128 b"S ''\n.",
1129 b'S ""\n.',
1130 b'S \n.',
1131 b'S\n.',
1132 b'S.']
1133 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001134 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001135
1136 def test_correctly_quoted_string(self):
1137 goodpickles = [(b"S''\n.", ''),
1138 (b'S""\n.', ''),
1139 (b'S"\\n"\n.', '\n'),
1140 (b"S'\\n'\n.", '\n')]
1141 for p, expected in goodpickles:
1142 self.assertEqual(self.loads(p), expected)
1143
1144 def test_frame_readline(self):
1145 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1146 # 0: \x80 PROTO 4
1147 # 2: \x95 FRAME 5
1148 # 11: I INT 42
1149 # 15: . STOP
1150 self.assertEqual(self.loads(pickled), 42)
1151
1152 def test_compat_unpickle(self):
1153 # xrange(1, 7)
1154 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1155 unpickled = self.loads(pickled)
1156 self.assertIs(type(unpickled), range)
1157 self.assertEqual(unpickled, range(1, 7))
1158 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1159 # reduce
1160 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1161 self.assertIs(self.loads(pickled), functools.reduce)
1162 # whichdb.whichdb
1163 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1164 self.assertIs(self.loads(pickled), dbm.whichdb)
1165 # Exception(), StandardError()
1166 for name in (b'Exception', b'StandardError'):
1167 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1168 unpickled = self.loads(pickled)
1169 self.assertIs(type(unpickled), Exception)
1170 self.assertEqual(str(unpickled), 'ugh')
1171 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1172 for name in (b'UserDict', b'IterableUserDict'):
1173 pickled = (b'\x80\x02(cUserDict\n' + name +
1174 b'\no}U\x04data}K\x01K\x02ssb.')
1175 unpickled = self.loads(pickled)
1176 self.assertIs(type(unpickled), collections.UserDict)
1177 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1178
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001179 def test_bad_stack(self):
1180 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001181 b'.', # STOP
1182 b'0', # POP
1183 b'1', # POP_MARK
1184 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001185 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001186 b'R', # REDUCE
1187 b')R',
1188 b'a', # APPEND
1189 b'Na',
1190 b'b', # BUILD
1191 b'Nb',
1192 b'd', # DICT
1193 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001194 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001195 b'ibuiltins\nlist\n', # INST
1196 b'l', # LIST
1197 b'o', # OBJ
1198 b'(o',
1199 b'p1\n', # PUT
1200 b'q\x00', # BINPUT
1201 b'r\x00\x00\x00\x00', # LONG_BINPUT
1202 b's', # SETITEM
1203 b'Ns',
1204 b'NNs',
1205 b't', # TUPLE
1206 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001207 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001208 b'}(Nu',
1209 b'\x81', # NEWOBJ
1210 b')\x81',
1211 b'\x85', # TUPLE1
1212 b'\x86', # TUPLE2
1213 b'N\x86',
1214 b'\x87', # TUPLE3
1215 b'N\x87',
1216 b'NN\x87',
1217 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001218 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001219 b'\x91', # FROZENSET
1220 b'\x92', # NEWOBJ_EX
1221 b')}\x92',
1222 b'\x93', # STACK_GLOBAL
1223 b'Vlist\n\x93',
1224 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001225 ]
1226 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001227 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001228
1229 def test_bad_mark(self):
1230 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001231 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001232 b'N(2', # DUP
1233 b'cbuiltins\nlist\n)(R', # REDUCE
1234 b'cbuiltins\nlist\n()R',
1235 b']N(a', # APPEND
1236 # BUILD
1237 b'cbuiltins\nValueError\n)R}(b',
1238 b'cbuiltins\nValueError\n)R(}b',
1239 b'(Nd', # DICT
1240 b'N(p1\n', # PUT
1241 b'N(q\x00', # BINPUT
1242 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1243 b'}NN(s', # SETITEM
1244 b'}N(Ns',
1245 b'}(NNs',
1246 b'}((u', # SETITEMS
1247 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1248 b'cbuiltins\nlist\n()\x81',
1249 b'N(\x85', # TUPLE1
1250 b'NN(\x86', # TUPLE2
1251 b'N(N\x86',
1252 b'NNN(\x87', # TUPLE3
1253 b'NN(N\x87',
1254 b'N(NN\x87',
1255 b']((\x90', # ADDITEMS
1256 # NEWOBJ_EX
1257 b'cbuiltins\nlist\n)}(\x92',
1258 b'cbuiltins\nlist\n)(}\x92',
1259 b'cbuiltins\nlist\n()}\x92',
1260 # STACK_GLOBAL
1261 b'Vbuiltins\n(Vlist\n\x93',
1262 b'Vbuiltins\nVlist\n(\x93',
1263 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001264 ]
1265 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001266 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001267
1268 def test_truncated_data(self):
1269 self.check_unpickling_error(EOFError, b'')
1270 self.check_unpickling_error(EOFError, b'N')
1271 badpickles = [
1272 b'B', # BINBYTES
1273 b'B\x03\x00\x00',
1274 b'B\x03\x00\x00\x00',
1275 b'B\x03\x00\x00\x00ab',
1276 b'C', # SHORT_BINBYTES
1277 b'C\x03',
1278 b'C\x03ab',
1279 b'F', # FLOAT
1280 b'F0.0',
1281 b'F0.00',
1282 b'G', # BINFLOAT
1283 b'G\x00\x00\x00\x00\x00\x00\x00',
1284 b'I', # INT
1285 b'I0',
1286 b'J', # BININT
1287 b'J\x00\x00\x00',
1288 b'K', # BININT1
1289 b'L', # LONG
1290 b'L0',
1291 b'L10',
1292 b'L0L',
1293 b'L10L',
1294 b'M', # BININT2
1295 b'M\x00',
1296 # b'P', # PERSID
1297 # b'Pabc',
1298 b'S', # STRING
1299 b"S'abc'",
1300 b'T', # BINSTRING
1301 b'T\x03\x00\x00',
1302 b'T\x03\x00\x00\x00',
1303 b'T\x03\x00\x00\x00ab',
1304 b'U', # SHORT_BINSTRING
1305 b'U\x03',
1306 b'U\x03ab',
1307 b'V', # UNICODE
1308 b'Vabc',
1309 b'X', # BINUNICODE
1310 b'X\x03\x00\x00',
1311 b'X\x03\x00\x00\x00',
1312 b'X\x03\x00\x00\x00ab',
1313 b'(c', # GLOBAL
1314 b'(cbuiltins',
1315 b'(cbuiltins\n',
1316 b'(cbuiltins\nlist',
1317 b'Ng', # GET
1318 b'Ng0',
1319 b'(i', # INST
1320 b'(ibuiltins',
1321 b'(ibuiltins\n',
1322 b'(ibuiltins\nlist',
1323 b'Nh', # BINGET
1324 b'Nj', # LONG_BINGET
1325 b'Nj\x00\x00\x00',
1326 b'Np', # PUT
1327 b'Np0',
1328 b'Nq', # BINPUT
1329 b'Nr', # LONG_BINPUT
1330 b'Nr\x00\x00\x00',
1331 b'\x80', # PROTO
1332 b'\x82', # EXT1
1333 b'\x83', # EXT2
1334 b'\x84\x01',
1335 b'\x84', # EXT4
1336 b'\x84\x01\x00\x00',
1337 b'\x8a', # LONG1
1338 b'\x8b', # LONG4
1339 b'\x8b\x00\x00\x00',
1340 b'\x8c', # SHORT_BINUNICODE
1341 b'\x8c\x03',
1342 b'\x8c\x03ab',
1343 b'\x8d', # BINUNICODE8
1344 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1345 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1346 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1347 b'\x8e', # BINBYTES8
1348 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1349 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1350 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001351 b'\x96', # BYTEARRAY8
1352 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1353 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1354 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001355 b'\x95', # FRAME
1356 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1357 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1358 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1359 ]
1360 for p in badpickles:
1361 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001362
Hai Shie80697d2020-05-28 06:10:27 +08001363 @threading_helper.reap_threads
tjb9004371c0a2019-02-18 23:30:51 +08001364 def test_unpickle_module_race(self):
1365 # https://bugs.python.org/issue34572
1366 locker_module = dedent("""
1367 import threading
1368 barrier = threading.Barrier(2)
1369 """)
1370 locking_import_module = dedent("""
1371 import locker
1372 locker.barrier.wait()
1373 class ToBeUnpickled(object):
1374 pass
1375 """)
1376
1377 os.mkdir(TESTFN)
1378 self.addCleanup(shutil.rmtree, TESTFN)
1379 sys.path.insert(0, TESTFN)
1380 self.addCleanup(sys.path.remove, TESTFN)
1381 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1382 f.write(locker_module.encode('utf-8'))
1383 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1384 f.write(locking_import_module.encode('utf-8'))
1385 self.addCleanup(forget, "locker")
1386 self.addCleanup(forget, "locking_import")
1387
1388 import locker
1389
1390 pickle_bytes = (
1391 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1392
1393 # Then try to unpickle two of these simultaneously
1394 # One of them will cause the module import, and we want it to block
1395 # until the other one either:
1396 # - fails (before the patch for this issue)
1397 # - blocks on the import lock for the module, as it should
1398 results = []
1399 barrier = threading.Barrier(3)
1400 def t():
1401 # This ensures the threads have all started
1402 # presumably barrier release is faster than thread startup
1403 barrier.wait()
1404 results.append(pickle.loads(pickle_bytes))
1405
1406 t1 = threading.Thread(target=t)
1407 t2 = threading.Thread(target=t)
1408 t1.start()
1409 t2.start()
1410
1411 barrier.wait()
1412 # could have delay here
1413 locker.barrier.wait()
1414
1415 t1.join()
1416 t2.join()
1417
1418 from locking_import import ToBeUnpickled
1419 self.assertEqual(
1420 [type(x) for x in results],
1421 [ToBeUnpickled] * 2)
1422
1423
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001424
1425class AbstractPickleTests(unittest.TestCase):
1426 # Subclass must define self.dumps, self.loads.
1427
1428 optimized = False
1429
1430 _testdata = AbstractUnpickleTests._testdata
1431
1432 def setUp(self):
1433 pass
1434
1435 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1436
1437 def test_misc(self):
1438 # test various datatypes not tested by testdata
1439 for proto in protocols:
1440 x = myint(4)
1441 s = self.dumps(x, proto)
1442 y = self.loads(s)
1443 self.assert_is_copy(x, y)
1444
1445 x = (1, ())
1446 s = self.dumps(x, proto)
1447 y = self.loads(s)
1448 self.assert_is_copy(x, y)
1449
1450 x = initarg(1, x)
1451 s = self.dumps(x, proto)
1452 y = self.loads(s)
1453 self.assert_is_copy(x, y)
1454
1455 # XXX test __reduce__ protocol?
1456
1457 def test_roundtrip_equality(self):
1458 expected = self._testdata
1459 for proto in protocols:
1460 s = self.dumps(expected, proto)
1461 got = self.loads(s)
1462 self.assert_is_copy(expected, got)
1463
Tim Peters70b02d72003-02-02 17:26:40 +00001464 # There are gratuitous differences between pickles produced by
1465 # pickle and cPickle, largely because cPickle starts PUT indices at
1466 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1467 # there's a comment with an exclamation point there whose meaning
1468 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1469 # of 1.
1470 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001471 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001472 from pickletools import dis
1473
1474 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1475 s = self.dumps(self._testdata, proto)
1476 filelike = StringIO()
1477 dis(s, out=filelike)
1478 got = filelike.getvalue()
1479 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001480
1481 def test_recursive_list(self):
1482 l = []
1483 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001484 for proto in protocols:
1485 s = self.dumps(l, proto)
1486 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001487 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001488 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001489 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001490
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001491 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001492 t = ([],)
1493 t[0].append(t)
1494 for proto in protocols:
1495 s = self.dumps(t, proto)
1496 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001497 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001498 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001499 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001500 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001501 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001502
Jeremy Hylton66426532001-10-15 21:38:56 +00001503 def test_recursive_dict(self):
1504 d = {}
1505 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001506 for proto in protocols:
1507 s = self.dumps(d, proto)
1508 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001509 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001510 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001511 self.assertIs(x[1], x)
1512
1513 def test_recursive_dict_key(self):
1514 d = {}
1515 k = K(d)
1516 d[k] = 1
1517 for proto in protocols:
1518 s = self.dumps(d, proto)
1519 x = self.loads(s)
1520 self.assertIsInstance(x, dict)
1521 self.assertEqual(len(x.keys()), 1)
1522 self.assertIsInstance(list(x.keys())[0], K)
1523 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001524
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001525 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001526 y = set()
1527 k = K(y)
1528 y.add(k)
1529 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001530 s = self.dumps(y, proto)
1531 x = self.loads(s)
1532 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001533 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001534 self.assertIsInstance(list(x)[0], K)
1535 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001536
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001537 def test_recursive_list_subclass(self):
1538 y = MyList()
1539 y.append(y)
1540 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001541 s = self.dumps(y, proto)
1542 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001543 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001544 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001545 self.assertIs(x[0], x)
1546
1547 def test_recursive_dict_subclass(self):
1548 d = MyDict()
1549 d[1] = d
1550 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1551 s = self.dumps(d, proto)
1552 x = self.loads(s)
1553 self.assertIsInstance(x, MyDict)
1554 self.assertEqual(list(x.keys()), [1])
1555 self.assertIs(x[1], x)
1556
1557 def test_recursive_dict_subclass_key(self):
1558 d = MyDict()
1559 k = K(d)
1560 d[k] = 1
1561 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1562 s = self.dumps(d, proto)
1563 x = self.loads(s)
1564 self.assertIsInstance(x, MyDict)
1565 self.assertEqual(len(list(x.keys())), 1)
1566 self.assertIsInstance(list(x.keys())[0], K)
1567 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001568
Jeremy Hylton66426532001-10-15 21:38:56 +00001569 def test_recursive_inst(self):
1570 i = C()
1571 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001572 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001573 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001574 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001575 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001576 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001577 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001578
1579 def test_recursive_multi(self):
1580 l = []
1581 d = {1:l}
1582 i = C()
1583 i.attr = d
1584 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001585 for proto in protocols:
1586 s = self.dumps(l, proto)
1587 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001588 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001589 self.assertEqual(len(x), 1)
1590 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001591 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001592 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001593
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001594 def check_recursive_collection_and_inst(self, factory):
1595 h = H()
1596 y = factory([h])
1597 h.attr = y
1598 for proto in protocols:
1599 s = self.dumps(y, proto)
1600 x = self.loads(s)
1601 self.assertIsInstance(x, type(y))
1602 self.assertEqual(len(x), 1)
1603 self.assertIsInstance(list(x)[0], H)
1604 self.assertIs(list(x)[0].attr, x)
1605
1606 def test_recursive_list_and_inst(self):
1607 self.check_recursive_collection_and_inst(list)
1608
1609 def test_recursive_tuple_and_inst(self):
1610 self.check_recursive_collection_and_inst(tuple)
1611
1612 def test_recursive_dict_and_inst(self):
1613 self.check_recursive_collection_and_inst(dict.fromkeys)
1614
1615 def test_recursive_set_and_inst(self):
1616 self.check_recursive_collection_and_inst(set)
1617
1618 def test_recursive_frozenset_and_inst(self):
1619 self.check_recursive_collection_and_inst(frozenset)
1620
1621 def test_recursive_list_subclass_and_inst(self):
1622 self.check_recursive_collection_and_inst(MyList)
1623
1624 def test_recursive_tuple_subclass_and_inst(self):
1625 self.check_recursive_collection_and_inst(MyTuple)
1626
1627 def test_recursive_dict_subclass_and_inst(self):
1628 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1629
1630 def test_recursive_set_subclass_and_inst(self):
1631 self.check_recursive_collection_and_inst(MySet)
1632
1633 def test_recursive_frozenset_subclass_and_inst(self):
1634 self.check_recursive_collection_and_inst(MyFrozenSet)
1635
Walter Dörwald9b775532007-06-08 14:30:53 +00001636 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001637 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001638 '<\\>', '<\\\U00012345>',
1639 # surrogates
1640 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001641 for proto in protocols:
1642 for u in endcases:
1643 p = self.dumps(u, proto)
1644 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001645 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001646
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001647 def test_unicode_high_plane(self):
1648 t = '\U00012345'
1649 for proto in protocols:
1650 p = self.dumps(t, proto)
1651 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001652 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001653
Guido van Rossumf4169812008-03-17 22:56:06 +00001654 def test_bytes(self):
1655 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001656 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001657 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001658 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001659 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001660 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001661 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001662 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001663 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001664 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001665
Antoine Pitrou91f43802019-05-26 17:10:09 +02001666 def test_bytearray(self):
1667 for proto in protocols:
1668 for s in b'', b'xyz', b'xyz'*100:
1669 b = bytearray(s)
1670 p = self.dumps(b, proto)
1671 bb = self.loads(p)
1672 self.assertIsNot(bb, b)
1673 self.assert_is_copy(b, bb)
1674 if proto <= 3:
1675 # bytearray is serialized using a global reference
1676 self.assertIn(b'bytearray', p)
1677 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1678 elif proto == 4:
1679 self.assertIn(b'bytearray', p)
1680 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1681 elif proto == 5:
1682 self.assertNotIn(b'bytearray', p)
1683 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1684
Jeremy Hylton66426532001-10-15 21:38:56 +00001685 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001686 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001687 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001688 while n:
1689 for expected in (-n, n):
1690 s = self.dumps(expected, proto)
1691 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001692 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001693 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001694
Tim Petersee1a53c2003-02-02 02:57:53 +00001695 def test_long(self):
1696 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001697 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001698 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001699 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001700 for npos in nbase-1, nbase, nbase+1:
1701 for n in npos, -npos:
1702 pickle = self.dumps(n, proto)
1703 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001704 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001705 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1706 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001707 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001708 nbase += nbase << 1000000
1709 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001710 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001711 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001712 # assert_is_copy is very expensive here as it precomputes
1713 # a failure message by computing the repr() of n and got,
1714 # we just do the check ourselves.
1715 self.assertIs(type(got), int)
1716 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001717
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001718 def test_float(self):
1719 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1720 3.14, 263.44582062374053, 6.022e23, 1e30]
1721 test_values = test_values + [-x for x in test_values]
1722 for proto in protocols:
1723 for value in test_values:
1724 pickle = self.dumps(value, proto)
1725 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001726 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001727
Thomas Wouters477c8d52006-05-27 19:21:47 +00001728 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1729 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001730 # make sure that floats are formatted locale independent with proto 0
1731 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001732
Jeremy Hylton66426532001-10-15 21:38:56 +00001733 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001734 for proto in protocols:
1735 inst = AAA()
1736 dumped = self.dumps(inst, proto)
1737 loaded = self.loads(dumped)
1738 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001739
1740 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001741 for proto in protocols:
1742 inst = initarg(1, 2)
1743 dumped = self.dumps(inst, proto)
1744 loaded = self.loads(dumped)
1745 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001746
Guido van Rossum04a86612001-12-19 16:58:54 +00001747 def test_metaclass(self):
1748 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001749 for proto in protocols:
1750 s = self.dumps(a, proto)
1751 b = self.loads(s)
1752 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001753
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001754 def test_dynamic_class(self):
1755 a = create_dynamic_class("my_dynamic_class", (object,))
1756 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1757 for proto in protocols:
1758 s = self.dumps(a, proto)
1759 b = self.loads(s)
1760 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001761 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001762
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001763 def test_structseq(self):
1764 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001765 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001766
1767 t = time.localtime()
1768 for proto in protocols:
1769 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001770 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001771 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001772 t = os.stat(os.curdir)
1773 s = self.dumps(t, proto)
1774 u = self.loads(s)
1775 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001776 if hasattr(os, "statvfs"):
1777 t = os.statvfs(os.curdir)
1778 s = self.dumps(t, proto)
1779 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001780 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001781
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001782 def test_ellipsis(self):
1783 for proto in protocols:
1784 s = self.dumps(..., proto)
1785 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001786 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001787
1788 def test_notimplemented(self):
1789 for proto in protocols:
1790 s = self.dumps(NotImplemented, proto)
1791 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001792 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001793
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001794 def test_singleton_types(self):
1795 # Issue #6477: Test that types of built-in singletons can be pickled.
1796 singletons = [None, ..., NotImplemented]
1797 for singleton in singletons:
1798 for proto in protocols:
1799 s = self.dumps(type(singleton), proto)
1800 u = self.loads(s)
1801 self.assertIs(type(singleton), u)
1802
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001803 # Tests for protocol 2
1804
Tim Peters4190fb82003-02-02 16:09:05 +00001805 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001806 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001807 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001808 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001809 proto_header = pickle.PROTO + bytes([proto])
1810 self.assertTrue(pickled.startswith(proto_header))
1811 else:
1812 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001813
1814 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001815 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001816 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001817 try:
1818 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001819 except ValueError as err:
1820 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001821 else:
1822 self.fail("expected bad protocol number to raise ValueError")
1823
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001824 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001825 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001826 for proto in protocols:
1827 s = self.dumps(x, proto)
1828 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001829 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001830 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001831
1832 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001833 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001834 for proto in protocols:
1835 s = self.dumps(x, proto)
1836 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001837 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001838 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001839
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001840 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001841 # Map (proto, len(tuple)) to expected opcode.
1842 expected_opcode = {(0, 0): pickle.TUPLE,
1843 (0, 1): pickle.TUPLE,
1844 (0, 2): pickle.TUPLE,
1845 (0, 3): pickle.TUPLE,
1846 (0, 4): pickle.TUPLE,
1847
1848 (1, 0): pickle.EMPTY_TUPLE,
1849 (1, 1): pickle.TUPLE,
1850 (1, 2): pickle.TUPLE,
1851 (1, 3): pickle.TUPLE,
1852 (1, 4): pickle.TUPLE,
1853
1854 (2, 0): pickle.EMPTY_TUPLE,
1855 (2, 1): pickle.TUPLE1,
1856 (2, 2): pickle.TUPLE2,
1857 (2, 3): pickle.TUPLE3,
1858 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001859
1860 (3, 0): pickle.EMPTY_TUPLE,
1861 (3, 1): pickle.TUPLE1,
1862 (3, 2): pickle.TUPLE2,
1863 (3, 3): pickle.TUPLE3,
1864 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001865 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001866 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001867 b = (1,)
1868 c = (1, 2)
1869 d = (1, 2, 3)
1870 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001871 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001872 for x in a, b, c, d, e:
1873 s = self.dumps(x, proto)
1874 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001875 self.assert_is_copy(x, y)
1876 expected = expected_opcode[min(proto, 3), len(x)]
1877 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001878
Guido van Rossum7d97d312003-01-28 04:25:27 +00001879 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001880 # Map (proto, singleton) to expected opcode.
1881 expected_opcode = {(0, None): pickle.NONE,
1882 (1, None): pickle.NONE,
1883 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001884 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001885
1886 (0, True): pickle.INT,
1887 (1, True): pickle.INT,
1888 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001889 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001890
1891 (0, False): pickle.INT,
1892 (1, False): pickle.INT,
1893 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001894 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001895 }
Tim Peters4190fb82003-02-02 16:09:05 +00001896 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001897 for x in None, False, True:
1898 s = self.dumps(x, proto)
1899 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001900 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001901 expected = expected_opcode[min(proto, 3), x]
1902 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001903
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001904 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001905 x = MyTuple([1, 2, 3])
1906 x.foo = 42
1907 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001908 for proto in protocols:
1909 s = self.dumps(x, proto)
1910 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001911 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001912
1913 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001914 x = MyList([1, 2, 3])
1915 x.foo = 42
1916 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001917 for proto in protocols:
1918 s = self.dumps(x, proto)
1919 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001920 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001921
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001922 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001923 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001924 for C in myclasses:
1925 B = C.__base__
1926 x = C(C.sample)
1927 x.foo = 42
1928 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001929 y = self.loads(s)
1930 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001931 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001932 self.assertEqual(B(x), B(y), detail)
1933 self.assertEqual(x.__dict__, y.__dict__, detail)
1934
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001935 def test_newobj_proxies(self):
1936 # NEWOBJ should use the __class__ rather than the raw type
1937 classes = myclasses[:]
1938 # Cannot create weakproxies to these classes
1939 for c in (MyInt, MyTuple):
1940 classes.remove(c)
1941 for proto in protocols:
1942 for C in classes:
1943 B = C.__base__
1944 x = C(C.sample)
1945 x.foo = 42
1946 p = weakref.proxy(x)
1947 s = self.dumps(p, proto)
1948 y = self.loads(s)
1949 self.assertEqual(type(y), type(x)) # rather than type(p)
1950 detail = (proto, C, B, x, y, type(y))
1951 self.assertEqual(B(x), B(y), detail)
1952 self.assertEqual(x.__dict__, y.__dict__, detail)
1953
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001954 def test_newobj_not_class(self):
1955 # Issue 24552
1956 global SimpleNewObj
1957 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001958 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001959 b = self.dumps(o, 4)
1960 try:
1961 SimpleNewObj = 42
1962 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1963 finally:
1964 SimpleNewObj = save
1965
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001966 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001967 # an object of that type. Check that the resulting pickle uses opcode
1968 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001969
Tim Peters22e71712003-02-03 22:27:38 +00001970 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001971 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001972 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001973 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001974 x = MyList([1, 2, 3])
1975 x.foo = 42
1976 x.bar = "hello"
1977
Tim Peters22e71712003-02-03 22:27:38 +00001978 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001979 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001980 self.assertIn(__name__.encode("utf-8"), s1)
1981 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001982 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001983
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001984 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001985 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001986
Tim Peters22e71712003-02-03 22:27:38 +00001987 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001988 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001989 self.assertNotIn(__name__.encode("utf-8"), s2)
1990 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001991 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001992
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001993 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001994 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001995 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001996 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001997
1998 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001999 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
2000 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002001
2002 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002003 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
2004 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
2005 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002006
2007 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002008 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
2009 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
2010 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
2011
Tim Peters8d2613a2003-02-11 16:40:16 +00002012 def test_list_chunking(self):
2013 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002014 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002015 for proto in protocols:
2016 s = self.dumps(x, proto)
2017 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002018 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002019 num_appends = count_opcode(pickle.APPENDS, s)
2020 self.assertEqual(num_appends, proto > 0)
2021
2022 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002023 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002024 for proto in protocols:
2025 s = self.dumps(x, proto)
2026 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002027 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002028 num_appends = count_opcode(pickle.APPENDS, s)
2029 if proto == 0:
2030 self.assertEqual(num_appends, 0)
2031 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002032 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002033
2034 def test_dict_chunking(self):
2035 n = 10 # too small to chunk
2036 x = dict.fromkeys(range(n))
2037 for proto in protocols:
2038 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002039 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002040 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002041 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002042 num_setitems = count_opcode(pickle.SETITEMS, s)
2043 self.assertEqual(num_setitems, proto > 0)
2044
2045 n = 2500 # expect at least two chunks when proto > 0
2046 x = dict.fromkeys(range(n))
2047 for proto in protocols:
2048 s = self.dumps(x, proto)
2049 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002050 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002051 num_setitems = count_opcode(pickle.SETITEMS, s)
2052 if proto == 0:
2053 self.assertEqual(num_setitems, 0)
2054 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002055 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002056
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002057 def test_set_chunking(self):
2058 n = 10 # too small to chunk
2059 x = set(range(n))
2060 for proto in protocols:
2061 s = self.dumps(x, proto)
2062 y = self.loads(s)
2063 self.assert_is_copy(x, y)
2064 num_additems = count_opcode(pickle.ADDITEMS, s)
2065 if proto < 4:
2066 self.assertEqual(num_additems, 0)
2067 else:
2068 self.assertEqual(num_additems, 1)
2069
2070 n = 2500 # expect at least two chunks when proto >= 4
2071 x = set(range(n))
2072 for proto in protocols:
2073 s = self.dumps(x, proto)
2074 y = self.loads(s)
2075 self.assert_is_copy(x, y)
2076 num_additems = count_opcode(pickle.ADDITEMS, s)
2077 if proto < 4:
2078 self.assertEqual(num_additems, 0)
2079 else:
2080 self.assertGreaterEqual(num_additems, 2)
2081
Tim Peterse9ef2032003-02-13 18:42:00 +00002082 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002083 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002084 x.abc = 666
2085 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002086 with self.subTest(proto=proto):
2087 s = self.dumps(x, proto)
2088 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002089 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002090 else:
2091 self.assertIn(b'M\xce\xfa', s) # BININT2
2092 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2093 2 <= proto)
2094 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2095 y = self.loads(s) # will raise TypeError if __init__ called
2096 self.assert_is_copy(x, y)
2097
2098 def test_complex_newobj(self):
2099 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2100 x.abc = 666
2101 for proto in protocols:
2102 with self.subTest(proto=proto):
2103 s = self.dumps(x, proto)
2104 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002105 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002106 elif proto < 2:
2107 self.assertIn(b'M\xce\xfa', s) # BININT2
2108 elif proto < 4:
2109 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2110 else:
2111 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2112 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2113 2 <= proto)
2114 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2115 y = self.loads(s) # will raise TypeError if __init__ called
2116 self.assert_is_copy(x, y)
2117
2118 def test_complex_newobj_ex(self):
2119 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2120 x.abc = 666
2121 for proto in protocols:
2122 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002123 s = self.dumps(x, proto)
2124 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002125 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002126 elif proto < 2:
2127 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002128 elif proto < 4:
2129 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002130 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002131 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2132 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2133 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2134 4 <= proto)
2135 y = self.loads(s) # will raise TypeError if __init__ called
2136 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002137
Tim Peters42f08ac2003-02-11 22:43:24 +00002138 def test_newobj_list_slots(self):
2139 x = SlotList([1, 2, 3])
2140 x.foo = 42
2141 x.bar = "hello"
2142 s = self.dumps(x, 2)
2143 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002144 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002145
Guido van Rossum2a30b212003-02-18 22:41:24 +00002146 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002147 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002148 x = REX_one()
2149 self.assertEqual(x._reduce_called, 0)
2150 s = self.dumps(x, proto)
2151 self.assertEqual(x._reduce_called, 1)
2152 y = self.loads(s)
2153 self.assertEqual(y._reduce_called, 0)
2154
2155 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002156 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002157 x = REX_two()
2158 self.assertEqual(x._proto, None)
2159 s = self.dumps(x, proto)
2160 self.assertEqual(x._proto, proto)
2161 y = self.loads(s)
2162 self.assertEqual(y._proto, None)
2163
2164 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002165 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002166 x = REX_three()
2167 self.assertEqual(x._proto, None)
2168 s = self.dumps(x, proto)
2169 self.assertEqual(x._proto, proto)
2170 y = self.loads(s)
2171 self.assertEqual(y._proto, None)
2172
Guido van Rossumd8faa362007-04-27 19:54:29 +00002173 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002174 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002175 x = REX_four()
2176 self.assertEqual(x._proto, None)
2177 s = self.dumps(x, proto)
2178 self.assertEqual(x._proto, proto)
2179 y = self.loads(s)
2180 self.assertEqual(y._proto, proto)
2181
2182 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002183 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002184 x = REX_five()
2185 self.assertEqual(x._reduce_called, 0)
2186 s = self.dumps(x, proto)
2187 self.assertEqual(x._reduce_called, 1)
2188 y = self.loads(s)
2189 self.assertEqual(y._reduce_called, 1)
2190
Brett Cannon31f59292011-02-21 19:29:56 +00002191 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002192 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002193 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002194 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002195 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002196 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002197
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002198 def test_reduce_bad_iterator(self):
2199 # Issue4176: crash when 4th and 5th items of __reduce__()
2200 # are not iterators
2201 class C(object):
2202 def __reduce__(self):
2203 # 4th item is not an iterator
2204 return list, (), None, [], None
2205 class D(object):
2206 def __reduce__(self):
2207 # 5th item is not an iterator
2208 return dict, (), None, None, []
2209
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002210 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002211 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002212 try:
2213 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002214 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002215 pass
2216 try:
2217 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002218 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002219 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002220
Collin Winter771d8342009-04-16 03:18:06 +00002221 def test_many_puts_and_gets(self):
2222 # Test that internal data structures correctly deal with lots of
2223 # puts/gets.
2224 keys = ("aaa" + str(i) for i in range(100))
2225 large_dict = dict((k, [4, 5, 6]) for k in keys)
2226 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2227
2228 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002229 with self.subTest(proto=proto):
2230 dumped = self.dumps(obj, proto)
2231 loaded = self.loads(dumped)
2232 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002233
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002234 def test_attribute_name_interning(self):
2235 # Test that attribute names of pickled objects are interned when
2236 # unpickling.
2237 for proto in protocols:
2238 x = C()
2239 x.foo = 42
2240 x.bar = "hello"
2241 s = self.dumps(x, proto)
2242 y = self.loads(s)
2243 x_keys = sorted(x.__dict__)
2244 y_keys = sorted(y.__dict__)
2245 for x_key, y_key in zip(x_keys, y_keys):
2246 self.assertIs(x_key, y_key)
2247
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002248 def test_pickle_to_2x(self):
2249 # Pickle non-trivial data with protocol 2, expecting that it yields
2250 # the same result as Python 2.x did.
2251 # NOTE: this test is a bit too strong since we can produce different
2252 # bytecode that 2.x will still understand.
2253 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002254 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002255 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002256 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002257
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002258 def test_large_pickles(self):
2259 # Test the correctness of internal buffering routines when handling
2260 # large data.
2261 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002262 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002263 dumped = self.dumps(data, proto)
2264 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002265 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002266 self.assertEqual(loaded, data)
2267
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002268 def test_int_pickling_efficiency(self):
2269 # Test compacity of int representation (see issue #12744)
2270 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002271 with self.subTest(proto=proto):
2272 pickles = [self.dumps(2**n, proto) for n in range(70)]
2273 sizes = list(map(len, pickles))
2274 # the size function is monotonic
2275 self.assertEqual(sorted(sizes), sizes)
2276 if proto >= 2:
2277 for p in pickles:
2278 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002279
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002280 def _check_pickling_with_opcode(self, obj, opcode, proto):
2281 pickled = self.dumps(obj, proto)
2282 self.assertTrue(opcode_in_pickle(opcode, pickled))
2283 unpickled = self.loads(pickled)
2284 self.assertEqual(obj, unpickled)
2285
2286 def test_appends_on_non_lists(self):
2287 # Issue #17720
2288 obj = REX_six([1, 2, 3])
2289 for proto in protocols:
2290 if proto == 0:
2291 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2292 else:
2293 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2294
2295 def test_setitems_on_non_dicts(self):
2296 obj = REX_seven({1: -1, 2: -2, 3: -3})
2297 for proto in protocols:
2298 if proto == 0:
2299 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2300 else:
2301 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2302
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002303 # Exercise framing (proto >= 4) for significant workloads
2304
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002305 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002306 FRAME_SIZE_TARGET = 64 * 1024
2307
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002308 def check_frame_opcodes(self, pickled):
2309 """
2310 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002311
2312 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2313 framed by default and are therefore considered a frame by themselves in
2314 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002315 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002316 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002317 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2318 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002319 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002320 if frame_end is not None:
2321 self.assertLessEqual(pos, frame_end)
2322 if pos == frame_end:
2323 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002324
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002325 if frame_end is not None: # framed
2326 self.assertNotEqual(op.name, 'FRAME')
2327 if op.name in frameless_opcodes:
2328 # Only short bytes and str objects should be written
2329 # in a frame
2330 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2331
2332 else: # not framed
2333 if (op.name == 'FRAME' or
2334 (op.name in frameless_opcodes and
2335 len(arg) > self.FRAME_SIZE_TARGET)):
2336 # Frame or large bytes or str object
2337 if frameless_start is not None:
2338 # Only short data should be written outside of a frame
2339 self.assertLess(pos - frameless_start,
2340 self.FRAME_SIZE_MIN)
2341 frameless_start = None
2342 elif frameless_start is None and op.name != 'PROTO':
2343 frameless_start = pos
2344
2345 if op.name == 'FRAME':
2346 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2347 frame_end = pos + 9 + arg
2348
2349 pos = len(pickled)
2350 if frame_end is not None:
2351 self.assertEqual(frame_end, pos)
2352 elif frameless_start is not None:
2353 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002354
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002355 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002356 def test_framing_many_objects(self):
2357 obj = list(range(10**5))
2358 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2359 with self.subTest(proto=proto):
2360 pickled = self.dumps(obj, proto)
2361 unpickled = self.loads(pickled)
2362 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002363 bytes_per_frame = (len(pickled) /
2364 count_opcode(pickle.FRAME, pickled))
2365 self.assertGreater(bytes_per_frame,
2366 self.FRAME_SIZE_TARGET / 2)
2367 self.assertLessEqual(bytes_per_frame,
2368 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002369 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002370
2371 def test_framing_large_objects(self):
2372 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002373 small_items = [[i] for i in range(10)]
2374 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002375 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002376 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002377 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002378 if not fast:
2379 # fast=False by default.
2380 # This covers in-memory pickling with pickle.dumps().
2381 pickled = self.dumps(obj, proto)
2382 else:
2383 # Pickler is required when fast=True.
2384 if not hasattr(self, 'pickler'):
2385 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002386 buf = io.BytesIO()
2387 pickler = self.pickler(buf, protocol=proto)
2388 pickler.fast = fast
2389 pickler.dump(obj)
2390 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002391 unpickled = self.loads(pickled)
2392 # More informative error message in case of failure.
2393 self.assertEqual([len(x) for x in obj],
2394 [len(x) for x in unpickled])
2395 # Perform full equality check if the lengths match.
2396 self.assertEqual(obj, unpickled)
2397 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002398 # A single frame for small objects between
2399 # first two large objects.
2400 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002401 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002402
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002403 def test_optional_frames(self):
2404 if pickle.HIGHEST_PROTOCOL < 4:
2405 return
2406
2407 def remove_frames(pickled, keep_frame=None):
2408 """Remove frame opcodes from the given pickle."""
2409 frame_starts = []
2410 # 1 byte for the opcode and 8 for the argument
2411 frame_opcode_size = 9
2412 for opcode, _, pos in pickletools.genops(pickled):
2413 if opcode.name == 'FRAME':
2414 frame_starts.append(pos)
2415
2416 newpickle = bytearray()
2417 last_frame_end = 0
2418 for i, pos in enumerate(frame_starts):
2419 if keep_frame and keep_frame(i):
2420 continue
2421 newpickle += pickled[last_frame_end:pos]
2422 last_frame_end = pos + frame_opcode_size
2423 newpickle += pickled[last_frame_end:]
2424 return newpickle
2425
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002426 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002427 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002428 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002429 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002430 for bytes_type in (bytes, bytearray):
2431 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002432
Antoine Pitrou91f43802019-05-26 17:10:09 +02002433 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2434 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002435
Antoine Pitrou91f43802019-05-26 17:10:09 +02002436 frameless_pickle = remove_frames(pickled)
2437 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2438 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002439
Antoine Pitrou91f43802019-05-26 17:10:09 +02002440 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2441 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2442 count_opcode(pickle.FRAME, pickled))
2443 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002444
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002445 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002446 def test_framed_write_sizes_with_delayed_writer(self):
2447 class ChunkAccumulator:
2448 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002449 def __init__(self):
2450 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002451 def write(self, chunk):
2452 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002453 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002454 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002455
2456 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002457 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2458 for i in range(int(1e4))]
2459 # Add a large unique ASCII string
2460 objects.append('0123456789abcdef' *
2461 (self.FRAME_SIZE_TARGET // 16 + 1))
2462
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002463 # Protocol 4 packs groups of small objects into frames and issues
2464 # calls to write only once or twice per frame:
2465 # The C pickler issues one call to write per-frame (header and
2466 # contents) while Python pickler issues two calls to write: one for
2467 # the frame header and one for the frame binary contents.
2468 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002469 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002470
2471 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002472 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002473 # be released otherwise this delayed access would not be possible.
2474 pickled = writer.concatenate_chunks()
2475 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002476 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002477 self.assertGreater(len(writer.chunks), 1)
2478
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002479 # memoryviews should own the memory.
2480 del objects
2481 support.gc_collect()
2482 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002483
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002484 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002485 # There should be at least one call to write per frame
2486 self.assertGreaterEqual(len(writer.chunks), n_frames)
2487
2488 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002489 # one per-frame header, one per frame for the actual contents,
2490 # and two for the header.
2491 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002492
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002493 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002494 large_sizes = [s for s in chunk_sizes
2495 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002496 medium_sizes = [s for s in chunk_sizes
2497 if 9 < s < self.FRAME_SIZE_TARGET]
2498 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002499
2500 # Large chunks should not be too large:
2501 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002502 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2503 chunk_sizes)
2504 # There shouldn't bee too many small chunks: the protocol header,
2505 # the frame headers and the large string headers are written
2506 # in small chunks.
2507 self.assertLessEqual(len(small_sizes),
2508 len(large_sizes) + len(medium_sizes) + 3,
2509 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002510
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002511 def test_nested_names(self):
2512 global Nested
2513 class Nested:
2514 class A:
2515 class B:
2516 class C:
2517 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002518 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002519 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2520 with self.subTest(proto=proto, obj=obj):
2521 unpickled = self.loads(self.dumps(obj, proto))
2522 self.assertIs(obj, unpickled)
2523
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002524 def test_recursive_nested_names(self):
2525 global Recursive
2526 class Recursive:
2527 pass
2528 Recursive.mod = sys.modules[Recursive.__module__]
2529 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2530 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2531 with self.subTest(proto=proto):
2532 unpickled = self.loads(self.dumps(Recursive, proto))
2533 self.assertIs(unpickled, Recursive)
2534 del Recursive.mod # break reference loop
2535
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002536 def test_py_methods(self):
2537 global PyMethodsTest
2538 class PyMethodsTest:
2539 @staticmethod
2540 def cheese():
2541 return "cheese"
2542 @classmethod
2543 def wine(cls):
2544 assert cls is PyMethodsTest
2545 return "wine"
2546 def biscuits(self):
2547 assert isinstance(self, PyMethodsTest)
2548 return "biscuits"
2549 class Nested:
2550 "Nested class"
2551 @staticmethod
2552 def ketchup():
2553 return "ketchup"
2554 @classmethod
2555 def maple(cls):
2556 assert cls is PyMethodsTest.Nested
2557 return "maple"
2558 def pie(self):
2559 assert isinstance(self, PyMethodsTest.Nested)
2560 return "pie"
2561
2562 py_methods = (
2563 PyMethodsTest.cheese,
2564 PyMethodsTest.wine,
2565 PyMethodsTest().biscuits,
2566 PyMethodsTest.Nested.ketchup,
2567 PyMethodsTest.Nested.maple,
2568 PyMethodsTest.Nested().pie
2569 )
2570 py_unbound_methods = (
2571 (PyMethodsTest.biscuits, PyMethodsTest),
2572 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2573 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002574 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002575 for method in py_methods:
2576 with self.subTest(proto=proto, method=method):
2577 unpickled = self.loads(self.dumps(method, proto))
2578 self.assertEqual(method(), unpickled())
2579 for method, cls in py_unbound_methods:
2580 obj = cls()
2581 with self.subTest(proto=proto, method=method):
2582 unpickled = self.loads(self.dumps(method, proto))
2583 self.assertEqual(method(obj), unpickled(obj))
2584
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002585 def test_c_methods(self):
2586 global Subclass
2587 class Subclass(tuple):
2588 class Nested(str):
2589 pass
2590
2591 c_methods = (
2592 # bound built-in method
2593 ("abcd".index, ("c",)),
2594 # unbound built-in method
2595 (str.index, ("abcd", "c")),
2596 # bound "slot" method
2597 ([1, 2, 3].__len__, ()),
2598 # unbound "slot" method
2599 (list.__len__, ([1, 2, 3],)),
2600 # bound "coexist" method
2601 ({1, 2}.__contains__, (2,)),
2602 # unbound "coexist" method
2603 (set.__contains__, ({1, 2}, 2)),
2604 # built-in class method
2605 (dict.fromkeys, (("a", 1), ("b", 2))),
2606 # built-in static method
2607 (bytearray.maketrans, (b"abc", b"xyz")),
2608 # subclass methods
2609 (Subclass([1,2,2]).count, (2,)),
2610 (Subclass.count, (Subclass([1,2,2]), 2)),
2611 (Subclass.Nested("sweet").count, ("e",)),
2612 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2613 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002614 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002615 for method, args in c_methods:
2616 with self.subTest(proto=proto, method=method):
2617 unpickled = self.loads(self.dumps(method, proto))
2618 self.assertEqual(method(*args), unpickled(*args))
2619
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002620 def test_compat_pickle(self):
2621 tests = [
2622 (range(1, 7), '__builtin__', 'xrange'),
2623 (map(int, '123'), 'itertools', 'imap'),
2624 (functools.reduce, '__builtin__', 'reduce'),
2625 (dbm.whichdb, 'whichdb', 'whichdb'),
2626 (Exception(), 'exceptions', 'Exception'),
2627 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2628 (collections.UserList(), 'UserList', 'UserList'),
2629 (collections.defaultdict(), 'collections', 'defaultdict'),
2630 ]
2631 for val, mod, name in tests:
2632 for proto in range(3):
2633 with self.subTest(type=type(val), proto=proto):
2634 pickled = self.dumps(val, proto)
2635 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2636 self.assertIs(type(self.loads(pickled)), type(val))
2637
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002638 def test_local_lookup_error(self):
2639 # Test that whichmodule() errors out cleanly when looking up
2640 # an assumed globally-reachable object fails.
2641 def f():
2642 pass
2643 # Since the function is local, lookup will fail
2644 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2645 with self.assertRaises((AttributeError, pickle.PicklingError)):
2646 pickletools.dis(self.dumps(f, proto))
2647 # Same without a __module__ attribute (exercises a different path
2648 # in _pickle.c).
2649 del f.__module__
2650 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2651 with self.assertRaises((AttributeError, pickle.PicklingError)):
2652 pickletools.dis(self.dumps(f, proto))
2653 # Yet a different path.
2654 f.__name__ = f.__qualname__
2655 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2656 with self.assertRaises((AttributeError, pickle.PicklingError)):
2657 pickletools.dis(self.dumps(f, proto))
2658
Antoine Pitrou91f43802019-05-26 17:10:09 +02002659 #
2660 # PEP 574 tests below
2661 #
2662
2663 def buffer_like_objects(self):
2664 # Yield buffer-like objects with the bytestring "abcdef" in them
2665 bytestring = b"abcdefgh"
2666 yield ZeroCopyBytes(bytestring)
2667 yield ZeroCopyBytearray(bytestring)
2668 if _testbuffer is not None:
2669 items = list(bytestring)
2670 value = int.from_bytes(bytestring, byteorder='little')
2671 for flags in (0, _testbuffer.ND_WRITABLE):
2672 # 1-D, contiguous
2673 yield PicklableNDArray(items, format='B', shape=(8,),
2674 flags=flags)
2675 # 2-D, C-contiguous
2676 yield PicklableNDArray(items, format='B', shape=(4, 2),
2677 strides=(2, 1), flags=flags)
2678 # 2-D, Fortran-contiguous
2679 yield PicklableNDArray(items, format='B',
2680 shape=(4, 2), strides=(1, 4),
2681 flags=flags)
2682
2683 def test_in_band_buffers(self):
2684 # Test in-band buffers (PEP 574)
2685 for obj in self.buffer_like_objects():
2686 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2687 data = self.dumps(obj, proto)
2688 if obj.c_contiguous and proto >= 5:
2689 # The raw memory bytes are serialized in physical order
2690 self.assertIn(b"abcdefgh", data)
2691 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2692 if proto >= 5:
2693 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2694 1 if obj.readonly else 0)
2695 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2696 0 if obj.readonly else 1)
2697 # Return a true value from buffer_callback should have
2698 # the same effect
2699 def buffer_callback(obj):
2700 return True
2701 data2 = self.dumps(obj, proto,
2702 buffer_callback=buffer_callback)
2703 self.assertEqual(data2, data)
2704
2705 new = self.loads(data)
2706 # It's a copy
2707 self.assertIsNot(new, obj)
2708 self.assertIs(type(new), type(obj))
2709 self.assertEqual(new, obj)
2710
2711 # XXX Unfortunately cannot test non-contiguous array
2712 # (see comment in PicklableNDArray.__reduce_ex__)
2713
2714 def test_oob_buffers(self):
2715 # Test out-of-band buffers (PEP 574)
2716 for obj in self.buffer_like_objects():
2717 for proto in range(0, 5):
2718 # Need protocol >= 5 for buffer_callback
2719 with self.assertRaises(ValueError):
2720 self.dumps(obj, proto,
2721 buffer_callback=[].append)
2722 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2723 buffers = []
2724 buffer_callback = lambda pb: buffers.append(pb.raw())
2725 data = self.dumps(obj, proto,
2726 buffer_callback=buffer_callback)
2727 self.assertNotIn(b"abcdefgh", data)
2728 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2729 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2730 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2731 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2732 1 if obj.readonly else 0)
2733
2734 if obj.c_contiguous:
2735 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2736 # Need buffers argument to unpickle properly
2737 with self.assertRaises(pickle.UnpicklingError):
2738 self.loads(data)
2739
2740 new = self.loads(data, buffers=buffers)
2741 if obj.zero_copy_reconstruct:
2742 # Zero-copy achieved
2743 self.assertIs(new, obj)
2744 else:
2745 self.assertIs(type(new), type(obj))
2746 self.assertEqual(new, obj)
2747 # Non-sequence buffers accepted too
2748 new = self.loads(data, buffers=iter(buffers))
2749 if obj.zero_copy_reconstruct:
2750 # Zero-copy achieved
2751 self.assertIs(new, obj)
2752 else:
2753 self.assertIs(type(new), type(obj))
2754 self.assertEqual(new, obj)
2755
2756 def test_oob_buffers_writable_to_readonly(self):
2757 # Test reconstructing readonly object from writable buffer
2758 obj = ZeroCopyBytes(b"foobar")
2759 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2760 buffers = []
2761 buffer_callback = buffers.append
2762 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2763
2764 buffers = map(bytearray, buffers)
2765 new = self.loads(data, buffers=buffers)
2766 self.assertIs(type(new), type(obj))
2767 self.assertEqual(new, obj)
2768
2769 def test_picklebuffer_error(self):
2770 # PickleBuffer forbidden with protocol < 5
2771 pb = pickle.PickleBuffer(b"foobar")
2772 for proto in range(0, 5):
2773 with self.assertRaises(pickle.PickleError):
2774 self.dumps(pb, proto)
2775
2776 def test_buffer_callback_error(self):
2777 def buffer_callback(buffers):
2778 1/0
2779 pb = pickle.PickleBuffer(b"foobar")
2780 with self.assertRaises(ZeroDivisionError):
2781 self.dumps(pb, 5, buffer_callback=buffer_callback)
2782
2783 def test_buffers_error(self):
2784 pb = pickle.PickleBuffer(b"foobar")
2785 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2786 data = self.dumps(pb, proto, buffer_callback=[].append)
2787 # Non iterable buffers
2788 with self.assertRaises(TypeError):
2789 self.loads(data, buffers=object())
2790 # Buffer iterable exhausts too early
2791 with self.assertRaises(pickle.UnpicklingError):
2792 self.loads(data, buffers=[])
2793
Markus Mohrhard898318b2019-07-26 00:00:34 +08002794 def test_inband_accept_default_buffers_argument(self):
2795 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2796 data_pickled = self.dumps(1, proto, buffer_callback=None)
2797 data = self.loads(data_pickled, buffers=None)
2798
Antoine Pitrou91f43802019-05-26 17:10:09 +02002799 @unittest.skipIf(np is None, "Test needs Numpy")
2800 def test_buffers_numpy(self):
2801 def check_no_copy(x, y):
2802 np.testing.assert_equal(x, y)
2803 self.assertEqual(x.ctypes.data, y.ctypes.data)
2804
2805 def check_copy(x, y):
2806 np.testing.assert_equal(x, y)
2807 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2808
2809 def check_array(arr):
2810 # In-band
2811 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2812 data = self.dumps(arr, proto)
2813 new = self.loads(data)
2814 check_copy(arr, new)
2815 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2816 buffer_callback = lambda _: True
2817 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2818 new = self.loads(data)
2819 check_copy(arr, new)
2820 # Out-of-band
2821 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2822 buffers = []
2823 buffer_callback = buffers.append
2824 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2825 new = self.loads(data, buffers=buffers)
2826 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2827 check_no_copy(arr, new)
2828 else:
2829 check_copy(arr, new)
2830
2831 # 1-D
2832 arr = np.arange(6)
2833 check_array(arr)
2834 # 1-D, non-contiguous
2835 check_array(arr[::2])
2836 # 2-D, C-contiguous
2837 arr = np.arange(12).reshape((3, 4))
2838 check_array(arr)
2839 # 2-D, F-contiguous
2840 check_array(arr.T)
2841 # 2-D, non-contiguous
2842 check_array(arr[::2])
2843
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002844
2845class BigmemPickleTests(unittest.TestCase):
2846
Victor Stinner8c663fd2017-11-08 14:44:44 -08002847 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002848
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002849 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002850 def test_huge_long_32b(self, size):
2851 data = 1 << (8 * size)
2852 try:
2853 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002854 if proto < 2:
2855 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002856 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002857 with self.assertRaises((ValueError, OverflowError)):
2858 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002859 finally:
2860 data = None
2861
Victor Stinner8c663fd2017-11-08 14:44:44 -08002862 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002863 # (older protocols don't have a dedicated opcode for bytes and are
2864 # too inefficient)
2865
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002866 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002867 def test_huge_bytes_32b(self, size):
2868 data = b"abcd" * (size // 4)
2869 try:
2870 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002871 if proto < 3:
2872 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002873 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002874 try:
2875 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002876 header = (pickle.BINBYTES +
2877 struct.pack("<I", len(data)))
2878 data_start = pickled.index(data)
2879 self.assertEqual(
2880 header,
2881 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002882 finally:
2883 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002884 finally:
2885 data = None
2886
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002887 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002888 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002889 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002890 try:
2891 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002892 if proto < 3:
2893 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002894 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002895 if proto == 3:
2896 # Protocol 3 does not support large bytes objects.
2897 # Verify that we do not crash when processing one.
2898 with self.assertRaises((ValueError, OverflowError)):
2899 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002900 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002901 try:
2902 pickled = self.dumps(data, protocol=proto)
2903 header = (pickle.BINBYTES8 +
2904 struct.pack("<Q", len(data)))
2905 data_start = pickled.index(data)
2906 self.assertEqual(
2907 header,
2908 pickled[data_start-len(header):data_start])
2909 finally:
2910 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002911 finally:
2912 data = None
2913
2914 # All protocols use 1-byte per printable ASCII character; we add another
2915 # byte because the encoded form has to be copied into the internal buffer.
2916
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002917 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002918 def test_huge_str_32b(self, size):
2919 data = "abcd" * (size // 4)
2920 try:
2921 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002922 if proto == 0:
2923 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002924 with self.subTest(proto=proto):
2925 try:
2926 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002927 header = (pickle.BINUNICODE +
2928 struct.pack("<I", len(data)))
2929 data_start = pickled.index(b'abcd')
2930 self.assertEqual(
2931 header,
2932 pickled[data_start-len(header):data_start])
2933 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2934 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002935 finally:
2936 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002937 finally:
2938 data = None
2939
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002940 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2941 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2942 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002943
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002944 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002945 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002946 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002947 try:
2948 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002949 if proto == 0:
2950 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002951 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002952 if proto < 4:
2953 with self.assertRaises((ValueError, OverflowError)):
2954 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002955 continue
2956 try:
2957 pickled = self.dumps(data, protocol=proto)
2958 header = (pickle.BINUNICODE8 +
2959 struct.pack("<Q", len(data)))
2960 data_start = pickled.index(b'abcd')
2961 self.assertEqual(
2962 header,
2963 pickled[data_start-len(header):data_start])
2964 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2965 pickled.index(b"abcd")), len(data))
2966 finally:
2967 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002968 finally:
2969 data = None
2970
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002971
Guido van Rossum2a30b212003-02-18 22:41:24 +00002972# Test classes for reduce_ex
2973
2974class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002975 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002976 _reduce_called = 0
2977 def __reduce__(self):
2978 self._reduce_called = 1
2979 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002980
2981class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002982 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002983 _proto = None
2984 def __reduce_ex__(self, proto):
2985 self._proto = proto
2986 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002987
2988class REX_three(object):
2989 _proto = None
2990 def __reduce_ex__(self, proto):
2991 self._proto = proto
2992 return REX_two, ()
2993 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002994 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002995
Guido van Rossumd8faa362007-04-27 19:54:29 +00002996class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002997 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002998 _proto = None
2999 def __reduce_ex__(self, proto):
3000 self._proto = proto
3001 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00003002
3003class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003004 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003005 _reduce_called = 0
3006 def __reduce__(self):
3007 self._reduce_called = 1
3008 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003009
3010class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003011 """This class is used to check the 4th argument (list iterator) of
3012 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003013 """
3014 def __init__(self, items=None):
3015 self.items = items if items is not None else []
3016 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003017 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003018 def append(self, item):
3019 self.items.append(item)
3020 def __reduce__(self):
3021 return type(self), (), None, iter(self.items), None
3022
3023class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003024 """This class is used to check the 5th argument (dict iterator) of
3025 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003026 """
3027 def __init__(self, table=None):
3028 self.table = table if table is not None else {}
3029 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003030 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003031 def __setitem__(self, key, value):
3032 self.table[key] = value
3033 def __reduce__(self):
3034 return type(self), (), None, None, iter(self.table.items())
3035
Guido van Rossumd8faa362007-04-27 19:54:29 +00003036
Guido van Rossum2a30b212003-02-18 22:41:24 +00003037# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003038
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003039class MyInt(int):
3040 sample = 1
3041
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003042class MyFloat(float):
3043 sample = 1.0
3044
3045class MyComplex(complex):
3046 sample = 1.0 + 0.0j
3047
3048class MyStr(str):
3049 sample = "hello"
3050
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003051class MyUnicode(str):
3052 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003053
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003054class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003055 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003056
3057class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003058 sample = [1, 2, 3]
3059
3060class MyDict(dict):
3061 sample = {"a": 1, "b": 2}
3062
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003063class MySet(set):
3064 sample = {"a", "b"}
3065
3066class MyFrozenSet(frozenset):
3067 sample = frozenset({"a", "b"})
3068
Mark Dickinson5c2db372009-12-05 20:28:34 +00003069myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003070 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003071 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003072 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003073
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003074
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003075class SlotList(MyList):
3076 __slots__ = ["foo"]
3077
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003078class SimpleNewObj(int):
3079 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003080 # raise an error, to make sure this isn't called
3081 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003082 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003083 return int(self) == int(other) and self.__dict__ == other.__dict__
3084
3085class ComplexNewObj(SimpleNewObj):
3086 def __getnewargs__(self):
3087 return ('%X' % self, 16)
3088
3089class ComplexNewObjEx(SimpleNewObj):
3090 def __getnewargs_ex__(self):
3091 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003092
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003093class BadGetattr:
3094 def __getattr__(self, key):
3095 self.foo
3096
Collin Winter771d8342009-04-16 03:18:06 +00003097
Jeremy Hylton66426532001-10-15 21:38:56 +00003098class AbstractPickleModuleTests(unittest.TestCase):
3099
3100 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003101 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003102 try:
3103 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003104 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003105 finally:
Hai Shi883bc632020-07-06 17:12:49 +08003106 os_helper.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003107
3108 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003109 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003110 try:
3111 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003112 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003113 finally:
Hai Shi883bc632020-07-06 17:12:49 +08003114 os_helper.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003115
Collin Winter771d8342009-04-16 03:18:06 +00003116 def test_load_from_and_dump_to_file(self):
3117 stream = io.BytesIO()
3118 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003119 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003120 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003121 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003122 self.assertEqual(unpickled, data)
3123
Tim Petersc0c93702003-02-13 19:30:57 +00003124 def test_highest_protocol(self):
3125 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003126 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003127
Martin v. Löwis544f1192004-07-27 05:22:33 +00003128 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003129 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003130 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003131 self.dump(123, f, -1)
3132 self.dump(123, file=f, protocol=-1)
3133 self.dumps(123, -1)
3134 self.dumps(123, protocol=-1)
3135 self.Pickler(f, -1)
3136 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003137
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003138 def test_dump_text_file(self):
3139 f = open(TESTFN, "w")
3140 try:
3141 for proto in protocols:
3142 self.assertRaises(TypeError, self.dump, 123, f, proto)
3143 finally:
3144 f.close()
Hai Shi883bc632020-07-06 17:12:49 +08003145 os_helper.unlink(TESTFN)
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003146
3147 def test_incomplete_input(self):
3148 s = io.BytesIO(b"X''.")
3149 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3150
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003151 def test_bad_init(self):
3152 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003153 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003154 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003155 def __init__(self): pass
3156
Serhiy Storchaka65452562017-11-15 14:01:08 +02003157 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003158 def __init__(self): pass
3159
3160 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3161 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3162
Antoine Pitrou91f43802019-05-26 17:10:09 +02003163 def check_dumps_loads_oob_buffers(self, dumps, loads):
3164 # No need to do the full gamut of tests here, just enough to
3165 # check that dumps() and loads() redirect their arguments
3166 # to the underlying Pickler and Unpickler, respectively.
3167 obj = ZeroCopyBytes(b"foo")
3168
3169 for proto in range(0, 5):
3170 # Need protocol >= 5 for buffer_callback
3171 with self.assertRaises(ValueError):
3172 dumps(obj, protocol=proto,
3173 buffer_callback=[].append)
3174 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3175 buffers = []
3176 buffer_callback = buffers.append
3177 data = dumps(obj, protocol=proto,
3178 buffer_callback=buffer_callback)
3179 self.assertNotIn(b"foo", data)
3180 self.assertEqual(bytes(buffers[0]), b"foo")
3181 # Need buffers argument to unpickle properly
3182 with self.assertRaises(pickle.UnpicklingError):
3183 loads(data)
3184 new = loads(data, buffers=buffers)
3185 self.assertIs(new, obj)
3186
3187 def test_dumps_loads_oob_buffers(self):
3188 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3189 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3190
3191 def test_dump_load_oob_buffers(self):
3192 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3193 def dumps(obj, **kwargs):
3194 f = io.BytesIO()
3195 self.dump(obj, f, **kwargs)
3196 return f.getvalue()
3197
3198 def loads(data, **kwargs):
3199 f = io.BytesIO(data)
3200 return self.load(f, **kwargs)
3201
3202 self.check_dumps_loads_oob_buffers(dumps, loads)
3203
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003204
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003205class AbstractPersistentPicklerTests(unittest.TestCase):
3206
3207 # This class defines persistent_id() and persistent_load()
3208 # functions that should be used by the pickler. All even integers
3209 # are pickled using persistent ids.
3210
3211 def persistent_id(self, object):
3212 if isinstance(object, int) and object % 2 == 0:
3213 self.id_count += 1
3214 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003215 elif object == "test_false_value":
3216 self.false_count += 1
3217 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003218 else:
3219 return None
3220
3221 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003222 if not oid:
3223 self.load_false_count += 1
3224 return "test_false_value"
3225 else:
3226 self.load_count += 1
3227 object = int(oid)
3228 assert object % 2 == 0
3229 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003230
3231 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003232 L = list(range(10)) + ["test_false_value"]
3233 for proto in protocols:
3234 self.id_count = 0
3235 self.false_count = 0
3236 self.load_false_count = 0
3237 self.load_count = 0
3238 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3239 self.assertEqual(self.id_count, 5)
3240 self.assertEqual(self.false_count, 1)
3241 self.assertEqual(self.load_count, 5)
3242 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003243
Collin Winter771d8342009-04-16 03:18:06 +00003244
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003245class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3246
3247 def persistent_id(self, obj):
3248 return obj
3249
3250 def persistent_load(self, pid):
3251 return pid
3252
3253 def _check_return_correct_type(self, obj, proto):
3254 unpickled = self.loads(self.dumps(obj, proto))
3255 self.assertIsInstance(unpickled, type(obj))
3256 self.assertEqual(unpickled, obj)
3257
3258 def test_return_correct_type(self):
3259 for proto in protocols:
3260 # Protocol 0 supports only ASCII strings.
3261 if proto == 0:
3262 self._check_return_correct_type("abc", 0)
3263 else:
3264 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3265 self._check_return_correct_type(obj, proto)
3266
3267 def test_protocol0_is_ascii_only(self):
3268 non_ascii_str = "\N{EMPTY SET}"
3269 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3270 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3271 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3272
3273
Collin Winter771d8342009-04-16 03:18:06 +00003274class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3275
3276 pickler_class = None
3277 unpickler_class = None
3278
3279 def setUp(self):
3280 assert self.pickler_class
3281 assert self.unpickler_class
3282
3283 def test_clear_pickler_memo(self):
3284 # To test whether clear_memo() has any effect, we pickle an object,
3285 # then pickle it again without clearing the memo; the two serialized
3286 # forms should be different. If we clear_memo() and then pickle the
3287 # object again, the third serialized form should be identical to the
3288 # first one we obtained.
3289 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003290 for proto in protocols:
3291 f = io.BytesIO()
3292 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003293
Serhiy Storchakac8695292018-04-04 00:11:27 +03003294 pickler.dump(data)
3295 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003296
Serhiy Storchakac8695292018-04-04 00:11:27 +03003297 # Reset BytesIO object.
3298 f.seek(0)
3299 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003300
Serhiy Storchakac8695292018-04-04 00:11:27 +03003301 pickler.dump(data)
3302 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003303
Serhiy Storchakac8695292018-04-04 00:11:27 +03003304 # Reset the Pickler and BytesIO objects.
3305 pickler.clear_memo()
3306 f.seek(0)
3307 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003308
Serhiy Storchakac8695292018-04-04 00:11:27 +03003309 pickler.dump(data)
3310 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003311
Serhiy Storchakac8695292018-04-04 00:11:27 +03003312 self.assertNotEqual(first_pickled, second_pickled)
3313 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003314
3315 def test_priming_pickler_memo(self):
3316 # Verify that we can set the Pickler's memo attribute.
3317 data = ["abcdefg", "abcdefg", 44]
3318 f = io.BytesIO()
3319 pickler = self.pickler_class(f)
3320
3321 pickler.dump(data)
3322 first_pickled = f.getvalue()
3323
3324 f = io.BytesIO()
3325 primed = self.pickler_class(f)
3326 primed.memo = pickler.memo
3327
3328 primed.dump(data)
3329 primed_pickled = f.getvalue()
3330
3331 self.assertNotEqual(first_pickled, primed_pickled)
3332
3333 def test_priming_unpickler_memo(self):
3334 # Verify that we can set the Unpickler's memo attribute.
3335 data = ["abcdefg", "abcdefg", 44]
3336 f = io.BytesIO()
3337 pickler = self.pickler_class(f)
3338
3339 pickler.dump(data)
3340 first_pickled = f.getvalue()
3341
3342 f = io.BytesIO()
3343 primed = self.pickler_class(f)
3344 primed.memo = pickler.memo
3345
3346 primed.dump(data)
3347 primed_pickled = f.getvalue()
3348
3349 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3350 unpickled_data1 = unpickler.load()
3351
3352 self.assertEqual(unpickled_data1, data)
3353
3354 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3355 primed.memo = unpickler.memo
3356 unpickled_data2 = primed.load()
3357
3358 primed.memo.clear()
3359
3360 self.assertEqual(unpickled_data2, data)
3361 self.assertTrue(unpickled_data2 is unpickled_data1)
3362
3363 def test_reusing_unpickler_objects(self):
3364 data1 = ["abcdefg", "abcdefg", 44]
3365 f = io.BytesIO()
3366 pickler = self.pickler_class(f)
3367 pickler.dump(data1)
3368 pickled1 = f.getvalue()
3369
3370 data2 = ["abcdefg", 44, 44]
3371 f = io.BytesIO()
3372 pickler = self.pickler_class(f)
3373 pickler.dump(data2)
3374 pickled2 = f.getvalue()
3375
3376 f = io.BytesIO()
3377 f.write(pickled1)
3378 f.seek(0)
3379 unpickler = self.unpickler_class(f)
3380 self.assertEqual(unpickler.load(), data1)
3381
3382 f.seek(0)
3383 f.truncate()
3384 f.write(pickled2)
3385 f.seek(0)
3386 self.assertEqual(unpickler.load(), data2)
3387
Antoine Pitrou9f378722020-02-23 23:33:53 +01003388 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003389 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003390 with self.subTest(proto=proto):
3391 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3392 f = ioclass()
3393 pickler = self.pickler_class(f, protocol=proto)
3394 pickler.dump(data1)
3395 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003396
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003397 N = 5
3398 f = ioclass(pickled * N)
3399 unpickler = self.unpickler_class(f)
3400 for i in range(N):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003401 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003402 pos = f.tell()
3403 self.assertEqual(unpickler.load(), data1)
Antoine Pitrou9f378722020-02-23 23:33:53 +01003404 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003405 self.assertEqual(f.tell(), pos + len(pickled))
3406 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003407
3408 def test_multiple_unpicklings_seekable(self):
3409 self._check_multiple_unpicklings(io.BytesIO)
3410
3411 def test_multiple_unpicklings_unseekable(self):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003412 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3413
3414 def test_multiple_unpicklings_minimal(self):
3415 # File-like object that doesn't support peek() and readinto()
3416 # (bpo-39681)
3417 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003418
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003419 def test_unpickling_buffering_readline(self):
3420 # Issue #12687: the unpickler's buffering logic could fail with
3421 # text mode opcodes.
3422 data = list(range(10))
3423 for proto in protocols:
3424 for buf_size in range(1, 11):
3425 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3426 pickler = self.pickler_class(f, protocol=proto)
3427 pickler.dump(data)
3428 f.seek(0)
3429 unpickler = self.unpickler_class(f)
3430 self.assertEqual(unpickler.load(), data)
3431
Collin Winter771d8342009-04-16 03:18:06 +00003432
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003433# Tests for dispatch_table attribute
3434
3435REDUCE_A = 'reduce_A'
3436
3437class AAA(object):
3438 def __reduce__(self):
3439 return str, (REDUCE_A,)
3440
3441class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003442 def __init__(self):
3443 # Add an instance attribute to enable state-saving routines at pickling
3444 # time.
3445 self.a = "some attribute"
3446
3447 def __setstate__(self, state):
3448 self.a = "BBB.__setstate__"
3449
3450
3451def setstate_bbb(obj, state):
3452 """Custom state setter for BBB objects
3453
3454 Such callable may be created by other persons than the ones who created the
3455 BBB class. If passed as the state_setter item of a custom reducer, this
3456 allows for custom state setting behavior of BBB objects. One can think of
3457 it as the analogous of list_setitems or dict_setitems but for foreign
3458 classes/functions.
3459 """
3460 obj.a = "custom state_setter"
3461
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003462
Pierre Glaser289f1f82019-05-08 23:08:25 +02003463
3464class AbstractCustomPicklerClass:
3465 """Pickler implementing a reducing hook using reducer_override."""
3466 def reducer_override(self, obj):
3467 obj_name = getattr(obj, "__name__", None)
3468
3469 if obj_name == 'f':
3470 # asking the pickler to save f as 5
3471 return int, (5, )
3472
3473 if obj_name == 'MyClass':
3474 return str, ('some str',)
3475
3476 elif obj_name == 'g':
3477 # in this case, the callback returns an invalid result (not a 2-5
3478 # tuple or a string), the pickler should raise a proper error.
3479 return False
3480
3481 elif obj_name == 'h':
3482 # Simulate a case when the reducer fails. The error should
3483 # be propagated to the original ``dump`` call.
3484 raise ValueError('The reducer just failed')
3485
3486 return NotImplemented
3487
3488class AbstractHookTests(unittest.TestCase):
3489 def test_pickler_hook(self):
3490 # test the ability of a custom, user-defined CPickler subclass to
3491 # override the default reducing routines of any type using the method
3492 # reducer_override
3493
3494 def f():
3495 pass
3496
3497 def g():
3498 pass
3499
3500 def h():
3501 pass
3502
3503 class MyClass:
3504 pass
3505
3506 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3507 with self.subTest(proto=proto):
3508 bio = io.BytesIO()
3509 p = self.pickler_class(bio, proto)
3510
3511 p.dump([f, MyClass, math.log])
3512 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3513
3514 self.assertEqual(new_f, 5)
3515 self.assertEqual(some_str, 'some str')
3516 # math.log does not have its usual reducer overriden, so the
3517 # custom reduction callback should silently direct the pickler
3518 # to the default pickling by attribute, by returning
3519 # NotImplemented
3520 self.assertIs(math_log, math.log)
3521
3522 with self.assertRaises(pickle.PicklingError):
3523 p.dump(g)
3524
3525 with self.assertRaisesRegex(
3526 ValueError, 'The reducer just failed'):
3527 p.dump(h)
3528
Pierre Glaser0f2f35e2020-02-02 19:55:21 +01003529 @support.cpython_only
3530 def test_reducer_override_no_reference_cycle(self):
3531 # bpo-39492: reducer_override used to induce a spurious reference cycle
3532 # inside the Pickler object, that could prevent all serialized objects
3533 # from being garbage-collected without explicity invoking gc.collect.
3534
3535 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3536 with self.subTest(proto=proto):
3537 def f():
3538 pass
3539
3540 wr = weakref.ref(f)
3541
3542 bio = io.BytesIO()
3543 p = self.pickler_class(bio, proto)
3544 p.dump(f)
3545 new_f = pickle.loads(bio.getvalue())
3546 assert new_f == 5
3547
3548 del p
3549 del f
3550
3551 self.assertIsNone(wr())
3552
Pierre Glaser289f1f82019-05-08 23:08:25 +02003553
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003554class AbstractDispatchTableTests(unittest.TestCase):
3555
3556 def test_default_dispatch_table(self):
3557 # No dispatch_table attribute by default
3558 f = io.BytesIO()
3559 p = self.pickler_class(f, 0)
3560 with self.assertRaises(AttributeError):
3561 p.dispatch_table
3562 self.assertFalse(hasattr(p, 'dispatch_table'))
3563
3564 def test_class_dispatch_table(self):
3565 # A dispatch_table attribute can be specified class-wide
3566 dt = self.get_dispatch_table()
3567
3568 class MyPickler(self.pickler_class):
3569 dispatch_table = dt
3570
3571 def dumps(obj, protocol=None):
3572 f = io.BytesIO()
3573 p = MyPickler(f, protocol)
3574 self.assertEqual(p.dispatch_table, dt)
3575 p.dump(obj)
3576 return f.getvalue()
3577
3578 self._test_dispatch_table(dumps, dt)
3579
3580 def test_instance_dispatch_table(self):
3581 # A dispatch_table attribute can also be specified instance-wide
3582 dt = self.get_dispatch_table()
3583
3584 def dumps(obj, protocol=None):
3585 f = io.BytesIO()
3586 p = self.pickler_class(f, protocol)
3587 p.dispatch_table = dt
3588 self.assertEqual(p.dispatch_table, dt)
3589 p.dump(obj)
3590 return f.getvalue()
3591
3592 self._test_dispatch_table(dumps, dt)
3593
3594 def _test_dispatch_table(self, dumps, dispatch_table):
3595 def custom_load_dump(obj):
3596 return pickle.loads(dumps(obj, 0))
3597
3598 def default_load_dump(obj):
3599 return pickle.loads(pickle.dumps(obj, 0))
3600
3601 # pickling complex numbers using protocol 0 relies on copyreg
3602 # so check pickling a complex number still works
3603 z = 1 + 2j
3604 self.assertEqual(custom_load_dump(z), z)
3605 self.assertEqual(default_load_dump(z), z)
3606
3607 # modify pickling of complex
3608 REDUCE_1 = 'reduce_1'
3609 def reduce_1(obj):
3610 return str, (REDUCE_1,)
3611 dispatch_table[complex] = reduce_1
3612 self.assertEqual(custom_load_dump(z), REDUCE_1)
3613 self.assertEqual(default_load_dump(z), z)
3614
3615 # check picklability of AAA and BBB
3616 a = AAA()
3617 b = BBB()
3618 self.assertEqual(custom_load_dump(a), REDUCE_A)
3619 self.assertIsInstance(custom_load_dump(b), BBB)
3620 self.assertEqual(default_load_dump(a), REDUCE_A)
3621 self.assertIsInstance(default_load_dump(b), BBB)
3622
3623 # modify pickling of BBB
3624 dispatch_table[BBB] = reduce_1
3625 self.assertEqual(custom_load_dump(a), REDUCE_A)
3626 self.assertEqual(custom_load_dump(b), REDUCE_1)
3627 self.assertEqual(default_load_dump(a), REDUCE_A)
3628 self.assertIsInstance(default_load_dump(b), BBB)
3629
3630 # revert pickling of BBB and modify pickling of AAA
3631 REDUCE_2 = 'reduce_2'
3632 def reduce_2(obj):
3633 return str, (REDUCE_2,)
3634 dispatch_table[AAA] = reduce_2
3635 del dispatch_table[BBB]
3636 self.assertEqual(custom_load_dump(a), REDUCE_2)
3637 self.assertIsInstance(custom_load_dump(b), BBB)
3638 self.assertEqual(default_load_dump(a), REDUCE_A)
3639 self.assertIsInstance(default_load_dump(b), BBB)
3640
Pierre Glaser65d98d02019-05-08 21:40:25 +02003641 # End-to-end testing of save_reduce with the state_setter keyword
3642 # argument. This is a dispatch_table test as the primary goal of
3643 # state_setter is to tweak objects reduction behavior.
3644 # In particular, state_setter is useful when the default __setstate__
3645 # behavior is not flexible enough.
3646
3647 # No custom reducer for b has been registered for now, so
3648 # BBB.__setstate__ should be used at unpickling time
3649 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3650
3651 def reduce_bbb(obj):
3652 return BBB, (), obj.__dict__, None, None, setstate_bbb
3653
3654 dispatch_table[BBB] = reduce_bbb
3655
3656 # The custom reducer reduce_bbb includes a state setter, that should
3657 # have priority over BBB.__setstate__
3658 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3659
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003660
Guido van Rossum98297ee2007-11-06 21:34:58 +00003661if __name__ == "__main__":
3662 # Print some stuff that can be used to rewrite DATA{0,1,2}
3663 from pickletools import dis
3664 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003665 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003666 p = pickle.dumps(x, i)
3667 print("DATA{0} = (".format(i))
3668 for j in range(0, len(p), 20):
3669 b = bytes(p[j:j+20])
3670 print(" {0!r}".format(b))
3671 print(")")
3672 print()
3673 print("# Disassembly of DATA{0}".format(i))
3674 print("DATA{0}_DIS = \"\"\"\\".format(i))
3675 dis(p)
3676 print("\"\"\"")
3677 print()