blob: fb972a3ba5e9b05c79d3a9f00a14cfbc325fd4d5 [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 Storchaka4f309ab2020-07-13 15:49:26 +03001179 def test_bad_reduce(self):
1180 self.assertEqual(self.loads(b'cbuiltins\nint\n)R.'), 0)
1181 self.check_unpickling_error(TypeError, b'N)R.')
1182 self.check_unpickling_error(TypeError, b'cbuiltins\nint\nNR.')
1183
1184 def test_bad_newobj(self):
1185 error = (pickle.UnpicklingError, TypeError)
1186 self.assertEqual(self.loads(b'cbuiltins\nint\n)\x81.'), 0)
1187 self.check_unpickling_error(error, b'cbuiltins\nlen\n)\x81.')
1188 self.check_unpickling_error(error, b'cbuiltins\nint\nN\x81.')
1189
1190 def test_bad_newobj_ex(self):
1191 error = (pickle.UnpicklingError, TypeError)
1192 self.assertEqual(self.loads(b'cbuiltins\nint\n)}\x92.'), 0)
1193 self.check_unpickling_error(error, b'cbuiltins\nlen\n)}\x92.')
1194 self.check_unpickling_error(error, b'cbuiltins\nint\nN}\x92.')
1195 self.check_unpickling_error(error, b'cbuiltins\nint\n)N\x92.')
1196
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001197 def test_bad_stack(self):
1198 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001199 b'.', # STOP
1200 b'0', # POP
1201 b'1', # POP_MARK
1202 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001203 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001204 b'R', # REDUCE
1205 b')R',
1206 b'a', # APPEND
1207 b'Na',
1208 b'b', # BUILD
1209 b'Nb',
1210 b'd', # DICT
1211 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001212 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001213 b'ibuiltins\nlist\n', # INST
1214 b'l', # LIST
1215 b'o', # OBJ
1216 b'(o',
1217 b'p1\n', # PUT
1218 b'q\x00', # BINPUT
1219 b'r\x00\x00\x00\x00', # LONG_BINPUT
1220 b's', # SETITEM
1221 b'Ns',
1222 b'NNs',
1223 b't', # TUPLE
1224 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001225 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001226 b'}(Nu',
1227 b'\x81', # NEWOBJ
1228 b')\x81',
1229 b'\x85', # TUPLE1
1230 b'\x86', # TUPLE2
1231 b'N\x86',
1232 b'\x87', # TUPLE3
1233 b'N\x87',
1234 b'NN\x87',
1235 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001236 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001237 b'\x91', # FROZENSET
1238 b'\x92', # NEWOBJ_EX
1239 b')}\x92',
1240 b'\x93', # STACK_GLOBAL
1241 b'Vlist\n\x93',
1242 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001243 ]
1244 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001245 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001246
1247 def test_bad_mark(self):
1248 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001249 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001250 b'N(2', # DUP
1251 b'cbuiltins\nlist\n)(R', # REDUCE
1252 b'cbuiltins\nlist\n()R',
1253 b']N(a', # APPEND
1254 # BUILD
1255 b'cbuiltins\nValueError\n)R}(b',
1256 b'cbuiltins\nValueError\n)R(}b',
1257 b'(Nd', # DICT
1258 b'N(p1\n', # PUT
1259 b'N(q\x00', # BINPUT
1260 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1261 b'}NN(s', # SETITEM
1262 b'}N(Ns',
1263 b'}(NNs',
1264 b'}((u', # SETITEMS
1265 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1266 b'cbuiltins\nlist\n()\x81',
1267 b'N(\x85', # TUPLE1
1268 b'NN(\x86', # TUPLE2
1269 b'N(N\x86',
1270 b'NNN(\x87', # TUPLE3
1271 b'NN(N\x87',
1272 b'N(NN\x87',
1273 b']((\x90', # ADDITEMS
1274 # NEWOBJ_EX
1275 b'cbuiltins\nlist\n)}(\x92',
1276 b'cbuiltins\nlist\n)(}\x92',
1277 b'cbuiltins\nlist\n()}\x92',
1278 # STACK_GLOBAL
1279 b'Vbuiltins\n(Vlist\n\x93',
1280 b'Vbuiltins\nVlist\n(\x93',
1281 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001282 ]
1283 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001284 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001285
1286 def test_truncated_data(self):
1287 self.check_unpickling_error(EOFError, b'')
1288 self.check_unpickling_error(EOFError, b'N')
1289 badpickles = [
1290 b'B', # BINBYTES
1291 b'B\x03\x00\x00',
1292 b'B\x03\x00\x00\x00',
1293 b'B\x03\x00\x00\x00ab',
1294 b'C', # SHORT_BINBYTES
1295 b'C\x03',
1296 b'C\x03ab',
1297 b'F', # FLOAT
1298 b'F0.0',
1299 b'F0.00',
1300 b'G', # BINFLOAT
1301 b'G\x00\x00\x00\x00\x00\x00\x00',
1302 b'I', # INT
1303 b'I0',
1304 b'J', # BININT
1305 b'J\x00\x00\x00',
1306 b'K', # BININT1
1307 b'L', # LONG
1308 b'L0',
1309 b'L10',
1310 b'L0L',
1311 b'L10L',
1312 b'M', # BININT2
1313 b'M\x00',
1314 # b'P', # PERSID
1315 # b'Pabc',
1316 b'S', # STRING
1317 b"S'abc'",
1318 b'T', # BINSTRING
1319 b'T\x03\x00\x00',
1320 b'T\x03\x00\x00\x00',
1321 b'T\x03\x00\x00\x00ab',
1322 b'U', # SHORT_BINSTRING
1323 b'U\x03',
1324 b'U\x03ab',
1325 b'V', # UNICODE
1326 b'Vabc',
1327 b'X', # BINUNICODE
1328 b'X\x03\x00\x00',
1329 b'X\x03\x00\x00\x00',
1330 b'X\x03\x00\x00\x00ab',
1331 b'(c', # GLOBAL
1332 b'(cbuiltins',
1333 b'(cbuiltins\n',
1334 b'(cbuiltins\nlist',
1335 b'Ng', # GET
1336 b'Ng0',
1337 b'(i', # INST
1338 b'(ibuiltins',
1339 b'(ibuiltins\n',
1340 b'(ibuiltins\nlist',
1341 b'Nh', # BINGET
1342 b'Nj', # LONG_BINGET
1343 b'Nj\x00\x00\x00',
1344 b'Np', # PUT
1345 b'Np0',
1346 b'Nq', # BINPUT
1347 b'Nr', # LONG_BINPUT
1348 b'Nr\x00\x00\x00',
1349 b'\x80', # PROTO
1350 b'\x82', # EXT1
1351 b'\x83', # EXT2
1352 b'\x84\x01',
1353 b'\x84', # EXT4
1354 b'\x84\x01\x00\x00',
1355 b'\x8a', # LONG1
1356 b'\x8b', # LONG4
1357 b'\x8b\x00\x00\x00',
1358 b'\x8c', # SHORT_BINUNICODE
1359 b'\x8c\x03',
1360 b'\x8c\x03ab',
1361 b'\x8d', # BINUNICODE8
1362 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1363 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1364 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1365 b'\x8e', # BINBYTES8
1366 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1367 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1368 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001369 b'\x96', # BYTEARRAY8
1370 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1371 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1372 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001373 b'\x95', # FRAME
1374 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1375 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1376 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1377 ]
1378 for p in badpickles:
1379 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001380
Hai Shie80697d2020-05-28 06:10:27 +08001381 @threading_helper.reap_threads
tjb9004371c0a2019-02-18 23:30:51 +08001382 def test_unpickle_module_race(self):
1383 # https://bugs.python.org/issue34572
1384 locker_module = dedent("""
1385 import threading
1386 barrier = threading.Barrier(2)
1387 """)
1388 locking_import_module = dedent("""
1389 import locker
1390 locker.barrier.wait()
1391 class ToBeUnpickled(object):
1392 pass
1393 """)
1394
1395 os.mkdir(TESTFN)
1396 self.addCleanup(shutil.rmtree, TESTFN)
1397 sys.path.insert(0, TESTFN)
1398 self.addCleanup(sys.path.remove, TESTFN)
1399 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1400 f.write(locker_module.encode('utf-8'))
1401 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1402 f.write(locking_import_module.encode('utf-8'))
1403 self.addCleanup(forget, "locker")
1404 self.addCleanup(forget, "locking_import")
1405
1406 import locker
1407
1408 pickle_bytes = (
1409 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1410
1411 # Then try to unpickle two of these simultaneously
1412 # One of them will cause the module import, and we want it to block
1413 # until the other one either:
1414 # - fails (before the patch for this issue)
1415 # - blocks on the import lock for the module, as it should
1416 results = []
1417 barrier = threading.Barrier(3)
1418 def t():
1419 # This ensures the threads have all started
1420 # presumably barrier release is faster than thread startup
1421 barrier.wait()
1422 results.append(pickle.loads(pickle_bytes))
1423
1424 t1 = threading.Thread(target=t)
1425 t2 = threading.Thread(target=t)
1426 t1.start()
1427 t2.start()
1428
1429 barrier.wait()
1430 # could have delay here
1431 locker.barrier.wait()
1432
1433 t1.join()
1434 t2.join()
1435
1436 from locking_import import ToBeUnpickled
1437 self.assertEqual(
1438 [type(x) for x in results],
1439 [ToBeUnpickled] * 2)
1440
1441
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001442
1443class AbstractPickleTests(unittest.TestCase):
1444 # Subclass must define self.dumps, self.loads.
1445
1446 optimized = False
1447
1448 _testdata = AbstractUnpickleTests._testdata
1449
1450 def setUp(self):
1451 pass
1452
1453 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1454
1455 def test_misc(self):
1456 # test various datatypes not tested by testdata
1457 for proto in protocols:
1458 x = myint(4)
1459 s = self.dumps(x, proto)
1460 y = self.loads(s)
1461 self.assert_is_copy(x, y)
1462
1463 x = (1, ())
1464 s = self.dumps(x, proto)
1465 y = self.loads(s)
1466 self.assert_is_copy(x, y)
1467
1468 x = initarg(1, x)
1469 s = self.dumps(x, proto)
1470 y = self.loads(s)
1471 self.assert_is_copy(x, y)
1472
1473 # XXX test __reduce__ protocol?
1474
1475 def test_roundtrip_equality(self):
1476 expected = self._testdata
1477 for proto in protocols:
1478 s = self.dumps(expected, proto)
1479 got = self.loads(s)
1480 self.assert_is_copy(expected, got)
1481
Tim Peters70b02d72003-02-02 17:26:40 +00001482 # There are gratuitous differences between pickles produced by
1483 # pickle and cPickle, largely because cPickle starts PUT indices at
1484 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1485 # there's a comment with an exclamation point there whose meaning
1486 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1487 # of 1.
1488 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001489 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001490 from pickletools import dis
1491
1492 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1493 s = self.dumps(self._testdata, proto)
1494 filelike = StringIO()
1495 dis(s, out=filelike)
1496 got = filelike.getvalue()
1497 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001498
1499 def test_recursive_list(self):
1500 l = []
1501 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001502 for proto in protocols:
1503 s = self.dumps(l, proto)
1504 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001505 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001506 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001507 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001508
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001509 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001510 t = ([],)
1511 t[0].append(t)
1512 for proto in protocols:
1513 s = self.dumps(t, proto)
1514 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001515 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001516 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001517 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001518 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001519 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001520
Jeremy Hylton66426532001-10-15 21:38:56 +00001521 def test_recursive_dict(self):
1522 d = {}
1523 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001524 for proto in protocols:
1525 s = self.dumps(d, proto)
1526 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001527 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001528 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001529 self.assertIs(x[1], x)
1530
1531 def test_recursive_dict_key(self):
1532 d = {}
1533 k = K(d)
1534 d[k] = 1
1535 for proto in protocols:
1536 s = self.dumps(d, proto)
1537 x = self.loads(s)
1538 self.assertIsInstance(x, dict)
1539 self.assertEqual(len(x.keys()), 1)
1540 self.assertIsInstance(list(x.keys())[0], K)
1541 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001542
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001543 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001544 y = set()
1545 k = K(y)
1546 y.add(k)
1547 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001548 s = self.dumps(y, proto)
1549 x = self.loads(s)
1550 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001551 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001552 self.assertIsInstance(list(x)[0], K)
1553 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001554
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001555 def test_recursive_list_subclass(self):
1556 y = MyList()
1557 y.append(y)
1558 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001559 s = self.dumps(y, proto)
1560 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001561 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001562 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001563 self.assertIs(x[0], x)
1564
1565 def test_recursive_dict_subclass(self):
1566 d = MyDict()
1567 d[1] = d
1568 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1569 s = self.dumps(d, proto)
1570 x = self.loads(s)
1571 self.assertIsInstance(x, MyDict)
1572 self.assertEqual(list(x.keys()), [1])
1573 self.assertIs(x[1], x)
1574
1575 def test_recursive_dict_subclass_key(self):
1576 d = MyDict()
1577 k = K(d)
1578 d[k] = 1
1579 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1580 s = self.dumps(d, proto)
1581 x = self.loads(s)
1582 self.assertIsInstance(x, MyDict)
1583 self.assertEqual(len(list(x.keys())), 1)
1584 self.assertIsInstance(list(x.keys())[0], K)
1585 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001586
Jeremy Hylton66426532001-10-15 21:38:56 +00001587 def test_recursive_inst(self):
1588 i = C()
1589 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001590 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001591 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001592 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001593 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001594 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001595 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001596
1597 def test_recursive_multi(self):
1598 l = []
1599 d = {1:l}
1600 i = C()
1601 i.attr = d
1602 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001603 for proto in protocols:
1604 s = self.dumps(l, proto)
1605 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001606 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001607 self.assertEqual(len(x), 1)
1608 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001609 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001610 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001611
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001612 def check_recursive_collection_and_inst(self, factory):
1613 h = H()
1614 y = factory([h])
1615 h.attr = y
1616 for proto in protocols:
1617 s = self.dumps(y, proto)
1618 x = self.loads(s)
1619 self.assertIsInstance(x, type(y))
1620 self.assertEqual(len(x), 1)
1621 self.assertIsInstance(list(x)[0], H)
1622 self.assertIs(list(x)[0].attr, x)
1623
1624 def test_recursive_list_and_inst(self):
1625 self.check_recursive_collection_and_inst(list)
1626
1627 def test_recursive_tuple_and_inst(self):
1628 self.check_recursive_collection_and_inst(tuple)
1629
1630 def test_recursive_dict_and_inst(self):
1631 self.check_recursive_collection_and_inst(dict.fromkeys)
1632
1633 def test_recursive_set_and_inst(self):
1634 self.check_recursive_collection_and_inst(set)
1635
1636 def test_recursive_frozenset_and_inst(self):
1637 self.check_recursive_collection_and_inst(frozenset)
1638
1639 def test_recursive_list_subclass_and_inst(self):
1640 self.check_recursive_collection_and_inst(MyList)
1641
1642 def test_recursive_tuple_subclass_and_inst(self):
1643 self.check_recursive_collection_and_inst(MyTuple)
1644
1645 def test_recursive_dict_subclass_and_inst(self):
1646 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1647
1648 def test_recursive_set_subclass_and_inst(self):
1649 self.check_recursive_collection_and_inst(MySet)
1650
1651 def test_recursive_frozenset_subclass_and_inst(self):
1652 self.check_recursive_collection_and_inst(MyFrozenSet)
1653
Walter Dörwald9b775532007-06-08 14:30:53 +00001654 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001655 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001656 '<\\>', '<\\\U00012345>',
1657 # surrogates
1658 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001659 for proto in protocols:
1660 for u in endcases:
1661 p = self.dumps(u, proto)
1662 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001663 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001664
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001665 def test_unicode_high_plane(self):
1666 t = '\U00012345'
1667 for proto in protocols:
1668 p = self.dumps(t, proto)
1669 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001670 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001671
Guido van Rossumf4169812008-03-17 22:56:06 +00001672 def test_bytes(self):
1673 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001674 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001675 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001676 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001677 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001678 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001679 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001680 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001681 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001682 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001683
Antoine Pitrou91f43802019-05-26 17:10:09 +02001684 def test_bytearray(self):
1685 for proto in protocols:
1686 for s in b'', b'xyz', b'xyz'*100:
1687 b = bytearray(s)
1688 p = self.dumps(b, proto)
1689 bb = self.loads(p)
1690 self.assertIsNot(bb, b)
1691 self.assert_is_copy(b, bb)
1692 if proto <= 3:
1693 # bytearray is serialized using a global reference
1694 self.assertIn(b'bytearray', p)
1695 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1696 elif proto == 4:
1697 self.assertIn(b'bytearray', p)
1698 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1699 elif proto == 5:
1700 self.assertNotIn(b'bytearray', p)
1701 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1702
Jeremy Hylton66426532001-10-15 21:38:56 +00001703 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001704 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001705 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001706 while n:
1707 for expected in (-n, n):
1708 s = self.dumps(expected, proto)
1709 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001710 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001711 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001712
Tim Petersee1a53c2003-02-02 02:57:53 +00001713 def test_long(self):
1714 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001715 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001716 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001717 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001718 for npos in nbase-1, nbase, nbase+1:
1719 for n in npos, -npos:
1720 pickle = self.dumps(n, proto)
1721 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001722 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001723 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1724 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001725 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001726 nbase += nbase << 1000000
1727 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001728 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001729 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001730 # assert_is_copy is very expensive here as it precomputes
1731 # a failure message by computing the repr() of n and got,
1732 # we just do the check ourselves.
1733 self.assertIs(type(got), int)
1734 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001735
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001736 def test_float(self):
1737 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1738 3.14, 263.44582062374053, 6.022e23, 1e30]
1739 test_values = test_values + [-x for x in test_values]
1740 for proto in protocols:
1741 for value in test_values:
1742 pickle = self.dumps(value, proto)
1743 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001744 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001745
Thomas Wouters477c8d52006-05-27 19:21:47 +00001746 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1747 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001748 # make sure that floats are formatted locale independent with proto 0
1749 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001750
Jeremy Hylton66426532001-10-15 21:38:56 +00001751 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001752 for proto in protocols:
1753 inst = AAA()
1754 dumped = self.dumps(inst, proto)
1755 loaded = self.loads(dumped)
1756 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001757
1758 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001759 for proto in protocols:
1760 inst = initarg(1, 2)
1761 dumped = self.dumps(inst, proto)
1762 loaded = self.loads(dumped)
1763 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001764
Guido van Rossum04a86612001-12-19 16:58:54 +00001765 def test_metaclass(self):
1766 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001767 for proto in protocols:
1768 s = self.dumps(a, proto)
1769 b = self.loads(s)
1770 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001771
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001772 def test_dynamic_class(self):
1773 a = create_dynamic_class("my_dynamic_class", (object,))
1774 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1775 for proto in protocols:
1776 s = self.dumps(a, proto)
1777 b = self.loads(s)
1778 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001779 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001780
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001781 def test_structseq(self):
1782 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001783 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001784
1785 t = time.localtime()
1786 for proto in protocols:
1787 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001788 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001789 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001790 t = os.stat(os.curdir)
1791 s = self.dumps(t, proto)
1792 u = self.loads(s)
1793 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001794 if hasattr(os, "statvfs"):
1795 t = os.statvfs(os.curdir)
1796 s = self.dumps(t, proto)
1797 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001798 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001799
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001800 def test_ellipsis(self):
1801 for proto in protocols:
1802 s = self.dumps(..., proto)
1803 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001804 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001805
1806 def test_notimplemented(self):
1807 for proto in protocols:
1808 s = self.dumps(NotImplemented, proto)
1809 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001810 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001811
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001812 def test_singleton_types(self):
1813 # Issue #6477: Test that types of built-in singletons can be pickled.
1814 singletons = [None, ..., NotImplemented]
1815 for singleton in singletons:
1816 for proto in protocols:
1817 s = self.dumps(type(singleton), proto)
1818 u = self.loads(s)
1819 self.assertIs(type(singleton), u)
1820
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001821 # Tests for protocol 2
1822
Tim Peters4190fb82003-02-02 16:09:05 +00001823 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001824 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001825 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001826 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001827 proto_header = pickle.PROTO + bytes([proto])
1828 self.assertTrue(pickled.startswith(proto_header))
1829 else:
1830 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001831
1832 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001833 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001834 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001835 try:
1836 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001837 except ValueError as err:
1838 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001839 else:
1840 self.fail("expected bad protocol number to raise ValueError")
1841
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001842 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001843 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001844 for proto in protocols:
1845 s = self.dumps(x, proto)
1846 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001847 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001848 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001849
1850 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001851 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001852 for proto in protocols:
1853 s = self.dumps(x, proto)
1854 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001855 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001856 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001857
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001858 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001859 # Map (proto, len(tuple)) to expected opcode.
1860 expected_opcode = {(0, 0): pickle.TUPLE,
1861 (0, 1): pickle.TUPLE,
1862 (0, 2): pickle.TUPLE,
1863 (0, 3): pickle.TUPLE,
1864 (0, 4): pickle.TUPLE,
1865
1866 (1, 0): pickle.EMPTY_TUPLE,
1867 (1, 1): pickle.TUPLE,
1868 (1, 2): pickle.TUPLE,
1869 (1, 3): pickle.TUPLE,
1870 (1, 4): pickle.TUPLE,
1871
1872 (2, 0): pickle.EMPTY_TUPLE,
1873 (2, 1): pickle.TUPLE1,
1874 (2, 2): pickle.TUPLE2,
1875 (2, 3): pickle.TUPLE3,
1876 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001877
1878 (3, 0): pickle.EMPTY_TUPLE,
1879 (3, 1): pickle.TUPLE1,
1880 (3, 2): pickle.TUPLE2,
1881 (3, 3): pickle.TUPLE3,
1882 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001883 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001884 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001885 b = (1,)
1886 c = (1, 2)
1887 d = (1, 2, 3)
1888 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001889 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001890 for x in a, b, c, d, e:
1891 s = self.dumps(x, proto)
1892 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001893 self.assert_is_copy(x, y)
1894 expected = expected_opcode[min(proto, 3), len(x)]
1895 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001896
Guido van Rossum7d97d312003-01-28 04:25:27 +00001897 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001898 # Map (proto, singleton) to expected opcode.
1899 expected_opcode = {(0, None): pickle.NONE,
1900 (1, None): pickle.NONE,
1901 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001902 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001903
1904 (0, True): pickle.INT,
1905 (1, True): pickle.INT,
1906 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001907 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001908
1909 (0, False): pickle.INT,
1910 (1, False): pickle.INT,
1911 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001912 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001913 }
Tim Peters4190fb82003-02-02 16:09:05 +00001914 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001915 for x in None, False, True:
1916 s = self.dumps(x, proto)
1917 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001918 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001919 expected = expected_opcode[min(proto, 3), x]
1920 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001921
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001922 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001923 x = MyTuple([1, 2, 3])
1924 x.foo = 42
1925 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001926 for proto in protocols:
1927 s = self.dumps(x, proto)
1928 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001929 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001930
1931 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001932 x = MyList([1, 2, 3])
1933 x.foo = 42
1934 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001935 for proto in protocols:
1936 s = self.dumps(x, proto)
1937 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001938 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001939
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001940 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001941 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001942 for C in myclasses:
1943 B = C.__base__
1944 x = C(C.sample)
1945 x.foo = 42
1946 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001947 y = self.loads(s)
1948 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001949 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001950 self.assertEqual(B(x), B(y), detail)
1951 self.assertEqual(x.__dict__, y.__dict__, detail)
1952
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001953 def test_newobj_proxies(self):
1954 # NEWOBJ should use the __class__ rather than the raw type
1955 classes = myclasses[:]
1956 # Cannot create weakproxies to these classes
1957 for c in (MyInt, MyTuple):
1958 classes.remove(c)
1959 for proto in protocols:
1960 for C in classes:
1961 B = C.__base__
1962 x = C(C.sample)
1963 x.foo = 42
1964 p = weakref.proxy(x)
1965 s = self.dumps(p, proto)
1966 y = self.loads(s)
1967 self.assertEqual(type(y), type(x)) # rather than type(p)
1968 detail = (proto, C, B, x, y, type(y))
1969 self.assertEqual(B(x), B(y), detail)
1970 self.assertEqual(x.__dict__, y.__dict__, detail)
1971
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001972 def test_newobj_not_class(self):
1973 # Issue 24552
1974 global SimpleNewObj
1975 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001976 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001977 b = self.dumps(o, 4)
1978 try:
1979 SimpleNewObj = 42
1980 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1981 finally:
1982 SimpleNewObj = save
1983
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001984 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001985 # an object of that type. Check that the resulting pickle uses opcode
1986 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001987
Tim Peters22e71712003-02-03 22:27:38 +00001988 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001989 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001990 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001991 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001992 x = MyList([1, 2, 3])
1993 x.foo = 42
1994 x.bar = "hello"
1995
Tim Peters22e71712003-02-03 22:27:38 +00001996 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001997 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001998 self.assertIn(__name__.encode("utf-8"), s1)
1999 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002000 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00002001
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002002 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002003 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002004
Tim Peters22e71712003-02-03 22:27:38 +00002005 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002006 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002007 self.assertNotIn(__name__.encode("utf-8"), s2)
2008 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00002009 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00002010
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002011 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002012 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002013 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00002014 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00002015
2016 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002017 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
2018 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002019
2020 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002021 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
2022 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
2023 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002024
2025 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002026 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
2027 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
2028 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
2029
Tim Peters8d2613a2003-02-11 16:40:16 +00002030 def test_list_chunking(self):
2031 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002032 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002033 for proto in protocols:
2034 s = self.dumps(x, proto)
2035 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002036 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002037 num_appends = count_opcode(pickle.APPENDS, s)
2038 self.assertEqual(num_appends, proto > 0)
2039
2040 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002041 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002042 for proto in protocols:
2043 s = self.dumps(x, proto)
2044 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002045 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002046 num_appends = count_opcode(pickle.APPENDS, s)
2047 if proto == 0:
2048 self.assertEqual(num_appends, 0)
2049 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002050 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002051
2052 def test_dict_chunking(self):
2053 n = 10 # too small to chunk
2054 x = dict.fromkeys(range(n))
2055 for proto in protocols:
2056 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002057 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002058 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002059 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002060 num_setitems = count_opcode(pickle.SETITEMS, s)
2061 self.assertEqual(num_setitems, proto > 0)
2062
2063 n = 2500 # expect at least two chunks when proto > 0
2064 x = dict.fromkeys(range(n))
2065 for proto in protocols:
2066 s = self.dumps(x, proto)
2067 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002068 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002069 num_setitems = count_opcode(pickle.SETITEMS, s)
2070 if proto == 0:
2071 self.assertEqual(num_setitems, 0)
2072 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002073 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002074
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002075 def test_set_chunking(self):
2076 n = 10 # too small to chunk
2077 x = set(range(n))
2078 for proto in protocols:
2079 s = self.dumps(x, proto)
2080 y = self.loads(s)
2081 self.assert_is_copy(x, y)
2082 num_additems = count_opcode(pickle.ADDITEMS, s)
2083 if proto < 4:
2084 self.assertEqual(num_additems, 0)
2085 else:
2086 self.assertEqual(num_additems, 1)
2087
2088 n = 2500 # expect at least two chunks when proto >= 4
2089 x = set(range(n))
2090 for proto in protocols:
2091 s = self.dumps(x, proto)
2092 y = self.loads(s)
2093 self.assert_is_copy(x, y)
2094 num_additems = count_opcode(pickle.ADDITEMS, s)
2095 if proto < 4:
2096 self.assertEqual(num_additems, 0)
2097 else:
2098 self.assertGreaterEqual(num_additems, 2)
2099
Tim Peterse9ef2032003-02-13 18:42:00 +00002100 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002101 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002102 x.abc = 666
2103 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002104 with self.subTest(proto=proto):
2105 s = self.dumps(x, proto)
2106 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002107 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002108 else:
2109 self.assertIn(b'M\xce\xfa', s) # BININT2
2110 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2111 2 <= proto)
2112 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2113 y = self.loads(s) # will raise TypeError if __init__ called
2114 self.assert_is_copy(x, y)
2115
2116 def test_complex_newobj(self):
2117 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2118 x.abc = 666
2119 for proto in protocols:
2120 with self.subTest(proto=proto):
2121 s = self.dumps(x, proto)
2122 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002123 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002124 elif proto < 2:
2125 self.assertIn(b'M\xce\xfa', s) # BININT2
2126 elif proto < 4:
2127 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2128 else:
2129 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2130 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2131 2 <= proto)
2132 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2133 y = self.loads(s) # will raise TypeError if __init__ called
2134 self.assert_is_copy(x, y)
2135
2136 def test_complex_newobj_ex(self):
2137 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2138 x.abc = 666
2139 for proto in protocols:
2140 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002141 s = self.dumps(x, proto)
2142 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002143 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002144 elif proto < 2:
2145 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002146 elif proto < 4:
2147 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002148 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002149 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2150 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2151 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2152 4 <= proto)
2153 y = self.loads(s) # will raise TypeError if __init__ called
2154 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002155
Tim Peters42f08ac2003-02-11 22:43:24 +00002156 def test_newobj_list_slots(self):
2157 x = SlotList([1, 2, 3])
2158 x.foo = 42
2159 x.bar = "hello"
2160 s = self.dumps(x, 2)
2161 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002162 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002163
Guido van Rossum2a30b212003-02-18 22:41:24 +00002164 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002165 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002166 x = REX_one()
2167 self.assertEqual(x._reduce_called, 0)
2168 s = self.dumps(x, proto)
2169 self.assertEqual(x._reduce_called, 1)
2170 y = self.loads(s)
2171 self.assertEqual(y._reduce_called, 0)
2172
2173 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002174 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002175 x = REX_two()
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, None)
2181
2182 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002183 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002184 x = REX_three()
2185 self.assertEqual(x._proto, None)
2186 s = self.dumps(x, proto)
2187 self.assertEqual(x._proto, proto)
2188 y = self.loads(s)
2189 self.assertEqual(y._proto, None)
2190
Guido van Rossumd8faa362007-04-27 19:54:29 +00002191 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002192 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002193 x = REX_four()
2194 self.assertEqual(x._proto, None)
2195 s = self.dumps(x, proto)
2196 self.assertEqual(x._proto, proto)
2197 y = self.loads(s)
2198 self.assertEqual(y._proto, proto)
2199
2200 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002201 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002202 x = REX_five()
2203 self.assertEqual(x._reduce_called, 0)
2204 s = self.dumps(x, proto)
2205 self.assertEqual(x._reduce_called, 1)
2206 y = self.loads(s)
2207 self.assertEqual(y._reduce_called, 1)
2208
Brett Cannon31f59292011-02-21 19:29:56 +00002209 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002210 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002211 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002212 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002213 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002214 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002215
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002216 def test_reduce_bad_iterator(self):
2217 # Issue4176: crash when 4th and 5th items of __reduce__()
2218 # are not iterators
2219 class C(object):
2220 def __reduce__(self):
2221 # 4th item is not an iterator
2222 return list, (), None, [], None
2223 class D(object):
2224 def __reduce__(self):
2225 # 5th item is not an iterator
2226 return dict, (), None, None, []
2227
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002228 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002229 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002230 try:
2231 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002232 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002233 pass
2234 try:
2235 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002236 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002237 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002238
Collin Winter771d8342009-04-16 03:18:06 +00002239 def test_many_puts_and_gets(self):
2240 # Test that internal data structures correctly deal with lots of
2241 # puts/gets.
2242 keys = ("aaa" + str(i) for i in range(100))
2243 large_dict = dict((k, [4, 5, 6]) for k in keys)
2244 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2245
2246 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002247 with self.subTest(proto=proto):
2248 dumped = self.dumps(obj, proto)
2249 loaded = self.loads(dumped)
2250 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002251
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002252 def test_attribute_name_interning(self):
2253 # Test that attribute names of pickled objects are interned when
2254 # unpickling.
2255 for proto in protocols:
2256 x = C()
2257 x.foo = 42
2258 x.bar = "hello"
2259 s = self.dumps(x, proto)
2260 y = self.loads(s)
2261 x_keys = sorted(x.__dict__)
2262 y_keys = sorted(y.__dict__)
2263 for x_key, y_key in zip(x_keys, y_keys):
2264 self.assertIs(x_key, y_key)
2265
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002266 def test_pickle_to_2x(self):
2267 # Pickle non-trivial data with protocol 2, expecting that it yields
2268 # the same result as Python 2.x did.
2269 # NOTE: this test is a bit too strong since we can produce different
2270 # bytecode that 2.x will still understand.
2271 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002272 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002273 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002274 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002275
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002276 def test_large_pickles(self):
2277 # Test the correctness of internal buffering routines when handling
2278 # large data.
2279 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002280 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002281 dumped = self.dumps(data, proto)
2282 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002283 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002284 self.assertEqual(loaded, data)
2285
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002286 def test_int_pickling_efficiency(self):
2287 # Test compacity of int representation (see issue #12744)
2288 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002289 with self.subTest(proto=proto):
2290 pickles = [self.dumps(2**n, proto) for n in range(70)]
2291 sizes = list(map(len, pickles))
2292 # the size function is monotonic
2293 self.assertEqual(sorted(sizes), sizes)
2294 if proto >= 2:
2295 for p in pickles:
2296 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002297
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002298 def _check_pickling_with_opcode(self, obj, opcode, proto):
2299 pickled = self.dumps(obj, proto)
2300 self.assertTrue(opcode_in_pickle(opcode, pickled))
2301 unpickled = self.loads(pickled)
2302 self.assertEqual(obj, unpickled)
2303
2304 def test_appends_on_non_lists(self):
2305 # Issue #17720
2306 obj = REX_six([1, 2, 3])
2307 for proto in protocols:
2308 if proto == 0:
2309 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2310 else:
2311 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2312
2313 def test_setitems_on_non_dicts(self):
2314 obj = REX_seven({1: -1, 2: -2, 3: -3})
2315 for proto in protocols:
2316 if proto == 0:
2317 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2318 else:
2319 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2320
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002321 # Exercise framing (proto >= 4) for significant workloads
2322
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002323 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002324 FRAME_SIZE_TARGET = 64 * 1024
2325
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002326 def check_frame_opcodes(self, pickled):
2327 """
2328 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002329
2330 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2331 framed by default and are therefore considered a frame by themselves in
2332 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002333 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002334 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002335 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2336 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002337 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002338 if frame_end is not None:
2339 self.assertLessEqual(pos, frame_end)
2340 if pos == frame_end:
2341 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002342
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002343 if frame_end is not None: # framed
2344 self.assertNotEqual(op.name, 'FRAME')
2345 if op.name in frameless_opcodes:
2346 # Only short bytes and str objects should be written
2347 # in a frame
2348 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2349
2350 else: # not framed
2351 if (op.name == 'FRAME' or
2352 (op.name in frameless_opcodes and
2353 len(arg) > self.FRAME_SIZE_TARGET)):
2354 # Frame or large bytes or str object
2355 if frameless_start is not None:
2356 # Only short data should be written outside of a frame
2357 self.assertLess(pos - frameless_start,
2358 self.FRAME_SIZE_MIN)
2359 frameless_start = None
2360 elif frameless_start is None and op.name != 'PROTO':
2361 frameless_start = pos
2362
2363 if op.name == 'FRAME':
2364 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2365 frame_end = pos + 9 + arg
2366
2367 pos = len(pickled)
2368 if frame_end is not None:
2369 self.assertEqual(frame_end, pos)
2370 elif frameless_start is not None:
2371 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002372
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002373 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002374 def test_framing_many_objects(self):
2375 obj = list(range(10**5))
2376 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2377 with self.subTest(proto=proto):
2378 pickled = self.dumps(obj, proto)
2379 unpickled = self.loads(pickled)
2380 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002381 bytes_per_frame = (len(pickled) /
2382 count_opcode(pickle.FRAME, pickled))
2383 self.assertGreater(bytes_per_frame,
2384 self.FRAME_SIZE_TARGET / 2)
2385 self.assertLessEqual(bytes_per_frame,
2386 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002387 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002388
2389 def test_framing_large_objects(self):
2390 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002391 small_items = [[i] for i in range(10)]
2392 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002393 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002394 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002395 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002396 if not fast:
2397 # fast=False by default.
2398 # This covers in-memory pickling with pickle.dumps().
2399 pickled = self.dumps(obj, proto)
2400 else:
2401 # Pickler is required when fast=True.
2402 if not hasattr(self, 'pickler'):
2403 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002404 buf = io.BytesIO()
2405 pickler = self.pickler(buf, protocol=proto)
2406 pickler.fast = fast
2407 pickler.dump(obj)
2408 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002409 unpickled = self.loads(pickled)
2410 # More informative error message in case of failure.
2411 self.assertEqual([len(x) for x in obj],
2412 [len(x) for x in unpickled])
2413 # Perform full equality check if the lengths match.
2414 self.assertEqual(obj, unpickled)
2415 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002416 # A single frame for small objects between
2417 # first two large objects.
2418 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002419 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002420
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002421 def test_optional_frames(self):
2422 if pickle.HIGHEST_PROTOCOL < 4:
2423 return
2424
2425 def remove_frames(pickled, keep_frame=None):
2426 """Remove frame opcodes from the given pickle."""
2427 frame_starts = []
2428 # 1 byte for the opcode and 8 for the argument
2429 frame_opcode_size = 9
2430 for opcode, _, pos in pickletools.genops(pickled):
2431 if opcode.name == 'FRAME':
2432 frame_starts.append(pos)
2433
2434 newpickle = bytearray()
2435 last_frame_end = 0
2436 for i, pos in enumerate(frame_starts):
2437 if keep_frame and keep_frame(i):
2438 continue
2439 newpickle += pickled[last_frame_end:pos]
2440 last_frame_end = pos + frame_opcode_size
2441 newpickle += pickled[last_frame_end:]
2442 return newpickle
2443
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002444 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002445 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002446 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002447 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002448 for bytes_type in (bytes, bytearray):
2449 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002450
Antoine Pitrou91f43802019-05-26 17:10:09 +02002451 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2452 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002453
Antoine Pitrou91f43802019-05-26 17:10:09 +02002454 frameless_pickle = remove_frames(pickled)
2455 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2456 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002457
Antoine Pitrou91f43802019-05-26 17:10:09 +02002458 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2459 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2460 count_opcode(pickle.FRAME, pickled))
2461 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002462
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002463 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002464 def test_framed_write_sizes_with_delayed_writer(self):
2465 class ChunkAccumulator:
2466 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002467 def __init__(self):
2468 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002469 def write(self, chunk):
2470 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002471 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002472 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002473
2474 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002475 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2476 for i in range(int(1e4))]
2477 # Add a large unique ASCII string
2478 objects.append('0123456789abcdef' *
2479 (self.FRAME_SIZE_TARGET // 16 + 1))
2480
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002481 # Protocol 4 packs groups of small objects into frames and issues
2482 # calls to write only once or twice per frame:
2483 # The C pickler issues one call to write per-frame (header and
2484 # contents) while Python pickler issues two calls to write: one for
2485 # the frame header and one for the frame binary contents.
2486 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002487 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002488
2489 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002490 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002491 # be released otherwise this delayed access would not be possible.
2492 pickled = writer.concatenate_chunks()
2493 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002494 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002495 self.assertGreater(len(writer.chunks), 1)
2496
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002497 # memoryviews should own the memory.
2498 del objects
2499 support.gc_collect()
2500 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002501
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002502 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002503 # There should be at least one call to write per frame
2504 self.assertGreaterEqual(len(writer.chunks), n_frames)
2505
2506 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002507 # one per-frame header, one per frame for the actual contents,
2508 # and two for the header.
2509 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002510
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002511 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002512 large_sizes = [s for s in chunk_sizes
2513 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002514 medium_sizes = [s for s in chunk_sizes
2515 if 9 < s < self.FRAME_SIZE_TARGET]
2516 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002517
2518 # Large chunks should not be too large:
2519 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002520 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2521 chunk_sizes)
2522 # There shouldn't bee too many small chunks: the protocol header,
2523 # the frame headers and the large string headers are written
2524 # in small chunks.
2525 self.assertLessEqual(len(small_sizes),
2526 len(large_sizes) + len(medium_sizes) + 3,
2527 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002528
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002529 def test_nested_names(self):
2530 global Nested
2531 class Nested:
2532 class A:
2533 class B:
2534 class C:
2535 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002536 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002537 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2538 with self.subTest(proto=proto, obj=obj):
2539 unpickled = self.loads(self.dumps(obj, proto))
2540 self.assertIs(obj, unpickled)
2541
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002542 def test_recursive_nested_names(self):
2543 global Recursive
2544 class Recursive:
2545 pass
2546 Recursive.mod = sys.modules[Recursive.__module__]
2547 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2548 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2549 with self.subTest(proto=proto):
2550 unpickled = self.loads(self.dumps(Recursive, proto))
2551 self.assertIs(unpickled, Recursive)
2552 del Recursive.mod # break reference loop
2553
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002554 def test_py_methods(self):
2555 global PyMethodsTest
2556 class PyMethodsTest:
2557 @staticmethod
2558 def cheese():
2559 return "cheese"
2560 @classmethod
2561 def wine(cls):
2562 assert cls is PyMethodsTest
2563 return "wine"
2564 def biscuits(self):
2565 assert isinstance(self, PyMethodsTest)
2566 return "biscuits"
2567 class Nested:
2568 "Nested class"
2569 @staticmethod
2570 def ketchup():
2571 return "ketchup"
2572 @classmethod
2573 def maple(cls):
2574 assert cls is PyMethodsTest.Nested
2575 return "maple"
2576 def pie(self):
2577 assert isinstance(self, PyMethodsTest.Nested)
2578 return "pie"
2579
2580 py_methods = (
2581 PyMethodsTest.cheese,
2582 PyMethodsTest.wine,
2583 PyMethodsTest().biscuits,
2584 PyMethodsTest.Nested.ketchup,
2585 PyMethodsTest.Nested.maple,
2586 PyMethodsTest.Nested().pie
2587 )
2588 py_unbound_methods = (
2589 (PyMethodsTest.biscuits, PyMethodsTest),
2590 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2591 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002592 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002593 for method in py_methods:
2594 with self.subTest(proto=proto, method=method):
2595 unpickled = self.loads(self.dumps(method, proto))
2596 self.assertEqual(method(), unpickled())
2597 for method, cls in py_unbound_methods:
2598 obj = cls()
2599 with self.subTest(proto=proto, method=method):
2600 unpickled = self.loads(self.dumps(method, proto))
2601 self.assertEqual(method(obj), unpickled(obj))
2602
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002603 def test_c_methods(self):
2604 global Subclass
2605 class Subclass(tuple):
2606 class Nested(str):
2607 pass
2608
2609 c_methods = (
2610 # bound built-in method
2611 ("abcd".index, ("c",)),
2612 # unbound built-in method
2613 (str.index, ("abcd", "c")),
2614 # bound "slot" method
2615 ([1, 2, 3].__len__, ()),
2616 # unbound "slot" method
2617 (list.__len__, ([1, 2, 3],)),
2618 # bound "coexist" method
2619 ({1, 2}.__contains__, (2,)),
2620 # unbound "coexist" method
2621 (set.__contains__, ({1, 2}, 2)),
2622 # built-in class method
2623 (dict.fromkeys, (("a", 1), ("b", 2))),
2624 # built-in static method
2625 (bytearray.maketrans, (b"abc", b"xyz")),
2626 # subclass methods
2627 (Subclass([1,2,2]).count, (2,)),
2628 (Subclass.count, (Subclass([1,2,2]), 2)),
2629 (Subclass.Nested("sweet").count, ("e",)),
2630 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2631 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002632 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002633 for method, args in c_methods:
2634 with self.subTest(proto=proto, method=method):
2635 unpickled = self.loads(self.dumps(method, proto))
2636 self.assertEqual(method(*args), unpickled(*args))
2637
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002638 def test_compat_pickle(self):
2639 tests = [
2640 (range(1, 7), '__builtin__', 'xrange'),
2641 (map(int, '123'), 'itertools', 'imap'),
2642 (functools.reduce, '__builtin__', 'reduce'),
2643 (dbm.whichdb, 'whichdb', 'whichdb'),
2644 (Exception(), 'exceptions', 'Exception'),
2645 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2646 (collections.UserList(), 'UserList', 'UserList'),
2647 (collections.defaultdict(), 'collections', 'defaultdict'),
2648 ]
2649 for val, mod, name in tests:
2650 for proto in range(3):
2651 with self.subTest(type=type(val), proto=proto):
2652 pickled = self.dumps(val, proto)
2653 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2654 self.assertIs(type(self.loads(pickled)), type(val))
2655
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002656 def test_local_lookup_error(self):
2657 # Test that whichmodule() errors out cleanly when looking up
2658 # an assumed globally-reachable object fails.
2659 def f():
2660 pass
2661 # Since the function is local, lookup will fail
2662 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2663 with self.assertRaises((AttributeError, pickle.PicklingError)):
2664 pickletools.dis(self.dumps(f, proto))
2665 # Same without a __module__ attribute (exercises a different path
2666 # in _pickle.c).
2667 del f.__module__
2668 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2669 with self.assertRaises((AttributeError, pickle.PicklingError)):
2670 pickletools.dis(self.dumps(f, proto))
2671 # Yet a different path.
2672 f.__name__ = f.__qualname__
2673 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2674 with self.assertRaises((AttributeError, pickle.PicklingError)):
2675 pickletools.dis(self.dumps(f, proto))
2676
Antoine Pitrou91f43802019-05-26 17:10:09 +02002677 #
2678 # PEP 574 tests below
2679 #
2680
2681 def buffer_like_objects(self):
2682 # Yield buffer-like objects with the bytestring "abcdef" in them
2683 bytestring = b"abcdefgh"
2684 yield ZeroCopyBytes(bytestring)
2685 yield ZeroCopyBytearray(bytestring)
2686 if _testbuffer is not None:
2687 items = list(bytestring)
2688 value = int.from_bytes(bytestring, byteorder='little')
2689 for flags in (0, _testbuffer.ND_WRITABLE):
2690 # 1-D, contiguous
2691 yield PicklableNDArray(items, format='B', shape=(8,),
2692 flags=flags)
2693 # 2-D, C-contiguous
2694 yield PicklableNDArray(items, format='B', shape=(4, 2),
2695 strides=(2, 1), flags=flags)
2696 # 2-D, Fortran-contiguous
2697 yield PicklableNDArray(items, format='B',
2698 shape=(4, 2), strides=(1, 4),
2699 flags=flags)
2700
2701 def test_in_band_buffers(self):
2702 # Test in-band buffers (PEP 574)
2703 for obj in self.buffer_like_objects():
2704 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2705 data = self.dumps(obj, proto)
2706 if obj.c_contiguous and proto >= 5:
2707 # The raw memory bytes are serialized in physical order
2708 self.assertIn(b"abcdefgh", data)
2709 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2710 if proto >= 5:
2711 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2712 1 if obj.readonly else 0)
2713 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2714 0 if obj.readonly else 1)
2715 # Return a true value from buffer_callback should have
2716 # the same effect
2717 def buffer_callback(obj):
2718 return True
2719 data2 = self.dumps(obj, proto,
2720 buffer_callback=buffer_callback)
2721 self.assertEqual(data2, data)
2722
2723 new = self.loads(data)
2724 # It's a copy
2725 self.assertIsNot(new, obj)
2726 self.assertIs(type(new), type(obj))
2727 self.assertEqual(new, obj)
2728
2729 # XXX Unfortunately cannot test non-contiguous array
2730 # (see comment in PicklableNDArray.__reduce_ex__)
2731
2732 def test_oob_buffers(self):
2733 # Test out-of-band buffers (PEP 574)
2734 for obj in self.buffer_like_objects():
2735 for proto in range(0, 5):
2736 # Need protocol >= 5 for buffer_callback
2737 with self.assertRaises(ValueError):
2738 self.dumps(obj, proto,
2739 buffer_callback=[].append)
2740 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2741 buffers = []
2742 buffer_callback = lambda pb: buffers.append(pb.raw())
2743 data = self.dumps(obj, proto,
2744 buffer_callback=buffer_callback)
2745 self.assertNotIn(b"abcdefgh", data)
2746 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2747 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2748 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2749 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2750 1 if obj.readonly else 0)
2751
2752 if obj.c_contiguous:
2753 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2754 # Need buffers argument to unpickle properly
2755 with self.assertRaises(pickle.UnpicklingError):
2756 self.loads(data)
2757
2758 new = self.loads(data, buffers=buffers)
2759 if obj.zero_copy_reconstruct:
2760 # Zero-copy achieved
2761 self.assertIs(new, obj)
2762 else:
2763 self.assertIs(type(new), type(obj))
2764 self.assertEqual(new, obj)
2765 # Non-sequence buffers accepted too
2766 new = self.loads(data, buffers=iter(buffers))
2767 if obj.zero_copy_reconstruct:
2768 # Zero-copy achieved
2769 self.assertIs(new, obj)
2770 else:
2771 self.assertIs(type(new), type(obj))
2772 self.assertEqual(new, obj)
2773
2774 def test_oob_buffers_writable_to_readonly(self):
2775 # Test reconstructing readonly object from writable buffer
2776 obj = ZeroCopyBytes(b"foobar")
2777 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2778 buffers = []
2779 buffer_callback = buffers.append
2780 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2781
2782 buffers = map(bytearray, buffers)
2783 new = self.loads(data, buffers=buffers)
2784 self.assertIs(type(new), type(obj))
2785 self.assertEqual(new, obj)
2786
2787 def test_picklebuffer_error(self):
2788 # PickleBuffer forbidden with protocol < 5
2789 pb = pickle.PickleBuffer(b"foobar")
2790 for proto in range(0, 5):
2791 with self.assertRaises(pickle.PickleError):
2792 self.dumps(pb, proto)
2793
2794 def test_buffer_callback_error(self):
2795 def buffer_callback(buffers):
2796 1/0
2797 pb = pickle.PickleBuffer(b"foobar")
2798 with self.assertRaises(ZeroDivisionError):
2799 self.dumps(pb, 5, buffer_callback=buffer_callback)
2800
2801 def test_buffers_error(self):
2802 pb = pickle.PickleBuffer(b"foobar")
2803 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2804 data = self.dumps(pb, proto, buffer_callback=[].append)
2805 # Non iterable buffers
2806 with self.assertRaises(TypeError):
2807 self.loads(data, buffers=object())
2808 # Buffer iterable exhausts too early
2809 with self.assertRaises(pickle.UnpicklingError):
2810 self.loads(data, buffers=[])
2811
Markus Mohrhard898318b2019-07-26 00:00:34 +08002812 def test_inband_accept_default_buffers_argument(self):
2813 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2814 data_pickled = self.dumps(1, proto, buffer_callback=None)
2815 data = self.loads(data_pickled, buffers=None)
2816
Antoine Pitrou91f43802019-05-26 17:10:09 +02002817 @unittest.skipIf(np is None, "Test needs Numpy")
2818 def test_buffers_numpy(self):
2819 def check_no_copy(x, y):
2820 np.testing.assert_equal(x, y)
2821 self.assertEqual(x.ctypes.data, y.ctypes.data)
2822
2823 def check_copy(x, y):
2824 np.testing.assert_equal(x, y)
2825 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2826
2827 def check_array(arr):
2828 # In-band
2829 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2830 data = self.dumps(arr, proto)
2831 new = self.loads(data)
2832 check_copy(arr, new)
2833 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2834 buffer_callback = lambda _: True
2835 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2836 new = self.loads(data)
2837 check_copy(arr, new)
2838 # Out-of-band
2839 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2840 buffers = []
2841 buffer_callback = buffers.append
2842 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2843 new = self.loads(data, buffers=buffers)
2844 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2845 check_no_copy(arr, new)
2846 else:
2847 check_copy(arr, new)
2848
2849 # 1-D
2850 arr = np.arange(6)
2851 check_array(arr)
2852 # 1-D, non-contiguous
2853 check_array(arr[::2])
2854 # 2-D, C-contiguous
2855 arr = np.arange(12).reshape((3, 4))
2856 check_array(arr)
2857 # 2-D, F-contiguous
2858 check_array(arr.T)
2859 # 2-D, non-contiguous
2860 check_array(arr[::2])
2861
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002862
2863class BigmemPickleTests(unittest.TestCase):
2864
Victor Stinner8c663fd2017-11-08 14:44:44 -08002865 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002866
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002867 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002868 def test_huge_long_32b(self, size):
2869 data = 1 << (8 * size)
2870 try:
2871 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002872 if proto < 2:
2873 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002874 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002875 with self.assertRaises((ValueError, OverflowError)):
2876 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002877 finally:
2878 data = None
2879
Victor Stinner8c663fd2017-11-08 14:44:44 -08002880 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002881 # (older protocols don't have a dedicated opcode for bytes and are
2882 # too inefficient)
2883
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002884 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002885 def test_huge_bytes_32b(self, size):
2886 data = b"abcd" * (size // 4)
2887 try:
2888 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002889 if proto < 3:
2890 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002891 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002892 try:
2893 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002894 header = (pickle.BINBYTES +
2895 struct.pack("<I", len(data)))
2896 data_start = pickled.index(data)
2897 self.assertEqual(
2898 header,
2899 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002900 finally:
2901 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002902 finally:
2903 data = None
2904
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002905 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002906 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002907 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002908 try:
2909 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002910 if proto < 3:
2911 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002912 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002913 if proto == 3:
2914 # Protocol 3 does not support large bytes objects.
2915 # Verify that we do not crash when processing one.
2916 with self.assertRaises((ValueError, OverflowError)):
2917 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002918 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002919 try:
2920 pickled = self.dumps(data, protocol=proto)
2921 header = (pickle.BINBYTES8 +
2922 struct.pack("<Q", len(data)))
2923 data_start = pickled.index(data)
2924 self.assertEqual(
2925 header,
2926 pickled[data_start-len(header):data_start])
2927 finally:
2928 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002929 finally:
2930 data = None
2931
2932 # All protocols use 1-byte per printable ASCII character; we add another
2933 # byte because the encoded form has to be copied into the internal buffer.
2934
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002935 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002936 def test_huge_str_32b(self, size):
2937 data = "abcd" * (size // 4)
2938 try:
2939 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002940 if proto == 0:
2941 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002942 with self.subTest(proto=proto):
2943 try:
2944 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002945 header = (pickle.BINUNICODE +
2946 struct.pack("<I", len(data)))
2947 data_start = pickled.index(b'abcd')
2948 self.assertEqual(
2949 header,
2950 pickled[data_start-len(header):data_start])
2951 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2952 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002953 finally:
2954 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002955 finally:
2956 data = None
2957
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002958 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2959 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2960 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002961
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002962 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002963 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002964 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002965 try:
2966 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002967 if proto == 0:
2968 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002969 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002970 if proto < 4:
2971 with self.assertRaises((ValueError, OverflowError)):
2972 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002973 continue
2974 try:
2975 pickled = self.dumps(data, protocol=proto)
2976 header = (pickle.BINUNICODE8 +
2977 struct.pack("<Q", len(data)))
2978 data_start = pickled.index(b'abcd')
2979 self.assertEqual(
2980 header,
2981 pickled[data_start-len(header):data_start])
2982 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2983 pickled.index(b"abcd")), len(data))
2984 finally:
2985 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002986 finally:
2987 data = None
2988
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002989
Guido van Rossum2a30b212003-02-18 22:41:24 +00002990# Test classes for reduce_ex
2991
2992class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002993 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002994 _reduce_called = 0
2995 def __reduce__(self):
2996 self._reduce_called = 1
2997 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002998
2999class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003000 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00003001 _proto = None
3002 def __reduce_ex__(self, proto):
3003 self._proto = proto
3004 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00003005
3006class REX_three(object):
3007 _proto = None
3008 def __reduce_ex__(self, proto):
3009 self._proto = proto
3010 return REX_two, ()
3011 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00003012 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00003013
Guido van Rossumd8faa362007-04-27 19:54:29 +00003014class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003015 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003016 _proto = None
3017 def __reduce_ex__(self, proto):
3018 self._proto = proto
3019 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00003020
3021class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003022 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003023 _reduce_called = 0
3024 def __reduce__(self):
3025 self._reduce_called = 1
3026 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003027
3028class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003029 """This class is used to check the 4th argument (list iterator) of
3030 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003031 """
3032 def __init__(self, items=None):
3033 self.items = items if items is not None else []
3034 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003035 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003036 def append(self, item):
3037 self.items.append(item)
3038 def __reduce__(self):
3039 return type(self), (), None, iter(self.items), None
3040
3041class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003042 """This class is used to check the 5th argument (dict iterator) of
3043 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003044 """
3045 def __init__(self, table=None):
3046 self.table = table if table is not None else {}
3047 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003048 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003049 def __setitem__(self, key, value):
3050 self.table[key] = value
3051 def __reduce__(self):
3052 return type(self), (), None, None, iter(self.table.items())
3053
Guido van Rossumd8faa362007-04-27 19:54:29 +00003054
Guido van Rossum2a30b212003-02-18 22:41:24 +00003055# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003056
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003057class MyInt(int):
3058 sample = 1
3059
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003060class MyFloat(float):
3061 sample = 1.0
3062
3063class MyComplex(complex):
3064 sample = 1.0 + 0.0j
3065
3066class MyStr(str):
3067 sample = "hello"
3068
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003069class MyUnicode(str):
3070 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003071
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003072class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003073 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003074
3075class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003076 sample = [1, 2, 3]
3077
3078class MyDict(dict):
3079 sample = {"a": 1, "b": 2}
3080
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003081class MySet(set):
3082 sample = {"a", "b"}
3083
3084class MyFrozenSet(frozenset):
3085 sample = frozenset({"a", "b"})
3086
Mark Dickinson5c2db372009-12-05 20:28:34 +00003087myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003088 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003089 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003090 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003091
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003092
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003093class SlotList(MyList):
3094 __slots__ = ["foo"]
3095
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003096class SimpleNewObj(int):
3097 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003098 # raise an error, to make sure this isn't called
3099 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003100 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003101 return int(self) == int(other) and self.__dict__ == other.__dict__
3102
3103class ComplexNewObj(SimpleNewObj):
3104 def __getnewargs__(self):
3105 return ('%X' % self, 16)
3106
3107class ComplexNewObjEx(SimpleNewObj):
3108 def __getnewargs_ex__(self):
3109 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003110
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003111class BadGetattr:
3112 def __getattr__(self, key):
3113 self.foo
3114
Collin Winter771d8342009-04-16 03:18:06 +00003115
Jeremy Hylton66426532001-10-15 21:38:56 +00003116class AbstractPickleModuleTests(unittest.TestCase):
3117
3118 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003119 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003120 try:
3121 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003122 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003123 finally:
Hai Shi883bc632020-07-06 17:12:49 +08003124 os_helper.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003125
3126 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003127 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003128 try:
3129 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003130 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003131 finally:
Hai Shi883bc632020-07-06 17:12:49 +08003132 os_helper.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003133
Collin Winter771d8342009-04-16 03:18:06 +00003134 def test_load_from_and_dump_to_file(self):
3135 stream = io.BytesIO()
3136 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003137 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003138 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003139 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003140 self.assertEqual(unpickled, data)
3141
Tim Petersc0c93702003-02-13 19:30:57 +00003142 def test_highest_protocol(self):
3143 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003144 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003145
Martin v. Löwis544f1192004-07-27 05:22:33 +00003146 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003147 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003148 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003149 self.dump(123, f, -1)
3150 self.dump(123, file=f, protocol=-1)
3151 self.dumps(123, -1)
3152 self.dumps(123, protocol=-1)
3153 self.Pickler(f, -1)
3154 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003155
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003156 def test_dump_text_file(self):
3157 f = open(TESTFN, "w")
3158 try:
3159 for proto in protocols:
3160 self.assertRaises(TypeError, self.dump, 123, f, proto)
3161 finally:
3162 f.close()
Hai Shi883bc632020-07-06 17:12:49 +08003163 os_helper.unlink(TESTFN)
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003164
3165 def test_incomplete_input(self):
3166 s = io.BytesIO(b"X''.")
3167 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3168
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003169 def test_bad_init(self):
3170 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003171 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003172 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003173 def __init__(self): pass
3174
Serhiy Storchaka65452562017-11-15 14:01:08 +02003175 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003176 def __init__(self): pass
3177
3178 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3179 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3180
Antoine Pitrou91f43802019-05-26 17:10:09 +02003181 def check_dumps_loads_oob_buffers(self, dumps, loads):
3182 # No need to do the full gamut of tests here, just enough to
3183 # check that dumps() and loads() redirect their arguments
3184 # to the underlying Pickler and Unpickler, respectively.
3185 obj = ZeroCopyBytes(b"foo")
3186
3187 for proto in range(0, 5):
3188 # Need protocol >= 5 for buffer_callback
3189 with self.assertRaises(ValueError):
3190 dumps(obj, protocol=proto,
3191 buffer_callback=[].append)
3192 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3193 buffers = []
3194 buffer_callback = buffers.append
3195 data = dumps(obj, protocol=proto,
3196 buffer_callback=buffer_callback)
3197 self.assertNotIn(b"foo", data)
3198 self.assertEqual(bytes(buffers[0]), b"foo")
3199 # Need buffers argument to unpickle properly
3200 with self.assertRaises(pickle.UnpicklingError):
3201 loads(data)
3202 new = loads(data, buffers=buffers)
3203 self.assertIs(new, obj)
3204
3205 def test_dumps_loads_oob_buffers(self):
3206 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3207 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3208
3209 def test_dump_load_oob_buffers(self):
3210 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3211 def dumps(obj, **kwargs):
3212 f = io.BytesIO()
3213 self.dump(obj, f, **kwargs)
3214 return f.getvalue()
3215
3216 def loads(data, **kwargs):
3217 f = io.BytesIO(data)
3218 return self.load(f, **kwargs)
3219
3220 self.check_dumps_loads_oob_buffers(dumps, loads)
3221
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003222
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003223class AbstractPersistentPicklerTests(unittest.TestCase):
3224
3225 # This class defines persistent_id() and persistent_load()
3226 # functions that should be used by the pickler. All even integers
3227 # are pickled using persistent ids.
3228
3229 def persistent_id(self, object):
3230 if isinstance(object, int) and object % 2 == 0:
3231 self.id_count += 1
3232 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003233 elif object == "test_false_value":
3234 self.false_count += 1
3235 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003236 else:
3237 return None
3238
3239 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003240 if not oid:
3241 self.load_false_count += 1
3242 return "test_false_value"
3243 else:
3244 self.load_count += 1
3245 object = int(oid)
3246 assert object % 2 == 0
3247 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003248
3249 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003250 L = list(range(10)) + ["test_false_value"]
3251 for proto in protocols:
3252 self.id_count = 0
3253 self.false_count = 0
3254 self.load_false_count = 0
3255 self.load_count = 0
3256 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3257 self.assertEqual(self.id_count, 5)
3258 self.assertEqual(self.false_count, 1)
3259 self.assertEqual(self.load_count, 5)
3260 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003261
Collin Winter771d8342009-04-16 03:18:06 +00003262
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003263class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3264
3265 def persistent_id(self, obj):
3266 return obj
3267
3268 def persistent_load(self, pid):
3269 return pid
3270
3271 def _check_return_correct_type(self, obj, proto):
3272 unpickled = self.loads(self.dumps(obj, proto))
3273 self.assertIsInstance(unpickled, type(obj))
3274 self.assertEqual(unpickled, obj)
3275
3276 def test_return_correct_type(self):
3277 for proto in protocols:
3278 # Protocol 0 supports only ASCII strings.
3279 if proto == 0:
3280 self._check_return_correct_type("abc", 0)
3281 else:
3282 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3283 self._check_return_correct_type(obj, proto)
3284
3285 def test_protocol0_is_ascii_only(self):
3286 non_ascii_str = "\N{EMPTY SET}"
3287 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3288 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3289 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3290
3291
Collin Winter771d8342009-04-16 03:18:06 +00003292class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3293
3294 pickler_class = None
3295 unpickler_class = None
3296
3297 def setUp(self):
3298 assert self.pickler_class
3299 assert self.unpickler_class
3300
3301 def test_clear_pickler_memo(self):
3302 # To test whether clear_memo() has any effect, we pickle an object,
3303 # then pickle it again without clearing the memo; the two serialized
3304 # forms should be different. If we clear_memo() and then pickle the
3305 # object again, the third serialized form should be identical to the
3306 # first one we obtained.
3307 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003308 for proto in protocols:
3309 f = io.BytesIO()
3310 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003311
Serhiy Storchakac8695292018-04-04 00:11:27 +03003312 pickler.dump(data)
3313 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003314
Serhiy Storchakac8695292018-04-04 00:11:27 +03003315 # Reset BytesIO object.
3316 f.seek(0)
3317 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003318
Serhiy Storchakac8695292018-04-04 00:11:27 +03003319 pickler.dump(data)
3320 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003321
Serhiy Storchakac8695292018-04-04 00:11:27 +03003322 # Reset the Pickler and BytesIO objects.
3323 pickler.clear_memo()
3324 f.seek(0)
3325 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003326
Serhiy Storchakac8695292018-04-04 00:11:27 +03003327 pickler.dump(data)
3328 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003329
Serhiy Storchakac8695292018-04-04 00:11:27 +03003330 self.assertNotEqual(first_pickled, second_pickled)
3331 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003332
3333 def test_priming_pickler_memo(self):
3334 # Verify that we can set the Pickler'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 self.assertNotEqual(first_pickled, primed_pickled)
3350
3351 def test_priming_unpickler_memo(self):
3352 # Verify that we can set the Unpickler's memo attribute.
3353 data = ["abcdefg", "abcdefg", 44]
3354 f = io.BytesIO()
3355 pickler = self.pickler_class(f)
3356
3357 pickler.dump(data)
3358 first_pickled = f.getvalue()
3359
3360 f = io.BytesIO()
3361 primed = self.pickler_class(f)
3362 primed.memo = pickler.memo
3363
3364 primed.dump(data)
3365 primed_pickled = f.getvalue()
3366
3367 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3368 unpickled_data1 = unpickler.load()
3369
3370 self.assertEqual(unpickled_data1, data)
3371
3372 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3373 primed.memo = unpickler.memo
3374 unpickled_data2 = primed.load()
3375
3376 primed.memo.clear()
3377
3378 self.assertEqual(unpickled_data2, data)
3379 self.assertTrue(unpickled_data2 is unpickled_data1)
3380
3381 def test_reusing_unpickler_objects(self):
3382 data1 = ["abcdefg", "abcdefg", 44]
3383 f = io.BytesIO()
3384 pickler = self.pickler_class(f)
3385 pickler.dump(data1)
3386 pickled1 = f.getvalue()
3387
3388 data2 = ["abcdefg", 44, 44]
3389 f = io.BytesIO()
3390 pickler = self.pickler_class(f)
3391 pickler.dump(data2)
3392 pickled2 = f.getvalue()
3393
3394 f = io.BytesIO()
3395 f.write(pickled1)
3396 f.seek(0)
3397 unpickler = self.unpickler_class(f)
3398 self.assertEqual(unpickler.load(), data1)
3399
3400 f.seek(0)
3401 f.truncate()
3402 f.write(pickled2)
3403 f.seek(0)
3404 self.assertEqual(unpickler.load(), data2)
3405
Antoine Pitrou9f378722020-02-23 23:33:53 +01003406 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003407 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003408 with self.subTest(proto=proto):
3409 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3410 f = ioclass()
3411 pickler = self.pickler_class(f, protocol=proto)
3412 pickler.dump(data1)
3413 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003414
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003415 N = 5
3416 f = ioclass(pickled * N)
3417 unpickler = self.unpickler_class(f)
3418 for i in range(N):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003419 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003420 pos = f.tell()
3421 self.assertEqual(unpickler.load(), data1)
Antoine Pitrou9f378722020-02-23 23:33:53 +01003422 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003423 self.assertEqual(f.tell(), pos + len(pickled))
3424 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003425
3426 def test_multiple_unpicklings_seekable(self):
3427 self._check_multiple_unpicklings(io.BytesIO)
3428
3429 def test_multiple_unpicklings_unseekable(self):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003430 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3431
3432 def test_multiple_unpicklings_minimal(self):
3433 # File-like object that doesn't support peek() and readinto()
3434 # (bpo-39681)
3435 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003436
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003437 def test_unpickling_buffering_readline(self):
3438 # Issue #12687: the unpickler's buffering logic could fail with
3439 # text mode opcodes.
3440 data = list(range(10))
3441 for proto in protocols:
3442 for buf_size in range(1, 11):
3443 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3444 pickler = self.pickler_class(f, protocol=proto)
3445 pickler.dump(data)
3446 f.seek(0)
3447 unpickler = self.unpickler_class(f)
3448 self.assertEqual(unpickler.load(), data)
3449
Collin Winter771d8342009-04-16 03:18:06 +00003450
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003451# Tests for dispatch_table attribute
3452
3453REDUCE_A = 'reduce_A'
3454
3455class AAA(object):
3456 def __reduce__(self):
3457 return str, (REDUCE_A,)
3458
3459class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003460 def __init__(self):
3461 # Add an instance attribute to enable state-saving routines at pickling
3462 # time.
3463 self.a = "some attribute"
3464
3465 def __setstate__(self, state):
3466 self.a = "BBB.__setstate__"
3467
3468
3469def setstate_bbb(obj, state):
3470 """Custom state setter for BBB objects
3471
3472 Such callable may be created by other persons than the ones who created the
3473 BBB class. If passed as the state_setter item of a custom reducer, this
3474 allows for custom state setting behavior of BBB objects. One can think of
3475 it as the analogous of list_setitems or dict_setitems but for foreign
3476 classes/functions.
3477 """
3478 obj.a = "custom state_setter"
3479
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003480
Pierre Glaser289f1f82019-05-08 23:08:25 +02003481
3482class AbstractCustomPicklerClass:
3483 """Pickler implementing a reducing hook using reducer_override."""
3484 def reducer_override(self, obj):
3485 obj_name = getattr(obj, "__name__", None)
3486
3487 if obj_name == 'f':
3488 # asking the pickler to save f as 5
3489 return int, (5, )
3490
3491 if obj_name == 'MyClass':
3492 return str, ('some str',)
3493
3494 elif obj_name == 'g':
3495 # in this case, the callback returns an invalid result (not a 2-5
3496 # tuple or a string), the pickler should raise a proper error.
3497 return False
3498
3499 elif obj_name == 'h':
3500 # Simulate a case when the reducer fails. The error should
3501 # be propagated to the original ``dump`` call.
3502 raise ValueError('The reducer just failed')
3503
3504 return NotImplemented
3505
3506class AbstractHookTests(unittest.TestCase):
3507 def test_pickler_hook(self):
3508 # test the ability of a custom, user-defined CPickler subclass to
3509 # override the default reducing routines of any type using the method
3510 # reducer_override
3511
3512 def f():
3513 pass
3514
3515 def g():
3516 pass
3517
3518 def h():
3519 pass
3520
3521 class MyClass:
3522 pass
3523
3524 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3525 with self.subTest(proto=proto):
3526 bio = io.BytesIO()
3527 p = self.pickler_class(bio, proto)
3528
3529 p.dump([f, MyClass, math.log])
3530 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3531
3532 self.assertEqual(new_f, 5)
3533 self.assertEqual(some_str, 'some str')
3534 # math.log does not have its usual reducer overriden, so the
3535 # custom reduction callback should silently direct the pickler
3536 # to the default pickling by attribute, by returning
3537 # NotImplemented
3538 self.assertIs(math_log, math.log)
3539
3540 with self.assertRaises(pickle.PicklingError):
3541 p.dump(g)
3542
3543 with self.assertRaisesRegex(
3544 ValueError, 'The reducer just failed'):
3545 p.dump(h)
3546
Pierre Glaser0f2f35e2020-02-02 19:55:21 +01003547 @support.cpython_only
3548 def test_reducer_override_no_reference_cycle(self):
3549 # bpo-39492: reducer_override used to induce a spurious reference cycle
3550 # inside the Pickler object, that could prevent all serialized objects
3551 # from being garbage-collected without explicity invoking gc.collect.
3552
3553 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3554 with self.subTest(proto=proto):
3555 def f():
3556 pass
3557
3558 wr = weakref.ref(f)
3559
3560 bio = io.BytesIO()
3561 p = self.pickler_class(bio, proto)
3562 p.dump(f)
3563 new_f = pickle.loads(bio.getvalue())
3564 assert new_f == 5
3565
3566 del p
3567 del f
3568
3569 self.assertIsNone(wr())
3570
Pierre Glaser289f1f82019-05-08 23:08:25 +02003571
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003572class AbstractDispatchTableTests(unittest.TestCase):
3573
3574 def test_default_dispatch_table(self):
3575 # No dispatch_table attribute by default
3576 f = io.BytesIO()
3577 p = self.pickler_class(f, 0)
3578 with self.assertRaises(AttributeError):
3579 p.dispatch_table
3580 self.assertFalse(hasattr(p, 'dispatch_table'))
3581
3582 def test_class_dispatch_table(self):
3583 # A dispatch_table attribute can be specified class-wide
3584 dt = self.get_dispatch_table()
3585
3586 class MyPickler(self.pickler_class):
3587 dispatch_table = dt
3588
3589 def dumps(obj, protocol=None):
3590 f = io.BytesIO()
3591 p = MyPickler(f, protocol)
3592 self.assertEqual(p.dispatch_table, dt)
3593 p.dump(obj)
3594 return f.getvalue()
3595
3596 self._test_dispatch_table(dumps, dt)
3597
3598 def test_instance_dispatch_table(self):
3599 # A dispatch_table attribute can also be specified instance-wide
3600 dt = self.get_dispatch_table()
3601
3602 def dumps(obj, protocol=None):
3603 f = io.BytesIO()
3604 p = self.pickler_class(f, protocol)
3605 p.dispatch_table = dt
3606 self.assertEqual(p.dispatch_table, dt)
3607 p.dump(obj)
3608 return f.getvalue()
3609
3610 self._test_dispatch_table(dumps, dt)
3611
3612 def _test_dispatch_table(self, dumps, dispatch_table):
3613 def custom_load_dump(obj):
3614 return pickle.loads(dumps(obj, 0))
3615
3616 def default_load_dump(obj):
3617 return pickle.loads(pickle.dumps(obj, 0))
3618
3619 # pickling complex numbers using protocol 0 relies on copyreg
3620 # so check pickling a complex number still works
3621 z = 1 + 2j
3622 self.assertEqual(custom_load_dump(z), z)
3623 self.assertEqual(default_load_dump(z), z)
3624
3625 # modify pickling of complex
3626 REDUCE_1 = 'reduce_1'
3627 def reduce_1(obj):
3628 return str, (REDUCE_1,)
3629 dispatch_table[complex] = reduce_1
3630 self.assertEqual(custom_load_dump(z), REDUCE_1)
3631 self.assertEqual(default_load_dump(z), z)
3632
3633 # check picklability of AAA and BBB
3634 a = AAA()
3635 b = BBB()
3636 self.assertEqual(custom_load_dump(a), REDUCE_A)
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
3641 # modify pickling of BBB
3642 dispatch_table[BBB] = reduce_1
3643 self.assertEqual(custom_load_dump(a), REDUCE_A)
3644 self.assertEqual(custom_load_dump(b), REDUCE_1)
3645 self.assertEqual(default_load_dump(a), REDUCE_A)
3646 self.assertIsInstance(default_load_dump(b), BBB)
3647
3648 # revert pickling of BBB and modify pickling of AAA
3649 REDUCE_2 = 'reduce_2'
3650 def reduce_2(obj):
3651 return str, (REDUCE_2,)
3652 dispatch_table[AAA] = reduce_2
3653 del dispatch_table[BBB]
3654 self.assertEqual(custom_load_dump(a), REDUCE_2)
3655 self.assertIsInstance(custom_load_dump(b), BBB)
3656 self.assertEqual(default_load_dump(a), REDUCE_A)
3657 self.assertIsInstance(default_load_dump(b), BBB)
3658
Pierre Glaser65d98d02019-05-08 21:40:25 +02003659 # End-to-end testing of save_reduce with the state_setter keyword
3660 # argument. This is a dispatch_table test as the primary goal of
3661 # state_setter is to tweak objects reduction behavior.
3662 # In particular, state_setter is useful when the default __setstate__
3663 # behavior is not flexible enough.
3664
3665 # No custom reducer for b has been registered for now, so
3666 # BBB.__setstate__ should be used at unpickling time
3667 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3668
3669 def reduce_bbb(obj):
3670 return BBB, (), obj.__dict__, None, None, setstate_bbb
3671
3672 dispatch_table[BBB] = reduce_bbb
3673
3674 # The custom reducer reduce_bbb includes a state setter, that should
3675 # have priority over BBB.__setstate__
3676 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3677
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003678
Guido van Rossum98297ee2007-11-06 21:34:58 +00003679if __name__ == "__main__":
3680 # Print some stuff that can be used to rewrite DATA{0,1,2}
3681 from pickletools import dis
3682 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003683 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003684 p = pickle.dumps(x, i)
3685 print("DATA{0} = (".format(i))
3686 for j in range(0, len(p), 20):
3687 b = bytes(p[j:j+20])
3688 print(" {0!r}".format(b))
3689 print(")")
3690 print()
3691 print("# Disassembly of DATA{0}".format(i))
3692 print("DATA{0}_DIS = \"\"\"\\".format(i))
3693 dis(p)
3694 print("\"\"\"")
3695 print()