blob: a34505aab51c171854e18fd3651d6518a7bce29c [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
Antoine Pitrou82be19f2011-08-29 23:09:33 +020025from test.support import (
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020026 TestFailed, TESTFN, run_with_locale, no_tracing,
Hai Shie80697d2020-05-28 06:10:27 +080027 _2G, _4G, bigmemtest, forget,
Antoine Pitrou82be19f2011-08-29 23:09:33 +020028 )
Hai Shie80697d2020-05-28 06:10:27 +080029from test.support import threading_helper
Victor Stinner83628932020-06-17 18:07:13 +020030from test.support.warnings_helper import save_restore_warnings_filters
Tim Peterse089c682001-04-10 03:41:41 +000031
Guido van Rossum98297ee2007-11-06 21:34:58 +000032from pickle import bytes_types
33
Victor Stinner83628932020-06-17 18:07:13 +020034
35# bpo-41003: Save/restore warnings filters to leave them unchanged.
36# Ignore filters installed by numpy.
37try:
38 with save_restore_warnings_filters():
39 import numpy as np
40except ImportError:
41 np = None
42
43
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030044requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
45 "test is only meaningful on 32-bit builds")
46
Tim Petersee1a53c2003-02-02 02:57:53 +000047# Tests that try a number of pickle protocols should have a
48# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000049# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000050protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000051
Tim Peters22e71712003-02-03 22:27:38 +000052
53# Return True if opcode code appears in the pickle, else False.
54def opcode_in_pickle(code, pickle):
55 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000056 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000057 return True
58 return False
59
Tim Peters8d2613a2003-02-11 16:40:16 +000060# Return the number of times opcode code appears in pickle.
61def count_opcode(code, pickle):
62 n = 0
63 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000064 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000065 n += 1
66 return n
67
Antoine Pitrou04248a82010-10-12 20:51:21 +000068
69class UnseekableIO(io.BytesIO):
70 def peek(self, *args):
71 raise NotImplementedError
72
73 def seekable(self):
74 return False
75
76 def seek(self, *args):
77 raise io.UnsupportedOperation
78
79 def tell(self):
80 raise io.UnsupportedOperation
81
82
Antoine Pitrou9f378722020-02-23 23:33:53 +010083class MinimalIO(object):
84 """
85 A file-like object that doesn't support readinto().
86 """
87 def __init__(self, *args):
88 self._bio = io.BytesIO(*args)
89 self.getvalue = self._bio.getvalue
90 self.read = self._bio.read
91 self.readline = self._bio.readline
92 self.write = self._bio.write
93
94
Tim Peters3e667d52003-02-04 21:47:44 +000095# We can't very well test the extension registry without putting known stuff
96# in it, but we have to be careful to restore its original state. Code
97# should do this:
98#
99# e = ExtensionSaver(extension_code)
100# try:
101# fiddle w/ the extension registry's stuff for extension_code
102# finally:
103# e.restore()
104
105class ExtensionSaver:
106 # Remember current registration for code (if any), and remove it (if
107 # there is one).
108 def __init__(self, code):
109 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000110 if code in copyreg._inverted_registry:
111 self.pair = copyreg._inverted_registry[code]
112 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000113 else:
114 self.pair = None
115
116 # Restore previous registration for code.
117 def restore(self):
118 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000119 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000120 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000121 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000122 pair = self.pair
123 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000124 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000125
Jeremy Hylton66426532001-10-15 21:38:56 +0000126class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000127 def __eq__(self, other):
128 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000129
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000130class D(C):
131 def __init__(self, arg):
132 pass
133
134class E(C):
135 def __getinitargs__(self):
136 return ()
137
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100138class H(object):
139 pass
140
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200141# Hashable mutable key
142class K(object):
143 def __init__(self, value):
144 self.value = value
145
146 def __reduce__(self):
147 # Shouldn't support the recursion itself
148 return K, (self.value,)
149
Jeremy Hylton66426532001-10-15 21:38:56 +0000150import __main__
151__main__.C = C
152C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000153__main__.D = D
154D.__module__ = "__main__"
155__main__.E = E
156E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100157__main__.H = H
158H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200159__main__.K = K
160K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000161
162class myint(int):
163 def __init__(self, x):
164 self.str = str(x)
165
166class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000167
Jeremy Hylton66426532001-10-15 21:38:56 +0000168 def __init__(self, a, b):
169 self.a = a
170 self.b = b
171
172 def __getinitargs__(self):
173 return self.a, self.b
174
Guido van Rossum04a86612001-12-19 16:58:54 +0000175class metaclass(type):
176 pass
177
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000178class use_metaclass(object, metaclass=metaclass):
179 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000180
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200181class pickling_metaclass(type):
182 def __eq__(self, other):
183 return (type(self) == type(other) and
184 self.reduce_args == other.reduce_args)
185
186 def __reduce__(self):
187 return (create_dynamic_class, self.reduce_args)
188
189def create_dynamic_class(name, bases):
190 result = pickling_metaclass(name, bases, dict())
191 result.reduce_args = (name, bases)
192 return result
193
Antoine Pitrou91f43802019-05-26 17:10:09 +0200194
195class ZeroCopyBytes(bytes):
196 readonly = True
197 c_contiguous = True
198 f_contiguous = True
199 zero_copy_reconstruct = True
200
201 def __reduce_ex__(self, protocol):
202 if protocol >= 5:
203 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
204 else:
205 return type(self)._reconstruct, (bytes(self),)
206
207 def __repr__(self):
208 return "{}({!r})".format(self.__class__.__name__, bytes(self))
209
210 __str__ = __repr__
211
212 @classmethod
213 def _reconstruct(cls, obj):
214 with memoryview(obj) as m:
215 obj = m.obj
216 if type(obj) is cls:
217 # Zero-copy
218 return obj
219 else:
220 return cls(obj)
221
222
223class ZeroCopyBytearray(bytearray):
224 readonly = False
225 c_contiguous = True
226 f_contiguous = True
227 zero_copy_reconstruct = True
228
229 def __reduce_ex__(self, protocol):
230 if protocol >= 5:
231 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
232 else:
233 return type(self)._reconstruct, (bytes(self),)
234
235 def __repr__(self):
236 return "{}({!r})".format(self.__class__.__name__, bytes(self))
237
238 __str__ = __repr__
239
240 @classmethod
241 def _reconstruct(cls, obj):
242 with memoryview(obj) as m:
243 obj = m.obj
244 if type(obj) is cls:
245 # Zero-copy
246 return obj
247 else:
248 return cls(obj)
249
250
251if _testbuffer is not None:
252
253 class PicklableNDArray:
254 # A not-really-zero-copy picklable ndarray, as the ndarray()
255 # constructor doesn't allow for it
256
257 zero_copy_reconstruct = False
258
259 def __init__(self, *args, **kwargs):
260 self.array = _testbuffer.ndarray(*args, **kwargs)
261
262 def __getitem__(self, idx):
263 cls = type(self)
264 new = cls.__new__(cls)
265 new.array = self.array[idx]
266 return new
267
268 @property
269 def readonly(self):
270 return self.array.readonly
271
272 @property
273 def c_contiguous(self):
274 return self.array.c_contiguous
275
276 @property
277 def f_contiguous(self):
278 return self.array.f_contiguous
279
280 def __eq__(self, other):
281 if not isinstance(other, PicklableNDArray):
282 return NotImplemented
283 return (other.array.format == self.array.format and
284 other.array.shape == self.array.shape and
285 other.array.strides == self.array.strides and
286 other.array.readonly == self.array.readonly and
287 other.array.tobytes() == self.array.tobytes())
288
289 def __ne__(self, other):
290 if not isinstance(other, PicklableNDArray):
291 return NotImplemented
292 return not (self == other)
293
294 def __repr__(self):
295 return (f"{type(self)}(shape={self.array.shape},"
296 f"strides={self.array.strides}, "
297 f"bytes={self.array.tobytes()})")
298
299 def __reduce_ex__(self, protocol):
300 if not self.array.contiguous:
301 raise NotImplementedError("Reconstructing a non-contiguous "
302 "ndarray does not seem possible")
303 ndarray_kwargs = {"shape": self.array.shape,
304 "strides": self.array.strides,
305 "format": self.array.format,
306 "flags": (0 if self.readonly
307 else _testbuffer.ND_WRITABLE)}
308 pb = pickle.PickleBuffer(self.array)
309 if protocol >= 5:
310 return (type(self)._reconstruct,
311 (pb, ndarray_kwargs))
312 else:
313 # Need to serialize the bytes in physical order
314 with pb.raw() as m:
315 return (type(self)._reconstruct,
316 (m.tobytes(), ndarray_kwargs))
317
318 @classmethod
319 def _reconstruct(cls, obj, kwargs):
320 with memoryview(obj) as m:
321 # For some reason, ndarray() wants a list of integers...
322 # XXX This only works if format == 'B'
323 items = list(m.tobytes())
324 return cls(items, **kwargs)
325
326
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300327# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000328# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000329
Guido van Rossum98297ee2007-11-06 21:34:58 +0000330DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200331 b'(lp0\nL0L\naL1L\naF2.0\n'
332 b'ac__builtin__\ncomple'
333 b'x\np1\n(F3.0\nF0.0\ntp2\n'
334 b'Rp3\naL1L\naL-1L\naL255'
335 b'L\naL-255L\naL-256L\naL'
336 b'65535L\naL-65535L\naL-'
337 b'65536L\naL2147483647L'
338 b'\naL-2147483647L\naL-2'
339 b'147483648L\na(Vabc\np4'
340 b'\ng4\nccopy_reg\n_recon'
341 b'structor\np5\n(c__main'
342 b'__\nC\np6\nc__builtin__'
343 b'\nobject\np7\nNtp8\nRp9\n'
344 b'(dp10\nVfoo\np11\nL1L\ns'
345 b'Vbar\np12\nL2L\nsbg9\ntp'
346 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000347)
Tim Peterse9358162001-01-22 22:05:20 +0000348
Guido van Rossum98297ee2007-11-06 21:34:58 +0000349# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000350DATA0_DIS = """\
351 0: ( MARK
352 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000353 2: p PUT 0
354 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000355 9: a APPEND
356 10: L LONG 1
357 14: a APPEND
358 15: F FLOAT 2.0
359 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200360 21: c GLOBAL '__builtin__ complex'
361 42: p PUT 1
362 45: ( MARK
363 46: F FLOAT 3.0
364 51: F FLOAT 0.0
365 56: t TUPLE (MARK at 45)
366 57: p PUT 2
367 60: R REDUCE
368 61: p PUT 3
369 64: a APPEND
370 65: L LONG 1
371 69: a APPEND
372 70: L LONG -1
373 75: a APPEND
374 76: L LONG 255
375 82: a APPEND
376 83: L LONG -255
377 90: a APPEND
378 91: L LONG -256
379 98: a APPEND
380 99: L LONG 65535
381 107: a APPEND
382 108: L LONG -65535
383 117: a APPEND
384 118: L LONG -65536
385 127: a APPEND
386 128: L LONG 2147483647
387 141: a APPEND
388 142: L LONG -2147483647
389 156: a APPEND
390 157: L LONG -2147483648
391 171: a APPEND
392 172: ( MARK
393 173: V UNICODE 'abc'
394 178: p PUT 4
395 181: g GET 4
396 184: c GLOBAL 'copy_reg _reconstructor'
397 209: p PUT 5
398 212: ( MARK
399 213: c GLOBAL '__main__ C'
400 225: p PUT 6
401 228: c GLOBAL '__builtin__ object'
402 248: p PUT 7
403 251: N NONE
404 252: t TUPLE (MARK at 212)
405 253: p PUT 8
406 256: R REDUCE
407 257: p PUT 9
408 260: ( MARK
409 261: d DICT (MARK at 260)
410 262: p PUT 10
411 266: V UNICODE 'foo'
412 271: p PUT 11
413 275: L LONG 1
414 279: s SETITEM
415 280: V UNICODE 'bar'
416 285: p PUT 12
417 289: L LONG 2
418 293: s SETITEM
419 294: b BUILD
420 295: g GET 9
421 298: t TUPLE (MARK at 172)
422 299: p PUT 13
423 303: a APPEND
424 304: g GET 13
425 308: a APPEND
426 309: L LONG 5
427 313: a APPEND
428 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000429highest protocol among opcodes = 0
430"""
431
Guido van Rossum98297ee2007-11-06 21:34:58 +0000432DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200433 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
434 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000435 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
436 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
437 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
438 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200439 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000440 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200441 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000442 b'object\nq\x07Ntq\x08Rq\t}q\n('
443 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
444 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
445)
Tim Peters70b02d72003-02-02 17:26:40 +0000446
Guido van Rossum98297ee2007-11-06 21:34:58 +0000447# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000448DATA1_DIS = """\
449 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000450 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000451 3: ( MARK
452 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000453 6: K BININT1 1
454 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200455 17: c GLOBAL '__builtin__ complex'
456 38: q BINPUT 1
457 40: ( MARK
458 41: G BINFLOAT 3.0
459 50: G BINFLOAT 0.0
460 59: t TUPLE (MARK at 40)
461 60: q BINPUT 2
462 62: R REDUCE
463 63: q BINPUT 3
464 65: K BININT1 1
465 67: J BININT -1
466 72: K BININT1 255
467 74: J BININT -255
468 79: J BININT -256
469 84: M BININT2 65535
470 87: J BININT -65535
471 92: J BININT -65536
472 97: J BININT 2147483647
473 102: J BININT -2147483647
474 107: J BININT -2147483648
475 112: ( MARK
476 113: X BINUNICODE 'abc'
477 121: q BINPUT 4
478 123: h BINGET 4
479 125: c GLOBAL 'copy_reg _reconstructor'
480 150: q BINPUT 5
481 152: ( MARK
482 153: c GLOBAL '__main__ C'
483 165: q BINPUT 6
484 167: c GLOBAL '__builtin__ object'
485 187: q BINPUT 7
486 189: N NONE
487 190: t TUPLE (MARK at 152)
488 191: q BINPUT 8
489 193: R REDUCE
490 194: q BINPUT 9
491 196: } EMPTY_DICT
492 197: q BINPUT 10
493 199: ( MARK
494 200: X BINUNICODE 'foo'
495 208: q BINPUT 11
496 210: K BININT1 1
497 212: X BINUNICODE 'bar'
498 220: q BINPUT 12
499 222: K BININT1 2
500 224: u SETITEMS (MARK at 199)
501 225: b BUILD
502 226: h BINGET 9
503 228: t TUPLE (MARK at 112)
504 229: q BINPUT 13
505 231: h BINGET 13
506 233: K BININT1 5
507 235: e APPENDS (MARK at 3)
508 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000509highest protocol among opcodes = 1
510"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000511
Guido van Rossum98297ee2007-11-06 21:34:58 +0000512DATA2 = (
513 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200514 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000515 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
516 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
517 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
518 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
519 b'bcq\x04h\x04c__main__\nC\nq\x05'
520 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
521 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
522 b'\nK\x05e.'
523)
Tim Petersfc273752003-03-02 04:54:24 +0000524
Guido van Rossum98297ee2007-11-06 21:34:58 +0000525# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000526DATA2_DIS = """\
527 0: \x80 PROTO 2
528 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000529 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000530 5: ( MARK
531 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000532 8: K BININT1 1
533 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200534 19: c GLOBAL '__builtin__ complex'
535 40: q BINPUT 1
536 42: G BINFLOAT 3.0
537 51: G BINFLOAT 0.0
538 60: \x86 TUPLE2
539 61: q BINPUT 2
540 63: R REDUCE
541 64: q BINPUT 3
542 66: K BININT1 1
543 68: J BININT -1
544 73: K BININT1 255
545 75: J BININT -255
546 80: J BININT -256
547 85: M BININT2 65535
548 88: J BININT -65535
549 93: J BININT -65536
550 98: J BININT 2147483647
551 103: J BININT -2147483647
552 108: J BININT -2147483648
553 113: ( MARK
554 114: X BINUNICODE 'abc'
555 122: q BINPUT 4
556 124: h BINGET 4
557 126: c GLOBAL '__main__ C'
558 138: q BINPUT 5
559 140: ) EMPTY_TUPLE
560 141: \x81 NEWOBJ
561 142: q BINPUT 6
562 144: } EMPTY_DICT
563 145: q BINPUT 7
564 147: ( MARK
565 148: X BINUNICODE 'foo'
566 156: q BINPUT 8
567 158: K BININT1 1
568 160: X BINUNICODE 'bar'
569 168: q BINPUT 9
570 170: K BININT1 2
571 172: u SETITEMS (MARK at 147)
572 173: b BUILD
573 174: h BINGET 6
574 176: t TUPLE (MARK at 113)
575 177: q BINPUT 10
576 179: h BINGET 10
577 181: K BININT1 5
578 183: e APPENDS (MARK at 5)
579 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000580highest protocol among opcodes = 2
581"""
582
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300583DATA3 = (
584 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
585 b'builtins\ncomplex\nq\x01G'
586 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
587 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
588 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
589 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
590 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
591 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
592 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
593 b'e.'
594)
595
596# Disassembly of DATA3
597DATA3_DIS = """\
598 0: \x80 PROTO 3
599 2: ] EMPTY_LIST
600 3: q BINPUT 0
601 5: ( MARK
602 6: K BININT1 0
603 8: K BININT1 1
604 10: G BINFLOAT 2.0
605 19: c GLOBAL 'builtins complex'
606 37: q BINPUT 1
607 39: G BINFLOAT 3.0
608 48: G BINFLOAT 0.0
609 57: \x86 TUPLE2
610 58: q BINPUT 2
611 60: R REDUCE
612 61: q BINPUT 3
613 63: K BININT1 1
614 65: J BININT -1
615 70: K BININT1 255
616 72: J BININT -255
617 77: J BININT -256
618 82: M BININT2 65535
619 85: J BININT -65535
620 90: J BININT -65536
621 95: J BININT 2147483647
622 100: J BININT -2147483647
623 105: J BININT -2147483648
624 110: ( MARK
625 111: X BINUNICODE 'abc'
626 119: q BINPUT 4
627 121: h BINGET 4
628 123: c GLOBAL '__main__ C'
629 135: q BINPUT 5
630 137: ) EMPTY_TUPLE
631 138: \x81 NEWOBJ
632 139: q BINPUT 6
633 141: } EMPTY_DICT
634 142: q BINPUT 7
635 144: ( MARK
636 145: X BINUNICODE 'bar'
637 153: q BINPUT 8
638 155: K BININT1 2
639 157: X BINUNICODE 'foo'
640 165: q BINPUT 9
641 167: K BININT1 1
642 169: u SETITEMS (MARK at 144)
643 170: b BUILD
644 171: h BINGET 6
645 173: t TUPLE (MARK at 110)
646 174: q BINPUT 10
647 176: h BINGET 10
648 178: K BININT1 5
649 180: e APPENDS (MARK at 5)
650 181: . STOP
651highest protocol among opcodes = 2
652"""
653
654DATA4 = (
655 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
656 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
657 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
658 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
659 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
660 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
661 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
662 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
663 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
664)
665
666# Disassembly of DATA4
667DATA4_DIS = """\
668 0: \x80 PROTO 4
669 2: \x95 FRAME 168
670 11: ] EMPTY_LIST
671 12: \x94 MEMOIZE
672 13: ( MARK
673 14: K BININT1 0
674 16: K BININT1 1
675 18: G BINFLOAT 2.0
676 27: \x8c SHORT_BINUNICODE 'builtins'
677 37: \x94 MEMOIZE
678 38: \x8c SHORT_BINUNICODE 'complex'
679 47: \x94 MEMOIZE
680 48: \x93 STACK_GLOBAL
681 49: \x94 MEMOIZE
682 50: G BINFLOAT 3.0
683 59: G BINFLOAT 0.0
684 68: \x86 TUPLE2
685 69: \x94 MEMOIZE
686 70: R REDUCE
687 71: \x94 MEMOIZE
688 72: K BININT1 1
689 74: J BININT -1
690 79: K BININT1 255
691 81: J BININT -255
692 86: J BININT -256
693 91: M BININT2 65535
694 94: J BININT -65535
695 99: J BININT -65536
696 104: J BININT 2147483647
697 109: J BININT -2147483647
698 114: J BININT -2147483648
699 119: ( MARK
700 120: \x8c SHORT_BINUNICODE 'abc'
701 125: \x94 MEMOIZE
702 126: h BINGET 6
703 128: \x8c SHORT_BINUNICODE '__main__'
704 138: \x94 MEMOIZE
705 139: \x8c SHORT_BINUNICODE 'C'
706 142: \x94 MEMOIZE
707 143: \x93 STACK_GLOBAL
708 144: \x94 MEMOIZE
709 145: ) EMPTY_TUPLE
710 146: \x81 NEWOBJ
711 147: \x94 MEMOIZE
712 148: } EMPTY_DICT
713 149: \x94 MEMOIZE
714 150: ( MARK
715 151: \x8c SHORT_BINUNICODE 'bar'
716 156: \x94 MEMOIZE
717 157: K BININT1 2
718 159: \x8c SHORT_BINUNICODE 'foo'
719 164: \x94 MEMOIZE
720 165: K BININT1 1
721 167: u SETITEMS (MARK at 150)
722 168: b BUILD
723 169: h BINGET 10
724 171: t TUPLE (MARK at 119)
725 172: \x94 MEMOIZE
726 173: h BINGET 14
727 175: K BININT1 5
728 177: e APPENDS (MARK at 13)
729 178: . STOP
730highest protocol among opcodes = 4
731"""
732
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000733# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300734DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000735
736# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300737DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000738
739# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300740DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
741 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
742 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
743 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
744 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
745 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000746
747# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300748DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000749
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100750python2_exceptions_without_args = (
751 ArithmeticError,
752 AssertionError,
753 AttributeError,
754 BaseException,
755 BufferError,
756 BytesWarning,
757 DeprecationWarning,
758 EOFError,
759 EnvironmentError,
760 Exception,
761 FloatingPointError,
762 FutureWarning,
763 GeneratorExit,
764 IOError,
765 ImportError,
766 ImportWarning,
767 IndentationError,
768 IndexError,
769 KeyError,
770 KeyboardInterrupt,
771 LookupError,
772 MemoryError,
773 NameError,
774 NotImplementedError,
775 OSError,
776 OverflowError,
777 PendingDeprecationWarning,
778 ReferenceError,
779 RuntimeError,
780 RuntimeWarning,
781 # StandardError is gone in Python 3, we map it to Exception
782 StopIteration,
783 SyntaxError,
784 SyntaxWarning,
785 SystemError,
786 SystemExit,
787 TabError,
788 TypeError,
789 UnboundLocalError,
790 UnicodeError,
791 UnicodeWarning,
792 UserWarning,
793 ValueError,
794 Warning,
795 ZeroDivisionError,
796)
797
798exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
799
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100800# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300801DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
802 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
803 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100804
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000805
Jeremy Hylton66426532001-10-15 21:38:56 +0000806def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000807 c = C()
808 c.foo = 1
809 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000810 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000811 # Append some integer test cases at cPickle.c's internal size
812 # cutoffs.
813 uint1max = 0xff
814 uint2max = 0xffff
815 int4max = 0x7fffffff
816 x.extend([1, -1,
817 uint1max, -uint1max, -uint1max-1,
818 uint2max, -uint2max, -uint2max-1,
819 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000820 y = ('abc', 'abc', c, c)
821 x.append(y)
822 x.append(y)
823 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000824 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000825
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100826
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300827class AbstractUnpickleTests(unittest.TestCase):
828 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100829
Jeremy Hylton66426532001-10-15 21:38:56 +0000830 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000831
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100832 def assert_is_copy(self, obj, objcopy, msg=None):
833 """Utility method to verify if two objects are copies of each others.
834 """
835 if msg is None:
836 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
837 self.assertEqual(obj, objcopy, msg=msg)
838 self.assertIs(type(obj), type(objcopy), msg=msg)
839 if hasattr(obj, '__dict__'):
840 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
841 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
842 if hasattr(obj, '__slots__'):
843 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
844 for slot in obj.__slots__:
845 self.assertEqual(
846 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
847 self.assertEqual(getattr(obj, slot, None),
848 getattr(objcopy, slot, None), msg=msg)
849
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200850 def check_unpickling_error(self, errors, data):
851 with self.subTest(data=data), \
852 self.assertRaises(errors):
853 try:
854 self.loads(data)
855 except BaseException as exc:
856 if support.verbose > 1:
857 print('%-32r - %s: %s' %
858 (data, exc.__class__.__name__, exc))
859 raise
860
Guido van Rossum98297ee2007-11-06 21:34:58 +0000861 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100862 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000863
864 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100865 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000866
867 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100868 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000869
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300870 def test_load_from_data3(self):
871 self.assert_is_copy(self._testdata, self.loads(DATA3))
872
873 def test_load_from_data4(self):
874 self.assert_is_copy(self._testdata, self.loads(DATA4))
875
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000876 def test_load_classic_instance(self):
877 # See issue5180. Test loading 2.x pickles that
878 # contain an instance of old style class.
879 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
880 xname = X.__name__.encode('ascii')
881 # Protocol 0 (text mode pickle):
882 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200883 0: ( MARK
884 1: i INST '__main__ X' (MARK at 0)
885 13: p PUT 0
886 16: ( MARK
887 17: d DICT (MARK at 16)
888 18: p PUT 1
889 21: b BUILD
890 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000891 """
892 pickle0 = (b"(i__main__\n"
893 b"X\n"
894 b"p0\n"
895 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100896 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000897
898 # Protocol 1 (binary mode pickle)
899 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200900 0: ( MARK
901 1: c GLOBAL '__main__ X'
902 13: q BINPUT 0
903 15: o OBJ (MARK at 0)
904 16: q BINPUT 1
905 18: } EMPTY_DICT
906 19: q BINPUT 2
907 21: b BUILD
908 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000909 """
910 pickle1 = (b'(c__main__\n'
911 b'X\n'
912 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100913 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000914
915 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
916 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200917 0: \x80 PROTO 2
918 2: ( MARK
919 3: c GLOBAL '__main__ X'
920 15: q BINPUT 0
921 17: o OBJ (MARK at 2)
922 18: q BINPUT 1
923 20: } EMPTY_DICT
924 21: q BINPUT 2
925 23: b BUILD
926 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000927 """
928 pickle2 = (b'\x80\x02(c__main__\n'
929 b'X\n'
930 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100931 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000932
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300933 def test_maxint64(self):
934 maxint64 = (1 << 63) - 1
935 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
936 got = self.loads(data)
937 self.assert_is_copy(maxint64, got)
938
939 # Try too with a bogus literal.
940 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200941 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300942
943 def test_unpickle_from_2x(self):
944 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300945 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300946 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300947 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300948 self.assertEqual(type(loaded), type(range(0)))
949 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300950 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300951 self.assertEqual(type(loaded), SimpleCookie)
952 self.assertEqual(list(loaded.keys()), ["key"])
953 self.assertEqual(loaded["key"].value, "value")
954
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300955 # Exception objects without arguments pickled from 2.x with protocol 2
956 for exc in python2_exceptions_without_args:
957 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300958 loaded = self.loads(data)
959 self.assertIs(type(loaded), exc)
960
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300961 # StandardError is mapped to Exception, test that separately
962 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300963 self.assertIs(type(loaded), Exception)
964
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300965 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300966 self.assertIs(type(loaded), UnicodeEncodeError)
967 self.assertEqual(loaded.object, "foo")
968 self.assertEqual(loaded.encoding, "ascii")
969 self.assertEqual(loaded.start, 0)
970 self.assertEqual(loaded.end, 1)
971 self.assertEqual(loaded.reason, "bad")
972
973 def test_load_python2_str_as_bytes(self):
974 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
975 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
976 encoding="bytes"), b'a\x00\xa0')
977 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
978 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
979 encoding="bytes"), b'a\x00\xa0')
980 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
981 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
982 encoding="bytes"), b'a\x00\xa0')
983
984 def test_load_python2_unicode_as_str(self):
985 # From Python 2: pickle.dumps(u'π', protocol=0)
986 self.assertEqual(self.loads(b'V\\u03c0\n.',
987 encoding='bytes'), 'π')
988 # From Python 2: pickle.dumps(u'π', protocol=1)
989 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
990 encoding="bytes"), 'π')
991 # From Python 2: pickle.dumps(u'π', protocol=2)
992 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
993 encoding="bytes"), 'π')
994
995 def test_load_long_python2_str_as_bytes(self):
996 # From Python 2: pickle.dumps('x' * 300, protocol=1)
997 self.assertEqual(self.loads(pickle.BINSTRING +
998 struct.pack("<I", 300) +
999 b'x' * 300 + pickle.STOP,
1000 encoding='bytes'), b'x' * 300)
1001
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001002 def test_constants(self):
1003 self.assertIsNone(self.loads(b'N.'))
1004 self.assertIs(self.loads(b'\x88.'), True)
1005 self.assertIs(self.loads(b'\x89.'), False)
1006 self.assertIs(self.loads(b'I01\n.'), True)
1007 self.assertIs(self.loads(b'I00\n.'), False)
1008
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001009 def test_empty_bytestring(self):
1010 # issue 11286
1011 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1012 self.assertEqual(empty, '')
1013
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001014 def test_short_binbytes(self):
1015 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
1016 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1017
1018 def test_binbytes(self):
1019 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1020 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1021
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001022 @requires_32b
1023 def test_negative_32b_binbytes(self):
1024 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1025 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001026 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1027 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001028
1029 @requires_32b
1030 def test_negative_32b_binunicode(self):
1031 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1032 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001033 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1034 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001035
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001036 def test_short_binunicode(self):
1037 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1038 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1039
1040 def test_misc_get(self):
Claudiu Popa6f03b232019-11-24 20:15:08 +01001041 self.check_unpickling_error(pickle.UnpicklingError, b'g0\np0')
1042 self.check_unpickling_error(pickle.UnpicklingError, b'jens:')
1043 self.check_unpickling_error(pickle.UnpicklingError, b'hens:')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001044 self.assert_is_copy([(100,), (100,)],
1045 self.loads(b'((Kdtp0\nh\x00l.))'))
1046
Serhiy Storchakae0606192015-09-29 22:10:07 +03001047 def test_binbytes8(self):
1048 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1049 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1050
1051 def test_binunicode8(self):
1052 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1053 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1054
Antoine Pitrou91f43802019-05-26 17:10:09 +02001055 def test_bytearray8(self):
1056 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1057 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1058
Serhiy Storchakae0606192015-09-29 22:10:07 +03001059 @requires_32b
1060 def test_large_32b_binbytes8(self):
1061 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001062 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1063 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001064
1065 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001066 def test_large_32b_bytearray8(self):
1067 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1068 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1069 dumped)
1070
1071 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001072 def test_large_32b_binunicode8(self):
1073 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001074 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1075 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001076
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001077 def test_get(self):
1078 pickled = b'((lp100000\ng100000\nt.'
1079 unpickled = self.loads(pickled)
1080 self.assertEqual(unpickled, ([],)*2)
1081 self.assertIs(unpickled[0], unpickled[1])
1082
1083 def test_binget(self):
1084 pickled = b'(]q\xffh\xfft.'
1085 unpickled = self.loads(pickled)
1086 self.assertEqual(unpickled, ([],)*2)
1087 self.assertIs(unpickled[0], unpickled[1])
1088
1089 def test_long_binget(self):
1090 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1091 unpickled = self.loads(pickled)
1092 self.assertEqual(unpickled, ([],)*2)
1093 self.assertIs(unpickled[0], unpickled[1])
1094
1095 def test_dup(self):
1096 pickled = b'((l2t.'
1097 unpickled = self.loads(pickled)
1098 self.assertEqual(unpickled, ([],)*2)
1099 self.assertIs(unpickled[0], unpickled[1])
1100
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001101 def test_negative_put(self):
1102 # Issue #12847
1103 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001104 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001105
1106 @requires_32b
1107 def test_negative_32b_binput(self):
1108 # Issue #12847
1109 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001110 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001111
1112 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001113 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001114
1115 def test_badly_quoted_string(self):
1116 # Issue #17710
1117 badpickles = [b"S'\n.",
1118 b'S"\n.',
1119 b'S\' \n.',
1120 b'S" \n.',
1121 b'S\'"\n.',
1122 b'S"\'\n.',
1123 b"S' ' \n.",
1124 b'S" " \n.',
1125 b"S ''\n.",
1126 b'S ""\n.',
1127 b'S \n.',
1128 b'S\n.',
1129 b'S.']
1130 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001131 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001132
1133 def test_correctly_quoted_string(self):
1134 goodpickles = [(b"S''\n.", ''),
1135 (b'S""\n.', ''),
1136 (b'S"\\n"\n.', '\n'),
1137 (b"S'\\n'\n.", '\n')]
1138 for p, expected in goodpickles:
1139 self.assertEqual(self.loads(p), expected)
1140
1141 def test_frame_readline(self):
1142 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1143 # 0: \x80 PROTO 4
1144 # 2: \x95 FRAME 5
1145 # 11: I INT 42
1146 # 15: . STOP
1147 self.assertEqual(self.loads(pickled), 42)
1148
1149 def test_compat_unpickle(self):
1150 # xrange(1, 7)
1151 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1152 unpickled = self.loads(pickled)
1153 self.assertIs(type(unpickled), range)
1154 self.assertEqual(unpickled, range(1, 7))
1155 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1156 # reduce
1157 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1158 self.assertIs(self.loads(pickled), functools.reduce)
1159 # whichdb.whichdb
1160 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1161 self.assertIs(self.loads(pickled), dbm.whichdb)
1162 # Exception(), StandardError()
1163 for name in (b'Exception', b'StandardError'):
1164 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1165 unpickled = self.loads(pickled)
1166 self.assertIs(type(unpickled), Exception)
1167 self.assertEqual(str(unpickled), 'ugh')
1168 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1169 for name in (b'UserDict', b'IterableUserDict'):
1170 pickled = (b'\x80\x02(cUserDict\n' + name +
1171 b'\no}U\x04data}K\x01K\x02ssb.')
1172 unpickled = self.loads(pickled)
1173 self.assertIs(type(unpickled), collections.UserDict)
1174 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1175
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001176 def test_bad_stack(self):
1177 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001178 b'.', # STOP
1179 b'0', # POP
1180 b'1', # POP_MARK
1181 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001182 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001183 b'R', # REDUCE
1184 b')R',
1185 b'a', # APPEND
1186 b'Na',
1187 b'b', # BUILD
1188 b'Nb',
1189 b'd', # DICT
1190 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001191 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001192 b'ibuiltins\nlist\n', # INST
1193 b'l', # LIST
1194 b'o', # OBJ
1195 b'(o',
1196 b'p1\n', # PUT
1197 b'q\x00', # BINPUT
1198 b'r\x00\x00\x00\x00', # LONG_BINPUT
1199 b's', # SETITEM
1200 b'Ns',
1201 b'NNs',
1202 b't', # TUPLE
1203 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001204 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001205 b'}(Nu',
1206 b'\x81', # NEWOBJ
1207 b')\x81',
1208 b'\x85', # TUPLE1
1209 b'\x86', # TUPLE2
1210 b'N\x86',
1211 b'\x87', # TUPLE3
1212 b'N\x87',
1213 b'NN\x87',
1214 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001215 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001216 b'\x91', # FROZENSET
1217 b'\x92', # NEWOBJ_EX
1218 b')}\x92',
1219 b'\x93', # STACK_GLOBAL
1220 b'Vlist\n\x93',
1221 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001222 ]
1223 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001224 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001225
1226 def test_bad_mark(self):
1227 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001228 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001229 b'N(2', # DUP
1230 b'cbuiltins\nlist\n)(R', # REDUCE
1231 b'cbuiltins\nlist\n()R',
1232 b']N(a', # APPEND
1233 # BUILD
1234 b'cbuiltins\nValueError\n)R}(b',
1235 b'cbuiltins\nValueError\n)R(}b',
1236 b'(Nd', # DICT
1237 b'N(p1\n', # PUT
1238 b'N(q\x00', # BINPUT
1239 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1240 b'}NN(s', # SETITEM
1241 b'}N(Ns',
1242 b'}(NNs',
1243 b'}((u', # SETITEMS
1244 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1245 b'cbuiltins\nlist\n()\x81',
1246 b'N(\x85', # TUPLE1
1247 b'NN(\x86', # TUPLE2
1248 b'N(N\x86',
1249 b'NNN(\x87', # TUPLE3
1250 b'NN(N\x87',
1251 b'N(NN\x87',
1252 b']((\x90', # ADDITEMS
1253 # NEWOBJ_EX
1254 b'cbuiltins\nlist\n)}(\x92',
1255 b'cbuiltins\nlist\n)(}\x92',
1256 b'cbuiltins\nlist\n()}\x92',
1257 # STACK_GLOBAL
1258 b'Vbuiltins\n(Vlist\n\x93',
1259 b'Vbuiltins\nVlist\n(\x93',
1260 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001261 ]
1262 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001263 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001264
1265 def test_truncated_data(self):
1266 self.check_unpickling_error(EOFError, b'')
1267 self.check_unpickling_error(EOFError, b'N')
1268 badpickles = [
1269 b'B', # BINBYTES
1270 b'B\x03\x00\x00',
1271 b'B\x03\x00\x00\x00',
1272 b'B\x03\x00\x00\x00ab',
1273 b'C', # SHORT_BINBYTES
1274 b'C\x03',
1275 b'C\x03ab',
1276 b'F', # FLOAT
1277 b'F0.0',
1278 b'F0.00',
1279 b'G', # BINFLOAT
1280 b'G\x00\x00\x00\x00\x00\x00\x00',
1281 b'I', # INT
1282 b'I0',
1283 b'J', # BININT
1284 b'J\x00\x00\x00',
1285 b'K', # BININT1
1286 b'L', # LONG
1287 b'L0',
1288 b'L10',
1289 b'L0L',
1290 b'L10L',
1291 b'M', # BININT2
1292 b'M\x00',
1293 # b'P', # PERSID
1294 # b'Pabc',
1295 b'S', # STRING
1296 b"S'abc'",
1297 b'T', # BINSTRING
1298 b'T\x03\x00\x00',
1299 b'T\x03\x00\x00\x00',
1300 b'T\x03\x00\x00\x00ab',
1301 b'U', # SHORT_BINSTRING
1302 b'U\x03',
1303 b'U\x03ab',
1304 b'V', # UNICODE
1305 b'Vabc',
1306 b'X', # BINUNICODE
1307 b'X\x03\x00\x00',
1308 b'X\x03\x00\x00\x00',
1309 b'X\x03\x00\x00\x00ab',
1310 b'(c', # GLOBAL
1311 b'(cbuiltins',
1312 b'(cbuiltins\n',
1313 b'(cbuiltins\nlist',
1314 b'Ng', # GET
1315 b'Ng0',
1316 b'(i', # INST
1317 b'(ibuiltins',
1318 b'(ibuiltins\n',
1319 b'(ibuiltins\nlist',
1320 b'Nh', # BINGET
1321 b'Nj', # LONG_BINGET
1322 b'Nj\x00\x00\x00',
1323 b'Np', # PUT
1324 b'Np0',
1325 b'Nq', # BINPUT
1326 b'Nr', # LONG_BINPUT
1327 b'Nr\x00\x00\x00',
1328 b'\x80', # PROTO
1329 b'\x82', # EXT1
1330 b'\x83', # EXT2
1331 b'\x84\x01',
1332 b'\x84', # EXT4
1333 b'\x84\x01\x00\x00',
1334 b'\x8a', # LONG1
1335 b'\x8b', # LONG4
1336 b'\x8b\x00\x00\x00',
1337 b'\x8c', # SHORT_BINUNICODE
1338 b'\x8c\x03',
1339 b'\x8c\x03ab',
1340 b'\x8d', # BINUNICODE8
1341 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1342 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1343 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1344 b'\x8e', # BINBYTES8
1345 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1346 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1347 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001348 b'\x96', # BYTEARRAY8
1349 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1350 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1351 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001352 b'\x95', # FRAME
1353 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1354 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1355 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1356 ]
1357 for p in badpickles:
1358 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001359
Hai Shie80697d2020-05-28 06:10:27 +08001360 @threading_helper.reap_threads
tjb9004371c0a2019-02-18 23:30:51 +08001361 def test_unpickle_module_race(self):
1362 # https://bugs.python.org/issue34572
1363 locker_module = dedent("""
1364 import threading
1365 barrier = threading.Barrier(2)
1366 """)
1367 locking_import_module = dedent("""
1368 import locker
1369 locker.barrier.wait()
1370 class ToBeUnpickled(object):
1371 pass
1372 """)
1373
1374 os.mkdir(TESTFN)
1375 self.addCleanup(shutil.rmtree, TESTFN)
1376 sys.path.insert(0, TESTFN)
1377 self.addCleanup(sys.path.remove, TESTFN)
1378 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1379 f.write(locker_module.encode('utf-8'))
1380 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1381 f.write(locking_import_module.encode('utf-8'))
1382 self.addCleanup(forget, "locker")
1383 self.addCleanup(forget, "locking_import")
1384
1385 import locker
1386
1387 pickle_bytes = (
1388 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1389
1390 # Then try to unpickle two of these simultaneously
1391 # One of them will cause the module import, and we want it to block
1392 # until the other one either:
1393 # - fails (before the patch for this issue)
1394 # - blocks on the import lock for the module, as it should
1395 results = []
1396 barrier = threading.Barrier(3)
1397 def t():
1398 # This ensures the threads have all started
1399 # presumably barrier release is faster than thread startup
1400 barrier.wait()
1401 results.append(pickle.loads(pickle_bytes))
1402
1403 t1 = threading.Thread(target=t)
1404 t2 = threading.Thread(target=t)
1405 t1.start()
1406 t2.start()
1407
1408 barrier.wait()
1409 # could have delay here
1410 locker.barrier.wait()
1411
1412 t1.join()
1413 t2.join()
1414
1415 from locking_import import ToBeUnpickled
1416 self.assertEqual(
1417 [type(x) for x in results],
1418 [ToBeUnpickled] * 2)
1419
1420
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001421
1422class AbstractPickleTests(unittest.TestCase):
1423 # Subclass must define self.dumps, self.loads.
1424
1425 optimized = False
1426
1427 _testdata = AbstractUnpickleTests._testdata
1428
1429 def setUp(self):
1430 pass
1431
1432 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1433
1434 def test_misc(self):
1435 # test various datatypes not tested by testdata
1436 for proto in protocols:
1437 x = myint(4)
1438 s = self.dumps(x, proto)
1439 y = self.loads(s)
1440 self.assert_is_copy(x, y)
1441
1442 x = (1, ())
1443 s = self.dumps(x, proto)
1444 y = self.loads(s)
1445 self.assert_is_copy(x, y)
1446
1447 x = initarg(1, x)
1448 s = self.dumps(x, proto)
1449 y = self.loads(s)
1450 self.assert_is_copy(x, y)
1451
1452 # XXX test __reduce__ protocol?
1453
1454 def test_roundtrip_equality(self):
1455 expected = self._testdata
1456 for proto in protocols:
1457 s = self.dumps(expected, proto)
1458 got = self.loads(s)
1459 self.assert_is_copy(expected, got)
1460
Tim Peters70b02d72003-02-02 17:26:40 +00001461 # There are gratuitous differences between pickles produced by
1462 # pickle and cPickle, largely because cPickle starts PUT indices at
1463 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1464 # there's a comment with an exclamation point there whose meaning
1465 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1466 # of 1.
1467 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001468 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001469 from pickletools import dis
1470
1471 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1472 s = self.dumps(self._testdata, proto)
1473 filelike = StringIO()
1474 dis(s, out=filelike)
1475 got = filelike.getvalue()
1476 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001477
1478 def test_recursive_list(self):
1479 l = []
1480 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001481 for proto in protocols:
1482 s = self.dumps(l, proto)
1483 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001484 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001485 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001486 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001487
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001488 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001489 t = ([],)
1490 t[0].append(t)
1491 for proto in protocols:
1492 s = self.dumps(t, proto)
1493 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001494 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001495 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001496 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001497 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001498 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001499
Jeremy Hylton66426532001-10-15 21:38:56 +00001500 def test_recursive_dict(self):
1501 d = {}
1502 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001503 for proto in protocols:
1504 s = self.dumps(d, proto)
1505 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001506 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001507 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001508 self.assertIs(x[1], x)
1509
1510 def test_recursive_dict_key(self):
1511 d = {}
1512 k = K(d)
1513 d[k] = 1
1514 for proto in protocols:
1515 s = self.dumps(d, proto)
1516 x = self.loads(s)
1517 self.assertIsInstance(x, dict)
1518 self.assertEqual(len(x.keys()), 1)
1519 self.assertIsInstance(list(x.keys())[0], K)
1520 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001521
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001522 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001523 y = set()
1524 k = K(y)
1525 y.add(k)
1526 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001527 s = self.dumps(y, proto)
1528 x = self.loads(s)
1529 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001530 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001531 self.assertIsInstance(list(x)[0], K)
1532 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001533
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001534 def test_recursive_list_subclass(self):
1535 y = MyList()
1536 y.append(y)
1537 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001538 s = self.dumps(y, proto)
1539 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001540 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001541 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001542 self.assertIs(x[0], x)
1543
1544 def test_recursive_dict_subclass(self):
1545 d = MyDict()
1546 d[1] = d
1547 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1548 s = self.dumps(d, proto)
1549 x = self.loads(s)
1550 self.assertIsInstance(x, MyDict)
1551 self.assertEqual(list(x.keys()), [1])
1552 self.assertIs(x[1], x)
1553
1554 def test_recursive_dict_subclass_key(self):
1555 d = MyDict()
1556 k = K(d)
1557 d[k] = 1
1558 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1559 s = self.dumps(d, proto)
1560 x = self.loads(s)
1561 self.assertIsInstance(x, MyDict)
1562 self.assertEqual(len(list(x.keys())), 1)
1563 self.assertIsInstance(list(x.keys())[0], K)
1564 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001565
Jeremy Hylton66426532001-10-15 21:38:56 +00001566 def test_recursive_inst(self):
1567 i = C()
1568 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001569 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001570 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001571 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001572 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001573 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001574 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001575
1576 def test_recursive_multi(self):
1577 l = []
1578 d = {1:l}
1579 i = C()
1580 i.attr = d
1581 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001582 for proto in protocols:
1583 s = self.dumps(l, proto)
1584 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001585 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001586 self.assertEqual(len(x), 1)
1587 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001588 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001589 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001590
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001591 def check_recursive_collection_and_inst(self, factory):
1592 h = H()
1593 y = factory([h])
1594 h.attr = y
1595 for proto in protocols:
1596 s = self.dumps(y, proto)
1597 x = self.loads(s)
1598 self.assertIsInstance(x, type(y))
1599 self.assertEqual(len(x), 1)
1600 self.assertIsInstance(list(x)[0], H)
1601 self.assertIs(list(x)[0].attr, x)
1602
1603 def test_recursive_list_and_inst(self):
1604 self.check_recursive_collection_and_inst(list)
1605
1606 def test_recursive_tuple_and_inst(self):
1607 self.check_recursive_collection_and_inst(tuple)
1608
1609 def test_recursive_dict_and_inst(self):
1610 self.check_recursive_collection_and_inst(dict.fromkeys)
1611
1612 def test_recursive_set_and_inst(self):
1613 self.check_recursive_collection_and_inst(set)
1614
1615 def test_recursive_frozenset_and_inst(self):
1616 self.check_recursive_collection_and_inst(frozenset)
1617
1618 def test_recursive_list_subclass_and_inst(self):
1619 self.check_recursive_collection_and_inst(MyList)
1620
1621 def test_recursive_tuple_subclass_and_inst(self):
1622 self.check_recursive_collection_and_inst(MyTuple)
1623
1624 def test_recursive_dict_subclass_and_inst(self):
1625 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1626
1627 def test_recursive_set_subclass_and_inst(self):
1628 self.check_recursive_collection_and_inst(MySet)
1629
1630 def test_recursive_frozenset_subclass_and_inst(self):
1631 self.check_recursive_collection_and_inst(MyFrozenSet)
1632
Walter Dörwald9b775532007-06-08 14:30:53 +00001633 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001634 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001635 '<\\>', '<\\\U00012345>',
1636 # surrogates
1637 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001638 for proto in protocols:
1639 for u in endcases:
1640 p = self.dumps(u, proto)
1641 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001642 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001643
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001644 def test_unicode_high_plane(self):
1645 t = '\U00012345'
1646 for proto in protocols:
1647 p = self.dumps(t, proto)
1648 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001649 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001650
Guido van Rossumf4169812008-03-17 22:56:06 +00001651 def test_bytes(self):
1652 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001653 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001654 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001655 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001656 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001657 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001658 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001659 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001660 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001661 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001662
Antoine Pitrou91f43802019-05-26 17:10:09 +02001663 def test_bytearray(self):
1664 for proto in protocols:
1665 for s in b'', b'xyz', b'xyz'*100:
1666 b = bytearray(s)
1667 p = self.dumps(b, proto)
1668 bb = self.loads(p)
1669 self.assertIsNot(bb, b)
1670 self.assert_is_copy(b, bb)
1671 if proto <= 3:
1672 # bytearray is serialized using a global reference
1673 self.assertIn(b'bytearray', p)
1674 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1675 elif proto == 4:
1676 self.assertIn(b'bytearray', p)
1677 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1678 elif proto == 5:
1679 self.assertNotIn(b'bytearray', p)
1680 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1681
Jeremy Hylton66426532001-10-15 21:38:56 +00001682 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001683 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001684 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001685 while n:
1686 for expected in (-n, n):
1687 s = self.dumps(expected, proto)
1688 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001689 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001690 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001691
Tim Petersee1a53c2003-02-02 02:57:53 +00001692 def test_long(self):
1693 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001694 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001695 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001696 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001697 for npos in nbase-1, nbase, nbase+1:
1698 for n in npos, -npos:
1699 pickle = self.dumps(n, proto)
1700 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001701 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001702 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1703 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001704 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001705 nbase += nbase << 1000000
1706 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001707 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001708 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001709 # assert_is_copy is very expensive here as it precomputes
1710 # a failure message by computing the repr() of n and got,
1711 # we just do the check ourselves.
1712 self.assertIs(type(got), int)
1713 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001714
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001715 def test_float(self):
1716 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1717 3.14, 263.44582062374053, 6.022e23, 1e30]
1718 test_values = test_values + [-x for x in test_values]
1719 for proto in protocols:
1720 for value in test_values:
1721 pickle = self.dumps(value, proto)
1722 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001723 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001724
Thomas Wouters477c8d52006-05-27 19:21:47 +00001725 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1726 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001727 # make sure that floats are formatted locale independent with proto 0
1728 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001729
Jeremy Hylton66426532001-10-15 21:38:56 +00001730 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001731 for proto in protocols:
1732 inst = AAA()
1733 dumped = self.dumps(inst, proto)
1734 loaded = self.loads(dumped)
1735 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001736
1737 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001738 for proto in protocols:
1739 inst = initarg(1, 2)
1740 dumped = self.dumps(inst, proto)
1741 loaded = self.loads(dumped)
1742 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001743
Guido van Rossum04a86612001-12-19 16:58:54 +00001744 def test_metaclass(self):
1745 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001746 for proto in protocols:
1747 s = self.dumps(a, proto)
1748 b = self.loads(s)
1749 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001750
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001751 def test_dynamic_class(self):
1752 a = create_dynamic_class("my_dynamic_class", (object,))
1753 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1754 for proto in protocols:
1755 s = self.dumps(a, proto)
1756 b = self.loads(s)
1757 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001758 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001759
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001760 def test_structseq(self):
1761 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001762 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001763
1764 t = time.localtime()
1765 for proto in protocols:
1766 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001767 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001768 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001769 t = os.stat(os.curdir)
1770 s = self.dumps(t, proto)
1771 u = self.loads(s)
1772 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001773 if hasattr(os, "statvfs"):
1774 t = os.statvfs(os.curdir)
1775 s = self.dumps(t, proto)
1776 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001777 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001778
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001779 def test_ellipsis(self):
1780 for proto in protocols:
1781 s = self.dumps(..., proto)
1782 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001783 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001784
1785 def test_notimplemented(self):
1786 for proto in protocols:
1787 s = self.dumps(NotImplemented, proto)
1788 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001789 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001790
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001791 def test_singleton_types(self):
1792 # Issue #6477: Test that types of built-in singletons can be pickled.
1793 singletons = [None, ..., NotImplemented]
1794 for singleton in singletons:
1795 for proto in protocols:
1796 s = self.dumps(type(singleton), proto)
1797 u = self.loads(s)
1798 self.assertIs(type(singleton), u)
1799
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001800 # Tests for protocol 2
1801
Tim Peters4190fb82003-02-02 16:09:05 +00001802 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001803 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001804 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001805 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001806 proto_header = pickle.PROTO + bytes([proto])
1807 self.assertTrue(pickled.startswith(proto_header))
1808 else:
1809 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001810
1811 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001812 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001813 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001814 try:
1815 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001816 except ValueError as err:
1817 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001818 else:
1819 self.fail("expected bad protocol number to raise ValueError")
1820
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001821 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001822 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001823 for proto in protocols:
1824 s = self.dumps(x, proto)
1825 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001826 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001827 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001828
1829 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001830 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001831 for proto in protocols:
1832 s = self.dumps(x, proto)
1833 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001834 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001835 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001836
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001837 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001838 # Map (proto, len(tuple)) to expected opcode.
1839 expected_opcode = {(0, 0): pickle.TUPLE,
1840 (0, 1): pickle.TUPLE,
1841 (0, 2): pickle.TUPLE,
1842 (0, 3): pickle.TUPLE,
1843 (0, 4): pickle.TUPLE,
1844
1845 (1, 0): pickle.EMPTY_TUPLE,
1846 (1, 1): pickle.TUPLE,
1847 (1, 2): pickle.TUPLE,
1848 (1, 3): pickle.TUPLE,
1849 (1, 4): pickle.TUPLE,
1850
1851 (2, 0): pickle.EMPTY_TUPLE,
1852 (2, 1): pickle.TUPLE1,
1853 (2, 2): pickle.TUPLE2,
1854 (2, 3): pickle.TUPLE3,
1855 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001856
1857 (3, 0): pickle.EMPTY_TUPLE,
1858 (3, 1): pickle.TUPLE1,
1859 (3, 2): pickle.TUPLE2,
1860 (3, 3): pickle.TUPLE3,
1861 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001862 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001863 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001864 b = (1,)
1865 c = (1, 2)
1866 d = (1, 2, 3)
1867 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001868 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001869 for x in a, b, c, d, e:
1870 s = self.dumps(x, proto)
1871 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001872 self.assert_is_copy(x, y)
1873 expected = expected_opcode[min(proto, 3), len(x)]
1874 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001875
Guido van Rossum7d97d312003-01-28 04:25:27 +00001876 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001877 # Map (proto, singleton) to expected opcode.
1878 expected_opcode = {(0, None): pickle.NONE,
1879 (1, None): pickle.NONE,
1880 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001881 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001882
1883 (0, True): pickle.INT,
1884 (1, True): pickle.INT,
1885 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001886 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001887
1888 (0, False): pickle.INT,
1889 (1, False): pickle.INT,
1890 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001891 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001892 }
Tim Peters4190fb82003-02-02 16:09:05 +00001893 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001894 for x in None, False, True:
1895 s = self.dumps(x, proto)
1896 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001897 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001898 expected = expected_opcode[min(proto, 3), x]
1899 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001900
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001901 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001902 x = MyTuple([1, 2, 3])
1903 x.foo = 42
1904 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001905 for proto in protocols:
1906 s = self.dumps(x, proto)
1907 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001908 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001909
1910 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001911 x = MyList([1, 2, 3])
1912 x.foo = 42
1913 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001914 for proto in protocols:
1915 s = self.dumps(x, proto)
1916 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001917 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001918
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001919 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001920 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001921 for C in myclasses:
1922 B = C.__base__
1923 x = C(C.sample)
1924 x.foo = 42
1925 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001926 y = self.loads(s)
1927 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001928 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001929 self.assertEqual(B(x), B(y), detail)
1930 self.assertEqual(x.__dict__, y.__dict__, detail)
1931
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001932 def test_newobj_proxies(self):
1933 # NEWOBJ should use the __class__ rather than the raw type
1934 classes = myclasses[:]
1935 # Cannot create weakproxies to these classes
1936 for c in (MyInt, MyTuple):
1937 classes.remove(c)
1938 for proto in protocols:
1939 for C in classes:
1940 B = C.__base__
1941 x = C(C.sample)
1942 x.foo = 42
1943 p = weakref.proxy(x)
1944 s = self.dumps(p, proto)
1945 y = self.loads(s)
1946 self.assertEqual(type(y), type(x)) # rather than type(p)
1947 detail = (proto, C, B, x, y, type(y))
1948 self.assertEqual(B(x), B(y), detail)
1949 self.assertEqual(x.__dict__, y.__dict__, detail)
1950
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001951 def test_newobj_not_class(self):
1952 # Issue 24552
1953 global SimpleNewObj
1954 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001955 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001956 b = self.dumps(o, 4)
1957 try:
1958 SimpleNewObj = 42
1959 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1960 finally:
1961 SimpleNewObj = save
1962
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001963 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001964 # an object of that type. Check that the resulting pickle uses opcode
1965 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001966
Tim Peters22e71712003-02-03 22:27:38 +00001967 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001968 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001969 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001970 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001971 x = MyList([1, 2, 3])
1972 x.foo = 42
1973 x.bar = "hello"
1974
Tim Peters22e71712003-02-03 22:27:38 +00001975 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001976 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001977 self.assertIn(__name__.encode("utf-8"), s1)
1978 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001979 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001980
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001981 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001982 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001983
Tim Peters22e71712003-02-03 22:27:38 +00001984 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001985 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001986 self.assertNotIn(__name__.encode("utf-8"), s2)
1987 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001988 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001989
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001990 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001991 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001992 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001993 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001994
1995 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001996 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1997 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001998
1999 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002000 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
2001 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
2002 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002003
2004 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002005 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
2006 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
2007 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
2008
Tim Peters8d2613a2003-02-11 16:40:16 +00002009 def test_list_chunking(self):
2010 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002011 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002012 for proto in protocols:
2013 s = self.dumps(x, proto)
2014 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002015 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002016 num_appends = count_opcode(pickle.APPENDS, s)
2017 self.assertEqual(num_appends, proto > 0)
2018
2019 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002020 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002021 for proto in protocols:
2022 s = self.dumps(x, proto)
2023 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002024 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002025 num_appends = count_opcode(pickle.APPENDS, s)
2026 if proto == 0:
2027 self.assertEqual(num_appends, 0)
2028 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002029 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002030
2031 def test_dict_chunking(self):
2032 n = 10 # too small to chunk
2033 x = dict.fromkeys(range(n))
2034 for proto in protocols:
2035 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002036 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002037 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002038 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002039 num_setitems = count_opcode(pickle.SETITEMS, s)
2040 self.assertEqual(num_setitems, proto > 0)
2041
2042 n = 2500 # expect at least two chunks when proto > 0
2043 x = dict.fromkeys(range(n))
2044 for proto in protocols:
2045 s = self.dumps(x, proto)
2046 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002047 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002048 num_setitems = count_opcode(pickle.SETITEMS, s)
2049 if proto == 0:
2050 self.assertEqual(num_setitems, 0)
2051 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002052 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002053
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002054 def test_set_chunking(self):
2055 n = 10 # too small to chunk
2056 x = set(range(n))
2057 for proto in protocols:
2058 s = self.dumps(x, proto)
2059 y = self.loads(s)
2060 self.assert_is_copy(x, y)
2061 num_additems = count_opcode(pickle.ADDITEMS, s)
2062 if proto < 4:
2063 self.assertEqual(num_additems, 0)
2064 else:
2065 self.assertEqual(num_additems, 1)
2066
2067 n = 2500 # expect at least two chunks when proto >= 4
2068 x = set(range(n))
2069 for proto in protocols:
2070 s = self.dumps(x, proto)
2071 y = self.loads(s)
2072 self.assert_is_copy(x, y)
2073 num_additems = count_opcode(pickle.ADDITEMS, s)
2074 if proto < 4:
2075 self.assertEqual(num_additems, 0)
2076 else:
2077 self.assertGreaterEqual(num_additems, 2)
2078
Tim Peterse9ef2032003-02-13 18:42:00 +00002079 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002080 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002081 x.abc = 666
2082 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002083 with self.subTest(proto=proto):
2084 s = self.dumps(x, proto)
2085 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002086 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002087 else:
2088 self.assertIn(b'M\xce\xfa', s) # BININT2
2089 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2090 2 <= proto)
2091 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2092 y = self.loads(s) # will raise TypeError if __init__ called
2093 self.assert_is_copy(x, y)
2094
2095 def test_complex_newobj(self):
2096 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2097 x.abc = 666
2098 for proto in protocols:
2099 with self.subTest(proto=proto):
2100 s = self.dumps(x, proto)
2101 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002102 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002103 elif proto < 2:
2104 self.assertIn(b'M\xce\xfa', s) # BININT2
2105 elif proto < 4:
2106 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2107 else:
2108 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2109 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2110 2 <= proto)
2111 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2112 y = self.loads(s) # will raise TypeError if __init__ called
2113 self.assert_is_copy(x, y)
2114
2115 def test_complex_newobj_ex(self):
2116 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2117 x.abc = 666
2118 for proto in protocols:
2119 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002120 s = self.dumps(x, proto)
2121 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002122 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002123 elif proto < 2:
2124 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002125 elif proto < 4:
2126 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002127 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002128 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2129 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2130 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2131 4 <= proto)
2132 y = self.loads(s) # will raise TypeError if __init__ called
2133 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002134
Tim Peters42f08ac2003-02-11 22:43:24 +00002135 def test_newobj_list_slots(self):
2136 x = SlotList([1, 2, 3])
2137 x.foo = 42
2138 x.bar = "hello"
2139 s = self.dumps(x, 2)
2140 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002141 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002142
Guido van Rossum2a30b212003-02-18 22:41:24 +00002143 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002144 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002145 x = REX_one()
2146 self.assertEqual(x._reduce_called, 0)
2147 s = self.dumps(x, proto)
2148 self.assertEqual(x._reduce_called, 1)
2149 y = self.loads(s)
2150 self.assertEqual(y._reduce_called, 0)
2151
2152 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002153 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002154 x = REX_two()
2155 self.assertEqual(x._proto, None)
2156 s = self.dumps(x, proto)
2157 self.assertEqual(x._proto, proto)
2158 y = self.loads(s)
2159 self.assertEqual(y._proto, None)
2160
2161 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002162 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002163 x = REX_three()
2164 self.assertEqual(x._proto, None)
2165 s = self.dumps(x, proto)
2166 self.assertEqual(x._proto, proto)
2167 y = self.loads(s)
2168 self.assertEqual(y._proto, None)
2169
Guido van Rossumd8faa362007-04-27 19:54:29 +00002170 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002171 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002172 x = REX_four()
2173 self.assertEqual(x._proto, None)
2174 s = self.dumps(x, proto)
2175 self.assertEqual(x._proto, proto)
2176 y = self.loads(s)
2177 self.assertEqual(y._proto, proto)
2178
2179 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002180 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002181 x = REX_five()
2182 self.assertEqual(x._reduce_called, 0)
2183 s = self.dumps(x, proto)
2184 self.assertEqual(x._reduce_called, 1)
2185 y = self.loads(s)
2186 self.assertEqual(y._reduce_called, 1)
2187
Brett Cannon31f59292011-02-21 19:29:56 +00002188 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002189 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002190 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002191 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002192 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002193 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002194
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002195 def test_reduce_bad_iterator(self):
2196 # Issue4176: crash when 4th and 5th items of __reduce__()
2197 # are not iterators
2198 class C(object):
2199 def __reduce__(self):
2200 # 4th item is not an iterator
2201 return list, (), None, [], None
2202 class D(object):
2203 def __reduce__(self):
2204 # 5th item is not an iterator
2205 return dict, (), None, None, []
2206
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002207 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002208 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002209 try:
2210 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002211 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002212 pass
2213 try:
2214 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002215 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002216 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002217
Collin Winter771d8342009-04-16 03:18:06 +00002218 def test_many_puts_and_gets(self):
2219 # Test that internal data structures correctly deal with lots of
2220 # puts/gets.
2221 keys = ("aaa" + str(i) for i in range(100))
2222 large_dict = dict((k, [4, 5, 6]) for k in keys)
2223 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2224
2225 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002226 with self.subTest(proto=proto):
2227 dumped = self.dumps(obj, proto)
2228 loaded = self.loads(dumped)
2229 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002230
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002231 def test_attribute_name_interning(self):
2232 # Test that attribute names of pickled objects are interned when
2233 # unpickling.
2234 for proto in protocols:
2235 x = C()
2236 x.foo = 42
2237 x.bar = "hello"
2238 s = self.dumps(x, proto)
2239 y = self.loads(s)
2240 x_keys = sorted(x.__dict__)
2241 y_keys = sorted(y.__dict__)
2242 for x_key, y_key in zip(x_keys, y_keys):
2243 self.assertIs(x_key, y_key)
2244
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002245 def test_pickle_to_2x(self):
2246 # Pickle non-trivial data with protocol 2, expecting that it yields
2247 # the same result as Python 2.x did.
2248 # NOTE: this test is a bit too strong since we can produce different
2249 # bytecode that 2.x will still understand.
2250 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002251 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002252 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002253 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002254
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002255 def test_large_pickles(self):
2256 # Test the correctness of internal buffering routines when handling
2257 # large data.
2258 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002259 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002260 dumped = self.dumps(data, proto)
2261 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002262 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002263 self.assertEqual(loaded, data)
2264
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002265 def test_int_pickling_efficiency(self):
2266 # Test compacity of int representation (see issue #12744)
2267 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002268 with self.subTest(proto=proto):
2269 pickles = [self.dumps(2**n, proto) for n in range(70)]
2270 sizes = list(map(len, pickles))
2271 # the size function is monotonic
2272 self.assertEqual(sorted(sizes), sizes)
2273 if proto >= 2:
2274 for p in pickles:
2275 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002276
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002277 def _check_pickling_with_opcode(self, obj, opcode, proto):
2278 pickled = self.dumps(obj, proto)
2279 self.assertTrue(opcode_in_pickle(opcode, pickled))
2280 unpickled = self.loads(pickled)
2281 self.assertEqual(obj, unpickled)
2282
2283 def test_appends_on_non_lists(self):
2284 # Issue #17720
2285 obj = REX_six([1, 2, 3])
2286 for proto in protocols:
2287 if proto == 0:
2288 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2289 else:
2290 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2291
2292 def test_setitems_on_non_dicts(self):
2293 obj = REX_seven({1: -1, 2: -2, 3: -3})
2294 for proto in protocols:
2295 if proto == 0:
2296 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2297 else:
2298 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2299
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002300 # Exercise framing (proto >= 4) for significant workloads
2301
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002302 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002303 FRAME_SIZE_TARGET = 64 * 1024
2304
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002305 def check_frame_opcodes(self, pickled):
2306 """
2307 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002308
2309 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2310 framed by default and are therefore considered a frame by themselves in
2311 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002312 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002313 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002314 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2315 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002316 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002317 if frame_end is not None:
2318 self.assertLessEqual(pos, frame_end)
2319 if pos == frame_end:
2320 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002321
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002322 if frame_end is not None: # framed
2323 self.assertNotEqual(op.name, 'FRAME')
2324 if op.name in frameless_opcodes:
2325 # Only short bytes and str objects should be written
2326 # in a frame
2327 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2328
2329 else: # not framed
2330 if (op.name == 'FRAME' or
2331 (op.name in frameless_opcodes and
2332 len(arg) > self.FRAME_SIZE_TARGET)):
2333 # Frame or large bytes or str object
2334 if frameless_start is not None:
2335 # Only short data should be written outside of a frame
2336 self.assertLess(pos - frameless_start,
2337 self.FRAME_SIZE_MIN)
2338 frameless_start = None
2339 elif frameless_start is None and op.name != 'PROTO':
2340 frameless_start = pos
2341
2342 if op.name == 'FRAME':
2343 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2344 frame_end = pos + 9 + arg
2345
2346 pos = len(pickled)
2347 if frame_end is not None:
2348 self.assertEqual(frame_end, pos)
2349 elif frameless_start is not None:
2350 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002351
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002352 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002353 def test_framing_many_objects(self):
2354 obj = list(range(10**5))
2355 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2356 with self.subTest(proto=proto):
2357 pickled = self.dumps(obj, proto)
2358 unpickled = self.loads(pickled)
2359 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002360 bytes_per_frame = (len(pickled) /
2361 count_opcode(pickle.FRAME, pickled))
2362 self.assertGreater(bytes_per_frame,
2363 self.FRAME_SIZE_TARGET / 2)
2364 self.assertLessEqual(bytes_per_frame,
2365 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002366 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002367
2368 def test_framing_large_objects(self):
2369 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002370 small_items = [[i] for i in range(10)]
2371 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002372 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002373 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002374 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002375 if not fast:
2376 # fast=False by default.
2377 # This covers in-memory pickling with pickle.dumps().
2378 pickled = self.dumps(obj, proto)
2379 else:
2380 # Pickler is required when fast=True.
2381 if not hasattr(self, 'pickler'):
2382 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002383 buf = io.BytesIO()
2384 pickler = self.pickler(buf, protocol=proto)
2385 pickler.fast = fast
2386 pickler.dump(obj)
2387 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002388 unpickled = self.loads(pickled)
2389 # More informative error message in case of failure.
2390 self.assertEqual([len(x) for x in obj],
2391 [len(x) for x in unpickled])
2392 # Perform full equality check if the lengths match.
2393 self.assertEqual(obj, unpickled)
2394 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002395 # A single frame for small objects between
2396 # first two large objects.
2397 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002398 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002399
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002400 def test_optional_frames(self):
2401 if pickle.HIGHEST_PROTOCOL < 4:
2402 return
2403
2404 def remove_frames(pickled, keep_frame=None):
2405 """Remove frame opcodes from the given pickle."""
2406 frame_starts = []
2407 # 1 byte for the opcode and 8 for the argument
2408 frame_opcode_size = 9
2409 for opcode, _, pos in pickletools.genops(pickled):
2410 if opcode.name == 'FRAME':
2411 frame_starts.append(pos)
2412
2413 newpickle = bytearray()
2414 last_frame_end = 0
2415 for i, pos in enumerate(frame_starts):
2416 if keep_frame and keep_frame(i):
2417 continue
2418 newpickle += pickled[last_frame_end:pos]
2419 last_frame_end = pos + frame_opcode_size
2420 newpickle += pickled[last_frame_end:]
2421 return newpickle
2422
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002423 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002424 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002425 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002426 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002427 for bytes_type in (bytes, bytearray):
2428 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002429
Antoine Pitrou91f43802019-05-26 17:10:09 +02002430 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2431 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002432
Antoine Pitrou91f43802019-05-26 17:10:09 +02002433 frameless_pickle = remove_frames(pickled)
2434 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2435 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002436
Antoine Pitrou91f43802019-05-26 17:10:09 +02002437 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2438 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2439 count_opcode(pickle.FRAME, pickled))
2440 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002441
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002442 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002443 def test_framed_write_sizes_with_delayed_writer(self):
2444 class ChunkAccumulator:
2445 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002446 def __init__(self):
2447 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002448 def write(self, chunk):
2449 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002450 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002451 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002452
2453 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002454 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2455 for i in range(int(1e4))]
2456 # Add a large unique ASCII string
2457 objects.append('0123456789abcdef' *
2458 (self.FRAME_SIZE_TARGET // 16 + 1))
2459
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002460 # Protocol 4 packs groups of small objects into frames and issues
2461 # calls to write only once or twice per frame:
2462 # The C pickler issues one call to write per-frame (header and
2463 # contents) while Python pickler issues two calls to write: one for
2464 # the frame header and one for the frame binary contents.
2465 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002466 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002467
2468 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002469 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002470 # be released otherwise this delayed access would not be possible.
2471 pickled = writer.concatenate_chunks()
2472 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002473 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002474 self.assertGreater(len(writer.chunks), 1)
2475
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002476 # memoryviews should own the memory.
2477 del objects
2478 support.gc_collect()
2479 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002480
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002481 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002482 # There should be at least one call to write per frame
2483 self.assertGreaterEqual(len(writer.chunks), n_frames)
2484
2485 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002486 # one per-frame header, one per frame for the actual contents,
2487 # and two for the header.
2488 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002489
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002490 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002491 large_sizes = [s for s in chunk_sizes
2492 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002493 medium_sizes = [s for s in chunk_sizes
2494 if 9 < s < self.FRAME_SIZE_TARGET]
2495 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002496
2497 # Large chunks should not be too large:
2498 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002499 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2500 chunk_sizes)
2501 # There shouldn't bee too many small chunks: the protocol header,
2502 # the frame headers and the large string headers are written
2503 # in small chunks.
2504 self.assertLessEqual(len(small_sizes),
2505 len(large_sizes) + len(medium_sizes) + 3,
2506 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002507
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002508 def test_nested_names(self):
2509 global Nested
2510 class Nested:
2511 class A:
2512 class B:
2513 class C:
2514 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002515 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002516 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2517 with self.subTest(proto=proto, obj=obj):
2518 unpickled = self.loads(self.dumps(obj, proto))
2519 self.assertIs(obj, unpickled)
2520
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002521 def test_recursive_nested_names(self):
2522 global Recursive
2523 class Recursive:
2524 pass
2525 Recursive.mod = sys.modules[Recursive.__module__]
2526 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2527 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2528 with self.subTest(proto=proto):
2529 unpickled = self.loads(self.dumps(Recursive, proto))
2530 self.assertIs(unpickled, Recursive)
2531 del Recursive.mod # break reference loop
2532
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002533 def test_py_methods(self):
2534 global PyMethodsTest
2535 class PyMethodsTest:
2536 @staticmethod
2537 def cheese():
2538 return "cheese"
2539 @classmethod
2540 def wine(cls):
2541 assert cls is PyMethodsTest
2542 return "wine"
2543 def biscuits(self):
2544 assert isinstance(self, PyMethodsTest)
2545 return "biscuits"
2546 class Nested:
2547 "Nested class"
2548 @staticmethod
2549 def ketchup():
2550 return "ketchup"
2551 @classmethod
2552 def maple(cls):
2553 assert cls is PyMethodsTest.Nested
2554 return "maple"
2555 def pie(self):
2556 assert isinstance(self, PyMethodsTest.Nested)
2557 return "pie"
2558
2559 py_methods = (
2560 PyMethodsTest.cheese,
2561 PyMethodsTest.wine,
2562 PyMethodsTest().biscuits,
2563 PyMethodsTest.Nested.ketchup,
2564 PyMethodsTest.Nested.maple,
2565 PyMethodsTest.Nested().pie
2566 )
2567 py_unbound_methods = (
2568 (PyMethodsTest.biscuits, PyMethodsTest),
2569 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2570 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002571 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002572 for method in py_methods:
2573 with self.subTest(proto=proto, method=method):
2574 unpickled = self.loads(self.dumps(method, proto))
2575 self.assertEqual(method(), unpickled())
2576 for method, cls in py_unbound_methods:
2577 obj = cls()
2578 with self.subTest(proto=proto, method=method):
2579 unpickled = self.loads(self.dumps(method, proto))
2580 self.assertEqual(method(obj), unpickled(obj))
2581
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002582 def test_c_methods(self):
2583 global Subclass
2584 class Subclass(tuple):
2585 class Nested(str):
2586 pass
2587
2588 c_methods = (
2589 # bound built-in method
2590 ("abcd".index, ("c",)),
2591 # unbound built-in method
2592 (str.index, ("abcd", "c")),
2593 # bound "slot" method
2594 ([1, 2, 3].__len__, ()),
2595 # unbound "slot" method
2596 (list.__len__, ([1, 2, 3],)),
2597 # bound "coexist" method
2598 ({1, 2}.__contains__, (2,)),
2599 # unbound "coexist" method
2600 (set.__contains__, ({1, 2}, 2)),
2601 # built-in class method
2602 (dict.fromkeys, (("a", 1), ("b", 2))),
2603 # built-in static method
2604 (bytearray.maketrans, (b"abc", b"xyz")),
2605 # subclass methods
2606 (Subclass([1,2,2]).count, (2,)),
2607 (Subclass.count, (Subclass([1,2,2]), 2)),
2608 (Subclass.Nested("sweet").count, ("e",)),
2609 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2610 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002611 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002612 for method, args in c_methods:
2613 with self.subTest(proto=proto, method=method):
2614 unpickled = self.loads(self.dumps(method, proto))
2615 self.assertEqual(method(*args), unpickled(*args))
2616
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002617 def test_compat_pickle(self):
2618 tests = [
2619 (range(1, 7), '__builtin__', 'xrange'),
2620 (map(int, '123'), 'itertools', 'imap'),
2621 (functools.reduce, '__builtin__', 'reduce'),
2622 (dbm.whichdb, 'whichdb', 'whichdb'),
2623 (Exception(), 'exceptions', 'Exception'),
2624 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2625 (collections.UserList(), 'UserList', 'UserList'),
2626 (collections.defaultdict(), 'collections', 'defaultdict'),
2627 ]
2628 for val, mod, name in tests:
2629 for proto in range(3):
2630 with self.subTest(type=type(val), proto=proto):
2631 pickled = self.dumps(val, proto)
2632 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2633 self.assertIs(type(self.loads(pickled)), type(val))
2634
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002635 def test_local_lookup_error(self):
2636 # Test that whichmodule() errors out cleanly when looking up
2637 # an assumed globally-reachable object fails.
2638 def f():
2639 pass
2640 # Since the function is local, lookup will fail
2641 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2642 with self.assertRaises((AttributeError, pickle.PicklingError)):
2643 pickletools.dis(self.dumps(f, proto))
2644 # Same without a __module__ attribute (exercises a different path
2645 # in _pickle.c).
2646 del f.__module__
2647 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2648 with self.assertRaises((AttributeError, pickle.PicklingError)):
2649 pickletools.dis(self.dumps(f, proto))
2650 # Yet a different path.
2651 f.__name__ = f.__qualname__
2652 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2653 with self.assertRaises((AttributeError, pickle.PicklingError)):
2654 pickletools.dis(self.dumps(f, proto))
2655
Antoine Pitrou91f43802019-05-26 17:10:09 +02002656 #
2657 # PEP 574 tests below
2658 #
2659
2660 def buffer_like_objects(self):
2661 # Yield buffer-like objects with the bytestring "abcdef" in them
2662 bytestring = b"abcdefgh"
2663 yield ZeroCopyBytes(bytestring)
2664 yield ZeroCopyBytearray(bytestring)
2665 if _testbuffer is not None:
2666 items = list(bytestring)
2667 value = int.from_bytes(bytestring, byteorder='little')
2668 for flags in (0, _testbuffer.ND_WRITABLE):
2669 # 1-D, contiguous
2670 yield PicklableNDArray(items, format='B', shape=(8,),
2671 flags=flags)
2672 # 2-D, C-contiguous
2673 yield PicklableNDArray(items, format='B', shape=(4, 2),
2674 strides=(2, 1), flags=flags)
2675 # 2-D, Fortran-contiguous
2676 yield PicklableNDArray(items, format='B',
2677 shape=(4, 2), strides=(1, 4),
2678 flags=flags)
2679
2680 def test_in_band_buffers(self):
2681 # Test in-band buffers (PEP 574)
2682 for obj in self.buffer_like_objects():
2683 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2684 data = self.dumps(obj, proto)
2685 if obj.c_contiguous and proto >= 5:
2686 # The raw memory bytes are serialized in physical order
2687 self.assertIn(b"abcdefgh", data)
2688 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2689 if proto >= 5:
2690 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2691 1 if obj.readonly else 0)
2692 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2693 0 if obj.readonly else 1)
2694 # Return a true value from buffer_callback should have
2695 # the same effect
2696 def buffer_callback(obj):
2697 return True
2698 data2 = self.dumps(obj, proto,
2699 buffer_callback=buffer_callback)
2700 self.assertEqual(data2, data)
2701
2702 new = self.loads(data)
2703 # It's a copy
2704 self.assertIsNot(new, obj)
2705 self.assertIs(type(new), type(obj))
2706 self.assertEqual(new, obj)
2707
2708 # XXX Unfortunately cannot test non-contiguous array
2709 # (see comment in PicklableNDArray.__reduce_ex__)
2710
2711 def test_oob_buffers(self):
2712 # Test out-of-band buffers (PEP 574)
2713 for obj in self.buffer_like_objects():
2714 for proto in range(0, 5):
2715 # Need protocol >= 5 for buffer_callback
2716 with self.assertRaises(ValueError):
2717 self.dumps(obj, proto,
2718 buffer_callback=[].append)
2719 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2720 buffers = []
2721 buffer_callback = lambda pb: buffers.append(pb.raw())
2722 data = self.dumps(obj, proto,
2723 buffer_callback=buffer_callback)
2724 self.assertNotIn(b"abcdefgh", data)
2725 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2726 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2727 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2728 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2729 1 if obj.readonly else 0)
2730
2731 if obj.c_contiguous:
2732 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2733 # Need buffers argument to unpickle properly
2734 with self.assertRaises(pickle.UnpicklingError):
2735 self.loads(data)
2736
2737 new = self.loads(data, buffers=buffers)
2738 if obj.zero_copy_reconstruct:
2739 # Zero-copy achieved
2740 self.assertIs(new, obj)
2741 else:
2742 self.assertIs(type(new), type(obj))
2743 self.assertEqual(new, obj)
2744 # Non-sequence buffers accepted too
2745 new = self.loads(data, buffers=iter(buffers))
2746 if obj.zero_copy_reconstruct:
2747 # Zero-copy achieved
2748 self.assertIs(new, obj)
2749 else:
2750 self.assertIs(type(new), type(obj))
2751 self.assertEqual(new, obj)
2752
2753 def test_oob_buffers_writable_to_readonly(self):
2754 # Test reconstructing readonly object from writable buffer
2755 obj = ZeroCopyBytes(b"foobar")
2756 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2757 buffers = []
2758 buffer_callback = buffers.append
2759 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2760
2761 buffers = map(bytearray, buffers)
2762 new = self.loads(data, buffers=buffers)
2763 self.assertIs(type(new), type(obj))
2764 self.assertEqual(new, obj)
2765
2766 def test_picklebuffer_error(self):
2767 # PickleBuffer forbidden with protocol < 5
2768 pb = pickle.PickleBuffer(b"foobar")
2769 for proto in range(0, 5):
2770 with self.assertRaises(pickle.PickleError):
2771 self.dumps(pb, proto)
2772
2773 def test_buffer_callback_error(self):
2774 def buffer_callback(buffers):
2775 1/0
2776 pb = pickle.PickleBuffer(b"foobar")
2777 with self.assertRaises(ZeroDivisionError):
2778 self.dumps(pb, 5, buffer_callback=buffer_callback)
2779
2780 def test_buffers_error(self):
2781 pb = pickle.PickleBuffer(b"foobar")
2782 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2783 data = self.dumps(pb, proto, buffer_callback=[].append)
2784 # Non iterable buffers
2785 with self.assertRaises(TypeError):
2786 self.loads(data, buffers=object())
2787 # Buffer iterable exhausts too early
2788 with self.assertRaises(pickle.UnpicklingError):
2789 self.loads(data, buffers=[])
2790
Markus Mohrhard898318b2019-07-26 00:00:34 +08002791 def test_inband_accept_default_buffers_argument(self):
2792 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2793 data_pickled = self.dumps(1, proto, buffer_callback=None)
2794 data = self.loads(data_pickled, buffers=None)
2795
Antoine Pitrou91f43802019-05-26 17:10:09 +02002796 @unittest.skipIf(np is None, "Test needs Numpy")
2797 def test_buffers_numpy(self):
2798 def check_no_copy(x, y):
2799 np.testing.assert_equal(x, y)
2800 self.assertEqual(x.ctypes.data, y.ctypes.data)
2801
2802 def check_copy(x, y):
2803 np.testing.assert_equal(x, y)
2804 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2805
2806 def check_array(arr):
2807 # In-band
2808 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2809 data = self.dumps(arr, proto)
2810 new = self.loads(data)
2811 check_copy(arr, new)
2812 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2813 buffer_callback = lambda _: True
2814 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2815 new = self.loads(data)
2816 check_copy(arr, new)
2817 # Out-of-band
2818 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2819 buffers = []
2820 buffer_callback = buffers.append
2821 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2822 new = self.loads(data, buffers=buffers)
2823 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2824 check_no_copy(arr, new)
2825 else:
2826 check_copy(arr, new)
2827
2828 # 1-D
2829 arr = np.arange(6)
2830 check_array(arr)
2831 # 1-D, non-contiguous
2832 check_array(arr[::2])
2833 # 2-D, C-contiguous
2834 arr = np.arange(12).reshape((3, 4))
2835 check_array(arr)
2836 # 2-D, F-contiguous
2837 check_array(arr.T)
2838 # 2-D, non-contiguous
2839 check_array(arr[::2])
2840
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002841
2842class BigmemPickleTests(unittest.TestCase):
2843
Victor Stinner8c663fd2017-11-08 14:44:44 -08002844 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002845
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002846 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002847 def test_huge_long_32b(self, size):
2848 data = 1 << (8 * size)
2849 try:
2850 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002851 if proto < 2:
2852 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002853 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002854 with self.assertRaises((ValueError, OverflowError)):
2855 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002856 finally:
2857 data = None
2858
Victor Stinner8c663fd2017-11-08 14:44:44 -08002859 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002860 # (older protocols don't have a dedicated opcode for bytes and are
2861 # too inefficient)
2862
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002863 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002864 def test_huge_bytes_32b(self, size):
2865 data = b"abcd" * (size // 4)
2866 try:
2867 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002868 if proto < 3:
2869 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002870 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002871 try:
2872 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002873 header = (pickle.BINBYTES +
2874 struct.pack("<I", len(data)))
2875 data_start = pickled.index(data)
2876 self.assertEqual(
2877 header,
2878 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002879 finally:
2880 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002881 finally:
2882 data = None
2883
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002884 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002885 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002886 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002887 try:
2888 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002889 if proto < 3:
2890 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002891 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002892 if proto == 3:
2893 # Protocol 3 does not support large bytes objects.
2894 # Verify that we do not crash when processing one.
2895 with self.assertRaises((ValueError, OverflowError)):
2896 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002897 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002898 try:
2899 pickled = self.dumps(data, protocol=proto)
2900 header = (pickle.BINBYTES8 +
2901 struct.pack("<Q", len(data)))
2902 data_start = pickled.index(data)
2903 self.assertEqual(
2904 header,
2905 pickled[data_start-len(header):data_start])
2906 finally:
2907 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002908 finally:
2909 data = None
2910
2911 # All protocols use 1-byte per printable ASCII character; we add another
2912 # byte because the encoded form has to be copied into the internal buffer.
2913
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002914 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002915 def test_huge_str_32b(self, size):
2916 data = "abcd" * (size // 4)
2917 try:
2918 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002919 if proto == 0:
2920 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002921 with self.subTest(proto=proto):
2922 try:
2923 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002924 header = (pickle.BINUNICODE +
2925 struct.pack("<I", len(data)))
2926 data_start = pickled.index(b'abcd')
2927 self.assertEqual(
2928 header,
2929 pickled[data_start-len(header):data_start])
2930 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2931 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002932 finally:
2933 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002934 finally:
2935 data = None
2936
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002937 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2938 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2939 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002940
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002941 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002942 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002943 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002944 try:
2945 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002946 if proto == 0:
2947 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002948 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002949 if proto < 4:
2950 with self.assertRaises((ValueError, OverflowError)):
2951 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002952 continue
2953 try:
2954 pickled = self.dumps(data, protocol=proto)
2955 header = (pickle.BINUNICODE8 +
2956 struct.pack("<Q", len(data)))
2957 data_start = pickled.index(b'abcd')
2958 self.assertEqual(
2959 header,
2960 pickled[data_start-len(header):data_start])
2961 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2962 pickled.index(b"abcd")), len(data))
2963 finally:
2964 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002965 finally:
2966 data = None
2967
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002968
Guido van Rossum2a30b212003-02-18 22:41:24 +00002969# Test classes for reduce_ex
2970
2971class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002972 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002973 _reduce_called = 0
2974 def __reduce__(self):
2975 self._reduce_called = 1
2976 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002977
2978class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002979 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002980 _proto = None
2981 def __reduce_ex__(self, proto):
2982 self._proto = proto
2983 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002984
2985class REX_three(object):
2986 _proto = None
2987 def __reduce_ex__(self, proto):
2988 self._proto = proto
2989 return REX_two, ()
2990 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002991 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002992
Guido van Rossumd8faa362007-04-27 19:54:29 +00002993class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002994 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002995 _proto = None
2996 def __reduce_ex__(self, proto):
2997 self._proto = proto
2998 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002999
3000class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003001 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003002 _reduce_called = 0
3003 def __reduce__(self):
3004 self._reduce_called = 1
3005 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003006
3007class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003008 """This class is used to check the 4th argument (list iterator) of
3009 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003010 """
3011 def __init__(self, items=None):
3012 self.items = items if items is not None else []
3013 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003014 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003015 def append(self, item):
3016 self.items.append(item)
3017 def __reduce__(self):
3018 return type(self), (), None, iter(self.items), None
3019
3020class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003021 """This class is used to check the 5th argument (dict iterator) of
3022 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003023 """
3024 def __init__(self, table=None):
3025 self.table = table if table is not None else {}
3026 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003027 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003028 def __setitem__(self, key, value):
3029 self.table[key] = value
3030 def __reduce__(self):
3031 return type(self), (), None, None, iter(self.table.items())
3032
Guido van Rossumd8faa362007-04-27 19:54:29 +00003033
Guido van Rossum2a30b212003-02-18 22:41:24 +00003034# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003035
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003036class MyInt(int):
3037 sample = 1
3038
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003039class MyFloat(float):
3040 sample = 1.0
3041
3042class MyComplex(complex):
3043 sample = 1.0 + 0.0j
3044
3045class MyStr(str):
3046 sample = "hello"
3047
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003048class MyUnicode(str):
3049 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003050
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003051class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003052 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003053
3054class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003055 sample = [1, 2, 3]
3056
3057class MyDict(dict):
3058 sample = {"a": 1, "b": 2}
3059
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003060class MySet(set):
3061 sample = {"a", "b"}
3062
3063class MyFrozenSet(frozenset):
3064 sample = frozenset({"a", "b"})
3065
Mark Dickinson5c2db372009-12-05 20:28:34 +00003066myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003067 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003068 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003069 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003070
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003071
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003072class SlotList(MyList):
3073 __slots__ = ["foo"]
3074
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003075class SimpleNewObj(int):
3076 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003077 # raise an error, to make sure this isn't called
3078 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003079 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003080 return int(self) == int(other) and self.__dict__ == other.__dict__
3081
3082class ComplexNewObj(SimpleNewObj):
3083 def __getnewargs__(self):
3084 return ('%X' % self, 16)
3085
3086class ComplexNewObjEx(SimpleNewObj):
3087 def __getnewargs_ex__(self):
3088 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003089
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003090class BadGetattr:
3091 def __getattr__(self, key):
3092 self.foo
3093
Collin Winter771d8342009-04-16 03:18:06 +00003094
Jeremy Hylton66426532001-10-15 21:38:56 +00003095class AbstractPickleModuleTests(unittest.TestCase):
3096
3097 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003098 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003099 try:
3100 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003101 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003102 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003103 support.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003104
3105 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003106 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003107 try:
3108 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003109 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003110 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003111 support.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003112
Collin Winter771d8342009-04-16 03:18:06 +00003113 def test_load_from_and_dump_to_file(self):
3114 stream = io.BytesIO()
3115 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003116 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003117 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003118 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003119 self.assertEqual(unpickled, data)
3120
Tim Petersc0c93702003-02-13 19:30:57 +00003121 def test_highest_protocol(self):
3122 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003123 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003124
Martin v. Löwis544f1192004-07-27 05:22:33 +00003125 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003126 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003127 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003128 self.dump(123, f, -1)
3129 self.dump(123, file=f, protocol=-1)
3130 self.dumps(123, -1)
3131 self.dumps(123, protocol=-1)
3132 self.Pickler(f, -1)
3133 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003134
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003135 def test_dump_text_file(self):
3136 f = open(TESTFN, "w")
3137 try:
3138 for proto in protocols:
3139 self.assertRaises(TypeError, self.dump, 123, f, proto)
3140 finally:
3141 f.close()
3142 support.unlink(TESTFN)
3143
3144 def test_incomplete_input(self):
3145 s = io.BytesIO(b"X''.")
3146 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3147
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003148 def test_bad_init(self):
3149 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003150 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003151 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003152 def __init__(self): pass
3153
Serhiy Storchaka65452562017-11-15 14:01:08 +02003154 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003155 def __init__(self): pass
3156
3157 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3158 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3159
Antoine Pitrou91f43802019-05-26 17:10:09 +02003160 def check_dumps_loads_oob_buffers(self, dumps, loads):
3161 # No need to do the full gamut of tests here, just enough to
3162 # check that dumps() and loads() redirect their arguments
3163 # to the underlying Pickler and Unpickler, respectively.
3164 obj = ZeroCopyBytes(b"foo")
3165
3166 for proto in range(0, 5):
3167 # Need protocol >= 5 for buffer_callback
3168 with self.assertRaises(ValueError):
3169 dumps(obj, protocol=proto,
3170 buffer_callback=[].append)
3171 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3172 buffers = []
3173 buffer_callback = buffers.append
3174 data = dumps(obj, protocol=proto,
3175 buffer_callback=buffer_callback)
3176 self.assertNotIn(b"foo", data)
3177 self.assertEqual(bytes(buffers[0]), b"foo")
3178 # Need buffers argument to unpickle properly
3179 with self.assertRaises(pickle.UnpicklingError):
3180 loads(data)
3181 new = loads(data, buffers=buffers)
3182 self.assertIs(new, obj)
3183
3184 def test_dumps_loads_oob_buffers(self):
3185 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3186 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3187
3188 def test_dump_load_oob_buffers(self):
3189 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3190 def dumps(obj, **kwargs):
3191 f = io.BytesIO()
3192 self.dump(obj, f, **kwargs)
3193 return f.getvalue()
3194
3195 def loads(data, **kwargs):
3196 f = io.BytesIO(data)
3197 return self.load(f, **kwargs)
3198
3199 self.check_dumps_loads_oob_buffers(dumps, loads)
3200
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003201
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003202class AbstractPersistentPicklerTests(unittest.TestCase):
3203
3204 # This class defines persistent_id() and persistent_load()
3205 # functions that should be used by the pickler. All even integers
3206 # are pickled using persistent ids.
3207
3208 def persistent_id(self, object):
3209 if isinstance(object, int) and object % 2 == 0:
3210 self.id_count += 1
3211 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003212 elif object == "test_false_value":
3213 self.false_count += 1
3214 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003215 else:
3216 return None
3217
3218 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003219 if not oid:
3220 self.load_false_count += 1
3221 return "test_false_value"
3222 else:
3223 self.load_count += 1
3224 object = int(oid)
3225 assert object % 2 == 0
3226 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003227
3228 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003229 L = list(range(10)) + ["test_false_value"]
3230 for proto in protocols:
3231 self.id_count = 0
3232 self.false_count = 0
3233 self.load_false_count = 0
3234 self.load_count = 0
3235 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3236 self.assertEqual(self.id_count, 5)
3237 self.assertEqual(self.false_count, 1)
3238 self.assertEqual(self.load_count, 5)
3239 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003240
Collin Winter771d8342009-04-16 03:18:06 +00003241
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003242class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3243
3244 def persistent_id(self, obj):
3245 return obj
3246
3247 def persistent_load(self, pid):
3248 return pid
3249
3250 def _check_return_correct_type(self, obj, proto):
3251 unpickled = self.loads(self.dumps(obj, proto))
3252 self.assertIsInstance(unpickled, type(obj))
3253 self.assertEqual(unpickled, obj)
3254
3255 def test_return_correct_type(self):
3256 for proto in protocols:
3257 # Protocol 0 supports only ASCII strings.
3258 if proto == 0:
3259 self._check_return_correct_type("abc", 0)
3260 else:
3261 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3262 self._check_return_correct_type(obj, proto)
3263
3264 def test_protocol0_is_ascii_only(self):
3265 non_ascii_str = "\N{EMPTY SET}"
3266 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3267 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3268 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3269
3270
Collin Winter771d8342009-04-16 03:18:06 +00003271class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3272
3273 pickler_class = None
3274 unpickler_class = None
3275
3276 def setUp(self):
3277 assert self.pickler_class
3278 assert self.unpickler_class
3279
3280 def test_clear_pickler_memo(self):
3281 # To test whether clear_memo() has any effect, we pickle an object,
3282 # then pickle it again without clearing the memo; the two serialized
3283 # forms should be different. If we clear_memo() and then pickle the
3284 # object again, the third serialized form should be identical to the
3285 # first one we obtained.
3286 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003287 for proto in protocols:
3288 f = io.BytesIO()
3289 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003290
Serhiy Storchakac8695292018-04-04 00:11:27 +03003291 pickler.dump(data)
3292 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003293
Serhiy Storchakac8695292018-04-04 00:11:27 +03003294 # Reset BytesIO object.
3295 f.seek(0)
3296 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003297
Serhiy Storchakac8695292018-04-04 00:11:27 +03003298 pickler.dump(data)
3299 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003300
Serhiy Storchakac8695292018-04-04 00:11:27 +03003301 # Reset the Pickler and BytesIO objects.
3302 pickler.clear_memo()
3303 f.seek(0)
3304 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003305
Serhiy Storchakac8695292018-04-04 00:11:27 +03003306 pickler.dump(data)
3307 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003308
Serhiy Storchakac8695292018-04-04 00:11:27 +03003309 self.assertNotEqual(first_pickled, second_pickled)
3310 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003311
3312 def test_priming_pickler_memo(self):
3313 # Verify that we can set the Pickler's memo attribute.
3314 data = ["abcdefg", "abcdefg", 44]
3315 f = io.BytesIO()
3316 pickler = self.pickler_class(f)
3317
3318 pickler.dump(data)
3319 first_pickled = f.getvalue()
3320
3321 f = io.BytesIO()
3322 primed = self.pickler_class(f)
3323 primed.memo = pickler.memo
3324
3325 primed.dump(data)
3326 primed_pickled = f.getvalue()
3327
3328 self.assertNotEqual(first_pickled, primed_pickled)
3329
3330 def test_priming_unpickler_memo(self):
3331 # Verify that we can set the Unpickler's memo attribute.
3332 data = ["abcdefg", "abcdefg", 44]
3333 f = io.BytesIO()
3334 pickler = self.pickler_class(f)
3335
3336 pickler.dump(data)
3337 first_pickled = f.getvalue()
3338
3339 f = io.BytesIO()
3340 primed = self.pickler_class(f)
3341 primed.memo = pickler.memo
3342
3343 primed.dump(data)
3344 primed_pickled = f.getvalue()
3345
3346 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3347 unpickled_data1 = unpickler.load()
3348
3349 self.assertEqual(unpickled_data1, data)
3350
3351 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3352 primed.memo = unpickler.memo
3353 unpickled_data2 = primed.load()
3354
3355 primed.memo.clear()
3356
3357 self.assertEqual(unpickled_data2, data)
3358 self.assertTrue(unpickled_data2 is unpickled_data1)
3359
3360 def test_reusing_unpickler_objects(self):
3361 data1 = ["abcdefg", "abcdefg", 44]
3362 f = io.BytesIO()
3363 pickler = self.pickler_class(f)
3364 pickler.dump(data1)
3365 pickled1 = f.getvalue()
3366
3367 data2 = ["abcdefg", 44, 44]
3368 f = io.BytesIO()
3369 pickler = self.pickler_class(f)
3370 pickler.dump(data2)
3371 pickled2 = f.getvalue()
3372
3373 f = io.BytesIO()
3374 f.write(pickled1)
3375 f.seek(0)
3376 unpickler = self.unpickler_class(f)
3377 self.assertEqual(unpickler.load(), data1)
3378
3379 f.seek(0)
3380 f.truncate()
3381 f.write(pickled2)
3382 f.seek(0)
3383 self.assertEqual(unpickler.load(), data2)
3384
Antoine Pitrou9f378722020-02-23 23:33:53 +01003385 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003386 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003387 with self.subTest(proto=proto):
3388 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3389 f = ioclass()
3390 pickler = self.pickler_class(f, protocol=proto)
3391 pickler.dump(data1)
3392 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003393
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003394 N = 5
3395 f = ioclass(pickled * N)
3396 unpickler = self.unpickler_class(f)
3397 for i in range(N):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003398 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003399 pos = f.tell()
3400 self.assertEqual(unpickler.load(), data1)
Antoine Pitrou9f378722020-02-23 23:33:53 +01003401 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003402 self.assertEqual(f.tell(), pos + len(pickled))
3403 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003404
3405 def test_multiple_unpicklings_seekable(self):
3406 self._check_multiple_unpicklings(io.BytesIO)
3407
3408 def test_multiple_unpicklings_unseekable(self):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003409 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3410
3411 def test_multiple_unpicklings_minimal(self):
3412 # File-like object that doesn't support peek() and readinto()
3413 # (bpo-39681)
3414 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003415
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003416 def test_unpickling_buffering_readline(self):
3417 # Issue #12687: the unpickler's buffering logic could fail with
3418 # text mode opcodes.
3419 data = list(range(10))
3420 for proto in protocols:
3421 for buf_size in range(1, 11):
3422 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3423 pickler = self.pickler_class(f, protocol=proto)
3424 pickler.dump(data)
3425 f.seek(0)
3426 unpickler = self.unpickler_class(f)
3427 self.assertEqual(unpickler.load(), data)
3428
Collin Winter771d8342009-04-16 03:18:06 +00003429
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003430# Tests for dispatch_table attribute
3431
3432REDUCE_A = 'reduce_A'
3433
3434class AAA(object):
3435 def __reduce__(self):
3436 return str, (REDUCE_A,)
3437
3438class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003439 def __init__(self):
3440 # Add an instance attribute to enable state-saving routines at pickling
3441 # time.
3442 self.a = "some attribute"
3443
3444 def __setstate__(self, state):
3445 self.a = "BBB.__setstate__"
3446
3447
3448def setstate_bbb(obj, state):
3449 """Custom state setter for BBB objects
3450
3451 Such callable may be created by other persons than the ones who created the
3452 BBB class. If passed as the state_setter item of a custom reducer, this
3453 allows for custom state setting behavior of BBB objects. One can think of
3454 it as the analogous of list_setitems or dict_setitems but for foreign
3455 classes/functions.
3456 """
3457 obj.a = "custom state_setter"
3458
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003459
Pierre Glaser289f1f82019-05-08 23:08:25 +02003460
3461class AbstractCustomPicklerClass:
3462 """Pickler implementing a reducing hook using reducer_override."""
3463 def reducer_override(self, obj):
3464 obj_name = getattr(obj, "__name__", None)
3465
3466 if obj_name == 'f':
3467 # asking the pickler to save f as 5
3468 return int, (5, )
3469
3470 if obj_name == 'MyClass':
3471 return str, ('some str',)
3472
3473 elif obj_name == 'g':
3474 # in this case, the callback returns an invalid result (not a 2-5
3475 # tuple or a string), the pickler should raise a proper error.
3476 return False
3477
3478 elif obj_name == 'h':
3479 # Simulate a case when the reducer fails. The error should
3480 # be propagated to the original ``dump`` call.
3481 raise ValueError('The reducer just failed')
3482
3483 return NotImplemented
3484
3485class AbstractHookTests(unittest.TestCase):
3486 def test_pickler_hook(self):
3487 # test the ability of a custom, user-defined CPickler subclass to
3488 # override the default reducing routines of any type using the method
3489 # reducer_override
3490
3491 def f():
3492 pass
3493
3494 def g():
3495 pass
3496
3497 def h():
3498 pass
3499
3500 class MyClass:
3501 pass
3502
3503 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3504 with self.subTest(proto=proto):
3505 bio = io.BytesIO()
3506 p = self.pickler_class(bio, proto)
3507
3508 p.dump([f, MyClass, math.log])
3509 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3510
3511 self.assertEqual(new_f, 5)
3512 self.assertEqual(some_str, 'some str')
3513 # math.log does not have its usual reducer overriden, so the
3514 # custom reduction callback should silently direct the pickler
3515 # to the default pickling by attribute, by returning
3516 # NotImplemented
3517 self.assertIs(math_log, math.log)
3518
3519 with self.assertRaises(pickle.PicklingError):
3520 p.dump(g)
3521
3522 with self.assertRaisesRegex(
3523 ValueError, 'The reducer just failed'):
3524 p.dump(h)
3525
Pierre Glaser0f2f35e2020-02-02 19:55:21 +01003526 @support.cpython_only
3527 def test_reducer_override_no_reference_cycle(self):
3528 # bpo-39492: reducer_override used to induce a spurious reference cycle
3529 # inside the Pickler object, that could prevent all serialized objects
3530 # from being garbage-collected without explicity invoking gc.collect.
3531
3532 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3533 with self.subTest(proto=proto):
3534 def f():
3535 pass
3536
3537 wr = weakref.ref(f)
3538
3539 bio = io.BytesIO()
3540 p = self.pickler_class(bio, proto)
3541 p.dump(f)
3542 new_f = pickle.loads(bio.getvalue())
3543 assert new_f == 5
3544
3545 del p
3546 del f
3547
3548 self.assertIsNone(wr())
3549
Pierre Glaser289f1f82019-05-08 23:08:25 +02003550
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003551class AbstractDispatchTableTests(unittest.TestCase):
3552
3553 def test_default_dispatch_table(self):
3554 # No dispatch_table attribute by default
3555 f = io.BytesIO()
3556 p = self.pickler_class(f, 0)
3557 with self.assertRaises(AttributeError):
3558 p.dispatch_table
3559 self.assertFalse(hasattr(p, 'dispatch_table'))
3560
3561 def test_class_dispatch_table(self):
3562 # A dispatch_table attribute can be specified class-wide
3563 dt = self.get_dispatch_table()
3564
3565 class MyPickler(self.pickler_class):
3566 dispatch_table = dt
3567
3568 def dumps(obj, protocol=None):
3569 f = io.BytesIO()
3570 p = MyPickler(f, protocol)
3571 self.assertEqual(p.dispatch_table, dt)
3572 p.dump(obj)
3573 return f.getvalue()
3574
3575 self._test_dispatch_table(dumps, dt)
3576
3577 def test_instance_dispatch_table(self):
3578 # A dispatch_table attribute can also be specified instance-wide
3579 dt = self.get_dispatch_table()
3580
3581 def dumps(obj, protocol=None):
3582 f = io.BytesIO()
3583 p = self.pickler_class(f, protocol)
3584 p.dispatch_table = dt
3585 self.assertEqual(p.dispatch_table, dt)
3586 p.dump(obj)
3587 return f.getvalue()
3588
3589 self._test_dispatch_table(dumps, dt)
3590
3591 def _test_dispatch_table(self, dumps, dispatch_table):
3592 def custom_load_dump(obj):
3593 return pickle.loads(dumps(obj, 0))
3594
3595 def default_load_dump(obj):
3596 return pickle.loads(pickle.dumps(obj, 0))
3597
3598 # pickling complex numbers using protocol 0 relies on copyreg
3599 # so check pickling a complex number still works
3600 z = 1 + 2j
3601 self.assertEqual(custom_load_dump(z), z)
3602 self.assertEqual(default_load_dump(z), z)
3603
3604 # modify pickling of complex
3605 REDUCE_1 = 'reduce_1'
3606 def reduce_1(obj):
3607 return str, (REDUCE_1,)
3608 dispatch_table[complex] = reduce_1
3609 self.assertEqual(custom_load_dump(z), REDUCE_1)
3610 self.assertEqual(default_load_dump(z), z)
3611
3612 # check picklability of AAA and BBB
3613 a = AAA()
3614 b = BBB()
3615 self.assertEqual(custom_load_dump(a), REDUCE_A)
3616 self.assertIsInstance(custom_load_dump(b), BBB)
3617 self.assertEqual(default_load_dump(a), REDUCE_A)
3618 self.assertIsInstance(default_load_dump(b), BBB)
3619
3620 # modify pickling of BBB
3621 dispatch_table[BBB] = reduce_1
3622 self.assertEqual(custom_load_dump(a), REDUCE_A)
3623 self.assertEqual(custom_load_dump(b), REDUCE_1)
3624 self.assertEqual(default_load_dump(a), REDUCE_A)
3625 self.assertIsInstance(default_load_dump(b), BBB)
3626
3627 # revert pickling of BBB and modify pickling of AAA
3628 REDUCE_2 = 'reduce_2'
3629 def reduce_2(obj):
3630 return str, (REDUCE_2,)
3631 dispatch_table[AAA] = reduce_2
3632 del dispatch_table[BBB]
3633 self.assertEqual(custom_load_dump(a), REDUCE_2)
3634 self.assertIsInstance(custom_load_dump(b), BBB)
3635 self.assertEqual(default_load_dump(a), REDUCE_A)
3636 self.assertIsInstance(default_load_dump(b), BBB)
3637
Pierre Glaser65d98d02019-05-08 21:40:25 +02003638 # End-to-end testing of save_reduce with the state_setter keyword
3639 # argument. This is a dispatch_table test as the primary goal of
3640 # state_setter is to tweak objects reduction behavior.
3641 # In particular, state_setter is useful when the default __setstate__
3642 # behavior is not flexible enough.
3643
3644 # No custom reducer for b has been registered for now, so
3645 # BBB.__setstate__ should be used at unpickling time
3646 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3647
3648 def reduce_bbb(obj):
3649 return BBB, (), obj.__dict__, None, None, setstate_bbb
3650
3651 dispatch_table[BBB] = reduce_bbb
3652
3653 # The custom reducer reduce_bbb includes a state setter, that should
3654 # have priority over BBB.__setstate__
3655 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3656
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003657
Guido van Rossum98297ee2007-11-06 21:34:58 +00003658if __name__ == "__main__":
3659 # Print some stuff that can be used to rewrite DATA{0,1,2}
3660 from pickletools import dis
3661 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003662 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003663 p = pickle.dumps(x, i)
3664 print("DATA{0} = (".format(i))
3665 for j in range(0, len(p), 20):
3666 b = bytes(p[j:j+20])
3667 print(" {0!r}".format(b))
3668 print(")")
3669 print()
3670 print("# Disassembly of DATA{0}".format(i))
3671 print("DATA{0}_DIS = \"\"\"\\".format(i))
3672 dis(p)
3673 print("\"\"\"")
3674 print()