blob: fd05e7af94a1a78df2a5fdeceddf361452557105 [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
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300831class AbstractUnpickleTests(unittest.TestCase):
832 # 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
1444class AbstractPickleTests(unittest.TestCase):
1445 # 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
Jeremy Hylton66426532001-10-15 21:38:56 +00001856 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001857 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001858 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001859 while n:
1860 for expected in (-n, n):
1861 s = self.dumps(expected, proto)
1862 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001863 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001864 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001865
Tim Petersee1a53c2003-02-02 02:57:53 +00001866 def test_long(self):
1867 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001868 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001869 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001870 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001871 for npos in nbase-1, nbase, nbase+1:
1872 for n in npos, -npos:
1873 pickle = self.dumps(n, proto)
1874 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001875 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001876 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1877 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001878 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001879 nbase += nbase << 1000000
1880 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001881 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001882 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001883 # assert_is_copy is very expensive here as it precomputes
1884 # a failure message by computing the repr() of n and got,
1885 # we just do the check ourselves.
1886 self.assertIs(type(got), int)
1887 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001888
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001889 def test_float(self):
1890 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1891 3.14, 263.44582062374053, 6.022e23, 1e30]
1892 test_values = test_values + [-x for x in test_values]
1893 for proto in protocols:
1894 for value in test_values:
1895 pickle = self.dumps(value, proto)
1896 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001897 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001898
Thomas Wouters477c8d52006-05-27 19:21:47 +00001899 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1900 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001901 # make sure that floats are formatted locale independent with proto 0
1902 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001903
Jeremy Hylton66426532001-10-15 21:38:56 +00001904 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001905 for proto in protocols:
1906 inst = AAA()
1907 dumped = self.dumps(inst, proto)
1908 loaded = self.loads(dumped)
1909 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001910
1911 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001912 for proto in protocols:
1913 inst = initarg(1, 2)
1914 dumped = self.dumps(inst, proto)
1915 loaded = self.loads(dumped)
1916 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001917
Guido van Rossum04a86612001-12-19 16:58:54 +00001918 def test_metaclass(self):
1919 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001920 for proto in protocols:
1921 s = self.dumps(a, proto)
1922 b = self.loads(s)
1923 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001924
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001925 def test_dynamic_class(self):
1926 a = create_dynamic_class("my_dynamic_class", (object,))
1927 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1928 for proto in protocols:
1929 s = self.dumps(a, proto)
1930 b = self.loads(s)
1931 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001932 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001933
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001934 def test_structseq(self):
1935 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001936 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001937
1938 t = time.localtime()
1939 for proto in protocols:
1940 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001941 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001942 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001943 t = os.stat(os.curdir)
1944 s = self.dumps(t, proto)
1945 u = self.loads(s)
1946 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001947 if hasattr(os, "statvfs"):
1948 t = os.statvfs(os.curdir)
1949 s = self.dumps(t, proto)
1950 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001951 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001952
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001953 def test_ellipsis(self):
1954 for proto in protocols:
1955 s = self.dumps(..., proto)
1956 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001957 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001958
1959 def test_notimplemented(self):
1960 for proto in protocols:
1961 s = self.dumps(NotImplemented, proto)
1962 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001963 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001964
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001965 def test_singleton_types(self):
1966 # Issue #6477: Test that types of built-in singletons can be pickled.
1967 singletons = [None, ..., NotImplemented]
1968 for singleton in singletons:
1969 for proto in protocols:
1970 s = self.dumps(type(singleton), proto)
1971 u = self.loads(s)
1972 self.assertIs(type(singleton), u)
1973
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001974 # Tests for protocol 2
1975
Tim Peters4190fb82003-02-02 16:09:05 +00001976 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001977 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001978 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001979 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001980 proto_header = pickle.PROTO + bytes([proto])
1981 self.assertTrue(pickled.startswith(proto_header))
1982 else:
1983 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001984
1985 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001986 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001987 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001988 try:
1989 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001990 except ValueError as err:
1991 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001992 else:
1993 self.fail("expected bad protocol number to raise ValueError")
1994
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001995 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001996 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001997 for proto in protocols:
1998 s = self.dumps(x, proto)
1999 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002000 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00002001 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00002002
2003 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00002004 x = 12345678910111213141516178920 << (256*8)
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.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00002010
Guido van Rossum44f0ea52003-01-28 04:14:51 +00002011 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00002012 # Map (proto, len(tuple)) to expected opcode.
2013 expected_opcode = {(0, 0): pickle.TUPLE,
2014 (0, 1): pickle.TUPLE,
2015 (0, 2): pickle.TUPLE,
2016 (0, 3): pickle.TUPLE,
2017 (0, 4): pickle.TUPLE,
2018
2019 (1, 0): pickle.EMPTY_TUPLE,
2020 (1, 1): pickle.TUPLE,
2021 (1, 2): pickle.TUPLE,
2022 (1, 3): pickle.TUPLE,
2023 (1, 4): pickle.TUPLE,
2024
2025 (2, 0): pickle.EMPTY_TUPLE,
2026 (2, 1): pickle.TUPLE1,
2027 (2, 2): pickle.TUPLE2,
2028 (2, 3): pickle.TUPLE3,
2029 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00002030
2031 (3, 0): pickle.EMPTY_TUPLE,
2032 (3, 1): pickle.TUPLE1,
2033 (3, 2): pickle.TUPLE2,
2034 (3, 3): pickle.TUPLE3,
2035 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00002036 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00002037 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00002038 b = (1,)
2039 c = (1, 2)
2040 d = (1, 2, 3)
2041 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00002042 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00002043 for x in a, b, c, d, e:
2044 s = self.dumps(x, proto)
2045 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002046 self.assert_is_copy(x, y)
2047 expected = expected_opcode[min(proto, 3), len(x)]
2048 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00002049
Guido van Rossum7d97d312003-01-28 04:25:27 +00002050 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00002051 # Map (proto, singleton) to expected opcode.
2052 expected_opcode = {(0, None): pickle.NONE,
2053 (1, None): pickle.NONE,
2054 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00002055 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00002056
2057 (0, True): pickle.INT,
2058 (1, True): pickle.INT,
2059 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00002060 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00002061
2062 (0, False): pickle.INT,
2063 (1, False): pickle.INT,
2064 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00002065 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00002066 }
Tim Peters4190fb82003-02-02 16:09:05 +00002067 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00002068 for x in None, False, True:
2069 s = self.dumps(x, proto)
2070 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002071 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002072 expected = expected_opcode[min(proto, 3), x]
2073 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00002074
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002075 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00002076 x = MyTuple([1, 2, 3])
2077 x.foo = 42
2078 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00002079 for proto in protocols:
2080 s = self.dumps(x, proto)
2081 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002082 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002083
2084 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00002085 x = MyList([1, 2, 3])
2086 x.foo = 42
2087 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00002088 for proto in protocols:
2089 s = self.dumps(x, proto)
2090 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002091 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00002092
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002093 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00002094 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002095 for C in myclasses:
2096 B = C.__base__
2097 x = C(C.sample)
2098 x.foo = 42
2099 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002100 y = self.loads(s)
2101 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002102 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00002103 self.assertEqual(B(x), B(y), detail)
2104 self.assertEqual(x.__dict__, y.__dict__, detail)
2105
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01002106 def test_newobj_proxies(self):
2107 # NEWOBJ should use the __class__ rather than the raw type
2108 classes = myclasses[:]
2109 # Cannot create weakproxies to these classes
2110 for c in (MyInt, MyTuple):
2111 classes.remove(c)
2112 for proto in protocols:
2113 for C in classes:
2114 B = C.__base__
2115 x = C(C.sample)
2116 x.foo = 42
2117 p = weakref.proxy(x)
2118 s = self.dumps(p, proto)
2119 y = self.loads(s)
2120 self.assertEqual(type(y), type(x)) # rather than type(p)
2121 detail = (proto, C, B, x, y, type(y))
2122 self.assertEqual(B(x), B(y), detail)
2123 self.assertEqual(x.__dict__, y.__dict__, detail)
2124
Serhiy Storchaka8cd1dba2020-10-24 21:14:23 +03002125 def test_newobj_overridden_new(self):
2126 # Test that Python class with C implemented __new__ is pickleable
2127 for proto in protocols:
2128 x = MyIntWithNew2(1)
2129 x.foo = 42
2130 s = self.dumps(x, proto)
2131 y = self.loads(s)
2132 self.assertIs(type(y), MyIntWithNew2)
2133 self.assertEqual(int(y), 1)
2134 self.assertEqual(y.foo, 42)
2135
Benjamin Peterson80f78a32015-07-02 16:18:38 -05002136 def test_newobj_not_class(self):
2137 # Issue 24552
2138 global SimpleNewObj
2139 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05002140 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05002141 b = self.dumps(o, 4)
2142 try:
2143 SimpleNewObj = 42
2144 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
2145 finally:
2146 SimpleNewObj = save
2147
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00002148 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00002149 # an object of that type. Check that the resulting pickle uses opcode
2150 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00002151
Tim Peters22e71712003-02-03 22:27:38 +00002152 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00002153 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002154 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00002155 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002156 x = MyList([1, 2, 3])
2157 x.foo = 42
2158 x.bar = "hello"
2159
Tim Peters22e71712003-02-03 22:27:38 +00002160 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002161 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002162 self.assertIn(__name__.encode("utf-8"), s1)
2163 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002164 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00002165
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002166 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002167 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002168
Tim Peters22e71712003-02-03 22:27:38 +00002169 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002170 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002171 self.assertNotIn(__name__.encode("utf-8"), s2)
2172 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00002173 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00002174
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002175 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002176 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002177 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00002178 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00002179
2180 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002181 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
2182 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002183
2184 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002185 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
2186 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
2187 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002188
2189 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002190 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
2191 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
2192 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
2193
Tim Peters8d2613a2003-02-11 16:40:16 +00002194 def test_list_chunking(self):
2195 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002196 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002197 for proto in protocols:
2198 s = self.dumps(x, proto)
2199 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002200 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002201 num_appends = count_opcode(pickle.APPENDS, s)
2202 self.assertEqual(num_appends, proto > 0)
2203
2204 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002205 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002206 for proto in protocols:
2207 s = self.dumps(x, proto)
2208 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002209 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002210 num_appends = count_opcode(pickle.APPENDS, s)
2211 if proto == 0:
2212 self.assertEqual(num_appends, 0)
2213 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002214 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002215
2216 def test_dict_chunking(self):
2217 n = 10 # too small to chunk
2218 x = dict.fromkeys(range(n))
2219 for proto in protocols:
2220 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002221 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002222 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002223 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002224 num_setitems = count_opcode(pickle.SETITEMS, s)
2225 self.assertEqual(num_setitems, proto > 0)
2226
2227 n = 2500 # expect at least two chunks when proto > 0
2228 x = dict.fromkeys(range(n))
2229 for proto in protocols:
2230 s = self.dumps(x, proto)
2231 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002232 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002233 num_setitems = count_opcode(pickle.SETITEMS, s)
2234 if proto == 0:
2235 self.assertEqual(num_setitems, 0)
2236 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002237 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002238
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002239 def test_set_chunking(self):
2240 n = 10 # too small to chunk
2241 x = set(range(n))
2242 for proto in protocols:
2243 s = self.dumps(x, proto)
2244 y = self.loads(s)
2245 self.assert_is_copy(x, y)
2246 num_additems = count_opcode(pickle.ADDITEMS, s)
2247 if proto < 4:
2248 self.assertEqual(num_additems, 0)
2249 else:
2250 self.assertEqual(num_additems, 1)
2251
2252 n = 2500 # expect at least two chunks when proto >= 4
2253 x = set(range(n))
2254 for proto in protocols:
2255 s = self.dumps(x, proto)
2256 y = self.loads(s)
2257 self.assert_is_copy(x, y)
2258 num_additems = count_opcode(pickle.ADDITEMS, s)
2259 if proto < 4:
2260 self.assertEqual(num_additems, 0)
2261 else:
2262 self.assertGreaterEqual(num_additems, 2)
2263
Tim Peterse9ef2032003-02-13 18:42:00 +00002264 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002265 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002266 x.abc = 666
2267 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002268 with self.subTest(proto=proto):
2269 s = self.dumps(x, proto)
2270 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002271 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002272 else:
2273 self.assertIn(b'M\xce\xfa', s) # BININT2
2274 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2275 2 <= proto)
2276 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2277 y = self.loads(s) # will raise TypeError if __init__ called
2278 self.assert_is_copy(x, y)
2279
2280 def test_complex_newobj(self):
2281 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2282 x.abc = 666
2283 for proto in protocols:
2284 with self.subTest(proto=proto):
2285 s = self.dumps(x, proto)
2286 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002287 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002288 elif proto < 2:
2289 self.assertIn(b'M\xce\xfa', s) # BININT2
2290 elif proto < 4:
2291 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2292 else:
2293 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2294 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2295 2 <= proto)
2296 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2297 y = self.loads(s) # will raise TypeError if __init__ called
2298 self.assert_is_copy(x, y)
2299
2300 def test_complex_newobj_ex(self):
2301 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2302 x.abc = 666
2303 for proto in protocols:
2304 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002305 s = self.dumps(x, proto)
2306 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002307 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002308 elif proto < 2:
2309 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002310 elif proto < 4:
2311 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002312 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002313 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2314 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2315 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2316 4 <= proto)
2317 y = self.loads(s) # will raise TypeError if __init__ called
2318 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002319
Tim Peters42f08ac2003-02-11 22:43:24 +00002320 def test_newobj_list_slots(self):
2321 x = SlotList([1, 2, 3])
2322 x.foo = 42
2323 x.bar = "hello"
2324 s = self.dumps(x, 2)
2325 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002326 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002327
Guido van Rossum2a30b212003-02-18 22:41:24 +00002328 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002329 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002330 x = REX_one()
2331 self.assertEqual(x._reduce_called, 0)
2332 s = self.dumps(x, proto)
2333 self.assertEqual(x._reduce_called, 1)
2334 y = self.loads(s)
2335 self.assertEqual(y._reduce_called, 0)
2336
2337 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002338 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002339 x = REX_two()
2340 self.assertEqual(x._proto, None)
2341 s = self.dumps(x, proto)
2342 self.assertEqual(x._proto, proto)
2343 y = self.loads(s)
2344 self.assertEqual(y._proto, None)
2345
2346 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002347 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002348 x = REX_three()
2349 self.assertEqual(x._proto, None)
2350 s = self.dumps(x, proto)
2351 self.assertEqual(x._proto, proto)
2352 y = self.loads(s)
2353 self.assertEqual(y._proto, None)
2354
Guido van Rossumd8faa362007-04-27 19:54:29 +00002355 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002356 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002357 x = REX_four()
2358 self.assertEqual(x._proto, None)
2359 s = self.dumps(x, proto)
2360 self.assertEqual(x._proto, proto)
2361 y = self.loads(s)
2362 self.assertEqual(y._proto, proto)
2363
2364 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002365 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002366 x = REX_five()
2367 self.assertEqual(x._reduce_called, 0)
2368 s = self.dumps(x, proto)
2369 self.assertEqual(x._reduce_called, 1)
2370 y = self.loads(s)
2371 self.assertEqual(y._reduce_called, 1)
2372
Brett Cannon31f59292011-02-21 19:29:56 +00002373 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002374 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002375 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002376 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002377 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002378 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002379
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002380 def test_reduce_bad_iterator(self):
2381 # Issue4176: crash when 4th and 5th items of __reduce__()
2382 # are not iterators
2383 class C(object):
2384 def __reduce__(self):
2385 # 4th item is not an iterator
2386 return list, (), None, [], None
2387 class D(object):
2388 def __reduce__(self):
2389 # 5th item is not an iterator
2390 return dict, (), None, None, []
2391
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002392 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002393 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002394 try:
2395 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002396 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002397 pass
2398 try:
2399 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002400 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002401 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002402
Collin Winter771d8342009-04-16 03:18:06 +00002403 def test_many_puts_and_gets(self):
2404 # Test that internal data structures correctly deal with lots of
2405 # puts/gets.
2406 keys = ("aaa" + str(i) for i in range(100))
2407 large_dict = dict((k, [4, 5, 6]) for k in keys)
2408 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2409
2410 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002411 with self.subTest(proto=proto):
2412 dumped = self.dumps(obj, proto)
2413 loaded = self.loads(dumped)
2414 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002415
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002416 def test_attribute_name_interning(self):
2417 # Test that attribute names of pickled objects are interned when
2418 # unpickling.
2419 for proto in protocols:
2420 x = C()
2421 x.foo = 42
2422 x.bar = "hello"
2423 s = self.dumps(x, proto)
2424 y = self.loads(s)
2425 x_keys = sorted(x.__dict__)
2426 y_keys = sorted(y.__dict__)
2427 for x_key, y_key in zip(x_keys, y_keys):
2428 self.assertIs(x_key, y_key)
2429
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002430 def test_pickle_to_2x(self):
2431 # Pickle non-trivial data with protocol 2, expecting that it yields
2432 # the same result as Python 2.x did.
2433 # NOTE: this test is a bit too strong since we can produce different
2434 # bytecode that 2.x will still understand.
2435 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002436 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002437 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002438 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002439
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002440 def test_large_pickles(self):
2441 # Test the correctness of internal buffering routines when handling
2442 # large data.
2443 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002444 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002445 dumped = self.dumps(data, proto)
2446 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002447 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002448 self.assertEqual(loaded, data)
2449
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002450 def test_int_pickling_efficiency(self):
2451 # Test compacity of int representation (see issue #12744)
2452 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002453 with self.subTest(proto=proto):
2454 pickles = [self.dumps(2**n, proto) for n in range(70)]
2455 sizes = list(map(len, pickles))
2456 # the size function is monotonic
2457 self.assertEqual(sorted(sizes), sizes)
2458 if proto >= 2:
2459 for p in pickles:
2460 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002461
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002462 def _check_pickling_with_opcode(self, obj, opcode, proto):
2463 pickled = self.dumps(obj, proto)
2464 self.assertTrue(opcode_in_pickle(opcode, pickled))
2465 unpickled = self.loads(pickled)
2466 self.assertEqual(obj, unpickled)
2467
2468 def test_appends_on_non_lists(self):
2469 # Issue #17720
2470 obj = REX_six([1, 2, 3])
2471 for proto in protocols:
2472 if proto == 0:
2473 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2474 else:
2475 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2476
2477 def test_setitems_on_non_dicts(self):
2478 obj = REX_seven({1: -1, 2: -2, 3: -3})
2479 for proto in protocols:
2480 if proto == 0:
2481 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2482 else:
2483 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2484
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002485 # Exercise framing (proto >= 4) for significant workloads
2486
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002487 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002488 FRAME_SIZE_TARGET = 64 * 1024
2489
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002490 def check_frame_opcodes(self, pickled):
2491 """
2492 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002493
2494 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2495 framed by default and are therefore considered a frame by themselves in
2496 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002497 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002498 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002499 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2500 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002501 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002502 if frame_end is not None:
2503 self.assertLessEqual(pos, frame_end)
2504 if pos == frame_end:
2505 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002506
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002507 if frame_end is not None: # framed
2508 self.assertNotEqual(op.name, 'FRAME')
2509 if op.name in frameless_opcodes:
2510 # Only short bytes and str objects should be written
2511 # in a frame
2512 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2513
2514 else: # not framed
2515 if (op.name == 'FRAME' or
2516 (op.name in frameless_opcodes and
2517 len(arg) > self.FRAME_SIZE_TARGET)):
2518 # Frame or large bytes or str object
2519 if frameless_start is not None:
2520 # Only short data should be written outside of a frame
2521 self.assertLess(pos - frameless_start,
2522 self.FRAME_SIZE_MIN)
2523 frameless_start = None
2524 elif frameless_start is None and op.name != 'PROTO':
2525 frameless_start = pos
2526
2527 if op.name == 'FRAME':
2528 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2529 frame_end = pos + 9 + arg
2530
2531 pos = len(pickled)
2532 if frame_end is not None:
2533 self.assertEqual(frame_end, pos)
2534 elif frameless_start is not None:
2535 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002536
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002537 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002538 def test_framing_many_objects(self):
2539 obj = list(range(10**5))
2540 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2541 with self.subTest(proto=proto):
2542 pickled = self.dumps(obj, proto)
2543 unpickled = self.loads(pickled)
2544 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002545 bytes_per_frame = (len(pickled) /
2546 count_opcode(pickle.FRAME, pickled))
2547 self.assertGreater(bytes_per_frame,
2548 self.FRAME_SIZE_TARGET / 2)
2549 self.assertLessEqual(bytes_per_frame,
2550 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002551 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002552
2553 def test_framing_large_objects(self):
2554 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002555 small_items = [[i] for i in range(10)]
2556 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002557 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002558 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002559 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002560 if not fast:
2561 # fast=False by default.
2562 # This covers in-memory pickling with pickle.dumps().
2563 pickled = self.dumps(obj, proto)
2564 else:
2565 # Pickler is required when fast=True.
2566 if not hasattr(self, 'pickler'):
2567 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002568 buf = io.BytesIO()
2569 pickler = self.pickler(buf, protocol=proto)
2570 pickler.fast = fast
2571 pickler.dump(obj)
2572 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002573 unpickled = self.loads(pickled)
2574 # More informative error message in case of failure.
2575 self.assertEqual([len(x) for x in obj],
2576 [len(x) for x in unpickled])
2577 # Perform full equality check if the lengths match.
2578 self.assertEqual(obj, unpickled)
2579 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002580 # A single frame for small objects between
2581 # first two large objects.
2582 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002583 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002584
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002585 def test_optional_frames(self):
2586 if pickle.HIGHEST_PROTOCOL < 4:
2587 return
2588
2589 def remove_frames(pickled, keep_frame=None):
2590 """Remove frame opcodes from the given pickle."""
2591 frame_starts = []
2592 # 1 byte for the opcode and 8 for the argument
2593 frame_opcode_size = 9
2594 for opcode, _, pos in pickletools.genops(pickled):
2595 if opcode.name == 'FRAME':
2596 frame_starts.append(pos)
2597
2598 newpickle = bytearray()
2599 last_frame_end = 0
2600 for i, pos in enumerate(frame_starts):
2601 if keep_frame and keep_frame(i):
2602 continue
2603 newpickle += pickled[last_frame_end:pos]
2604 last_frame_end = pos + frame_opcode_size
2605 newpickle += pickled[last_frame_end:]
2606 return newpickle
2607
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002608 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002609 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002610 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002611 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002612 for bytes_type in (bytes, bytearray):
2613 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002614
Antoine Pitrou91f43802019-05-26 17:10:09 +02002615 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2616 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002617
Antoine Pitrou91f43802019-05-26 17:10:09 +02002618 frameless_pickle = remove_frames(pickled)
2619 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2620 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002621
Antoine Pitrou91f43802019-05-26 17:10:09 +02002622 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2623 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2624 count_opcode(pickle.FRAME, pickled))
2625 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002626
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002627 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002628 def test_framed_write_sizes_with_delayed_writer(self):
2629 class ChunkAccumulator:
2630 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002631 def __init__(self):
2632 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002633 def write(self, chunk):
2634 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002635 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002636 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002637
2638 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002639 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2640 for i in range(int(1e4))]
2641 # Add a large unique ASCII string
2642 objects.append('0123456789abcdef' *
2643 (self.FRAME_SIZE_TARGET // 16 + 1))
2644
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002645 # Protocol 4 packs groups of small objects into frames and issues
2646 # calls to write only once or twice per frame:
2647 # The C pickler issues one call to write per-frame (header and
2648 # contents) while Python pickler issues two calls to write: one for
2649 # the frame header and one for the frame binary contents.
2650 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002651 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002652
2653 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002654 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002655 # be released otherwise this delayed access would not be possible.
2656 pickled = writer.concatenate_chunks()
2657 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002658 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002659 self.assertGreater(len(writer.chunks), 1)
2660
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002661 # memoryviews should own the memory.
2662 del objects
2663 support.gc_collect()
2664 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002665
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002666 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002667 # There should be at least one call to write per frame
2668 self.assertGreaterEqual(len(writer.chunks), n_frames)
2669
2670 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002671 # one per-frame header, one per frame for the actual contents,
2672 # and two for the header.
2673 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002674
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002675 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002676 large_sizes = [s for s in chunk_sizes
2677 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002678 medium_sizes = [s for s in chunk_sizes
2679 if 9 < s < self.FRAME_SIZE_TARGET]
2680 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002681
2682 # Large chunks should not be too large:
2683 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002684 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2685 chunk_sizes)
2686 # There shouldn't bee too many small chunks: the protocol header,
2687 # the frame headers and the large string headers are written
2688 # in small chunks.
2689 self.assertLessEqual(len(small_sizes),
2690 len(large_sizes) + len(medium_sizes) + 3,
2691 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002692
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002693 def test_nested_names(self):
2694 global Nested
2695 class Nested:
2696 class A:
2697 class B:
2698 class C:
2699 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002700 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002701 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2702 with self.subTest(proto=proto, obj=obj):
2703 unpickled = self.loads(self.dumps(obj, proto))
2704 self.assertIs(obj, unpickled)
2705
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002706 def test_recursive_nested_names(self):
2707 global Recursive
2708 class Recursive:
2709 pass
2710 Recursive.mod = sys.modules[Recursive.__module__]
2711 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2712 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2713 with self.subTest(proto=proto):
2714 unpickled = self.loads(self.dumps(Recursive, proto))
2715 self.assertIs(unpickled, Recursive)
2716 del Recursive.mod # break reference loop
2717
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002718 def test_py_methods(self):
2719 global PyMethodsTest
2720 class PyMethodsTest:
2721 @staticmethod
2722 def cheese():
2723 return "cheese"
2724 @classmethod
2725 def wine(cls):
2726 assert cls is PyMethodsTest
2727 return "wine"
2728 def biscuits(self):
2729 assert isinstance(self, PyMethodsTest)
2730 return "biscuits"
2731 class Nested:
2732 "Nested class"
2733 @staticmethod
2734 def ketchup():
2735 return "ketchup"
2736 @classmethod
2737 def maple(cls):
2738 assert cls is PyMethodsTest.Nested
2739 return "maple"
2740 def pie(self):
2741 assert isinstance(self, PyMethodsTest.Nested)
2742 return "pie"
2743
2744 py_methods = (
2745 PyMethodsTest.cheese,
2746 PyMethodsTest.wine,
2747 PyMethodsTest().biscuits,
2748 PyMethodsTest.Nested.ketchup,
2749 PyMethodsTest.Nested.maple,
2750 PyMethodsTest.Nested().pie
2751 )
2752 py_unbound_methods = (
2753 (PyMethodsTest.biscuits, PyMethodsTest),
2754 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2755 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002756 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002757 for method in py_methods:
2758 with self.subTest(proto=proto, method=method):
2759 unpickled = self.loads(self.dumps(method, proto))
2760 self.assertEqual(method(), unpickled())
2761 for method, cls in py_unbound_methods:
2762 obj = cls()
2763 with self.subTest(proto=proto, method=method):
2764 unpickled = self.loads(self.dumps(method, proto))
2765 self.assertEqual(method(obj), unpickled(obj))
2766
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002767 def test_c_methods(self):
2768 global Subclass
2769 class Subclass(tuple):
2770 class Nested(str):
2771 pass
2772
2773 c_methods = (
2774 # bound built-in method
2775 ("abcd".index, ("c",)),
2776 # unbound built-in method
2777 (str.index, ("abcd", "c")),
2778 # bound "slot" method
2779 ([1, 2, 3].__len__, ()),
2780 # unbound "slot" method
2781 (list.__len__, ([1, 2, 3],)),
2782 # bound "coexist" method
2783 ({1, 2}.__contains__, (2,)),
2784 # unbound "coexist" method
2785 (set.__contains__, ({1, 2}, 2)),
2786 # built-in class method
2787 (dict.fromkeys, (("a", 1), ("b", 2))),
2788 # built-in static method
2789 (bytearray.maketrans, (b"abc", b"xyz")),
2790 # subclass methods
2791 (Subclass([1,2,2]).count, (2,)),
2792 (Subclass.count, (Subclass([1,2,2]), 2)),
2793 (Subclass.Nested("sweet").count, ("e",)),
2794 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2795 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002796 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002797 for method, args in c_methods:
2798 with self.subTest(proto=proto, method=method):
2799 unpickled = self.loads(self.dumps(method, proto))
2800 self.assertEqual(method(*args), unpickled(*args))
2801
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002802 def test_compat_pickle(self):
2803 tests = [
2804 (range(1, 7), '__builtin__', 'xrange'),
2805 (map(int, '123'), 'itertools', 'imap'),
2806 (functools.reduce, '__builtin__', 'reduce'),
2807 (dbm.whichdb, 'whichdb', 'whichdb'),
2808 (Exception(), 'exceptions', 'Exception'),
2809 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2810 (collections.UserList(), 'UserList', 'UserList'),
2811 (collections.defaultdict(), 'collections', 'defaultdict'),
2812 ]
2813 for val, mod, name in tests:
2814 for proto in range(3):
2815 with self.subTest(type=type(val), proto=proto):
2816 pickled = self.dumps(val, proto)
2817 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2818 self.assertIs(type(self.loads(pickled)), type(val))
2819
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002820 def test_local_lookup_error(self):
2821 # Test that whichmodule() errors out cleanly when looking up
2822 # an assumed globally-reachable object fails.
2823 def f():
2824 pass
2825 # Since the function is local, lookup will fail
2826 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2827 with self.assertRaises((AttributeError, pickle.PicklingError)):
2828 pickletools.dis(self.dumps(f, proto))
2829 # Same without a __module__ attribute (exercises a different path
2830 # in _pickle.c).
2831 del f.__module__
2832 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2833 with self.assertRaises((AttributeError, pickle.PicklingError)):
2834 pickletools.dis(self.dumps(f, proto))
2835 # Yet a different path.
2836 f.__name__ = f.__qualname__
2837 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2838 with self.assertRaises((AttributeError, pickle.PicklingError)):
2839 pickletools.dis(self.dumps(f, proto))
2840
Antoine Pitrou91f43802019-05-26 17:10:09 +02002841 #
2842 # PEP 574 tests below
2843 #
2844
2845 def buffer_like_objects(self):
2846 # Yield buffer-like objects with the bytestring "abcdef" in them
2847 bytestring = b"abcdefgh"
2848 yield ZeroCopyBytes(bytestring)
2849 yield ZeroCopyBytearray(bytestring)
2850 if _testbuffer is not None:
2851 items = list(bytestring)
2852 value = int.from_bytes(bytestring, byteorder='little')
2853 for flags in (0, _testbuffer.ND_WRITABLE):
2854 # 1-D, contiguous
2855 yield PicklableNDArray(items, format='B', shape=(8,),
2856 flags=flags)
2857 # 2-D, C-contiguous
2858 yield PicklableNDArray(items, format='B', shape=(4, 2),
2859 strides=(2, 1), flags=flags)
2860 # 2-D, Fortran-contiguous
2861 yield PicklableNDArray(items, format='B',
2862 shape=(4, 2), strides=(1, 4),
2863 flags=flags)
2864
2865 def test_in_band_buffers(self):
2866 # Test in-band buffers (PEP 574)
2867 for obj in self.buffer_like_objects():
2868 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2869 data = self.dumps(obj, proto)
2870 if obj.c_contiguous and proto >= 5:
2871 # The raw memory bytes are serialized in physical order
2872 self.assertIn(b"abcdefgh", data)
2873 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2874 if proto >= 5:
2875 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2876 1 if obj.readonly else 0)
2877 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2878 0 if obj.readonly else 1)
2879 # Return a true value from buffer_callback should have
2880 # the same effect
2881 def buffer_callback(obj):
2882 return True
2883 data2 = self.dumps(obj, proto,
2884 buffer_callback=buffer_callback)
2885 self.assertEqual(data2, data)
2886
2887 new = self.loads(data)
2888 # It's a copy
2889 self.assertIsNot(new, obj)
2890 self.assertIs(type(new), type(obj))
2891 self.assertEqual(new, obj)
2892
2893 # XXX Unfortunately cannot test non-contiguous array
2894 # (see comment in PicklableNDArray.__reduce_ex__)
2895
2896 def test_oob_buffers(self):
2897 # Test out-of-band buffers (PEP 574)
2898 for obj in self.buffer_like_objects():
2899 for proto in range(0, 5):
2900 # Need protocol >= 5 for buffer_callback
2901 with self.assertRaises(ValueError):
2902 self.dumps(obj, proto,
2903 buffer_callback=[].append)
2904 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2905 buffers = []
2906 buffer_callback = lambda pb: buffers.append(pb.raw())
2907 data = self.dumps(obj, proto,
2908 buffer_callback=buffer_callback)
2909 self.assertNotIn(b"abcdefgh", data)
2910 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2911 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2912 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2913 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2914 1 if obj.readonly else 0)
2915
2916 if obj.c_contiguous:
2917 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2918 # Need buffers argument to unpickle properly
2919 with self.assertRaises(pickle.UnpicklingError):
2920 self.loads(data)
2921
2922 new = self.loads(data, buffers=buffers)
2923 if obj.zero_copy_reconstruct:
2924 # Zero-copy achieved
2925 self.assertIs(new, obj)
2926 else:
2927 self.assertIs(type(new), type(obj))
2928 self.assertEqual(new, obj)
2929 # Non-sequence buffers accepted too
2930 new = self.loads(data, buffers=iter(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
2938 def test_oob_buffers_writable_to_readonly(self):
2939 # Test reconstructing readonly object from writable buffer
2940 obj = ZeroCopyBytes(b"foobar")
2941 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2942 buffers = []
2943 buffer_callback = buffers.append
2944 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2945
2946 buffers = map(bytearray, buffers)
2947 new = self.loads(data, buffers=buffers)
2948 self.assertIs(type(new), type(obj))
2949 self.assertEqual(new, obj)
2950
2951 def test_picklebuffer_error(self):
2952 # PickleBuffer forbidden with protocol < 5
2953 pb = pickle.PickleBuffer(b"foobar")
2954 for proto in range(0, 5):
2955 with self.assertRaises(pickle.PickleError):
2956 self.dumps(pb, proto)
2957
2958 def test_buffer_callback_error(self):
2959 def buffer_callback(buffers):
2960 1/0
2961 pb = pickle.PickleBuffer(b"foobar")
2962 with self.assertRaises(ZeroDivisionError):
2963 self.dumps(pb, 5, buffer_callback=buffer_callback)
2964
2965 def test_buffers_error(self):
2966 pb = pickle.PickleBuffer(b"foobar")
2967 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2968 data = self.dumps(pb, proto, buffer_callback=[].append)
2969 # Non iterable buffers
2970 with self.assertRaises(TypeError):
2971 self.loads(data, buffers=object())
2972 # Buffer iterable exhausts too early
2973 with self.assertRaises(pickle.UnpicklingError):
2974 self.loads(data, buffers=[])
2975
Markus Mohrhard898318b2019-07-26 00:00:34 +08002976 def test_inband_accept_default_buffers_argument(self):
2977 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2978 data_pickled = self.dumps(1, proto, buffer_callback=None)
2979 data = self.loads(data_pickled, buffers=None)
2980
Antoine Pitrou91f43802019-05-26 17:10:09 +02002981 @unittest.skipIf(np is None, "Test needs Numpy")
2982 def test_buffers_numpy(self):
2983 def check_no_copy(x, y):
2984 np.testing.assert_equal(x, y)
2985 self.assertEqual(x.ctypes.data, y.ctypes.data)
2986
2987 def check_copy(x, y):
2988 np.testing.assert_equal(x, y)
2989 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2990
2991 def check_array(arr):
2992 # In-band
2993 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2994 data = self.dumps(arr, proto)
2995 new = self.loads(data)
2996 check_copy(arr, new)
2997 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2998 buffer_callback = lambda _: True
2999 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
3000 new = self.loads(data)
3001 check_copy(arr, new)
3002 # Out-of-band
3003 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3004 buffers = []
3005 buffer_callback = buffers.append
3006 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
3007 new = self.loads(data, buffers=buffers)
3008 if arr.flags.c_contiguous or arr.flags.f_contiguous:
3009 check_no_copy(arr, new)
3010 else:
3011 check_copy(arr, new)
3012
3013 # 1-D
3014 arr = np.arange(6)
3015 check_array(arr)
3016 # 1-D, non-contiguous
3017 check_array(arr[::2])
3018 # 2-D, C-contiguous
3019 arr = np.arange(12).reshape((3, 4))
3020 check_array(arr)
3021 # 2-D, F-contiguous
3022 check_array(arr.T)
3023 # 2-D, non-contiguous
3024 check_array(arr[::2])
3025
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003026
3027class BigmemPickleTests(unittest.TestCase):
3028
Victor Stinner8c663fd2017-11-08 14:44:44 -08003029 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003030
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003031 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003032 def test_huge_long_32b(self, size):
3033 data = 1 << (8 * size)
3034 try:
3035 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003036 if proto < 2:
3037 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003038 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003039 with self.assertRaises((ValueError, OverflowError)):
3040 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003041 finally:
3042 data = None
3043
Victor Stinner8c663fd2017-11-08 14:44:44 -08003044 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003045 # (older protocols don't have a dedicated opcode for bytes and are
3046 # too inefficient)
3047
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003048 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003049 def test_huge_bytes_32b(self, size):
3050 data = b"abcd" * (size // 4)
3051 try:
3052 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003053 if proto < 3:
3054 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003055 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003056 try:
3057 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003058 header = (pickle.BINBYTES +
3059 struct.pack("<I", len(data)))
3060 data_start = pickled.index(data)
3061 self.assertEqual(
3062 header,
3063 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003064 finally:
3065 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003066 finally:
3067 data = None
3068
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003069 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003070 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003071 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003072 try:
3073 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003074 if proto < 3:
3075 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003076 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003077 if proto == 3:
3078 # Protocol 3 does not support large bytes objects.
3079 # Verify that we do not crash when processing one.
3080 with self.assertRaises((ValueError, OverflowError)):
3081 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003082 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003083 try:
3084 pickled = self.dumps(data, protocol=proto)
3085 header = (pickle.BINBYTES8 +
3086 struct.pack("<Q", len(data)))
3087 data_start = pickled.index(data)
3088 self.assertEqual(
3089 header,
3090 pickled[data_start-len(header):data_start])
3091 finally:
3092 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003093 finally:
3094 data = None
3095
3096 # All protocols use 1-byte per printable ASCII character; we add another
3097 # byte because the encoded form has to be copied into the internal buffer.
3098
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003099 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003100 def test_huge_str_32b(self, size):
3101 data = "abcd" * (size // 4)
3102 try:
3103 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003104 if proto == 0:
3105 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003106 with self.subTest(proto=proto):
3107 try:
3108 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003109 header = (pickle.BINUNICODE +
3110 struct.pack("<I", len(data)))
3111 data_start = pickled.index(b'abcd')
3112 self.assertEqual(
3113 header,
3114 pickled[data_start-len(header):data_start])
3115 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
3116 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003117 finally:
3118 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003119 finally:
3120 data = None
3121
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003122 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
3123 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
3124 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02003125
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02003126 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003127 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003128 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003129 try:
3130 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003131 if proto == 0:
3132 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003133 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003134 if proto < 4:
3135 with self.assertRaises((ValueError, OverflowError)):
3136 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08003137 continue
3138 try:
3139 pickled = self.dumps(data, protocol=proto)
3140 header = (pickle.BINUNICODE8 +
3141 struct.pack("<Q", len(data)))
3142 data_start = pickled.index(b'abcd')
3143 self.assertEqual(
3144 header,
3145 pickled[data_start-len(header):data_start])
3146 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
3147 pickled.index(b"abcd")), len(data))
3148 finally:
3149 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02003150 finally:
3151 data = None
3152
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02003153
Guido van Rossum2a30b212003-02-18 22:41:24 +00003154# Test classes for reduce_ex
3155
3156class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003157 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00003158 _reduce_called = 0
3159 def __reduce__(self):
3160 self._reduce_called = 1
3161 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00003162
3163class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003164 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00003165 _proto = None
3166 def __reduce_ex__(self, proto):
3167 self._proto = proto
3168 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00003169
3170class REX_three(object):
3171 _proto = None
3172 def __reduce_ex__(self, proto):
3173 self._proto = proto
3174 return REX_two, ()
3175 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00003176 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00003177
Guido van Rossumd8faa362007-04-27 19:54:29 +00003178class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003179 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003180 _proto = None
3181 def __reduce_ex__(self, proto):
3182 self._proto = proto
3183 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00003184
3185class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003186 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003187 _reduce_called = 0
3188 def __reduce__(self):
3189 self._reduce_called = 1
3190 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003191
3192class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003193 """This class is used to check the 4th argument (list iterator) of
3194 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003195 """
3196 def __init__(self, items=None):
3197 self.items = items if items is not None else []
3198 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003199 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003200 def append(self, item):
3201 self.items.append(item)
3202 def __reduce__(self):
3203 return type(self), (), None, iter(self.items), None
3204
3205class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003206 """This class is used to check the 5th argument (dict iterator) of
3207 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003208 """
3209 def __init__(self, table=None):
3210 self.table = table if table is not None else {}
3211 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003212 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003213 def __setitem__(self, key, value):
3214 self.table[key] = value
3215 def __reduce__(self):
3216 return type(self), (), None, None, iter(self.table.items())
3217
Serhiy Storchakaa25011b2021-01-02 19:32:47 +02003218class REX_state(object):
3219 """This class is used to check the 3th argument (state) of
3220 the reduce protocol.
3221 """
3222 def __init__(self, state=None):
3223 self.state = state
3224 def __eq__(self, other):
3225 return type(self) is type(other) and self.state == other.state
3226 def __setstate__(self, state):
3227 self.state = state
3228 def __reduce__(self):
3229 return type(self), (), self.state
3230
Guido van Rossumd8faa362007-04-27 19:54:29 +00003231
Guido van Rossum2a30b212003-02-18 22:41:24 +00003232# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003233
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003234class MyInt(int):
3235 sample = 1
3236
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003237class MyFloat(float):
3238 sample = 1.0
3239
3240class MyComplex(complex):
3241 sample = 1.0 + 0.0j
3242
3243class MyStr(str):
3244 sample = "hello"
3245
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003246class MyUnicode(str):
3247 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003248
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003249class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003250 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003251
3252class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003253 sample = [1, 2, 3]
3254
3255class MyDict(dict):
3256 sample = {"a": 1, "b": 2}
3257
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003258class MySet(set):
3259 sample = {"a", "b"}
3260
3261class MyFrozenSet(frozenset):
3262 sample = frozenset({"a", "b"})
3263
Mark Dickinson5c2db372009-12-05 20:28:34 +00003264myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003265 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003266 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003267 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003268
Serhiy Storchaka8cd1dba2020-10-24 21:14:23 +03003269class MyIntWithNew(int):
3270 def __new__(cls, value):
3271 raise AssertionError
3272
3273class MyIntWithNew2(MyIntWithNew):
3274 __new__ = int.__new__
3275
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003276
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003277class SlotList(MyList):
3278 __slots__ = ["foo"]
3279
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003280class SimpleNewObj(int):
3281 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003282 # raise an error, to make sure this isn't called
3283 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003284 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003285 return int(self) == int(other) and self.__dict__ == other.__dict__
3286
3287class ComplexNewObj(SimpleNewObj):
3288 def __getnewargs__(self):
3289 return ('%X' % self, 16)
3290
3291class ComplexNewObjEx(SimpleNewObj):
3292 def __getnewargs_ex__(self):
3293 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003294
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003295class BadGetattr:
3296 def __getattr__(self, key):
3297 self.foo
3298
Collin Winter771d8342009-04-16 03:18:06 +00003299
Jeremy Hylton66426532001-10-15 21:38:56 +00003300class AbstractPickleModuleTests(unittest.TestCase):
3301
3302 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003303 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003304 try:
3305 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003306 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003307 finally:
Hai Shi883bc632020-07-06 17:12:49 +08003308 os_helper.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003309
3310 def test_load_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 Hylton4c8be852002-11-13 22:10:47 +00003317
Collin Winter771d8342009-04-16 03:18:06 +00003318 def test_load_from_and_dump_to_file(self):
3319 stream = io.BytesIO()
3320 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003321 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003322 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003323 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003324 self.assertEqual(unpickled, data)
3325
Tim Petersc0c93702003-02-13 19:30:57 +00003326 def test_highest_protocol(self):
3327 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003328 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003329
Martin v. Löwis544f1192004-07-27 05:22:33 +00003330 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003331 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003332 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003333 self.dump(123, f, -1)
3334 self.dump(123, file=f, protocol=-1)
3335 self.dumps(123, -1)
3336 self.dumps(123, protocol=-1)
3337 self.Pickler(f, -1)
3338 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003339
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003340 def test_dump_text_file(self):
3341 f = open(TESTFN, "w")
3342 try:
3343 for proto in protocols:
3344 self.assertRaises(TypeError, self.dump, 123, f, proto)
3345 finally:
3346 f.close()
Hai Shi883bc632020-07-06 17:12:49 +08003347 os_helper.unlink(TESTFN)
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003348
3349 def test_incomplete_input(self):
3350 s = io.BytesIO(b"X''.")
3351 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3352
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003353 def test_bad_init(self):
3354 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003355 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003356 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003357 def __init__(self): pass
3358
Serhiy Storchaka65452562017-11-15 14:01:08 +02003359 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003360 def __init__(self): pass
3361
3362 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3363 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3364
Antoine Pitrou91f43802019-05-26 17:10:09 +02003365 def check_dumps_loads_oob_buffers(self, dumps, loads):
3366 # No need to do the full gamut of tests here, just enough to
3367 # check that dumps() and loads() redirect their arguments
3368 # to the underlying Pickler and Unpickler, respectively.
3369 obj = ZeroCopyBytes(b"foo")
3370
3371 for proto in range(0, 5):
3372 # Need protocol >= 5 for buffer_callback
3373 with self.assertRaises(ValueError):
3374 dumps(obj, protocol=proto,
3375 buffer_callback=[].append)
3376 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3377 buffers = []
3378 buffer_callback = buffers.append
3379 data = dumps(obj, protocol=proto,
3380 buffer_callback=buffer_callback)
3381 self.assertNotIn(b"foo", data)
3382 self.assertEqual(bytes(buffers[0]), b"foo")
3383 # Need buffers argument to unpickle properly
3384 with self.assertRaises(pickle.UnpicklingError):
3385 loads(data)
3386 new = loads(data, buffers=buffers)
3387 self.assertIs(new, obj)
3388
3389 def test_dumps_loads_oob_buffers(self):
3390 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3391 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3392
3393 def test_dump_load_oob_buffers(self):
3394 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3395 def dumps(obj, **kwargs):
3396 f = io.BytesIO()
3397 self.dump(obj, f, **kwargs)
3398 return f.getvalue()
3399
3400 def loads(data, **kwargs):
3401 f = io.BytesIO(data)
3402 return self.load(f, **kwargs)
3403
3404 self.check_dumps_loads_oob_buffers(dumps, loads)
3405
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003406
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003407class AbstractPersistentPicklerTests(unittest.TestCase):
3408
3409 # This class defines persistent_id() and persistent_load()
3410 # functions that should be used by the pickler. All even integers
3411 # are pickled using persistent ids.
3412
3413 def persistent_id(self, object):
3414 if isinstance(object, int) and object % 2 == 0:
3415 self.id_count += 1
3416 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003417 elif object == "test_false_value":
3418 self.false_count += 1
3419 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003420 else:
3421 return None
3422
3423 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003424 if not oid:
3425 self.load_false_count += 1
3426 return "test_false_value"
3427 else:
3428 self.load_count += 1
3429 object = int(oid)
3430 assert object % 2 == 0
3431 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003432
3433 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003434 L = list(range(10)) + ["test_false_value"]
3435 for proto in protocols:
3436 self.id_count = 0
3437 self.false_count = 0
3438 self.load_false_count = 0
3439 self.load_count = 0
3440 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3441 self.assertEqual(self.id_count, 5)
3442 self.assertEqual(self.false_count, 1)
3443 self.assertEqual(self.load_count, 5)
3444 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003445
Collin Winter771d8342009-04-16 03:18:06 +00003446
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003447class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3448
3449 def persistent_id(self, obj):
3450 return obj
3451
3452 def persistent_load(self, pid):
3453 return pid
3454
3455 def _check_return_correct_type(self, obj, proto):
3456 unpickled = self.loads(self.dumps(obj, proto))
3457 self.assertIsInstance(unpickled, type(obj))
3458 self.assertEqual(unpickled, obj)
3459
3460 def test_return_correct_type(self):
3461 for proto in protocols:
3462 # Protocol 0 supports only ASCII strings.
3463 if proto == 0:
3464 self._check_return_correct_type("abc", 0)
3465 else:
3466 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3467 self._check_return_correct_type(obj, proto)
3468
3469 def test_protocol0_is_ascii_only(self):
3470 non_ascii_str = "\N{EMPTY SET}"
3471 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3472 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3473 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3474
3475
Collin Winter771d8342009-04-16 03:18:06 +00003476class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3477
3478 pickler_class = None
3479 unpickler_class = None
3480
3481 def setUp(self):
3482 assert self.pickler_class
3483 assert self.unpickler_class
3484
3485 def test_clear_pickler_memo(self):
3486 # To test whether clear_memo() has any effect, we pickle an object,
3487 # then pickle it again without clearing the memo; the two serialized
3488 # forms should be different. If we clear_memo() and then pickle the
3489 # object again, the third serialized form should be identical to the
3490 # first one we obtained.
3491 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003492 for proto in protocols:
3493 f = io.BytesIO()
3494 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003495
Serhiy Storchakac8695292018-04-04 00:11:27 +03003496 pickler.dump(data)
3497 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003498
Serhiy Storchakac8695292018-04-04 00:11:27 +03003499 # Reset BytesIO object.
3500 f.seek(0)
3501 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003502
Serhiy Storchakac8695292018-04-04 00:11:27 +03003503 pickler.dump(data)
3504 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003505
Serhiy Storchakac8695292018-04-04 00:11:27 +03003506 # Reset the Pickler and BytesIO objects.
3507 pickler.clear_memo()
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 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003513
Serhiy Storchakac8695292018-04-04 00:11:27 +03003514 self.assertNotEqual(first_pickled, second_pickled)
3515 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003516
3517 def test_priming_pickler_memo(self):
3518 # Verify that we can set the Pickler's memo attribute.
3519 data = ["abcdefg", "abcdefg", 44]
3520 f = io.BytesIO()
3521 pickler = self.pickler_class(f)
3522
3523 pickler.dump(data)
3524 first_pickled = f.getvalue()
3525
3526 f = io.BytesIO()
3527 primed = self.pickler_class(f)
3528 primed.memo = pickler.memo
3529
3530 primed.dump(data)
3531 primed_pickled = f.getvalue()
3532
3533 self.assertNotEqual(first_pickled, primed_pickled)
3534
3535 def test_priming_unpickler_memo(self):
3536 # Verify that we can set the Unpickler's memo attribute.
3537 data = ["abcdefg", "abcdefg", 44]
3538 f = io.BytesIO()
3539 pickler = self.pickler_class(f)
3540
3541 pickler.dump(data)
3542 first_pickled = f.getvalue()
3543
3544 f = io.BytesIO()
3545 primed = self.pickler_class(f)
3546 primed.memo = pickler.memo
3547
3548 primed.dump(data)
3549 primed_pickled = f.getvalue()
3550
3551 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3552 unpickled_data1 = unpickler.load()
3553
3554 self.assertEqual(unpickled_data1, data)
3555
3556 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3557 primed.memo = unpickler.memo
3558 unpickled_data2 = primed.load()
3559
3560 primed.memo.clear()
3561
3562 self.assertEqual(unpickled_data2, data)
3563 self.assertTrue(unpickled_data2 is unpickled_data1)
3564
3565 def test_reusing_unpickler_objects(self):
3566 data1 = ["abcdefg", "abcdefg", 44]
3567 f = io.BytesIO()
3568 pickler = self.pickler_class(f)
3569 pickler.dump(data1)
3570 pickled1 = f.getvalue()
3571
3572 data2 = ["abcdefg", 44, 44]
3573 f = io.BytesIO()
3574 pickler = self.pickler_class(f)
3575 pickler.dump(data2)
3576 pickled2 = f.getvalue()
3577
3578 f = io.BytesIO()
3579 f.write(pickled1)
3580 f.seek(0)
3581 unpickler = self.unpickler_class(f)
3582 self.assertEqual(unpickler.load(), data1)
3583
3584 f.seek(0)
3585 f.truncate()
3586 f.write(pickled2)
3587 f.seek(0)
3588 self.assertEqual(unpickler.load(), data2)
3589
Antoine Pitrou9f378722020-02-23 23:33:53 +01003590 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003591 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003592 with self.subTest(proto=proto):
3593 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3594 f = ioclass()
3595 pickler = self.pickler_class(f, protocol=proto)
3596 pickler.dump(data1)
3597 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003598
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003599 N = 5
3600 f = ioclass(pickled * N)
3601 unpickler = self.unpickler_class(f)
3602 for i in range(N):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003603 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003604 pos = f.tell()
3605 self.assertEqual(unpickler.load(), data1)
Antoine Pitrou9f378722020-02-23 23:33:53 +01003606 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003607 self.assertEqual(f.tell(), pos + len(pickled))
3608 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003609
3610 def test_multiple_unpicklings_seekable(self):
3611 self._check_multiple_unpicklings(io.BytesIO)
3612
3613 def test_multiple_unpicklings_unseekable(self):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003614 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3615
3616 def test_multiple_unpicklings_minimal(self):
3617 # File-like object that doesn't support peek() and readinto()
3618 # (bpo-39681)
3619 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003620
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003621 def test_unpickling_buffering_readline(self):
3622 # Issue #12687: the unpickler's buffering logic could fail with
3623 # text mode opcodes.
3624 data = list(range(10))
3625 for proto in protocols:
3626 for buf_size in range(1, 11):
3627 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3628 pickler = self.pickler_class(f, protocol=proto)
3629 pickler.dump(data)
3630 f.seek(0)
3631 unpickler = self.unpickler_class(f)
3632 self.assertEqual(unpickler.load(), data)
3633
Collin Winter771d8342009-04-16 03:18:06 +00003634
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003635# Tests for dispatch_table attribute
3636
3637REDUCE_A = 'reduce_A'
3638
3639class AAA(object):
3640 def __reduce__(self):
3641 return str, (REDUCE_A,)
3642
3643class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003644 def __init__(self):
3645 # Add an instance attribute to enable state-saving routines at pickling
3646 # time.
3647 self.a = "some attribute"
3648
3649 def __setstate__(self, state):
3650 self.a = "BBB.__setstate__"
3651
3652
3653def setstate_bbb(obj, state):
3654 """Custom state setter for BBB objects
3655
3656 Such callable may be created by other persons than the ones who created the
3657 BBB class. If passed as the state_setter item of a custom reducer, this
3658 allows for custom state setting behavior of BBB objects. One can think of
3659 it as the analogous of list_setitems or dict_setitems but for foreign
3660 classes/functions.
3661 """
3662 obj.a = "custom state_setter"
3663
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003664
Pierre Glaser289f1f82019-05-08 23:08:25 +02003665
3666class AbstractCustomPicklerClass:
3667 """Pickler implementing a reducing hook using reducer_override."""
3668 def reducer_override(self, obj):
3669 obj_name = getattr(obj, "__name__", None)
3670
3671 if obj_name == 'f':
3672 # asking the pickler to save f as 5
3673 return int, (5, )
3674
3675 if obj_name == 'MyClass':
3676 return str, ('some str',)
3677
3678 elif obj_name == 'g':
3679 # in this case, the callback returns an invalid result (not a 2-5
3680 # tuple or a string), the pickler should raise a proper error.
3681 return False
3682
3683 elif obj_name == 'h':
3684 # Simulate a case when the reducer fails. The error should
3685 # be propagated to the original ``dump`` call.
3686 raise ValueError('The reducer just failed')
3687
3688 return NotImplemented
3689
3690class AbstractHookTests(unittest.TestCase):
3691 def test_pickler_hook(self):
3692 # test the ability of a custom, user-defined CPickler subclass to
3693 # override the default reducing routines of any type using the method
3694 # reducer_override
3695
3696 def f():
3697 pass
3698
3699 def g():
3700 pass
3701
3702 def h():
3703 pass
3704
3705 class MyClass:
3706 pass
3707
3708 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3709 with self.subTest(proto=proto):
3710 bio = io.BytesIO()
3711 p = self.pickler_class(bio, proto)
3712
3713 p.dump([f, MyClass, math.log])
3714 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3715
3716 self.assertEqual(new_f, 5)
3717 self.assertEqual(some_str, 'some str')
3718 # math.log does not have its usual reducer overriden, so the
3719 # custom reduction callback should silently direct the pickler
3720 # to the default pickling by attribute, by returning
3721 # NotImplemented
3722 self.assertIs(math_log, math.log)
3723
3724 with self.assertRaises(pickle.PicklingError):
3725 p.dump(g)
3726
3727 with self.assertRaisesRegex(
3728 ValueError, 'The reducer just failed'):
3729 p.dump(h)
3730
Pierre Glaser0f2f35e2020-02-02 19:55:21 +01003731 @support.cpython_only
3732 def test_reducer_override_no_reference_cycle(self):
3733 # bpo-39492: reducer_override used to induce a spurious reference cycle
3734 # inside the Pickler object, that could prevent all serialized objects
3735 # from being garbage-collected without explicity invoking gc.collect.
3736
3737 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3738 with self.subTest(proto=proto):
3739 def f():
3740 pass
3741
3742 wr = weakref.ref(f)
3743
3744 bio = io.BytesIO()
3745 p = self.pickler_class(bio, proto)
3746 p.dump(f)
3747 new_f = pickle.loads(bio.getvalue())
3748 assert new_f == 5
3749
3750 del p
3751 del f
3752
3753 self.assertIsNone(wr())
3754
Pierre Glaser289f1f82019-05-08 23:08:25 +02003755
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003756class AbstractDispatchTableTests(unittest.TestCase):
3757
3758 def test_default_dispatch_table(self):
3759 # No dispatch_table attribute by default
3760 f = io.BytesIO()
3761 p = self.pickler_class(f, 0)
3762 with self.assertRaises(AttributeError):
3763 p.dispatch_table
3764 self.assertFalse(hasattr(p, 'dispatch_table'))
3765
3766 def test_class_dispatch_table(self):
3767 # A dispatch_table attribute can be specified class-wide
3768 dt = self.get_dispatch_table()
3769
3770 class MyPickler(self.pickler_class):
3771 dispatch_table = dt
3772
3773 def dumps(obj, protocol=None):
3774 f = io.BytesIO()
3775 p = MyPickler(f, protocol)
3776 self.assertEqual(p.dispatch_table, dt)
3777 p.dump(obj)
3778 return f.getvalue()
3779
3780 self._test_dispatch_table(dumps, dt)
3781
3782 def test_instance_dispatch_table(self):
3783 # A dispatch_table attribute can also be specified instance-wide
3784 dt = self.get_dispatch_table()
3785
3786 def dumps(obj, protocol=None):
3787 f = io.BytesIO()
3788 p = self.pickler_class(f, protocol)
3789 p.dispatch_table = dt
3790 self.assertEqual(p.dispatch_table, dt)
3791 p.dump(obj)
3792 return f.getvalue()
3793
3794 self._test_dispatch_table(dumps, dt)
3795
3796 def _test_dispatch_table(self, dumps, dispatch_table):
3797 def custom_load_dump(obj):
3798 return pickle.loads(dumps(obj, 0))
3799
3800 def default_load_dump(obj):
3801 return pickle.loads(pickle.dumps(obj, 0))
3802
3803 # pickling complex numbers using protocol 0 relies on copyreg
3804 # so check pickling a complex number still works
3805 z = 1 + 2j
3806 self.assertEqual(custom_load_dump(z), z)
3807 self.assertEqual(default_load_dump(z), z)
3808
3809 # modify pickling of complex
3810 REDUCE_1 = 'reduce_1'
3811 def reduce_1(obj):
3812 return str, (REDUCE_1,)
3813 dispatch_table[complex] = reduce_1
3814 self.assertEqual(custom_load_dump(z), REDUCE_1)
3815 self.assertEqual(default_load_dump(z), z)
3816
3817 # check picklability of AAA and BBB
3818 a = AAA()
3819 b = BBB()
3820 self.assertEqual(custom_load_dump(a), REDUCE_A)
3821 self.assertIsInstance(custom_load_dump(b), BBB)
3822 self.assertEqual(default_load_dump(a), REDUCE_A)
3823 self.assertIsInstance(default_load_dump(b), BBB)
3824
3825 # modify pickling of BBB
3826 dispatch_table[BBB] = reduce_1
3827 self.assertEqual(custom_load_dump(a), REDUCE_A)
3828 self.assertEqual(custom_load_dump(b), REDUCE_1)
3829 self.assertEqual(default_load_dump(a), REDUCE_A)
3830 self.assertIsInstance(default_load_dump(b), BBB)
3831
3832 # revert pickling of BBB and modify pickling of AAA
3833 REDUCE_2 = 'reduce_2'
3834 def reduce_2(obj):
3835 return str, (REDUCE_2,)
3836 dispatch_table[AAA] = reduce_2
3837 del dispatch_table[BBB]
3838 self.assertEqual(custom_load_dump(a), REDUCE_2)
3839 self.assertIsInstance(custom_load_dump(b), BBB)
3840 self.assertEqual(default_load_dump(a), REDUCE_A)
3841 self.assertIsInstance(default_load_dump(b), BBB)
3842
Pierre Glaser65d98d02019-05-08 21:40:25 +02003843 # End-to-end testing of save_reduce with the state_setter keyword
3844 # argument. This is a dispatch_table test as the primary goal of
3845 # state_setter is to tweak objects reduction behavior.
3846 # In particular, state_setter is useful when the default __setstate__
3847 # behavior is not flexible enough.
3848
3849 # No custom reducer for b has been registered for now, so
3850 # BBB.__setstate__ should be used at unpickling time
3851 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3852
3853 def reduce_bbb(obj):
3854 return BBB, (), obj.__dict__, None, None, setstate_bbb
3855
3856 dispatch_table[BBB] = reduce_bbb
3857
3858 # The custom reducer reduce_bbb includes a state setter, that should
3859 # have priority over BBB.__setstate__
3860 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3861
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003862
Guido van Rossum98297ee2007-11-06 21:34:58 +00003863if __name__ == "__main__":
3864 # Print some stuff that can be used to rewrite DATA{0,1,2}
3865 from pickletools import dis
3866 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003867 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003868 p = pickle.dumps(x, i)
3869 print("DATA{0} = (".format(i))
3870 for j in range(0, len(p), 20):
3871 b = bytes(p[j:j+20])
3872 print(" {0!r}".format(b))
3873 print(")")
3874 print()
3875 print("# Disassembly of DATA{0}".format(i))
3876 print("DATA{0}_DIS = \"\"\"\\".format(i))
3877 dis(p)
3878 print("\"\"\"")
3879 print()