blob: 3e2c781caa11acbf25dc436b1e6a044d2b8f9536 [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
Serhiy Storchakaa25011b2021-01-02 19:32:47 +020072def identity(x):
73 return x
74
75
Antoine Pitrou04248a82010-10-12 20:51:21 +000076class UnseekableIO(io.BytesIO):
77 def peek(self, *args):
78 raise NotImplementedError
79
80 def seekable(self):
81 return False
82
83 def seek(self, *args):
84 raise io.UnsupportedOperation
85
86 def tell(self):
87 raise io.UnsupportedOperation
88
89
Antoine Pitrou9f378722020-02-23 23:33:53 +010090class MinimalIO(object):
91 """
92 A file-like object that doesn't support readinto().
93 """
94 def __init__(self, *args):
95 self._bio = io.BytesIO(*args)
96 self.getvalue = self._bio.getvalue
97 self.read = self._bio.read
98 self.readline = self._bio.readline
99 self.write = self._bio.write
100
101
Tim Peters3e667d52003-02-04 21:47:44 +0000102# We can't very well test the extension registry without putting known stuff
103# in it, but we have to be careful to restore its original state. Code
104# should do this:
105#
106# e = ExtensionSaver(extension_code)
107# try:
108# fiddle w/ the extension registry's stuff for extension_code
109# finally:
110# e.restore()
111
112class ExtensionSaver:
113 # Remember current registration for code (if any), and remove it (if
114 # there is one).
115 def __init__(self, code):
116 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000117 if code in copyreg._inverted_registry:
118 self.pair = copyreg._inverted_registry[code]
119 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000120 else:
121 self.pair = None
122
123 # Restore previous registration for code.
124 def restore(self):
125 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000126 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000127 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000128 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000129 pair = self.pair
130 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000131 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000132
Jeremy Hylton66426532001-10-15 21:38:56 +0000133class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000134 def __eq__(self, other):
135 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000136
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000137class D(C):
138 def __init__(self, arg):
139 pass
140
141class E(C):
142 def __getinitargs__(self):
143 return ()
144
Serhiy Storchakaa25011b2021-01-02 19:32:47 +0200145# Simple mutable object.
146class Object:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100147 pass
148
Serhiy Storchakaa25011b2021-01-02 19:32:47 +0200149# Hashable immutable key object containing unheshable mutable data.
150class K:
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200151 def __init__(self, value):
152 self.value = value
153
154 def __reduce__(self):
155 # Shouldn't support the recursion itself
156 return K, (self.value,)
157
Jeremy Hylton66426532001-10-15 21:38:56 +0000158import __main__
159__main__.C = C
160C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000161__main__.D = D
162D.__module__ = "__main__"
163__main__.E = E
164E.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000165
166class myint(int):
167 def __init__(self, x):
168 self.str = str(x)
169
170class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000171
Jeremy Hylton66426532001-10-15 21:38:56 +0000172 def __init__(self, a, b):
173 self.a = a
174 self.b = b
175
176 def __getinitargs__(self):
177 return self.a, self.b
178
Guido van Rossum04a86612001-12-19 16:58:54 +0000179class metaclass(type):
180 pass
181
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000182class use_metaclass(object, metaclass=metaclass):
183 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000184
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200185class pickling_metaclass(type):
186 def __eq__(self, other):
187 return (type(self) == type(other) and
188 self.reduce_args == other.reduce_args)
189
190 def __reduce__(self):
191 return (create_dynamic_class, self.reduce_args)
192
193def create_dynamic_class(name, bases):
194 result = pickling_metaclass(name, bases, dict())
195 result.reduce_args = (name, bases)
196 return result
197
Antoine Pitrou91f43802019-05-26 17:10:09 +0200198
199class ZeroCopyBytes(bytes):
200 readonly = True
201 c_contiguous = True
202 f_contiguous = True
203 zero_copy_reconstruct = True
204
205 def __reduce_ex__(self, protocol):
206 if protocol >= 5:
207 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
208 else:
209 return type(self)._reconstruct, (bytes(self),)
210
211 def __repr__(self):
212 return "{}({!r})".format(self.__class__.__name__, bytes(self))
213
214 __str__ = __repr__
215
216 @classmethod
217 def _reconstruct(cls, obj):
218 with memoryview(obj) as m:
219 obj = m.obj
220 if type(obj) is cls:
221 # Zero-copy
222 return obj
223 else:
224 return cls(obj)
225
226
227class ZeroCopyBytearray(bytearray):
228 readonly = False
229 c_contiguous = True
230 f_contiguous = True
231 zero_copy_reconstruct = True
232
233 def __reduce_ex__(self, protocol):
234 if protocol >= 5:
235 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
236 else:
237 return type(self)._reconstruct, (bytes(self),)
238
239 def __repr__(self):
240 return "{}({!r})".format(self.__class__.__name__, bytes(self))
241
242 __str__ = __repr__
243
244 @classmethod
245 def _reconstruct(cls, obj):
246 with memoryview(obj) as m:
247 obj = m.obj
248 if type(obj) is cls:
249 # Zero-copy
250 return obj
251 else:
252 return cls(obj)
253
254
255if _testbuffer is not None:
256
257 class PicklableNDArray:
258 # A not-really-zero-copy picklable ndarray, as the ndarray()
259 # constructor doesn't allow for it
260
261 zero_copy_reconstruct = False
262
263 def __init__(self, *args, **kwargs):
264 self.array = _testbuffer.ndarray(*args, **kwargs)
265
266 def __getitem__(self, idx):
267 cls = type(self)
268 new = cls.__new__(cls)
269 new.array = self.array[idx]
270 return new
271
272 @property
273 def readonly(self):
274 return self.array.readonly
275
276 @property
277 def c_contiguous(self):
278 return self.array.c_contiguous
279
280 @property
281 def f_contiguous(self):
282 return self.array.f_contiguous
283
284 def __eq__(self, other):
285 if not isinstance(other, PicklableNDArray):
286 return NotImplemented
287 return (other.array.format == self.array.format and
288 other.array.shape == self.array.shape and
289 other.array.strides == self.array.strides and
290 other.array.readonly == self.array.readonly and
291 other.array.tobytes() == self.array.tobytes())
292
293 def __ne__(self, other):
294 if not isinstance(other, PicklableNDArray):
295 return NotImplemented
296 return not (self == other)
297
298 def __repr__(self):
299 return (f"{type(self)}(shape={self.array.shape},"
300 f"strides={self.array.strides}, "
301 f"bytes={self.array.tobytes()})")
302
303 def __reduce_ex__(self, protocol):
304 if not self.array.contiguous:
305 raise NotImplementedError("Reconstructing a non-contiguous "
306 "ndarray does not seem possible")
307 ndarray_kwargs = {"shape": self.array.shape,
308 "strides": self.array.strides,
309 "format": self.array.format,
310 "flags": (0 if self.readonly
311 else _testbuffer.ND_WRITABLE)}
312 pb = pickle.PickleBuffer(self.array)
313 if protocol >= 5:
314 return (type(self)._reconstruct,
315 (pb, ndarray_kwargs))
316 else:
317 # Need to serialize the bytes in physical order
318 with pb.raw() as m:
319 return (type(self)._reconstruct,
320 (m.tobytes(), ndarray_kwargs))
321
322 @classmethod
323 def _reconstruct(cls, obj, kwargs):
324 with memoryview(obj) as m:
325 # For some reason, ndarray() wants a list of integers...
326 # XXX This only works if format == 'B'
327 items = list(m.tobytes())
328 return cls(items, **kwargs)
329
330
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300331# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000332# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000333
Guido van Rossum98297ee2007-11-06 21:34:58 +0000334DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200335 b'(lp0\nL0L\naL1L\naF2.0\n'
336 b'ac__builtin__\ncomple'
337 b'x\np1\n(F3.0\nF0.0\ntp2\n'
338 b'Rp3\naL1L\naL-1L\naL255'
339 b'L\naL-255L\naL-256L\naL'
340 b'65535L\naL-65535L\naL-'
341 b'65536L\naL2147483647L'
342 b'\naL-2147483647L\naL-2'
343 b'147483648L\na(Vabc\np4'
344 b'\ng4\nccopy_reg\n_recon'
345 b'structor\np5\n(c__main'
346 b'__\nC\np6\nc__builtin__'
347 b'\nobject\np7\nNtp8\nRp9\n'
348 b'(dp10\nVfoo\np11\nL1L\ns'
349 b'Vbar\np12\nL2L\nsbg9\ntp'
350 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000351)
Tim Peterse9358162001-01-22 22:05:20 +0000352
Guido van Rossum98297ee2007-11-06 21:34:58 +0000353# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000354DATA0_DIS = """\
355 0: ( MARK
356 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000357 2: p PUT 0
358 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000359 9: a APPEND
360 10: L LONG 1
361 14: a APPEND
362 15: F FLOAT 2.0
363 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200364 21: c GLOBAL '__builtin__ complex'
365 42: p PUT 1
366 45: ( MARK
367 46: F FLOAT 3.0
368 51: F FLOAT 0.0
369 56: t TUPLE (MARK at 45)
370 57: p PUT 2
371 60: R REDUCE
372 61: p PUT 3
373 64: a APPEND
374 65: L LONG 1
375 69: a APPEND
376 70: L LONG -1
377 75: a APPEND
378 76: L LONG 255
379 82: a APPEND
380 83: L LONG -255
381 90: a APPEND
382 91: L LONG -256
383 98: a APPEND
384 99: L LONG 65535
385 107: a APPEND
386 108: L LONG -65535
387 117: a APPEND
388 118: L LONG -65536
389 127: a APPEND
390 128: L LONG 2147483647
391 141: a APPEND
392 142: L LONG -2147483647
393 156: a APPEND
394 157: L LONG -2147483648
395 171: a APPEND
396 172: ( MARK
397 173: V UNICODE 'abc'
398 178: p PUT 4
399 181: g GET 4
400 184: c GLOBAL 'copy_reg _reconstructor'
401 209: p PUT 5
402 212: ( MARK
403 213: c GLOBAL '__main__ C'
404 225: p PUT 6
405 228: c GLOBAL '__builtin__ object'
406 248: p PUT 7
407 251: N NONE
408 252: t TUPLE (MARK at 212)
409 253: p PUT 8
410 256: R REDUCE
411 257: p PUT 9
412 260: ( MARK
413 261: d DICT (MARK at 260)
414 262: p PUT 10
415 266: V UNICODE 'foo'
416 271: p PUT 11
417 275: L LONG 1
418 279: s SETITEM
419 280: V UNICODE 'bar'
420 285: p PUT 12
421 289: L LONG 2
422 293: s SETITEM
423 294: b BUILD
424 295: g GET 9
425 298: t TUPLE (MARK at 172)
426 299: p PUT 13
427 303: a APPEND
428 304: g GET 13
429 308: a APPEND
430 309: L LONG 5
431 313: a APPEND
432 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000433highest protocol among opcodes = 0
434"""
435
Guido van Rossum98297ee2007-11-06 21:34:58 +0000436DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200437 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
438 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000439 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
440 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
441 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
442 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200443 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000444 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200445 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000446 b'object\nq\x07Ntq\x08Rq\t}q\n('
447 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
448 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
449)
Tim Peters70b02d72003-02-02 17:26:40 +0000450
Guido van Rossum98297ee2007-11-06 21:34:58 +0000451# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000452DATA1_DIS = """\
453 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000454 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000455 3: ( MARK
456 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000457 6: K BININT1 1
458 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200459 17: c GLOBAL '__builtin__ complex'
460 38: q BINPUT 1
461 40: ( MARK
462 41: G BINFLOAT 3.0
463 50: G BINFLOAT 0.0
464 59: t TUPLE (MARK at 40)
465 60: q BINPUT 2
466 62: R REDUCE
467 63: q BINPUT 3
468 65: K BININT1 1
469 67: J BININT -1
470 72: K BININT1 255
471 74: J BININT -255
472 79: J BININT -256
473 84: M BININT2 65535
474 87: J BININT -65535
475 92: J BININT -65536
476 97: J BININT 2147483647
477 102: J BININT -2147483647
478 107: J BININT -2147483648
479 112: ( MARK
480 113: X BINUNICODE 'abc'
481 121: q BINPUT 4
482 123: h BINGET 4
483 125: c GLOBAL 'copy_reg _reconstructor'
484 150: q BINPUT 5
485 152: ( MARK
486 153: c GLOBAL '__main__ C'
487 165: q BINPUT 6
488 167: c GLOBAL '__builtin__ object'
489 187: q BINPUT 7
490 189: N NONE
491 190: t TUPLE (MARK at 152)
492 191: q BINPUT 8
493 193: R REDUCE
494 194: q BINPUT 9
495 196: } EMPTY_DICT
496 197: q BINPUT 10
497 199: ( MARK
498 200: X BINUNICODE 'foo'
499 208: q BINPUT 11
500 210: K BININT1 1
501 212: X BINUNICODE 'bar'
502 220: q BINPUT 12
503 222: K BININT1 2
504 224: u SETITEMS (MARK at 199)
505 225: b BUILD
506 226: h BINGET 9
507 228: t TUPLE (MARK at 112)
508 229: q BINPUT 13
509 231: h BINGET 13
510 233: K BININT1 5
511 235: e APPENDS (MARK at 3)
512 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000513highest protocol among opcodes = 1
514"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000515
Guido van Rossum98297ee2007-11-06 21:34:58 +0000516DATA2 = (
517 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200518 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000519 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
520 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
521 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
522 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
523 b'bcq\x04h\x04c__main__\nC\nq\x05'
524 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
525 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
526 b'\nK\x05e.'
527)
Tim Petersfc273752003-03-02 04:54:24 +0000528
Guido van Rossum98297ee2007-11-06 21:34:58 +0000529# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000530DATA2_DIS = """\
531 0: \x80 PROTO 2
532 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000533 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000534 5: ( MARK
535 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000536 8: K BININT1 1
537 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200538 19: c GLOBAL '__builtin__ complex'
539 40: q BINPUT 1
540 42: G BINFLOAT 3.0
541 51: G BINFLOAT 0.0
542 60: \x86 TUPLE2
543 61: q BINPUT 2
544 63: R REDUCE
545 64: q BINPUT 3
546 66: K BININT1 1
547 68: J BININT -1
548 73: K BININT1 255
549 75: J BININT -255
550 80: J BININT -256
551 85: M BININT2 65535
552 88: J BININT -65535
553 93: J BININT -65536
554 98: J BININT 2147483647
555 103: J BININT -2147483647
556 108: J BININT -2147483648
557 113: ( MARK
558 114: X BINUNICODE 'abc'
559 122: q BINPUT 4
560 124: h BINGET 4
561 126: c GLOBAL '__main__ C'
562 138: q BINPUT 5
563 140: ) EMPTY_TUPLE
564 141: \x81 NEWOBJ
565 142: q BINPUT 6
566 144: } EMPTY_DICT
567 145: q BINPUT 7
568 147: ( MARK
569 148: X BINUNICODE 'foo'
570 156: q BINPUT 8
571 158: K BININT1 1
572 160: X BINUNICODE 'bar'
573 168: q BINPUT 9
574 170: K BININT1 2
575 172: u SETITEMS (MARK at 147)
576 173: b BUILD
577 174: h BINGET 6
578 176: t TUPLE (MARK at 113)
579 177: q BINPUT 10
580 179: h BINGET 10
581 181: K BININT1 5
582 183: e APPENDS (MARK at 5)
583 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000584highest protocol among opcodes = 2
585"""
586
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300587DATA3 = (
588 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
589 b'builtins\ncomplex\nq\x01G'
590 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
591 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
592 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
593 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
594 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
595 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
596 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
597 b'e.'
598)
599
600# Disassembly of DATA3
601DATA3_DIS = """\
602 0: \x80 PROTO 3
603 2: ] EMPTY_LIST
604 3: q BINPUT 0
605 5: ( MARK
606 6: K BININT1 0
607 8: K BININT1 1
608 10: G BINFLOAT 2.0
609 19: c GLOBAL 'builtins complex'
610 37: q BINPUT 1
611 39: G BINFLOAT 3.0
612 48: G BINFLOAT 0.0
613 57: \x86 TUPLE2
614 58: q BINPUT 2
615 60: R REDUCE
616 61: q BINPUT 3
617 63: K BININT1 1
618 65: J BININT -1
619 70: K BININT1 255
620 72: J BININT -255
621 77: J BININT -256
622 82: M BININT2 65535
623 85: J BININT -65535
624 90: J BININT -65536
625 95: J BININT 2147483647
626 100: J BININT -2147483647
627 105: J BININT -2147483648
628 110: ( MARK
629 111: X BINUNICODE 'abc'
630 119: q BINPUT 4
631 121: h BINGET 4
632 123: c GLOBAL '__main__ C'
633 135: q BINPUT 5
634 137: ) EMPTY_TUPLE
635 138: \x81 NEWOBJ
636 139: q BINPUT 6
637 141: } EMPTY_DICT
638 142: q BINPUT 7
639 144: ( MARK
640 145: X BINUNICODE 'bar'
641 153: q BINPUT 8
642 155: K BININT1 2
643 157: X BINUNICODE 'foo'
644 165: q BINPUT 9
645 167: K BININT1 1
646 169: u SETITEMS (MARK at 144)
647 170: b BUILD
648 171: h BINGET 6
649 173: t TUPLE (MARK at 110)
650 174: q BINPUT 10
651 176: h BINGET 10
652 178: K BININT1 5
653 180: e APPENDS (MARK at 5)
654 181: . STOP
655highest protocol among opcodes = 2
656"""
657
658DATA4 = (
659 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
660 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
661 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
662 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
663 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
664 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
665 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
666 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
667 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
668)
669
670# Disassembly of DATA4
671DATA4_DIS = """\
672 0: \x80 PROTO 4
673 2: \x95 FRAME 168
674 11: ] EMPTY_LIST
675 12: \x94 MEMOIZE
676 13: ( MARK
677 14: K BININT1 0
678 16: K BININT1 1
679 18: G BINFLOAT 2.0
680 27: \x8c SHORT_BINUNICODE 'builtins'
681 37: \x94 MEMOIZE
682 38: \x8c SHORT_BINUNICODE 'complex'
683 47: \x94 MEMOIZE
684 48: \x93 STACK_GLOBAL
685 49: \x94 MEMOIZE
686 50: G BINFLOAT 3.0
687 59: G BINFLOAT 0.0
688 68: \x86 TUPLE2
689 69: \x94 MEMOIZE
690 70: R REDUCE
691 71: \x94 MEMOIZE
692 72: K BININT1 1
693 74: J BININT -1
694 79: K BININT1 255
695 81: J BININT -255
696 86: J BININT -256
697 91: M BININT2 65535
698 94: J BININT -65535
699 99: J BININT -65536
700 104: J BININT 2147483647
701 109: J BININT -2147483647
702 114: J BININT -2147483648
703 119: ( MARK
704 120: \x8c SHORT_BINUNICODE 'abc'
705 125: \x94 MEMOIZE
706 126: h BINGET 6
707 128: \x8c SHORT_BINUNICODE '__main__'
708 138: \x94 MEMOIZE
709 139: \x8c SHORT_BINUNICODE 'C'
710 142: \x94 MEMOIZE
711 143: \x93 STACK_GLOBAL
712 144: \x94 MEMOIZE
713 145: ) EMPTY_TUPLE
714 146: \x81 NEWOBJ
715 147: \x94 MEMOIZE
716 148: } EMPTY_DICT
717 149: \x94 MEMOIZE
718 150: ( MARK
719 151: \x8c SHORT_BINUNICODE 'bar'
720 156: \x94 MEMOIZE
721 157: K BININT1 2
722 159: \x8c SHORT_BINUNICODE 'foo'
723 164: \x94 MEMOIZE
724 165: K BININT1 1
725 167: u SETITEMS (MARK at 150)
726 168: b BUILD
727 169: h BINGET 10
728 171: t TUPLE (MARK at 119)
729 172: \x94 MEMOIZE
730 173: h BINGET 14
731 175: K BININT1 5
732 177: e APPENDS (MARK at 13)
733 178: . STOP
734highest protocol among opcodes = 4
735"""
736
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000737# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300738DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000739
740# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300741DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000742
743# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300744DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
745 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
746 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
747 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
748 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
749 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000750
751# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300752DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000753
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100754python2_exceptions_without_args = (
755 ArithmeticError,
756 AssertionError,
757 AttributeError,
758 BaseException,
759 BufferError,
760 BytesWarning,
761 DeprecationWarning,
762 EOFError,
763 EnvironmentError,
764 Exception,
765 FloatingPointError,
766 FutureWarning,
767 GeneratorExit,
768 IOError,
769 ImportError,
770 ImportWarning,
771 IndentationError,
772 IndexError,
773 KeyError,
774 KeyboardInterrupt,
775 LookupError,
776 MemoryError,
777 NameError,
778 NotImplementedError,
779 OSError,
780 OverflowError,
781 PendingDeprecationWarning,
782 ReferenceError,
783 RuntimeError,
784 RuntimeWarning,
785 # StandardError is gone in Python 3, we map it to Exception
786 StopIteration,
787 SyntaxError,
788 SyntaxWarning,
789 SystemError,
790 SystemExit,
791 TabError,
792 TypeError,
793 UnboundLocalError,
794 UnicodeError,
795 UnicodeWarning,
796 UserWarning,
797 ValueError,
798 Warning,
799 ZeroDivisionError,
800)
801
802exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
803
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100804# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300805DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
806 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
807 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100808
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000809
Jeremy Hylton66426532001-10-15 21:38:56 +0000810def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000811 c = C()
812 c.foo = 1
813 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000814 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000815 # Append some integer test cases at cPickle.c's internal size
816 # cutoffs.
817 uint1max = 0xff
818 uint2max = 0xffff
819 int4max = 0x7fffffff
820 x.extend([1, -1,
821 uint1max, -uint1max, -uint1max-1,
822 uint2max, -uint2max, -uint2max-1,
823 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000824 y = ('abc', 'abc', c, c)
825 x.append(y)
826 x.append(y)
827 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000828 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000829
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100830
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -0700831class AbstractUnpickleTests:
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300832 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100833
Jeremy Hylton66426532001-10-15 21:38:56 +0000834 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000835
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100836 def assert_is_copy(self, obj, objcopy, msg=None):
837 """Utility method to verify if two objects are copies of each others.
838 """
839 if msg is None:
840 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
841 self.assertEqual(obj, objcopy, msg=msg)
842 self.assertIs(type(obj), type(objcopy), msg=msg)
843 if hasattr(obj, '__dict__'):
844 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
845 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
846 if hasattr(obj, '__slots__'):
847 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
848 for slot in obj.__slots__:
849 self.assertEqual(
850 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
851 self.assertEqual(getattr(obj, slot, None),
852 getattr(objcopy, slot, None), msg=msg)
853
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200854 def check_unpickling_error(self, errors, data):
855 with self.subTest(data=data), \
856 self.assertRaises(errors):
857 try:
858 self.loads(data)
859 except BaseException as exc:
860 if support.verbose > 1:
861 print('%-32r - %s: %s' %
862 (data, exc.__class__.__name__, exc))
863 raise
864
Guido van Rossum98297ee2007-11-06 21:34:58 +0000865 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100866 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000867
868 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100869 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000870
871 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100872 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000873
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300874 def test_load_from_data3(self):
875 self.assert_is_copy(self._testdata, self.loads(DATA3))
876
877 def test_load_from_data4(self):
878 self.assert_is_copy(self._testdata, self.loads(DATA4))
879
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000880 def test_load_classic_instance(self):
881 # See issue5180. Test loading 2.x pickles that
882 # contain an instance of old style class.
883 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
884 xname = X.__name__.encode('ascii')
885 # Protocol 0 (text mode pickle):
886 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200887 0: ( MARK
888 1: i INST '__main__ X' (MARK at 0)
889 13: p PUT 0
890 16: ( MARK
891 17: d DICT (MARK at 16)
892 18: p PUT 1
893 21: b BUILD
894 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000895 """
896 pickle0 = (b"(i__main__\n"
897 b"X\n"
898 b"p0\n"
899 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100900 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000901
902 # Protocol 1 (binary mode pickle)
903 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200904 0: ( MARK
905 1: c GLOBAL '__main__ X'
906 13: q BINPUT 0
907 15: o OBJ (MARK at 0)
908 16: q BINPUT 1
909 18: } EMPTY_DICT
910 19: q BINPUT 2
911 21: b BUILD
912 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000913 """
914 pickle1 = (b'(c__main__\n'
915 b'X\n'
916 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100917 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000918
919 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
920 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200921 0: \x80 PROTO 2
922 2: ( MARK
923 3: c GLOBAL '__main__ X'
924 15: q BINPUT 0
925 17: o OBJ (MARK at 2)
926 18: q BINPUT 1
927 20: } EMPTY_DICT
928 21: q BINPUT 2
929 23: b BUILD
930 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000931 """
932 pickle2 = (b'\x80\x02(c__main__\n'
933 b'X\n'
934 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100935 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000936
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300937 def test_maxint64(self):
938 maxint64 = (1 << 63) - 1
939 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
940 got = self.loads(data)
941 self.assert_is_copy(maxint64, got)
942
943 # Try too with a bogus literal.
944 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200945 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300946
947 def test_unpickle_from_2x(self):
948 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300949 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300950 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300951 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300952 self.assertEqual(type(loaded), type(range(0)))
953 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300954 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300955 self.assertEqual(type(loaded), SimpleCookie)
956 self.assertEqual(list(loaded.keys()), ["key"])
957 self.assertEqual(loaded["key"].value, "value")
958
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300959 # Exception objects without arguments pickled from 2.x with protocol 2
960 for exc in python2_exceptions_without_args:
961 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300962 loaded = self.loads(data)
963 self.assertIs(type(loaded), exc)
964
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300965 # StandardError is mapped to Exception, test that separately
966 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300967 self.assertIs(type(loaded), Exception)
968
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300969 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300970 self.assertIs(type(loaded), UnicodeEncodeError)
971 self.assertEqual(loaded.object, "foo")
972 self.assertEqual(loaded.encoding, "ascii")
973 self.assertEqual(loaded.start, 0)
974 self.assertEqual(loaded.end, 1)
975 self.assertEqual(loaded.reason, "bad")
976
977 def test_load_python2_str_as_bytes(self):
978 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
979 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
980 encoding="bytes"), b'a\x00\xa0')
981 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
982 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
983 encoding="bytes"), b'a\x00\xa0')
984 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
985 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
986 encoding="bytes"), b'a\x00\xa0')
987
988 def test_load_python2_unicode_as_str(self):
989 # From Python 2: pickle.dumps(u'π', protocol=0)
990 self.assertEqual(self.loads(b'V\\u03c0\n.',
991 encoding='bytes'), 'π')
992 # From Python 2: pickle.dumps(u'π', protocol=1)
993 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
994 encoding="bytes"), 'π')
995 # From Python 2: pickle.dumps(u'π', protocol=2)
996 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
997 encoding="bytes"), 'π')
998
999 def test_load_long_python2_str_as_bytes(self):
1000 # From Python 2: pickle.dumps('x' * 300, protocol=1)
1001 self.assertEqual(self.loads(pickle.BINSTRING +
1002 struct.pack("<I", 300) +
1003 b'x' * 300 + pickle.STOP,
1004 encoding='bytes'), b'x' * 300)
1005
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001006 def test_constants(self):
1007 self.assertIsNone(self.loads(b'N.'))
1008 self.assertIs(self.loads(b'\x88.'), True)
1009 self.assertIs(self.loads(b'\x89.'), False)
1010 self.assertIs(self.loads(b'I01\n.'), True)
1011 self.assertIs(self.loads(b'I00\n.'), False)
1012
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001013 def test_empty_bytestring(self):
1014 # issue 11286
1015 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1016 self.assertEqual(empty, '')
1017
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001018 def test_short_binbytes(self):
1019 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
1020 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1021
1022 def test_binbytes(self):
1023 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1024 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1025
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001026 @requires_32b
1027 def test_negative_32b_binbytes(self):
1028 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1029 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001030 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1031 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001032
1033 @requires_32b
1034 def test_negative_32b_binunicode(self):
1035 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1036 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001037 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1038 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001039
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001040 def test_short_binunicode(self):
1041 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1042 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1043
1044 def test_misc_get(self):
Claudiu Popa6f03b232019-11-24 20:15:08 +01001045 self.check_unpickling_error(pickle.UnpicklingError, b'g0\np0')
1046 self.check_unpickling_error(pickle.UnpicklingError, b'jens:')
1047 self.check_unpickling_error(pickle.UnpicklingError, b'hens:')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001048 self.assert_is_copy([(100,), (100,)],
1049 self.loads(b'((Kdtp0\nh\x00l.))'))
1050
Serhiy Storchakae0606192015-09-29 22:10:07 +03001051 def test_binbytes8(self):
1052 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1053 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1054
1055 def test_binunicode8(self):
1056 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1057 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1058
Antoine Pitrou91f43802019-05-26 17:10:09 +02001059 def test_bytearray8(self):
1060 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1061 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1062
Serhiy Storchakae0606192015-09-29 22:10:07 +03001063 @requires_32b
1064 def test_large_32b_binbytes8(self):
1065 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001066 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1067 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001068
1069 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001070 def test_large_32b_bytearray8(self):
1071 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1072 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1073 dumped)
1074
1075 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001076 def test_large_32b_binunicode8(self):
1077 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001078 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1079 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001080
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001081 def test_get(self):
1082 pickled = b'((lp100000\ng100000\nt.'
1083 unpickled = self.loads(pickled)
1084 self.assertEqual(unpickled, ([],)*2)
1085 self.assertIs(unpickled[0], unpickled[1])
1086
1087 def test_binget(self):
1088 pickled = b'(]q\xffh\xfft.'
1089 unpickled = self.loads(pickled)
1090 self.assertEqual(unpickled, ([],)*2)
1091 self.assertIs(unpickled[0], unpickled[1])
1092
1093 def test_long_binget(self):
1094 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1095 unpickled = self.loads(pickled)
1096 self.assertEqual(unpickled, ([],)*2)
1097 self.assertIs(unpickled[0], unpickled[1])
1098
1099 def test_dup(self):
1100 pickled = b'((l2t.'
1101 unpickled = self.loads(pickled)
1102 self.assertEqual(unpickled, ([],)*2)
1103 self.assertIs(unpickled[0], unpickled[1])
1104
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001105 def test_negative_put(self):
1106 # Issue #12847
1107 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001108 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001109
1110 @requires_32b
1111 def test_negative_32b_binput(self):
1112 # Issue #12847
1113 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001114 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001115
1116 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001117 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001118
1119 def test_badly_quoted_string(self):
1120 # Issue #17710
1121 badpickles = [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\n.',
1133 b'S.']
1134 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001135 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001136
1137 def test_correctly_quoted_string(self):
1138 goodpickles = [(b"S''\n.", ''),
1139 (b'S""\n.', ''),
1140 (b'S"\\n"\n.', '\n'),
1141 (b"S'\\n'\n.", '\n')]
1142 for p, expected in goodpickles:
1143 self.assertEqual(self.loads(p), expected)
1144
1145 def test_frame_readline(self):
1146 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1147 # 0: \x80 PROTO 4
1148 # 2: \x95 FRAME 5
1149 # 11: I INT 42
1150 # 15: . STOP
1151 self.assertEqual(self.loads(pickled), 42)
1152
1153 def test_compat_unpickle(self):
1154 # xrange(1, 7)
1155 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1156 unpickled = self.loads(pickled)
1157 self.assertIs(type(unpickled), range)
1158 self.assertEqual(unpickled, range(1, 7))
1159 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1160 # reduce
1161 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1162 self.assertIs(self.loads(pickled), functools.reduce)
1163 # whichdb.whichdb
1164 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1165 self.assertIs(self.loads(pickled), dbm.whichdb)
1166 # Exception(), StandardError()
1167 for name in (b'Exception', b'StandardError'):
1168 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1169 unpickled = self.loads(pickled)
1170 self.assertIs(type(unpickled), Exception)
1171 self.assertEqual(str(unpickled), 'ugh')
1172 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1173 for name in (b'UserDict', b'IterableUserDict'):
1174 pickled = (b'\x80\x02(cUserDict\n' + name +
1175 b'\no}U\x04data}K\x01K\x02ssb.')
1176 unpickled = self.loads(pickled)
1177 self.assertIs(type(unpickled), collections.UserDict)
1178 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1179
Serhiy Storchaka4f309ab2020-07-13 15:49:26 +03001180 def test_bad_reduce(self):
1181 self.assertEqual(self.loads(b'cbuiltins\nint\n)R.'), 0)
1182 self.check_unpickling_error(TypeError, b'N)R.')
1183 self.check_unpickling_error(TypeError, b'cbuiltins\nint\nNR.')
1184
1185 def test_bad_newobj(self):
1186 error = (pickle.UnpicklingError, TypeError)
1187 self.assertEqual(self.loads(b'cbuiltins\nint\n)\x81.'), 0)
1188 self.check_unpickling_error(error, b'cbuiltins\nlen\n)\x81.')
1189 self.check_unpickling_error(error, b'cbuiltins\nint\nN\x81.')
1190
1191 def test_bad_newobj_ex(self):
1192 error = (pickle.UnpicklingError, TypeError)
1193 self.assertEqual(self.loads(b'cbuiltins\nint\n)}\x92.'), 0)
1194 self.check_unpickling_error(error, b'cbuiltins\nlen\n)}\x92.')
1195 self.check_unpickling_error(error, b'cbuiltins\nint\nN}\x92.')
1196 self.check_unpickling_error(error, b'cbuiltins\nint\n)N\x92.')
1197
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001198 def test_bad_stack(self):
1199 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001200 b'.', # STOP
1201 b'0', # POP
1202 b'1', # POP_MARK
1203 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001204 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001205 b'R', # REDUCE
1206 b')R',
1207 b'a', # APPEND
1208 b'Na',
1209 b'b', # BUILD
1210 b'Nb',
1211 b'd', # DICT
1212 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001213 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001214 b'ibuiltins\nlist\n', # INST
1215 b'l', # LIST
1216 b'o', # OBJ
1217 b'(o',
1218 b'p1\n', # PUT
1219 b'q\x00', # BINPUT
1220 b'r\x00\x00\x00\x00', # LONG_BINPUT
1221 b's', # SETITEM
1222 b'Ns',
1223 b'NNs',
1224 b't', # TUPLE
1225 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001226 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001227 b'}(Nu',
1228 b'\x81', # NEWOBJ
1229 b')\x81',
1230 b'\x85', # TUPLE1
1231 b'\x86', # TUPLE2
1232 b'N\x86',
1233 b'\x87', # TUPLE3
1234 b'N\x87',
1235 b'NN\x87',
1236 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001237 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001238 b'\x91', # FROZENSET
1239 b'\x92', # NEWOBJ_EX
1240 b')}\x92',
1241 b'\x93', # STACK_GLOBAL
1242 b'Vlist\n\x93',
1243 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001244 ]
1245 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001246 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001247
1248 def test_bad_mark(self):
1249 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001250 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001251 b'N(2', # DUP
1252 b'cbuiltins\nlist\n)(R', # REDUCE
1253 b'cbuiltins\nlist\n()R',
1254 b']N(a', # APPEND
1255 # BUILD
1256 b'cbuiltins\nValueError\n)R}(b',
1257 b'cbuiltins\nValueError\n)R(}b',
1258 b'(Nd', # DICT
1259 b'N(p1\n', # PUT
1260 b'N(q\x00', # BINPUT
1261 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1262 b'}NN(s', # SETITEM
1263 b'}N(Ns',
1264 b'}(NNs',
1265 b'}((u', # SETITEMS
1266 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1267 b'cbuiltins\nlist\n()\x81',
1268 b'N(\x85', # TUPLE1
1269 b'NN(\x86', # TUPLE2
1270 b'N(N\x86',
1271 b'NNN(\x87', # TUPLE3
1272 b'NN(N\x87',
1273 b'N(NN\x87',
1274 b']((\x90', # ADDITEMS
1275 # NEWOBJ_EX
1276 b'cbuiltins\nlist\n)}(\x92',
1277 b'cbuiltins\nlist\n)(}\x92',
1278 b'cbuiltins\nlist\n()}\x92',
1279 # STACK_GLOBAL
1280 b'Vbuiltins\n(Vlist\n\x93',
1281 b'Vbuiltins\nVlist\n(\x93',
1282 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001283 ]
1284 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001285 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001286
1287 def test_truncated_data(self):
1288 self.check_unpickling_error(EOFError, b'')
1289 self.check_unpickling_error(EOFError, b'N')
1290 badpickles = [
1291 b'B', # BINBYTES
1292 b'B\x03\x00\x00',
1293 b'B\x03\x00\x00\x00',
1294 b'B\x03\x00\x00\x00ab',
1295 b'C', # SHORT_BINBYTES
1296 b'C\x03',
1297 b'C\x03ab',
1298 b'F', # FLOAT
1299 b'F0.0',
1300 b'F0.00',
1301 b'G', # BINFLOAT
1302 b'G\x00\x00\x00\x00\x00\x00\x00',
1303 b'I', # INT
1304 b'I0',
1305 b'J', # BININT
1306 b'J\x00\x00\x00',
1307 b'K', # BININT1
1308 b'L', # LONG
1309 b'L0',
1310 b'L10',
1311 b'L0L',
1312 b'L10L',
1313 b'M', # BININT2
1314 b'M\x00',
1315 # b'P', # PERSID
1316 # b'Pabc',
1317 b'S', # STRING
1318 b"S'abc'",
1319 b'T', # BINSTRING
1320 b'T\x03\x00\x00',
1321 b'T\x03\x00\x00\x00',
1322 b'T\x03\x00\x00\x00ab',
1323 b'U', # SHORT_BINSTRING
1324 b'U\x03',
1325 b'U\x03ab',
1326 b'V', # UNICODE
1327 b'Vabc',
1328 b'X', # BINUNICODE
1329 b'X\x03\x00\x00',
1330 b'X\x03\x00\x00\x00',
1331 b'X\x03\x00\x00\x00ab',
1332 b'(c', # GLOBAL
1333 b'(cbuiltins',
1334 b'(cbuiltins\n',
1335 b'(cbuiltins\nlist',
1336 b'Ng', # GET
1337 b'Ng0',
1338 b'(i', # INST
1339 b'(ibuiltins',
1340 b'(ibuiltins\n',
1341 b'(ibuiltins\nlist',
1342 b'Nh', # BINGET
1343 b'Nj', # LONG_BINGET
1344 b'Nj\x00\x00\x00',
1345 b'Np', # PUT
1346 b'Np0',
1347 b'Nq', # BINPUT
1348 b'Nr', # LONG_BINPUT
1349 b'Nr\x00\x00\x00',
1350 b'\x80', # PROTO
1351 b'\x82', # EXT1
1352 b'\x83', # EXT2
1353 b'\x84\x01',
1354 b'\x84', # EXT4
1355 b'\x84\x01\x00\x00',
1356 b'\x8a', # LONG1
1357 b'\x8b', # LONG4
1358 b'\x8b\x00\x00\x00',
1359 b'\x8c', # SHORT_BINUNICODE
1360 b'\x8c\x03',
1361 b'\x8c\x03ab',
1362 b'\x8d', # BINUNICODE8
1363 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1364 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1365 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1366 b'\x8e', # BINBYTES8
1367 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1368 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1369 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001370 b'\x96', # BYTEARRAY8
1371 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1372 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1373 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001374 b'\x95', # FRAME
1375 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1376 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1377 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1378 ]
1379 for p in badpickles:
1380 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001381
Hai Shie80697d2020-05-28 06:10:27 +08001382 @threading_helper.reap_threads
tjb9004371c0a2019-02-18 23:30:51 +08001383 def test_unpickle_module_race(self):
1384 # https://bugs.python.org/issue34572
1385 locker_module = dedent("""
1386 import threading
1387 barrier = threading.Barrier(2)
1388 """)
1389 locking_import_module = dedent("""
1390 import locker
1391 locker.barrier.wait()
1392 class ToBeUnpickled(object):
1393 pass
1394 """)
1395
1396 os.mkdir(TESTFN)
1397 self.addCleanup(shutil.rmtree, TESTFN)
1398 sys.path.insert(0, TESTFN)
1399 self.addCleanup(sys.path.remove, TESTFN)
1400 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1401 f.write(locker_module.encode('utf-8'))
1402 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1403 f.write(locking_import_module.encode('utf-8'))
1404 self.addCleanup(forget, "locker")
1405 self.addCleanup(forget, "locking_import")
1406
1407 import locker
1408
1409 pickle_bytes = (
1410 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1411
1412 # Then try to unpickle two of these simultaneously
1413 # One of them will cause the module import, and we want it to block
1414 # until the other one either:
1415 # - fails (before the patch for this issue)
1416 # - blocks on the import lock for the module, as it should
1417 results = []
1418 barrier = threading.Barrier(3)
1419 def t():
1420 # This ensures the threads have all started
1421 # presumably barrier release is faster than thread startup
1422 barrier.wait()
1423 results.append(pickle.loads(pickle_bytes))
1424
1425 t1 = threading.Thread(target=t)
1426 t2 = threading.Thread(target=t)
1427 t1.start()
1428 t2.start()
1429
1430 barrier.wait()
1431 # could have delay here
1432 locker.barrier.wait()
1433
1434 t1.join()
1435 t2.join()
1436
1437 from locking_import import ToBeUnpickled
1438 self.assertEqual(
1439 [type(x) for x in results],
1440 [ToBeUnpickled] * 2)
1441
1442
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001443
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -07001444class AbstractPickleTests:
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001445 # Subclass must define self.dumps, self.loads.
1446
1447 optimized = False
1448
1449 _testdata = AbstractUnpickleTests._testdata
1450
1451 def setUp(self):
1452 pass
1453
1454 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1455
1456 def test_misc(self):
1457 # test various datatypes not tested by testdata
1458 for proto in protocols:
1459 x = myint(4)
1460 s = self.dumps(x, proto)
1461 y = self.loads(s)
1462 self.assert_is_copy(x, y)
1463
1464 x = (1, ())
1465 s = self.dumps(x, proto)
1466 y = self.loads(s)
1467 self.assert_is_copy(x, y)
1468
1469 x = initarg(1, x)
1470 s = self.dumps(x, proto)
1471 y = self.loads(s)
1472 self.assert_is_copy(x, y)
1473
1474 # XXX test __reduce__ protocol?
1475
1476 def test_roundtrip_equality(self):
1477 expected = self._testdata
1478 for proto in protocols:
1479 s = self.dumps(expected, proto)
1480 got = self.loads(s)
1481 self.assert_is_copy(expected, got)
1482
Tim Peters70b02d72003-02-02 17:26:40 +00001483 # There are gratuitous differences between pickles produced by
1484 # pickle and cPickle, largely because cPickle starts PUT indices at
1485 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1486 # there's a comment with an exclamation point there whose meaning
1487 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1488 # of 1.
1489 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001490 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001491 from pickletools import dis
1492
1493 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1494 s = self.dumps(self._testdata, proto)
1495 filelike = StringIO()
1496 dis(s, out=filelike)
1497 got = filelike.getvalue()
1498 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001499
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001500 def _test_recursive_list(self, cls, aslist=identity, minprotocol=0):
1501 # List containing itself.
1502 l = cls()
Jeremy Hylton66426532001-10-15 21:38:56 +00001503 l.append(l)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001504 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
Tim Peters70b02d72003-02-02 17:26:40 +00001505 s = self.dumps(l, proto)
1506 x = self.loads(s)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001507 self.assertIsInstance(x, cls)
1508 y = aslist(x)
1509 self.assertEqual(len(y), 1)
1510 self.assertIs(y[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001511
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001512 def test_recursive_list(self):
1513 self._test_recursive_list(list)
1514
1515 def test_recursive_list_subclass(self):
1516 self._test_recursive_list(MyList, minprotocol=2)
1517
1518 def test_recursive_list_like(self):
1519 self._test_recursive_list(REX_six, aslist=lambda x: x.items)
1520
1521 def _test_recursive_tuple_and_list(self, cls, aslist=identity, minprotocol=0):
1522 # Tuple containing a list containing the original tuple.
1523 t = (cls(),)
Collin Winter8ca69de2009-05-26 16:53:41 +00001524 t[0].append(t)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001525 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
Collin Winter8ca69de2009-05-26 16:53:41 +00001526 s = self.dumps(t, proto)
1527 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001528 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001529 self.assertEqual(len(x), 1)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001530 self.assertIsInstance(x[0], cls)
1531 y = aslist(x[0])
1532 self.assertEqual(len(y), 1)
1533 self.assertIs(y[0], x)
1534
1535 # List containing a tuple containing the original list.
1536 t, = t
1537 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
1538 s = self.dumps(t, proto)
1539 x = self.loads(s)
1540 self.assertIsInstance(x, cls)
1541 y = aslist(x)
1542 self.assertEqual(len(y), 1)
1543 self.assertIsInstance(y[0], tuple)
1544 self.assertEqual(len(y[0]), 1)
1545 self.assertIs(y[0][0], x)
1546
1547 def test_recursive_tuple_and_list(self):
1548 self._test_recursive_tuple_and_list(list)
1549
1550 def test_recursive_tuple_and_list_subclass(self):
1551 self._test_recursive_tuple_and_list(MyList, minprotocol=2)
1552
1553 def test_recursive_tuple_and_list_like(self):
1554 self._test_recursive_tuple_and_list(REX_six, aslist=lambda x: x.items)
1555
1556 def _test_recursive_dict(self, cls, asdict=identity, minprotocol=0):
1557 # Dict containing itself.
1558 d = cls()
1559 d[1] = d
1560 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
1561 s = self.dumps(d, proto)
1562 x = self.loads(s)
1563 self.assertIsInstance(x, cls)
1564 y = asdict(x)
1565 self.assertEqual(list(y.keys()), [1])
1566 self.assertIs(y[1], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001567
Jeremy Hylton66426532001-10-15 21:38:56 +00001568 def test_recursive_dict(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001569 self._test_recursive_dict(dict)
1570
1571 def test_recursive_dict_subclass(self):
1572 self._test_recursive_dict(MyDict, minprotocol=2)
1573
1574 def test_recursive_dict_like(self):
1575 self._test_recursive_dict(REX_seven, asdict=lambda x: x.table)
1576
1577 def _test_recursive_tuple_and_dict(self, cls, asdict=identity, minprotocol=0):
1578 # Tuple containing a dict containing the original tuple.
1579 t = (cls(),)
1580 t[0][1] = t
1581 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
1582 s = self.dumps(t, proto)
1583 x = self.loads(s)
1584 self.assertIsInstance(x, tuple)
1585 self.assertEqual(len(x), 1)
1586 self.assertIsInstance(x[0], cls)
1587 y = asdict(x[0])
1588 self.assertEqual(list(y), [1])
1589 self.assertIs(y[1], x)
1590
1591 # Dict containing a tuple containing the original dict.
1592 t, = t
1593 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
1594 s = self.dumps(t, proto)
1595 x = self.loads(s)
1596 self.assertIsInstance(x, cls)
1597 y = asdict(x)
1598 self.assertEqual(list(y), [1])
1599 self.assertIsInstance(y[1], tuple)
1600 self.assertEqual(len(y[1]), 1)
1601 self.assertIs(y[1][0], x)
1602
1603 def test_recursive_tuple_and_dict(self):
1604 self._test_recursive_tuple_and_dict(dict)
1605
1606 def test_recursive_tuple_and_dict_subclass(self):
1607 self._test_recursive_tuple_and_dict(MyDict, minprotocol=2)
1608
1609 def test_recursive_tuple_and_dict_like(self):
1610 self._test_recursive_tuple_and_dict(REX_seven, asdict=lambda x: x.table)
1611
1612 def _test_recursive_dict_key(self, cls, asdict=identity, minprotocol=0):
1613 # Dict containing an immutable object (as key) containing the original
1614 # dict.
1615 d = cls()
1616 d[K(d)] = 1
1617 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
Tim Peters70b02d72003-02-02 17:26:40 +00001618 s = self.dumps(d, proto)
1619 x = self.loads(s)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001620 self.assertIsInstance(x, cls)
1621 y = asdict(x)
1622 self.assertEqual(len(y.keys()), 1)
1623 self.assertIsInstance(list(y.keys())[0], K)
1624 self.assertIs(list(y.keys())[0].value, x)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001625
1626 def test_recursive_dict_key(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001627 self._test_recursive_dict_key(dict)
1628
1629 def test_recursive_dict_subclass_key(self):
1630 self._test_recursive_dict_key(MyDict, minprotocol=2)
1631
1632 def test_recursive_dict_like_key(self):
1633 self._test_recursive_dict_key(REX_seven, asdict=lambda x: x.table)
1634
1635 def _test_recursive_tuple_and_dict_key(self, cls, asdict=identity, minprotocol=0):
1636 # Tuple containing a dict containing an immutable object (as key)
1637 # containing the original tuple.
1638 t = (cls(),)
1639 t[0][K(t)] = 1
1640 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
1641 s = self.dumps(t, proto)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001642 x = self.loads(s)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001643 self.assertIsInstance(x, tuple)
1644 self.assertEqual(len(x), 1)
1645 self.assertIsInstance(x[0], cls)
1646 y = asdict(x[0])
1647 self.assertEqual(len(y), 1)
1648 self.assertIsInstance(list(y.keys())[0], K)
1649 self.assertIs(list(y.keys())[0].value, x)
1650
1651 # Dict containing an immutable object (as key) containing a tuple
1652 # containing the original dict.
1653 t, = t
1654 for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
1655 s = self.dumps(t, proto)
1656 x = self.loads(s)
1657 self.assertIsInstance(x, cls)
1658 y = asdict(x)
1659 self.assertEqual(len(y), 1)
1660 self.assertIsInstance(list(y.keys())[0], K)
1661 self.assertIs(list(y.keys())[0].value[0], x)
1662
1663 def test_recursive_tuple_and_dict_key(self):
1664 self._test_recursive_tuple_and_dict_key(dict)
1665
1666 def test_recursive_tuple_and_dict_subclass_key(self):
1667 self._test_recursive_tuple_and_dict_key(MyDict, minprotocol=2)
1668
1669 def test_recursive_tuple_and_dict_like_key(self):
1670 self._test_recursive_tuple_and_dict_key(REX_seven, asdict=lambda x: x.table)
Jeremy Hylton66426532001-10-15 21:38:56 +00001671
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001672 def test_recursive_set(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001673 # Set containing an immutable object containing the original set.
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001674 y = set()
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001675 y.add(K(y))
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001676 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001677 s = self.dumps(y, proto)
1678 x = self.loads(s)
1679 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001680 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001681 self.assertIsInstance(list(x)[0], K)
1682 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001683
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001684 # Immutable object containing a set containing the original object.
1685 y, = y
1686 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001687 s = self.dumps(y, proto)
1688 x = self.loads(s)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001689 self.assertIsInstance(x, K)
1690 self.assertIsInstance(x.value, set)
1691 self.assertEqual(len(x.value), 1)
1692 self.assertIs(list(x.value)[0], x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001693
Jeremy Hylton66426532001-10-15 21:38:56 +00001694 def test_recursive_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001695 # Mutable object containing itself.
1696 i = Object()
Jeremy Hylton66426532001-10-15 21:38:56 +00001697 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001698 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001699 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001700 x = self.loads(s)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001701 self.assertIsInstance(x, Object)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001702 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001703 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001704
1705 def test_recursive_multi(self):
1706 l = []
1707 d = {1:l}
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001708 i = Object()
Jeremy Hylton66426532001-10-15 21:38:56 +00001709 i.attr = d
1710 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001711 for proto in protocols:
1712 s = self.dumps(l, proto)
1713 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001714 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001715 self.assertEqual(len(x), 1)
1716 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001717 self.assertEqual(list(x[0].attr.keys()), [1])
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001718 self.assertIs(x[0].attr[1], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001719
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001720 def _test_recursive_collection_and_inst(self, factory):
1721 # Mutable object containing a collection containing the original
1722 # object.
1723 o = Object()
1724 o.attr = factory([o])
1725 t = type(o.attr)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001726 for proto in protocols:
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001727 s = self.dumps(o, proto)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001728 x = self.loads(s)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001729 self.assertIsInstance(x.attr, t)
1730 self.assertEqual(len(x.attr), 1)
1731 self.assertIsInstance(list(x.attr)[0], Object)
1732 self.assertIs(list(x.attr)[0], x)
1733
1734 # Collection containing a mutable object containing the original
1735 # collection.
1736 o = o.attr
1737 for proto in protocols:
1738 s = self.dumps(o, proto)
1739 x = self.loads(s)
1740 self.assertIsInstance(x, t)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001741 self.assertEqual(len(x), 1)
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001742 self.assertIsInstance(list(x)[0], Object)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001743 self.assertIs(list(x)[0].attr, x)
1744
1745 def test_recursive_list_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001746 self._test_recursive_collection_and_inst(list)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001747
1748 def test_recursive_tuple_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001749 self._test_recursive_collection_and_inst(tuple)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001750
1751 def test_recursive_dict_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001752 self._test_recursive_collection_and_inst(dict.fromkeys)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001753
1754 def test_recursive_set_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001755 self._test_recursive_collection_and_inst(set)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001756
1757 def test_recursive_frozenset_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001758 self._test_recursive_collection_and_inst(frozenset)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001759
1760 def test_recursive_list_subclass_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001761 self._test_recursive_collection_and_inst(MyList)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001762
1763 def test_recursive_tuple_subclass_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001764 self._test_recursive_collection_and_inst(MyTuple)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001765
1766 def test_recursive_dict_subclass_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001767 self._test_recursive_collection_and_inst(MyDict.fromkeys)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001768
1769 def test_recursive_set_subclass_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001770 self._test_recursive_collection_and_inst(MySet)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001771
1772 def test_recursive_frozenset_subclass_and_inst(self):
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02001773 self._test_recursive_collection_and_inst(MyFrozenSet)
1774
1775 def test_recursive_inst_state(self):
1776 # Mutable object containing itself.
1777 y = REX_state()
1778 y.state = y
1779 for proto in protocols:
1780 s = self.dumps(y, proto)
1781 x = self.loads(s)
1782 self.assertIsInstance(x, REX_state)
1783 self.assertIs(x.state, x)
1784
1785 def test_recursive_tuple_and_inst_state(self):
1786 # Tuple containing a mutable object containing the original tuple.
1787 t = (REX_state(),)
1788 t[0].state = t
1789 for proto in protocols:
1790 s = self.dumps(t, proto)
1791 x = self.loads(s)
1792 self.assertIsInstance(x, tuple)
1793 self.assertEqual(len(x), 1)
1794 self.assertIsInstance(x[0], REX_state)
1795 self.assertIs(x[0].state, x)
1796
1797 # Mutable object containing a tuple containing the object.
1798 t, = t
1799 for proto in protocols:
1800 s = self.dumps(t, proto)
1801 x = self.loads(s)
1802 self.assertIsInstance(x, REX_state)
1803 self.assertIsInstance(x.state, tuple)
1804 self.assertEqual(len(x.state), 1)
1805 self.assertIs(x.state[0], x)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001806
Walter Dörwald9b775532007-06-08 14:30:53 +00001807 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001808 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001809 '<\\>', '<\\\U00012345>',
1810 # surrogates
1811 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001812 for proto in protocols:
1813 for u in endcases:
1814 p = self.dumps(u, proto)
1815 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001816 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001817
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001818 def test_unicode_high_plane(self):
1819 t = '\U00012345'
1820 for proto in protocols:
1821 p = self.dumps(t, proto)
1822 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001823 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001824
Guido van Rossumf4169812008-03-17 22:56:06 +00001825 def test_bytes(self):
1826 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001827 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001828 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001829 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001830 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001831 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001832 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001833 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001834 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001835 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001836
Antoine Pitrou91f43802019-05-26 17:10:09 +02001837 def test_bytearray(self):
1838 for proto in protocols:
1839 for s in b'', b'xyz', b'xyz'*100:
1840 b = bytearray(s)
1841 p = self.dumps(b, proto)
1842 bb = self.loads(p)
1843 self.assertIsNot(bb, b)
1844 self.assert_is_copy(b, bb)
1845 if proto <= 3:
1846 # bytearray is serialized using a global reference
1847 self.assertIn(b'bytearray', p)
1848 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1849 elif proto == 4:
1850 self.assertIn(b'bytearray', p)
1851 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1852 elif proto == 5:
1853 self.assertNotIn(b'bytearray', p)
1854 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1855
Carl Friedrich Bolz-Tereick1e9f0932021-04-23 23:27:14 +02001856 def test_bytearray_memoization_bug(self):
1857 for proto in protocols:
1858 for s in b'', b'xyz', b'xyz'*100:
1859 b = bytearray(s)
1860 p = self.dumps((b, b), proto)
1861 b1, b2 = self.loads(p)
1862 self.assertIs(b1, b2)
1863
Jeremy Hylton66426532001-10-15 21:38:56 +00001864 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001865 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001866 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001867 while n:
1868 for expected in (-n, n):
1869 s = self.dumps(expected, proto)
1870 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001871 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001872 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001873
Tim Petersee1a53c2003-02-02 02:57:53 +00001874 def test_long(self):
1875 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001876 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001877 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001878 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001879 for npos in nbase-1, nbase, nbase+1:
1880 for n in npos, -npos:
1881 pickle = self.dumps(n, proto)
1882 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001883 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001884 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1885 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001886 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001887 nbase += nbase << 1000000
1888 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001889 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001890 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001891 # assert_is_copy is very expensive here as it precomputes
1892 # a failure message by computing the repr() of n and got,
1893 # we just do the check ourselves.
1894 self.assertIs(type(got), int)
1895 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001896
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001897 def test_float(self):
1898 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1899 3.14, 263.44582062374053, 6.022e23, 1e30]
1900 test_values = test_values + [-x for x in test_values]
1901 for proto in protocols:
1902 for value in test_values:
1903 pickle = self.dumps(value, proto)
1904 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001905 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001906
Thomas Wouters477c8d52006-05-27 19:21:47 +00001907 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1908 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001909 # make sure that floats are formatted locale independent with proto 0
1910 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001911
Jeremy Hylton66426532001-10-15 21:38:56 +00001912 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001913 for proto in protocols:
1914 inst = AAA()
1915 dumped = self.dumps(inst, proto)
1916 loaded = self.loads(dumped)
1917 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001918
1919 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001920 for proto in protocols:
1921 inst = initarg(1, 2)
1922 dumped = self.dumps(inst, proto)
1923 loaded = self.loads(dumped)
1924 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001925
Guido van Rossum04a86612001-12-19 16:58:54 +00001926 def test_metaclass(self):
1927 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001928 for proto in protocols:
1929 s = self.dumps(a, proto)
1930 b = self.loads(s)
1931 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001932
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001933 def test_dynamic_class(self):
1934 a = create_dynamic_class("my_dynamic_class", (object,))
1935 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1936 for proto in protocols:
1937 s = self.dumps(a, proto)
1938 b = self.loads(s)
1939 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001940 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001941
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001942 def test_structseq(self):
1943 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001944 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001945
1946 t = time.localtime()
1947 for proto in protocols:
1948 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001949 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001950 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001951 t = os.stat(os.curdir)
1952 s = self.dumps(t, proto)
1953 u = self.loads(s)
1954 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001955 if hasattr(os, "statvfs"):
1956 t = os.statvfs(os.curdir)
1957 s = self.dumps(t, proto)
1958 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001959 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001960
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001961 def test_ellipsis(self):
1962 for proto in protocols:
1963 s = self.dumps(..., proto)
1964 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001965 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001966
1967 def test_notimplemented(self):
1968 for proto in protocols:
1969 s = self.dumps(NotImplemented, proto)
1970 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001971 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001972
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001973 def test_singleton_types(self):
1974 # Issue #6477: Test that types of built-in singletons can be pickled.
1975 singletons = [None, ..., NotImplemented]
1976 for singleton in singletons:
1977 for proto in protocols:
1978 s = self.dumps(type(singleton), proto)
1979 u = self.loads(s)
1980 self.assertIs(type(singleton), u)
1981
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001982 # Tests for protocol 2
1983
Tim Peters4190fb82003-02-02 16:09:05 +00001984 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001985 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001986 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001987 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001988 proto_header = pickle.PROTO + bytes([proto])
1989 self.assertTrue(pickled.startswith(proto_header))
1990 else:
1991 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001992
1993 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001994 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001995 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001996 try:
1997 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001998 except ValueError as err:
1999 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00002000 else:
2001 self.fail("expected bad protocol number to raise ValueError")
2002
Guido van Rossumd6c9e632003-01-28 03:49:52 +00002003 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00002004 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00002005 for proto in protocols:
2006 s = self.dumps(x, proto)
2007 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002008 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00002009 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00002010
2011 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00002012 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00002013 for proto in protocols:
2014 s = self.dumps(x, proto)
2015 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002016 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00002017 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00002018
Guido van Rossum44f0ea52003-01-28 04:14:51 +00002019 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00002020 # Map (proto, len(tuple)) to expected opcode.
2021 expected_opcode = {(0, 0): pickle.TUPLE,
2022 (0, 1): pickle.TUPLE,
2023 (0, 2): pickle.TUPLE,
2024 (0, 3): pickle.TUPLE,
2025 (0, 4): pickle.TUPLE,
2026
2027 (1, 0): pickle.EMPTY_TUPLE,
2028 (1, 1): pickle.TUPLE,
2029 (1, 2): pickle.TUPLE,
2030 (1, 3): pickle.TUPLE,
2031 (1, 4): pickle.TUPLE,
2032
2033 (2, 0): pickle.EMPTY_TUPLE,
2034 (2, 1): pickle.TUPLE1,
2035 (2, 2): pickle.TUPLE2,
2036 (2, 3): pickle.TUPLE3,
2037 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00002038
2039 (3, 0): pickle.EMPTY_TUPLE,
2040 (3, 1): pickle.TUPLE1,
2041 (3, 2): pickle.TUPLE2,
2042 (3, 3): pickle.TUPLE3,
2043 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00002044 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00002045 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00002046 b = (1,)
2047 c = (1, 2)
2048 d = (1, 2, 3)
2049 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00002050 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00002051 for x in a, b, c, d, e:
2052 s = self.dumps(x, proto)
2053 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002054 self.assert_is_copy(x, y)
2055 expected = expected_opcode[min(proto, 3), len(x)]
2056 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00002057
Guido van Rossum7d97d312003-01-28 04:25:27 +00002058 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00002059 # Map (proto, singleton) to expected opcode.
2060 expected_opcode = {(0, None): pickle.NONE,
2061 (1, None): pickle.NONE,
2062 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00002063 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00002064
2065 (0, True): pickle.INT,
2066 (1, True): pickle.INT,
2067 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00002068 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00002069
2070 (0, False): pickle.INT,
2071 (1, False): pickle.INT,
2072 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00002073 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00002074 }
Tim Peters4190fb82003-02-02 16:09:05 +00002075 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00002076 for x in None, False, True:
2077 s = self.dumps(x, proto)
2078 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002079 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002080 expected = expected_opcode[min(proto, 3), x]
2081 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00002082
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002083 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00002084 x = MyTuple([1, 2, 3])
2085 x.foo = 42
2086 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00002087 for proto in protocols:
2088 s = self.dumps(x, proto)
2089 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002090 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002091
2092 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00002093 x = MyList([1, 2, 3])
2094 x.foo = 42
2095 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00002096 for proto in protocols:
2097 s = self.dumps(x, proto)
2098 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002099 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002100
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002101 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00002102 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002103 for C in myclasses:
2104 B = C.__base__
2105 x = C(C.sample)
2106 x.foo = 42
2107 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002108 y = self.loads(s)
2109 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002110 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002111 self.assertEqual(B(x), B(y), detail)
2112 self.assertEqual(x.__dict__, y.__dict__, detail)
2113
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01002114 def test_newobj_proxies(self):
2115 # NEWOBJ should use the __class__ rather than the raw type
2116 classes = myclasses[:]
2117 # Cannot create weakproxies to these classes
2118 for c in (MyInt, MyTuple):
2119 classes.remove(c)
2120 for proto in protocols:
2121 for C in classes:
2122 B = C.__base__
2123 x = C(C.sample)
2124 x.foo = 42
2125 p = weakref.proxy(x)
2126 s = self.dumps(p, proto)
2127 y = self.loads(s)
2128 self.assertEqual(type(y), type(x)) # rather than type(p)
2129 detail = (proto, C, B, x, y, type(y))
2130 self.assertEqual(B(x), B(y), detail)
2131 self.assertEqual(x.__dict__, y.__dict__, detail)
2132
Serhiy Storchaka8cd1dba2020-10-24 21:14:23 +03002133 def test_newobj_overridden_new(self):
2134 # Test that Python class with C implemented __new__ is pickleable
2135 for proto in protocols:
2136 x = MyIntWithNew2(1)
2137 x.foo = 42
2138 s = self.dumps(x, proto)
2139 y = self.loads(s)
2140 self.assertIs(type(y), MyIntWithNew2)
2141 self.assertEqual(int(y), 1)
2142 self.assertEqual(y.foo, 42)
2143
Benjamin Peterson80f78a32015-07-02 16:18:38 -05002144 def test_newobj_not_class(self):
2145 # Issue 24552
2146 global SimpleNewObj
2147 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05002148 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05002149 b = self.dumps(o, 4)
2150 try:
2151 SimpleNewObj = 42
2152 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
2153 finally:
2154 SimpleNewObj = save
2155
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00002156 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00002157 # an object of that type. Check that the resulting pickle uses opcode
2158 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00002159
Tim Peters22e71712003-02-03 22:27:38 +00002160 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00002161 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002162 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00002163 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002164 x = MyList([1, 2, 3])
2165 x.foo = 42
2166 x.bar = "hello"
2167
Tim Peters22e71712003-02-03 22:27:38 +00002168 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002169 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002170 self.assertIn(__name__.encode("utf-8"), s1)
2171 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002172 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00002173
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002174 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002175 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002176
Tim Peters22e71712003-02-03 22:27:38 +00002177 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002178 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002179 self.assertNotIn(__name__.encode("utf-8"), s2)
2180 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00002181 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00002182
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002183 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002184 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002185 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00002186 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00002187
2188 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002189 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
2190 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002191
2192 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002193 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
2194 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
2195 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002196
2197 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002198 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
2199 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
2200 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
2201
Tim Peters8d2613a2003-02-11 16:40:16 +00002202 def test_list_chunking(self):
2203 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002204 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002205 for proto in protocols:
2206 s = self.dumps(x, proto)
2207 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002208 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002209 num_appends = count_opcode(pickle.APPENDS, s)
2210 self.assertEqual(num_appends, proto > 0)
2211
2212 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002213 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002214 for proto in protocols:
2215 s = self.dumps(x, proto)
2216 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002217 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002218 num_appends = count_opcode(pickle.APPENDS, s)
2219 if proto == 0:
2220 self.assertEqual(num_appends, 0)
2221 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002222 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002223
2224 def test_dict_chunking(self):
2225 n = 10 # too small to chunk
2226 x = dict.fromkeys(range(n))
2227 for proto in protocols:
2228 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002229 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002230 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002231 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002232 num_setitems = count_opcode(pickle.SETITEMS, s)
2233 self.assertEqual(num_setitems, proto > 0)
2234
2235 n = 2500 # expect at least two chunks when proto > 0
2236 x = dict.fromkeys(range(n))
2237 for proto in protocols:
2238 s = self.dumps(x, proto)
2239 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002240 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002241 num_setitems = count_opcode(pickle.SETITEMS, s)
2242 if proto == 0:
2243 self.assertEqual(num_setitems, 0)
2244 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002245 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002246
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002247 def test_set_chunking(self):
2248 n = 10 # too small to chunk
2249 x = set(range(n))
2250 for proto in protocols:
2251 s = self.dumps(x, proto)
2252 y = self.loads(s)
2253 self.assert_is_copy(x, y)
2254 num_additems = count_opcode(pickle.ADDITEMS, s)
2255 if proto < 4:
2256 self.assertEqual(num_additems, 0)
2257 else:
2258 self.assertEqual(num_additems, 1)
2259
2260 n = 2500 # expect at least two chunks when proto >= 4
2261 x = set(range(n))
2262 for proto in protocols:
2263 s = self.dumps(x, proto)
2264 y = self.loads(s)
2265 self.assert_is_copy(x, y)
2266 num_additems = count_opcode(pickle.ADDITEMS, s)
2267 if proto < 4:
2268 self.assertEqual(num_additems, 0)
2269 else:
2270 self.assertGreaterEqual(num_additems, 2)
2271
Tim Peterse9ef2032003-02-13 18:42:00 +00002272 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002273 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002274 x.abc = 666
2275 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002276 with self.subTest(proto=proto):
2277 s = self.dumps(x, proto)
2278 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002279 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002280 else:
2281 self.assertIn(b'M\xce\xfa', s) # BININT2
2282 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2283 2 <= proto)
2284 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2285 y = self.loads(s) # will raise TypeError if __init__ called
2286 self.assert_is_copy(x, y)
2287
2288 def test_complex_newobj(self):
2289 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2290 x.abc = 666
2291 for proto in protocols:
2292 with self.subTest(proto=proto):
2293 s = self.dumps(x, proto)
2294 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002295 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002296 elif proto < 2:
2297 self.assertIn(b'M\xce\xfa', s) # BININT2
2298 elif proto < 4:
2299 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2300 else:
2301 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2302 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2303 2 <= proto)
2304 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2305 y = self.loads(s) # will raise TypeError if __init__ called
2306 self.assert_is_copy(x, y)
2307
2308 def test_complex_newobj_ex(self):
2309 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2310 x.abc = 666
2311 for proto in protocols:
2312 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002313 s = self.dumps(x, proto)
2314 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002315 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002316 elif proto < 2:
2317 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002318 elif proto < 4:
2319 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002320 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002321 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2322 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2323 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2324 4 <= proto)
2325 y = self.loads(s) # will raise TypeError if __init__ called
2326 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002327
Tim Peters42f08ac2003-02-11 22:43:24 +00002328 def test_newobj_list_slots(self):
2329 x = SlotList([1, 2, 3])
2330 x.foo = 42
2331 x.bar = "hello"
2332 s = self.dumps(x, 2)
2333 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002334 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002335
Guido van Rossum2a30b212003-02-18 22:41:24 +00002336 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002337 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002338 x = REX_one()
2339 self.assertEqual(x._reduce_called, 0)
2340 s = self.dumps(x, proto)
2341 self.assertEqual(x._reduce_called, 1)
2342 y = self.loads(s)
2343 self.assertEqual(y._reduce_called, 0)
2344
2345 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002346 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002347 x = REX_two()
2348 self.assertEqual(x._proto, None)
2349 s = self.dumps(x, proto)
2350 self.assertEqual(x._proto, proto)
2351 y = self.loads(s)
2352 self.assertEqual(y._proto, None)
2353
2354 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002355 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002356 x = REX_three()
2357 self.assertEqual(x._proto, None)
2358 s = self.dumps(x, proto)
2359 self.assertEqual(x._proto, proto)
2360 y = self.loads(s)
2361 self.assertEqual(y._proto, None)
2362
Guido van Rossumd8faa362007-04-27 19:54:29 +00002363 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002364 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002365 x = REX_four()
2366 self.assertEqual(x._proto, None)
2367 s = self.dumps(x, proto)
2368 self.assertEqual(x._proto, proto)
2369 y = self.loads(s)
2370 self.assertEqual(y._proto, proto)
2371
2372 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002373 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002374 x = REX_five()
2375 self.assertEqual(x._reduce_called, 0)
2376 s = self.dumps(x, proto)
2377 self.assertEqual(x._reduce_called, 1)
2378 y = self.loads(s)
2379 self.assertEqual(y._reduce_called, 1)
2380
Brett Cannon31f59292011-02-21 19:29:56 +00002381 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002382 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002383 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002384 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002385 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002386 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002387
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002388 def test_reduce_bad_iterator(self):
2389 # Issue4176: crash when 4th and 5th items of __reduce__()
2390 # are not iterators
2391 class C(object):
2392 def __reduce__(self):
2393 # 4th item is not an iterator
2394 return list, (), None, [], None
2395 class D(object):
2396 def __reduce__(self):
2397 # 5th item is not an iterator
2398 return dict, (), None, None, []
2399
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002400 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002401 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002402 try:
2403 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002404 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002405 pass
2406 try:
2407 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002408 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002409 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002410
Collin Winter771d8342009-04-16 03:18:06 +00002411 def test_many_puts_and_gets(self):
2412 # Test that internal data structures correctly deal with lots of
2413 # puts/gets.
2414 keys = ("aaa" + str(i) for i in range(100))
2415 large_dict = dict((k, [4, 5, 6]) for k in keys)
2416 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2417
2418 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002419 with self.subTest(proto=proto):
2420 dumped = self.dumps(obj, proto)
2421 loaded = self.loads(dumped)
2422 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002423
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002424 def test_attribute_name_interning(self):
2425 # Test that attribute names of pickled objects are interned when
2426 # unpickling.
2427 for proto in protocols:
2428 x = C()
2429 x.foo = 42
2430 x.bar = "hello"
2431 s = self.dumps(x, proto)
2432 y = self.loads(s)
2433 x_keys = sorted(x.__dict__)
2434 y_keys = sorted(y.__dict__)
2435 for x_key, y_key in zip(x_keys, y_keys):
2436 self.assertIs(x_key, y_key)
2437
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002438 def test_pickle_to_2x(self):
2439 # Pickle non-trivial data with protocol 2, expecting that it yields
2440 # the same result as Python 2.x did.
2441 # NOTE: this test is a bit too strong since we can produce different
2442 # bytecode that 2.x will still understand.
2443 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002444 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002445 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002446 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002447
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002448 def test_large_pickles(self):
2449 # Test the correctness of internal buffering routines when handling
2450 # large data.
2451 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002452 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002453 dumped = self.dumps(data, proto)
2454 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002455 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002456 self.assertEqual(loaded, data)
2457
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002458 def test_int_pickling_efficiency(self):
2459 # Test compacity of int representation (see issue #12744)
2460 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002461 with self.subTest(proto=proto):
2462 pickles = [self.dumps(2**n, proto) for n in range(70)]
2463 sizes = list(map(len, pickles))
2464 # the size function is monotonic
2465 self.assertEqual(sorted(sizes), sizes)
2466 if proto >= 2:
2467 for p in pickles:
2468 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002469
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002470 def _check_pickling_with_opcode(self, obj, opcode, proto):
2471 pickled = self.dumps(obj, proto)
2472 self.assertTrue(opcode_in_pickle(opcode, pickled))
2473 unpickled = self.loads(pickled)
2474 self.assertEqual(obj, unpickled)
2475
2476 def test_appends_on_non_lists(self):
2477 # Issue #17720
2478 obj = REX_six([1, 2, 3])
2479 for proto in protocols:
2480 if proto == 0:
2481 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2482 else:
2483 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2484
2485 def test_setitems_on_non_dicts(self):
2486 obj = REX_seven({1: -1, 2: -2, 3: -3})
2487 for proto in protocols:
2488 if proto == 0:
2489 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2490 else:
2491 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2492
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002493 # Exercise framing (proto >= 4) for significant workloads
2494
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002495 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002496 FRAME_SIZE_TARGET = 64 * 1024
2497
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002498 def check_frame_opcodes(self, pickled):
2499 """
2500 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002501
2502 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2503 framed by default and are therefore considered a frame by themselves in
2504 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002505 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002506 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002507 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2508 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002509 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002510 if frame_end is not None:
2511 self.assertLessEqual(pos, frame_end)
2512 if pos == frame_end:
2513 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002514
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002515 if frame_end is not None: # framed
2516 self.assertNotEqual(op.name, 'FRAME')
2517 if op.name in frameless_opcodes:
2518 # Only short bytes and str objects should be written
2519 # in a frame
2520 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2521
2522 else: # not framed
2523 if (op.name == 'FRAME' or
2524 (op.name in frameless_opcodes and
2525 len(arg) > self.FRAME_SIZE_TARGET)):
2526 # Frame or large bytes or str object
2527 if frameless_start is not None:
2528 # Only short data should be written outside of a frame
2529 self.assertLess(pos - frameless_start,
2530 self.FRAME_SIZE_MIN)
2531 frameless_start = None
2532 elif frameless_start is None and op.name != 'PROTO':
2533 frameless_start = pos
2534
2535 if op.name == 'FRAME':
2536 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2537 frame_end = pos + 9 + arg
2538
2539 pos = len(pickled)
2540 if frame_end is not None:
2541 self.assertEqual(frame_end, pos)
2542 elif frameless_start is not None:
2543 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002544
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002545 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002546 def test_framing_many_objects(self):
2547 obj = list(range(10**5))
2548 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2549 with self.subTest(proto=proto):
2550 pickled = self.dumps(obj, proto)
2551 unpickled = self.loads(pickled)
2552 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002553 bytes_per_frame = (len(pickled) /
2554 count_opcode(pickle.FRAME, pickled))
2555 self.assertGreater(bytes_per_frame,
2556 self.FRAME_SIZE_TARGET / 2)
2557 self.assertLessEqual(bytes_per_frame,
2558 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002559 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002560
2561 def test_framing_large_objects(self):
2562 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002563 small_items = [[i] for i in range(10)]
2564 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002565 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002566 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002567 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002568 if not fast:
2569 # fast=False by default.
2570 # This covers in-memory pickling with pickle.dumps().
2571 pickled = self.dumps(obj, proto)
2572 else:
2573 # Pickler is required when fast=True.
2574 if not hasattr(self, 'pickler'):
2575 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002576 buf = io.BytesIO()
2577 pickler = self.pickler(buf, protocol=proto)
2578 pickler.fast = fast
2579 pickler.dump(obj)
2580 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002581 unpickled = self.loads(pickled)
2582 # More informative error message in case of failure.
2583 self.assertEqual([len(x) for x in obj],
2584 [len(x) for x in unpickled])
2585 # Perform full equality check if the lengths match.
2586 self.assertEqual(obj, unpickled)
2587 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002588 # A single frame for small objects between
2589 # first two large objects.
2590 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002591 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002592
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002593 def test_optional_frames(self):
2594 if pickle.HIGHEST_PROTOCOL < 4:
2595 return
2596
2597 def remove_frames(pickled, keep_frame=None):
2598 """Remove frame opcodes from the given pickle."""
2599 frame_starts = []
2600 # 1 byte for the opcode and 8 for the argument
2601 frame_opcode_size = 9
2602 for opcode, _, pos in pickletools.genops(pickled):
2603 if opcode.name == 'FRAME':
2604 frame_starts.append(pos)
2605
2606 newpickle = bytearray()
2607 last_frame_end = 0
2608 for i, pos in enumerate(frame_starts):
2609 if keep_frame and keep_frame(i):
2610 continue
2611 newpickle += pickled[last_frame_end:pos]
2612 last_frame_end = pos + frame_opcode_size
2613 newpickle += pickled[last_frame_end:]
2614 return newpickle
2615
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002616 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002617 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002618 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002619 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002620 for bytes_type in (bytes, bytearray):
2621 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002622
Antoine Pitrou91f43802019-05-26 17:10:09 +02002623 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2624 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002625
Antoine Pitrou91f43802019-05-26 17:10:09 +02002626 frameless_pickle = remove_frames(pickled)
2627 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2628 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002629
Antoine Pitrou91f43802019-05-26 17:10:09 +02002630 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2631 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2632 count_opcode(pickle.FRAME, pickled))
2633 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002634
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002635 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002636 def test_framed_write_sizes_with_delayed_writer(self):
2637 class ChunkAccumulator:
2638 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002639 def __init__(self):
2640 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002641 def write(self, chunk):
2642 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002643 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002644 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002645
2646 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002647 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2648 for i in range(int(1e4))]
2649 # Add a large unique ASCII string
2650 objects.append('0123456789abcdef' *
2651 (self.FRAME_SIZE_TARGET // 16 + 1))
2652
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002653 # Protocol 4 packs groups of small objects into frames and issues
2654 # calls to write only once or twice per frame:
2655 # The C pickler issues one call to write per-frame (header and
2656 # contents) while Python pickler issues two calls to write: one for
2657 # the frame header and one for the frame binary contents.
2658 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002659 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002660
2661 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002662 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002663 # be released otherwise this delayed access would not be possible.
2664 pickled = writer.concatenate_chunks()
2665 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002666 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002667 self.assertGreater(len(writer.chunks), 1)
2668
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002669 # memoryviews should own the memory.
2670 del objects
2671 support.gc_collect()
2672 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002673
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002674 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002675 # There should be at least one call to write per frame
2676 self.assertGreaterEqual(len(writer.chunks), n_frames)
2677
2678 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002679 # one per-frame header, one per frame for the actual contents,
2680 # and two for the header.
2681 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002682
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002683 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002684 large_sizes = [s for s in chunk_sizes
2685 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002686 medium_sizes = [s for s in chunk_sizes
2687 if 9 < s < self.FRAME_SIZE_TARGET]
2688 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002689
2690 # Large chunks should not be too large:
2691 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002692 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2693 chunk_sizes)
2694 # There shouldn't bee too many small chunks: the protocol header,
2695 # the frame headers and the large string headers are written
2696 # in small chunks.
2697 self.assertLessEqual(len(small_sizes),
2698 len(large_sizes) + len(medium_sizes) + 3,
2699 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002700
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002701 def test_nested_names(self):
2702 global Nested
2703 class Nested:
2704 class A:
2705 class B:
2706 class C:
2707 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002708 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002709 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2710 with self.subTest(proto=proto, obj=obj):
2711 unpickled = self.loads(self.dumps(obj, proto))
2712 self.assertIs(obj, unpickled)
2713
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002714 def test_recursive_nested_names(self):
2715 global Recursive
2716 class Recursive:
2717 pass
2718 Recursive.mod = sys.modules[Recursive.__module__]
2719 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2720 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2721 with self.subTest(proto=proto):
2722 unpickled = self.loads(self.dumps(Recursive, proto))
2723 self.assertIs(unpickled, Recursive)
2724 del Recursive.mod # break reference loop
2725
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002726 def test_py_methods(self):
2727 global PyMethodsTest
2728 class PyMethodsTest:
2729 @staticmethod
2730 def cheese():
2731 return "cheese"
2732 @classmethod
2733 def wine(cls):
2734 assert cls is PyMethodsTest
2735 return "wine"
2736 def biscuits(self):
2737 assert isinstance(self, PyMethodsTest)
2738 return "biscuits"
2739 class Nested:
2740 "Nested class"
2741 @staticmethod
2742 def ketchup():
2743 return "ketchup"
2744 @classmethod
2745 def maple(cls):
2746 assert cls is PyMethodsTest.Nested
2747 return "maple"
2748 def pie(self):
2749 assert isinstance(self, PyMethodsTest.Nested)
2750 return "pie"
2751
2752 py_methods = (
2753 PyMethodsTest.cheese,
2754 PyMethodsTest.wine,
2755 PyMethodsTest().biscuits,
2756 PyMethodsTest.Nested.ketchup,
2757 PyMethodsTest.Nested.maple,
2758 PyMethodsTest.Nested().pie
2759 )
2760 py_unbound_methods = (
2761 (PyMethodsTest.biscuits, PyMethodsTest),
2762 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2763 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002764 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002765 for method in py_methods:
2766 with self.subTest(proto=proto, method=method):
2767 unpickled = self.loads(self.dumps(method, proto))
2768 self.assertEqual(method(), unpickled())
2769 for method, cls in py_unbound_methods:
2770 obj = cls()
2771 with self.subTest(proto=proto, method=method):
2772 unpickled = self.loads(self.dumps(method, proto))
2773 self.assertEqual(method(obj), unpickled(obj))
2774
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002775 def test_c_methods(self):
2776 global Subclass
2777 class Subclass(tuple):
2778 class Nested(str):
2779 pass
2780
2781 c_methods = (
2782 # bound built-in method
2783 ("abcd".index, ("c",)),
2784 # unbound built-in method
2785 (str.index, ("abcd", "c")),
2786 # bound "slot" method
2787 ([1, 2, 3].__len__, ()),
2788 # unbound "slot" method
2789 (list.__len__, ([1, 2, 3],)),
2790 # bound "coexist" method
2791 ({1, 2}.__contains__, (2,)),
2792 # unbound "coexist" method
2793 (set.__contains__, ({1, 2}, 2)),
2794 # built-in class method
2795 (dict.fromkeys, (("a", 1), ("b", 2))),
2796 # built-in static method
2797 (bytearray.maketrans, (b"abc", b"xyz")),
2798 # subclass methods
2799 (Subclass([1,2,2]).count, (2,)),
2800 (Subclass.count, (Subclass([1,2,2]), 2)),
2801 (Subclass.Nested("sweet").count, ("e",)),
2802 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2803 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002804 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002805 for method, args in c_methods:
2806 with self.subTest(proto=proto, method=method):
2807 unpickled = self.loads(self.dumps(method, proto))
2808 self.assertEqual(method(*args), unpickled(*args))
2809
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002810 def test_compat_pickle(self):
2811 tests = [
2812 (range(1, 7), '__builtin__', 'xrange'),
2813 (map(int, '123'), 'itertools', 'imap'),
2814 (functools.reduce, '__builtin__', 'reduce'),
2815 (dbm.whichdb, 'whichdb', 'whichdb'),
2816 (Exception(), 'exceptions', 'Exception'),
2817 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2818 (collections.UserList(), 'UserList', 'UserList'),
2819 (collections.defaultdict(), 'collections', 'defaultdict'),
2820 ]
2821 for val, mod, name in tests:
2822 for proto in range(3):
2823 with self.subTest(type=type(val), proto=proto):
2824 pickled = self.dumps(val, proto)
2825 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2826 self.assertIs(type(self.loads(pickled)), type(val))
2827
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002828 def test_local_lookup_error(self):
2829 # Test that whichmodule() errors out cleanly when looking up
2830 # an assumed globally-reachable object fails.
2831 def f():
2832 pass
2833 # Since the function is local, lookup will fail
2834 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2835 with self.assertRaises((AttributeError, pickle.PicklingError)):
2836 pickletools.dis(self.dumps(f, proto))
2837 # Same without a __module__ attribute (exercises a different path
2838 # in _pickle.c).
2839 del f.__module__
2840 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2841 with self.assertRaises((AttributeError, pickle.PicklingError)):
2842 pickletools.dis(self.dumps(f, proto))
2843 # Yet a different path.
2844 f.__name__ = f.__qualname__
2845 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2846 with self.assertRaises((AttributeError, pickle.PicklingError)):
2847 pickletools.dis(self.dumps(f, proto))
2848
Antoine Pitrou91f43802019-05-26 17:10:09 +02002849 #
2850 # PEP 574 tests below
2851 #
2852
2853 def buffer_like_objects(self):
2854 # Yield buffer-like objects with the bytestring "abcdef" in them
2855 bytestring = b"abcdefgh"
2856 yield ZeroCopyBytes(bytestring)
2857 yield ZeroCopyBytearray(bytestring)
2858 if _testbuffer is not None:
2859 items = list(bytestring)
2860 value = int.from_bytes(bytestring, byteorder='little')
2861 for flags in (0, _testbuffer.ND_WRITABLE):
2862 # 1-D, contiguous
2863 yield PicklableNDArray(items, format='B', shape=(8,),
2864 flags=flags)
2865 # 2-D, C-contiguous
2866 yield PicklableNDArray(items, format='B', shape=(4, 2),
2867 strides=(2, 1), flags=flags)
2868 # 2-D, Fortran-contiguous
2869 yield PicklableNDArray(items, format='B',
2870 shape=(4, 2), strides=(1, 4),
2871 flags=flags)
2872
2873 def test_in_band_buffers(self):
2874 # Test in-band buffers (PEP 574)
2875 for obj in self.buffer_like_objects():
2876 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2877 data = self.dumps(obj, proto)
2878 if obj.c_contiguous and proto >= 5:
2879 # The raw memory bytes are serialized in physical order
2880 self.assertIn(b"abcdefgh", data)
2881 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2882 if proto >= 5:
2883 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2884 1 if obj.readonly else 0)
2885 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2886 0 if obj.readonly else 1)
2887 # Return a true value from buffer_callback should have
2888 # the same effect
2889 def buffer_callback(obj):
2890 return True
2891 data2 = self.dumps(obj, proto,
2892 buffer_callback=buffer_callback)
2893 self.assertEqual(data2, data)
2894
2895 new = self.loads(data)
2896 # It's a copy
2897 self.assertIsNot(new, obj)
2898 self.assertIs(type(new), type(obj))
2899 self.assertEqual(new, obj)
2900
2901 # XXX Unfortunately cannot test non-contiguous array
2902 # (see comment in PicklableNDArray.__reduce_ex__)
2903
2904 def test_oob_buffers(self):
2905 # Test out-of-band buffers (PEP 574)
2906 for obj in self.buffer_like_objects():
2907 for proto in range(0, 5):
2908 # Need protocol >= 5 for buffer_callback
2909 with self.assertRaises(ValueError):
2910 self.dumps(obj, proto,
2911 buffer_callback=[].append)
2912 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2913 buffers = []
2914 buffer_callback = lambda pb: buffers.append(pb.raw())
2915 data = self.dumps(obj, proto,
2916 buffer_callback=buffer_callback)
2917 self.assertNotIn(b"abcdefgh", data)
2918 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2919 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2920 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2921 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2922 1 if obj.readonly else 0)
2923
2924 if obj.c_contiguous:
2925 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2926 # Need buffers argument to unpickle properly
2927 with self.assertRaises(pickle.UnpicklingError):
2928 self.loads(data)
2929
2930 new = self.loads(data, buffers=buffers)
2931 if obj.zero_copy_reconstruct:
2932 # Zero-copy achieved
2933 self.assertIs(new, obj)
2934 else:
2935 self.assertIs(type(new), type(obj))
2936 self.assertEqual(new, obj)
2937 # Non-sequence buffers accepted too
2938 new = self.loads(data, buffers=iter(buffers))
2939 if obj.zero_copy_reconstruct:
2940 # Zero-copy achieved
2941 self.assertIs(new, obj)
2942 else:
2943 self.assertIs(type(new), type(obj))
2944 self.assertEqual(new, obj)
2945
2946 def test_oob_buffers_writable_to_readonly(self):
2947 # Test reconstructing readonly object from writable buffer
2948 obj = ZeroCopyBytes(b"foobar")
2949 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2950 buffers = []
2951 buffer_callback = buffers.append
2952 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2953
2954 buffers = map(bytearray, buffers)
2955 new = self.loads(data, buffers=buffers)
2956 self.assertIs(type(new), type(obj))
2957 self.assertEqual(new, obj)
2958
2959 def test_picklebuffer_error(self):
2960 # PickleBuffer forbidden with protocol < 5
2961 pb = pickle.PickleBuffer(b"foobar")
2962 for proto in range(0, 5):
2963 with self.assertRaises(pickle.PickleError):
2964 self.dumps(pb, proto)
2965
2966 def test_buffer_callback_error(self):
2967 def buffer_callback(buffers):
2968 1/0
2969 pb = pickle.PickleBuffer(b"foobar")
2970 with self.assertRaises(ZeroDivisionError):
2971 self.dumps(pb, 5, buffer_callback=buffer_callback)
2972
2973 def test_buffers_error(self):
2974 pb = pickle.PickleBuffer(b"foobar")
2975 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2976 data = self.dumps(pb, proto, buffer_callback=[].append)
2977 # Non iterable buffers
2978 with self.assertRaises(TypeError):
2979 self.loads(data, buffers=object())
2980 # Buffer iterable exhausts too early
2981 with self.assertRaises(pickle.UnpicklingError):
2982 self.loads(data, buffers=[])
2983
Markus Mohrhard898318b2019-07-26 00:00:34 +08002984 def test_inband_accept_default_buffers_argument(self):
2985 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2986 data_pickled = self.dumps(1, proto, buffer_callback=None)
2987 data = self.loads(data_pickled, buffers=None)
2988
Antoine Pitrou91f43802019-05-26 17:10:09 +02002989 @unittest.skipIf(np is None, "Test needs Numpy")
2990 def test_buffers_numpy(self):
2991 def check_no_copy(x, y):
2992 np.testing.assert_equal(x, y)
2993 self.assertEqual(x.ctypes.data, y.ctypes.data)
2994
2995 def check_copy(x, y):
2996 np.testing.assert_equal(x, y)
2997 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2998
2999 def check_array(arr):
3000 # In-band
3001 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3002 data = self.dumps(arr, proto)
3003 new = self.loads(data)
3004 check_copy(arr, new)
3005 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3006 buffer_callback = lambda _: True
3007 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
3008 new = self.loads(data)
3009 check_copy(arr, new)
3010 # Out-of-band
3011 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3012 buffers = []
3013 buffer_callback = buffers.append
3014 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
3015 new = self.loads(data, buffers=buffers)
3016 if arr.flags.c_contiguous or arr.flags.f_contiguous:
3017 check_no_copy(arr, new)
3018 else:
3019 check_copy(arr, new)
3020
3021 # 1-D
3022 arr = np.arange(6)
3023 check_array(arr)
3024 # 1-D, non-contiguous
3025 check_array(arr[::2])
3026 # 2-D, C-contiguous
3027 arr = np.arange(12).reshape((3, 4))
3028 check_array(arr)
3029 # 2-D, F-contiguous
3030 check_array(arr.T)
3031 # 2-D, non-contiguous
3032 check_array(arr[::2])
3033
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003034
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -07003035class BigmemPickleTests:
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003036
Victor Stinner8c663fd2017-11-08 14:44:44 -08003037 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003038
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003039 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003040 def test_huge_long_32b(self, size):
3041 data = 1 << (8 * size)
3042 try:
3043 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003044 if proto < 2:
3045 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003046 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003047 with self.assertRaises((ValueError, OverflowError)):
3048 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003049 finally:
3050 data = None
3051
Victor Stinner8c663fd2017-11-08 14:44:44 -08003052 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003053 # (older protocols don't have a dedicated opcode for bytes and are
3054 # too inefficient)
3055
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003056 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003057 def test_huge_bytes_32b(self, size):
3058 data = b"abcd" * (size // 4)
3059 try:
3060 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003061 if proto < 3:
3062 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003063 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003064 try:
3065 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003066 header = (pickle.BINBYTES +
3067 struct.pack("<I", len(data)))
3068 data_start = pickled.index(data)
3069 self.assertEqual(
3070 header,
3071 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003072 finally:
3073 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003074 finally:
3075 data = None
3076
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003077 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003078 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003079 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003080 try:
3081 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003082 if proto < 3:
3083 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003084 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003085 if proto == 3:
3086 # Protocol 3 does not support large bytes objects.
3087 # Verify that we do not crash when processing one.
3088 with self.assertRaises((ValueError, OverflowError)):
3089 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003090 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003091 try:
3092 pickled = self.dumps(data, protocol=proto)
3093 header = (pickle.BINBYTES8 +
3094 struct.pack("<Q", len(data)))
3095 data_start = pickled.index(data)
3096 self.assertEqual(
3097 header,
3098 pickled[data_start-len(header):data_start])
3099 finally:
3100 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003101 finally:
3102 data = None
3103
3104 # All protocols use 1-byte per printable ASCII character; we add another
3105 # byte because the encoded form has to be copied into the internal buffer.
3106
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003107 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003108 def test_huge_str_32b(self, size):
3109 data = "abcd" * (size // 4)
3110 try:
3111 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003112 if proto == 0:
3113 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003114 with self.subTest(proto=proto):
3115 try:
3116 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003117 header = (pickle.BINUNICODE +
3118 struct.pack("<I", len(data)))
3119 data_start = pickled.index(b'abcd')
3120 self.assertEqual(
3121 header,
3122 pickled[data_start-len(header):data_start])
3123 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
3124 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003125 finally:
3126 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003127 finally:
3128 data = None
3129
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003130 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
3131 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
3132 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02003133
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003134 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003135 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003136 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003137 try:
3138 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003139 if proto == 0:
3140 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003141 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003142 if proto < 4:
3143 with self.assertRaises((ValueError, OverflowError)):
3144 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003145 continue
3146 try:
3147 pickled = self.dumps(data, protocol=proto)
3148 header = (pickle.BINUNICODE8 +
3149 struct.pack("<Q", len(data)))
3150 data_start = pickled.index(b'abcd')
3151 self.assertEqual(
3152 header,
3153 pickled[data_start-len(header):data_start])
3154 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
3155 pickled.index(b"abcd")), len(data))
3156 finally:
3157 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003158 finally:
3159 data = None
3160
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02003161
Guido van Rossum2a30b212003-02-18 22:41:24 +00003162# Test classes for reduce_ex
3163
3164class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003165 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00003166 _reduce_called = 0
3167 def __reduce__(self):
3168 self._reduce_called = 1
3169 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00003170
3171class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003172 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00003173 _proto = None
3174 def __reduce_ex__(self, proto):
3175 self._proto = proto
3176 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00003177
3178class REX_three(object):
3179 _proto = None
3180 def __reduce_ex__(self, proto):
3181 self._proto = proto
3182 return REX_two, ()
3183 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00003184 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00003185
Guido van Rossumd8faa362007-04-27 19:54:29 +00003186class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003187 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003188 _proto = None
3189 def __reduce_ex__(self, proto):
3190 self._proto = proto
3191 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00003192
3193class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003194 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003195 _reduce_called = 0
3196 def __reduce__(self):
3197 self._reduce_called = 1
3198 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003199
3200class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003201 """This class is used to check the 4th argument (list iterator) of
3202 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003203 """
3204 def __init__(self, items=None):
3205 self.items = items if items is not None else []
3206 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003207 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003208 def append(self, item):
3209 self.items.append(item)
3210 def __reduce__(self):
3211 return type(self), (), None, iter(self.items), None
3212
3213class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003214 """This class is used to check the 5th argument (dict iterator) of
3215 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003216 """
3217 def __init__(self, table=None):
3218 self.table = table if table is not None else {}
3219 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003220 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003221 def __setitem__(self, key, value):
3222 self.table[key] = value
3223 def __reduce__(self):
3224 return type(self), (), None, None, iter(self.table.items())
3225
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02003226class REX_state(object):
3227 """This class is used to check the 3th argument (state) of
3228 the reduce protocol.
3229 """
3230 def __init__(self, state=None):
3231 self.state = state
3232 def __eq__(self, other):
3233 return type(self) is type(other) and self.state == other.state
3234 def __setstate__(self, state):
3235 self.state = state
3236 def __reduce__(self):
3237 return type(self), (), self.state
3238
Guido van Rossumd8faa362007-04-27 19:54:29 +00003239
Guido van Rossum2a30b212003-02-18 22:41:24 +00003240# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003241
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003242class MyInt(int):
3243 sample = 1
3244
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003245class MyFloat(float):
3246 sample = 1.0
3247
3248class MyComplex(complex):
3249 sample = 1.0 + 0.0j
3250
3251class MyStr(str):
3252 sample = "hello"
3253
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003254class MyUnicode(str):
3255 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003256
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003257class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003258 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003259
3260class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003261 sample = [1, 2, 3]
3262
3263class MyDict(dict):
3264 sample = {"a": 1, "b": 2}
3265
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003266class MySet(set):
3267 sample = {"a", "b"}
3268
3269class MyFrozenSet(frozenset):
3270 sample = frozenset({"a", "b"})
3271
Mark Dickinson5c2db372009-12-05 20:28:34 +00003272myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003273 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003274 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003275 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003276
Serhiy Storchaka8cd1dba2020-10-24 21:14:23 +03003277class MyIntWithNew(int):
3278 def __new__(cls, value):
3279 raise AssertionError
3280
3281class MyIntWithNew2(MyIntWithNew):
3282 __new__ = int.__new__
3283
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003284
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003285class SlotList(MyList):
3286 __slots__ = ["foo"]
3287
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003288class SimpleNewObj(int):
3289 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003290 # raise an error, to make sure this isn't called
3291 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003292 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003293 return int(self) == int(other) and self.__dict__ == other.__dict__
3294
3295class ComplexNewObj(SimpleNewObj):
3296 def __getnewargs__(self):
3297 return ('%X' % self, 16)
3298
3299class ComplexNewObjEx(SimpleNewObj):
3300 def __getnewargs_ex__(self):
3301 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003302
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003303class BadGetattr:
3304 def __getattr__(self, key):
3305 self.foo
3306
Collin Winter771d8342009-04-16 03:18:06 +00003307
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -07003308class AbstractPickleModuleTests:
Jeremy Hylton66426532001-10-15 21:38:56 +00003309
3310 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003311 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003312 try:
3313 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003314 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003315 finally:
Hai Shi883bc632020-07-06 17:12:49 +08003316 os_helper.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003317
3318 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003319 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003320 try:
3321 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003322 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003323 finally:
Hai Shi883bc632020-07-06 17:12:49 +08003324 os_helper.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003325
Collin Winter771d8342009-04-16 03:18:06 +00003326 def test_load_from_and_dump_to_file(self):
3327 stream = io.BytesIO()
3328 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003329 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003330 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003331 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003332 self.assertEqual(unpickled, data)
3333
Tim Petersc0c93702003-02-13 19:30:57 +00003334 def test_highest_protocol(self):
3335 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003336 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003337
Martin v. Löwis544f1192004-07-27 05:22:33 +00003338 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003339 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003340 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003341 self.dump(123, f, -1)
3342 self.dump(123, file=f, protocol=-1)
3343 self.dumps(123, -1)
3344 self.dumps(123, protocol=-1)
3345 self.Pickler(f, -1)
3346 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003347
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003348 def test_dump_text_file(self):
3349 f = open(TESTFN, "w")
3350 try:
3351 for proto in protocols:
3352 self.assertRaises(TypeError, self.dump, 123, f, proto)
3353 finally:
3354 f.close()
Hai Shi883bc632020-07-06 17:12:49 +08003355 os_helper.unlink(TESTFN)
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003356
3357 def test_incomplete_input(self):
3358 s = io.BytesIO(b"X''.")
3359 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3360
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003361 def test_bad_init(self):
3362 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003363 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003364 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003365 def __init__(self): pass
3366
Serhiy Storchaka65452562017-11-15 14:01:08 +02003367 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003368 def __init__(self): pass
3369
3370 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3371 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3372
Antoine Pitrou91f43802019-05-26 17:10:09 +02003373 def check_dumps_loads_oob_buffers(self, dumps, loads):
3374 # No need to do the full gamut of tests here, just enough to
3375 # check that dumps() and loads() redirect their arguments
3376 # to the underlying Pickler and Unpickler, respectively.
3377 obj = ZeroCopyBytes(b"foo")
3378
3379 for proto in range(0, 5):
3380 # Need protocol >= 5 for buffer_callback
3381 with self.assertRaises(ValueError):
3382 dumps(obj, protocol=proto,
3383 buffer_callback=[].append)
3384 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3385 buffers = []
3386 buffer_callback = buffers.append
3387 data = dumps(obj, protocol=proto,
3388 buffer_callback=buffer_callback)
3389 self.assertNotIn(b"foo", data)
3390 self.assertEqual(bytes(buffers[0]), b"foo")
3391 # Need buffers argument to unpickle properly
3392 with self.assertRaises(pickle.UnpicklingError):
3393 loads(data)
3394 new = loads(data, buffers=buffers)
3395 self.assertIs(new, obj)
3396
3397 def test_dumps_loads_oob_buffers(self):
3398 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3399 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3400
3401 def test_dump_load_oob_buffers(self):
3402 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3403 def dumps(obj, **kwargs):
3404 f = io.BytesIO()
3405 self.dump(obj, f, **kwargs)
3406 return f.getvalue()
3407
3408 def loads(data, **kwargs):
3409 f = io.BytesIO(data)
3410 return self.load(f, **kwargs)
3411
3412 self.check_dumps_loads_oob_buffers(dumps, loads)
3413
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003414
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -07003415class AbstractPersistentPicklerTests:
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003416
3417 # This class defines persistent_id() and persistent_load()
3418 # functions that should be used by the pickler. All even integers
3419 # are pickled using persistent ids.
3420
3421 def persistent_id(self, object):
3422 if isinstance(object, int) and object % 2 == 0:
3423 self.id_count += 1
3424 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003425 elif object == "test_false_value":
3426 self.false_count += 1
3427 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003428 else:
3429 return None
3430
3431 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003432 if not oid:
3433 self.load_false_count += 1
3434 return "test_false_value"
3435 else:
3436 self.load_count += 1
3437 object = int(oid)
3438 assert object % 2 == 0
3439 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003440
3441 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003442 L = list(range(10)) + ["test_false_value"]
3443 for proto in protocols:
3444 self.id_count = 0
3445 self.false_count = 0
3446 self.load_false_count = 0
3447 self.load_count = 0
3448 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3449 self.assertEqual(self.id_count, 5)
3450 self.assertEqual(self.false_count, 1)
3451 self.assertEqual(self.load_count, 5)
3452 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003453
Collin Winter771d8342009-04-16 03:18:06 +00003454
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -07003455class AbstractIdentityPersistentPicklerTests:
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003456
3457 def persistent_id(self, obj):
3458 return obj
3459
3460 def persistent_load(self, pid):
3461 return pid
3462
3463 def _check_return_correct_type(self, obj, proto):
3464 unpickled = self.loads(self.dumps(obj, proto))
3465 self.assertIsInstance(unpickled, type(obj))
3466 self.assertEqual(unpickled, obj)
3467
3468 def test_return_correct_type(self):
3469 for proto in protocols:
3470 # Protocol 0 supports only ASCII strings.
3471 if proto == 0:
3472 self._check_return_correct_type("abc", 0)
3473 else:
3474 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3475 self._check_return_correct_type(obj, proto)
3476
3477 def test_protocol0_is_ascii_only(self):
3478 non_ascii_str = "\N{EMPTY SET}"
3479 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3480 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3481 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3482
3483
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -07003484class AbstractPicklerUnpicklerObjectTests:
Collin Winter771d8342009-04-16 03:18:06 +00003485
3486 pickler_class = None
3487 unpickler_class = None
3488
3489 def setUp(self):
3490 assert self.pickler_class
3491 assert self.unpickler_class
3492
3493 def test_clear_pickler_memo(self):
3494 # To test whether clear_memo() has any effect, we pickle an object,
3495 # then pickle it again without clearing the memo; the two serialized
3496 # forms should be different. If we clear_memo() and then pickle the
3497 # object again, the third serialized form should be identical to the
3498 # first one we obtained.
3499 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003500 for proto in protocols:
3501 f = io.BytesIO()
3502 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003503
Serhiy Storchakac8695292018-04-04 00:11:27 +03003504 pickler.dump(data)
3505 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003506
Serhiy Storchakac8695292018-04-04 00:11:27 +03003507 # Reset BytesIO object.
3508 f.seek(0)
3509 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003510
Serhiy Storchakac8695292018-04-04 00:11:27 +03003511 pickler.dump(data)
3512 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003513
Serhiy Storchakac8695292018-04-04 00:11:27 +03003514 # Reset the Pickler and BytesIO objects.
3515 pickler.clear_memo()
3516 f.seek(0)
3517 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003518
Serhiy Storchakac8695292018-04-04 00:11:27 +03003519 pickler.dump(data)
3520 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003521
Serhiy Storchakac8695292018-04-04 00:11:27 +03003522 self.assertNotEqual(first_pickled, second_pickled)
3523 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003524
3525 def test_priming_pickler_memo(self):
3526 # Verify that we can set the Pickler's memo attribute.
3527 data = ["abcdefg", "abcdefg", 44]
3528 f = io.BytesIO()
3529 pickler = self.pickler_class(f)
3530
3531 pickler.dump(data)
3532 first_pickled = f.getvalue()
3533
3534 f = io.BytesIO()
3535 primed = self.pickler_class(f)
3536 primed.memo = pickler.memo
3537
3538 primed.dump(data)
3539 primed_pickled = f.getvalue()
3540
3541 self.assertNotEqual(first_pickled, primed_pickled)
3542
3543 def test_priming_unpickler_memo(self):
3544 # Verify that we can set the Unpickler's memo attribute.
3545 data = ["abcdefg", "abcdefg", 44]
3546 f = io.BytesIO()
3547 pickler = self.pickler_class(f)
3548
3549 pickler.dump(data)
3550 first_pickled = f.getvalue()
3551
3552 f = io.BytesIO()
3553 primed = self.pickler_class(f)
3554 primed.memo = pickler.memo
3555
3556 primed.dump(data)
3557 primed_pickled = f.getvalue()
3558
3559 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3560 unpickled_data1 = unpickler.load()
3561
3562 self.assertEqual(unpickled_data1, data)
3563
3564 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3565 primed.memo = unpickler.memo
3566 unpickled_data2 = primed.load()
3567
3568 primed.memo.clear()
3569
3570 self.assertEqual(unpickled_data2, data)
3571 self.assertTrue(unpickled_data2 is unpickled_data1)
3572
3573 def test_reusing_unpickler_objects(self):
3574 data1 = ["abcdefg", "abcdefg", 44]
3575 f = io.BytesIO()
3576 pickler = self.pickler_class(f)
3577 pickler.dump(data1)
3578 pickled1 = f.getvalue()
3579
3580 data2 = ["abcdefg", 44, 44]
3581 f = io.BytesIO()
3582 pickler = self.pickler_class(f)
3583 pickler.dump(data2)
3584 pickled2 = f.getvalue()
3585
3586 f = io.BytesIO()
3587 f.write(pickled1)
3588 f.seek(0)
3589 unpickler = self.unpickler_class(f)
3590 self.assertEqual(unpickler.load(), data1)
3591
3592 f.seek(0)
3593 f.truncate()
3594 f.write(pickled2)
3595 f.seek(0)
3596 self.assertEqual(unpickler.load(), data2)
3597
Antoine Pitrou9f378722020-02-23 23:33:53 +01003598 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003599 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003600 with self.subTest(proto=proto):
3601 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3602 f = ioclass()
3603 pickler = self.pickler_class(f, protocol=proto)
3604 pickler.dump(data1)
3605 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003606
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003607 N = 5
3608 f = ioclass(pickled * N)
3609 unpickler = self.unpickler_class(f)
3610 for i in range(N):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003611 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003612 pos = f.tell()
3613 self.assertEqual(unpickler.load(), data1)
Antoine Pitrou9f378722020-02-23 23:33:53 +01003614 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003615 self.assertEqual(f.tell(), pos + len(pickled))
3616 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003617
3618 def test_multiple_unpicklings_seekable(self):
3619 self._check_multiple_unpicklings(io.BytesIO)
3620
3621 def test_multiple_unpicklings_unseekable(self):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003622 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3623
3624 def test_multiple_unpicklings_minimal(self):
3625 # File-like object that doesn't support peek() and readinto()
3626 # (bpo-39681)
3627 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003628
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003629 def test_unpickling_buffering_readline(self):
3630 # Issue #12687: the unpickler's buffering logic could fail with
3631 # text mode opcodes.
3632 data = list(range(10))
3633 for proto in protocols:
3634 for buf_size in range(1, 11):
3635 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3636 pickler = self.pickler_class(f, protocol=proto)
3637 pickler.dump(data)
3638 f.seek(0)
3639 unpickler = self.unpickler_class(f)
3640 self.assertEqual(unpickler.load(), data)
3641
Collin Winter771d8342009-04-16 03:18:06 +00003642
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003643# Tests for dispatch_table attribute
3644
3645REDUCE_A = 'reduce_A'
3646
3647class AAA(object):
3648 def __reduce__(self):
3649 return str, (REDUCE_A,)
3650
3651class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003652 def __init__(self):
3653 # Add an instance attribute to enable state-saving routines at pickling
3654 # time.
3655 self.a = "some attribute"
3656
3657 def __setstate__(self, state):
3658 self.a = "BBB.__setstate__"
3659
3660
3661def setstate_bbb(obj, state):
3662 """Custom state setter for BBB objects
3663
3664 Such callable may be created by other persons than the ones who created the
3665 BBB class. If passed as the state_setter item of a custom reducer, this
3666 allows for custom state setting behavior of BBB objects. One can think of
3667 it as the analogous of list_setitems or dict_setitems but for foreign
3668 classes/functions.
3669 """
3670 obj.a = "custom state_setter"
3671
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003672
Pierre Glaser289f1f82019-05-08 23:08:25 +02003673
3674class AbstractCustomPicklerClass:
3675 """Pickler implementing a reducing hook using reducer_override."""
3676 def reducer_override(self, obj):
3677 obj_name = getattr(obj, "__name__", None)
3678
3679 if obj_name == 'f':
3680 # asking the pickler to save f as 5
3681 return int, (5, )
3682
3683 if obj_name == 'MyClass':
3684 return str, ('some str',)
3685
3686 elif obj_name == 'g':
3687 # in this case, the callback returns an invalid result (not a 2-5
3688 # tuple or a string), the pickler should raise a proper error.
3689 return False
3690
3691 elif obj_name == 'h':
3692 # Simulate a case when the reducer fails. The error should
3693 # be propagated to the original ``dump`` call.
3694 raise ValueError('The reducer just failed')
3695
3696 return NotImplemented
3697
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -07003698class AbstractHookTests:
Pierre Glaser289f1f82019-05-08 23:08:25 +02003699 def test_pickler_hook(self):
3700 # test the ability of a custom, user-defined CPickler subclass to
3701 # override the default reducing routines of any type using the method
3702 # reducer_override
3703
3704 def f():
3705 pass
3706
3707 def g():
3708 pass
3709
3710 def h():
3711 pass
3712
3713 class MyClass:
3714 pass
3715
3716 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3717 with self.subTest(proto=proto):
3718 bio = io.BytesIO()
3719 p = self.pickler_class(bio, proto)
3720
3721 p.dump([f, MyClass, math.log])
3722 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3723
3724 self.assertEqual(new_f, 5)
3725 self.assertEqual(some_str, 'some str')
Christian Clausscfca4a62021-10-07 17:49:47 +02003726 # math.log does not have its usual reducer overridden, so the
Pierre Glaser289f1f82019-05-08 23:08:25 +02003727 # custom reduction callback should silently direct the pickler
3728 # to the default pickling by attribute, by returning
3729 # NotImplemented
3730 self.assertIs(math_log, math.log)
3731
3732 with self.assertRaises(pickle.PicklingError):
3733 p.dump(g)
3734
3735 with self.assertRaisesRegex(
3736 ValueError, 'The reducer just failed'):
3737 p.dump(h)
3738
Pierre Glaser0f2f35e2020-02-02 19:55:21 +01003739 @support.cpython_only
3740 def test_reducer_override_no_reference_cycle(self):
3741 # bpo-39492: reducer_override used to induce a spurious reference cycle
3742 # inside the Pickler object, that could prevent all serialized objects
Christian Clausscfca4a62021-10-07 17:49:47 +02003743 # from being garbage-collected without explicitly invoking gc.collect.
Pierre Glaser0f2f35e2020-02-02 19:55:21 +01003744
3745 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3746 with self.subTest(proto=proto):
3747 def f():
3748 pass
3749
3750 wr = weakref.ref(f)
3751
3752 bio = io.BytesIO()
3753 p = self.pickler_class(bio, proto)
3754 p.dump(f)
3755 new_f = pickle.loads(bio.getvalue())
3756 assert new_f == 5
3757
3758 del p
3759 del f
3760
3761 self.assertIsNone(wr())
3762
Pierre Glaser289f1f82019-05-08 23:08:25 +02003763
Miss Islington (bot)74c6acc2021-09-20 09:19:31 -07003764class AbstractDispatchTableTests:
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003765
3766 def test_default_dispatch_table(self):
3767 # No dispatch_table attribute by default
3768 f = io.BytesIO()
3769 p = self.pickler_class(f, 0)
3770 with self.assertRaises(AttributeError):
3771 p.dispatch_table
3772 self.assertFalse(hasattr(p, 'dispatch_table'))
3773
3774 def test_class_dispatch_table(self):
3775 # A dispatch_table attribute can be specified class-wide
3776 dt = self.get_dispatch_table()
3777
3778 class MyPickler(self.pickler_class):
3779 dispatch_table = dt
3780
3781 def dumps(obj, protocol=None):
3782 f = io.BytesIO()
3783 p = MyPickler(f, protocol)
3784 self.assertEqual(p.dispatch_table, dt)
3785 p.dump(obj)
3786 return f.getvalue()
3787
3788 self._test_dispatch_table(dumps, dt)
3789
3790 def test_instance_dispatch_table(self):
3791 # A dispatch_table attribute can also be specified instance-wide
3792 dt = self.get_dispatch_table()
3793
3794 def dumps(obj, protocol=None):
3795 f = io.BytesIO()
3796 p = self.pickler_class(f, protocol)
3797 p.dispatch_table = dt
3798 self.assertEqual(p.dispatch_table, dt)
3799 p.dump(obj)
3800 return f.getvalue()
3801
3802 self._test_dispatch_table(dumps, dt)
3803
3804 def _test_dispatch_table(self, dumps, dispatch_table):
3805 def custom_load_dump(obj):
3806 return pickle.loads(dumps(obj, 0))
3807
3808 def default_load_dump(obj):
3809 return pickle.loads(pickle.dumps(obj, 0))
3810
3811 # pickling complex numbers using protocol 0 relies on copyreg
3812 # so check pickling a complex number still works
3813 z = 1 + 2j
3814 self.assertEqual(custom_load_dump(z), z)
3815 self.assertEqual(default_load_dump(z), z)
3816
3817 # modify pickling of complex
3818 REDUCE_1 = 'reduce_1'
3819 def reduce_1(obj):
3820 return str, (REDUCE_1,)
3821 dispatch_table[complex] = reduce_1
3822 self.assertEqual(custom_load_dump(z), REDUCE_1)
3823 self.assertEqual(default_load_dump(z), z)
3824
3825 # check picklability of AAA and BBB
3826 a = AAA()
3827 b = BBB()
3828 self.assertEqual(custom_load_dump(a), REDUCE_A)
3829 self.assertIsInstance(custom_load_dump(b), BBB)
3830 self.assertEqual(default_load_dump(a), REDUCE_A)
3831 self.assertIsInstance(default_load_dump(b), BBB)
3832
3833 # modify pickling of BBB
3834 dispatch_table[BBB] = reduce_1
3835 self.assertEqual(custom_load_dump(a), REDUCE_A)
3836 self.assertEqual(custom_load_dump(b), REDUCE_1)
3837 self.assertEqual(default_load_dump(a), REDUCE_A)
3838 self.assertIsInstance(default_load_dump(b), BBB)
3839
3840 # revert pickling of BBB and modify pickling of AAA
3841 REDUCE_2 = 'reduce_2'
3842 def reduce_2(obj):
3843 return str, (REDUCE_2,)
3844 dispatch_table[AAA] = reduce_2
3845 del dispatch_table[BBB]
3846 self.assertEqual(custom_load_dump(a), REDUCE_2)
3847 self.assertIsInstance(custom_load_dump(b), BBB)
3848 self.assertEqual(default_load_dump(a), REDUCE_A)
3849 self.assertIsInstance(default_load_dump(b), BBB)
3850
Pierre Glaser65d98d02019-05-08 21:40:25 +02003851 # End-to-end testing of save_reduce with the state_setter keyword
3852 # argument. This is a dispatch_table test as the primary goal of
3853 # state_setter is to tweak objects reduction behavior.
3854 # In particular, state_setter is useful when the default __setstate__
3855 # behavior is not flexible enough.
3856
3857 # No custom reducer for b has been registered for now, so
3858 # BBB.__setstate__ should be used at unpickling time
3859 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3860
3861 def reduce_bbb(obj):
3862 return BBB, (), obj.__dict__, None, None, setstate_bbb
3863
3864 dispatch_table[BBB] = reduce_bbb
3865
3866 # The custom reducer reduce_bbb includes a state setter, that should
3867 # have priority over BBB.__setstate__
3868 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3869
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003870
Guido van Rossum98297ee2007-11-06 21:34:58 +00003871if __name__ == "__main__":
3872 # Print some stuff that can be used to rewrite DATA{0,1,2}
3873 from pickletools import dis
3874 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003875 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003876 p = pickle.dumps(x, i)
3877 print("DATA{0} = (".format(i))
3878 for j in range(0, len(p), 20):
3879 b = bytes(p[j:j+20])
3880 print(" {0!r}".format(b))
3881 print(")")
3882 print()
3883 print("# Disassembly of DATA{0}".format(i))
3884 print("DATA{0}_DIS = \"\"\"\\".format(i))
3885 dis(p)
3886 print("\"\"\"")
3887 print()