blob: 94d42c4f97115bd012b10f1c1d62c536babe6a19 [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,
tjb9004371c0a2019-02-18 23:30:51 +080027 _2G, _4G, bigmemtest, reap_threads, forget,
Victor Stinnerb39d41b2020-06-17 18:40:14 +020028 save_restore_warnings_filters
Antoine Pitrou82be19f2011-08-29 23:09:33 +020029 )
Tim Peterse089c682001-04-10 03:41:41 +000030
Guido van Rossum98297ee2007-11-06 21:34:58 +000031from pickle import bytes_types
32
Victor Stinnerb39d41b2020-06-17 18:40:14 +020033
34# bpo-41003: Save/restore warnings filters to leave them unchanged.
35# Ignore filters installed by numpy.
36try:
37 with save_restore_warnings_filters():
38 import numpy as np
39except ImportError:
40 np = None
41
42
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030043requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
44 "test is only meaningful on 32-bit builds")
45
Tim Petersee1a53c2003-02-02 02:57:53 +000046# Tests that try a number of pickle protocols should have a
47# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000048# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000049protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000050
Tim Peters22e71712003-02-03 22:27:38 +000051
52# Return True if opcode code appears in the pickle, else False.
53def opcode_in_pickle(code, pickle):
54 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000055 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000056 return True
57 return False
58
Tim Peters8d2613a2003-02-11 16:40:16 +000059# Return the number of times opcode code appears in pickle.
60def count_opcode(code, pickle):
61 n = 0
62 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000063 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000064 n += 1
65 return n
66
Antoine Pitrou04248a82010-10-12 20:51:21 +000067
68class UnseekableIO(io.BytesIO):
69 def peek(self, *args):
70 raise NotImplementedError
71
72 def seekable(self):
73 return False
74
75 def seek(self, *args):
76 raise io.UnsupportedOperation
77
78 def tell(self):
79 raise io.UnsupportedOperation
80
81
Antoine Pitrou9f378722020-02-23 23:33:53 +010082class MinimalIO(object):
83 """
84 A file-like object that doesn't support readinto().
85 """
86 def __init__(self, *args):
87 self._bio = io.BytesIO(*args)
88 self.getvalue = self._bio.getvalue
89 self.read = self._bio.read
90 self.readline = self._bio.readline
91 self.write = self._bio.write
92
93
Tim Peters3e667d52003-02-04 21:47:44 +000094# We can't very well test the extension registry without putting known stuff
95# in it, but we have to be careful to restore its original state. Code
96# should do this:
97#
98# e = ExtensionSaver(extension_code)
99# try:
100# fiddle w/ the extension registry's stuff for extension_code
101# finally:
102# e.restore()
103
104class ExtensionSaver:
105 # Remember current registration for code (if any), and remove it (if
106 # there is one).
107 def __init__(self, code):
108 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000109 if code in copyreg._inverted_registry:
110 self.pair = copyreg._inverted_registry[code]
111 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000112 else:
113 self.pair = None
114
115 # Restore previous registration for code.
116 def restore(self):
117 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000118 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000119 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000120 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000121 pair = self.pair
122 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000123 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000124
Jeremy Hylton66426532001-10-15 21:38:56 +0000125class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000126 def __eq__(self, other):
127 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000128
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000129class D(C):
130 def __init__(self, arg):
131 pass
132
133class E(C):
134 def __getinitargs__(self):
135 return ()
136
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100137class H(object):
138 pass
139
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200140# Hashable mutable key
141class K(object):
142 def __init__(self, value):
143 self.value = value
144
145 def __reduce__(self):
146 # Shouldn't support the recursion itself
147 return K, (self.value,)
148
Jeremy Hylton66426532001-10-15 21:38:56 +0000149import __main__
150__main__.C = C
151C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000152__main__.D = D
153D.__module__ = "__main__"
154__main__.E = E
155E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100156__main__.H = H
157H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200158__main__.K = K
159K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000160
161class myint(int):
162 def __init__(self, x):
163 self.str = str(x)
164
165class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000166
Jeremy Hylton66426532001-10-15 21:38:56 +0000167 def __init__(self, a, b):
168 self.a = a
169 self.b = b
170
171 def __getinitargs__(self):
172 return self.a, self.b
173
Guido van Rossum04a86612001-12-19 16:58:54 +0000174class metaclass(type):
175 pass
176
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000177class use_metaclass(object, metaclass=metaclass):
178 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000179
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200180class pickling_metaclass(type):
181 def __eq__(self, other):
182 return (type(self) == type(other) and
183 self.reduce_args == other.reduce_args)
184
185 def __reduce__(self):
186 return (create_dynamic_class, self.reduce_args)
187
188def create_dynamic_class(name, bases):
189 result = pickling_metaclass(name, bases, dict())
190 result.reduce_args = (name, bases)
191 return result
192
Antoine Pitrou91f43802019-05-26 17:10:09 +0200193
194class ZeroCopyBytes(bytes):
195 readonly = True
196 c_contiguous = True
197 f_contiguous = True
198 zero_copy_reconstruct = True
199
200 def __reduce_ex__(self, protocol):
201 if protocol >= 5:
202 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
203 else:
204 return type(self)._reconstruct, (bytes(self),)
205
206 def __repr__(self):
207 return "{}({!r})".format(self.__class__.__name__, bytes(self))
208
209 __str__ = __repr__
210
211 @classmethod
212 def _reconstruct(cls, obj):
213 with memoryview(obj) as m:
214 obj = m.obj
215 if type(obj) is cls:
216 # Zero-copy
217 return obj
218 else:
219 return cls(obj)
220
221
222class ZeroCopyBytearray(bytearray):
223 readonly = False
224 c_contiguous = True
225 f_contiguous = True
226 zero_copy_reconstruct = True
227
228 def __reduce_ex__(self, protocol):
229 if protocol >= 5:
230 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
231 else:
232 return type(self)._reconstruct, (bytes(self),)
233
234 def __repr__(self):
235 return "{}({!r})".format(self.__class__.__name__, bytes(self))
236
237 __str__ = __repr__
238
239 @classmethod
240 def _reconstruct(cls, obj):
241 with memoryview(obj) as m:
242 obj = m.obj
243 if type(obj) is cls:
244 # Zero-copy
245 return obj
246 else:
247 return cls(obj)
248
249
250if _testbuffer is not None:
251
252 class PicklableNDArray:
253 # A not-really-zero-copy picklable ndarray, as the ndarray()
254 # constructor doesn't allow for it
255
256 zero_copy_reconstruct = False
257
258 def __init__(self, *args, **kwargs):
259 self.array = _testbuffer.ndarray(*args, **kwargs)
260
261 def __getitem__(self, idx):
262 cls = type(self)
263 new = cls.__new__(cls)
264 new.array = self.array[idx]
265 return new
266
267 @property
268 def readonly(self):
269 return self.array.readonly
270
271 @property
272 def c_contiguous(self):
273 return self.array.c_contiguous
274
275 @property
276 def f_contiguous(self):
277 return self.array.f_contiguous
278
279 def __eq__(self, other):
280 if not isinstance(other, PicklableNDArray):
281 return NotImplemented
282 return (other.array.format == self.array.format and
283 other.array.shape == self.array.shape and
284 other.array.strides == self.array.strides and
285 other.array.readonly == self.array.readonly and
286 other.array.tobytes() == self.array.tobytes())
287
288 def __ne__(self, other):
289 if not isinstance(other, PicklableNDArray):
290 return NotImplemented
291 return not (self == other)
292
293 def __repr__(self):
294 return (f"{type(self)}(shape={self.array.shape},"
295 f"strides={self.array.strides}, "
296 f"bytes={self.array.tobytes()})")
297
298 def __reduce_ex__(self, protocol):
299 if not self.array.contiguous:
300 raise NotImplementedError("Reconstructing a non-contiguous "
301 "ndarray does not seem possible")
302 ndarray_kwargs = {"shape": self.array.shape,
303 "strides": self.array.strides,
304 "format": self.array.format,
305 "flags": (0 if self.readonly
306 else _testbuffer.ND_WRITABLE)}
307 pb = pickle.PickleBuffer(self.array)
308 if protocol >= 5:
309 return (type(self)._reconstruct,
310 (pb, ndarray_kwargs))
311 else:
312 # Need to serialize the bytes in physical order
313 with pb.raw() as m:
314 return (type(self)._reconstruct,
315 (m.tobytes(), ndarray_kwargs))
316
317 @classmethod
318 def _reconstruct(cls, obj, kwargs):
319 with memoryview(obj) as m:
320 # For some reason, ndarray() wants a list of integers...
321 # XXX This only works if format == 'B'
322 items = list(m.tobytes())
323 return cls(items, **kwargs)
324
325
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300326# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000327# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000328
Guido van Rossum98297ee2007-11-06 21:34:58 +0000329DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200330 b'(lp0\nL0L\naL1L\naF2.0\n'
331 b'ac__builtin__\ncomple'
332 b'x\np1\n(F3.0\nF0.0\ntp2\n'
333 b'Rp3\naL1L\naL-1L\naL255'
334 b'L\naL-255L\naL-256L\naL'
335 b'65535L\naL-65535L\naL-'
336 b'65536L\naL2147483647L'
337 b'\naL-2147483647L\naL-2'
338 b'147483648L\na(Vabc\np4'
339 b'\ng4\nccopy_reg\n_recon'
340 b'structor\np5\n(c__main'
341 b'__\nC\np6\nc__builtin__'
342 b'\nobject\np7\nNtp8\nRp9\n'
343 b'(dp10\nVfoo\np11\nL1L\ns'
344 b'Vbar\np12\nL2L\nsbg9\ntp'
345 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000346)
Tim Peterse9358162001-01-22 22:05:20 +0000347
Guido van Rossum98297ee2007-11-06 21:34:58 +0000348# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000349DATA0_DIS = """\
350 0: ( MARK
351 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000352 2: p PUT 0
353 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000354 9: a APPEND
355 10: L LONG 1
356 14: a APPEND
357 15: F FLOAT 2.0
358 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200359 21: c GLOBAL '__builtin__ complex'
360 42: p PUT 1
361 45: ( MARK
362 46: F FLOAT 3.0
363 51: F FLOAT 0.0
364 56: t TUPLE (MARK at 45)
365 57: p PUT 2
366 60: R REDUCE
367 61: p PUT 3
368 64: a APPEND
369 65: L LONG 1
370 69: a APPEND
371 70: L LONG -1
372 75: a APPEND
373 76: L LONG 255
374 82: a APPEND
375 83: L LONG -255
376 90: a APPEND
377 91: L LONG -256
378 98: a APPEND
379 99: L LONG 65535
380 107: a APPEND
381 108: L LONG -65535
382 117: a APPEND
383 118: L LONG -65536
384 127: a APPEND
385 128: L LONG 2147483647
386 141: a APPEND
387 142: L LONG -2147483647
388 156: a APPEND
389 157: L LONG -2147483648
390 171: a APPEND
391 172: ( MARK
392 173: V UNICODE 'abc'
393 178: p PUT 4
394 181: g GET 4
395 184: c GLOBAL 'copy_reg _reconstructor'
396 209: p PUT 5
397 212: ( MARK
398 213: c GLOBAL '__main__ C'
399 225: p PUT 6
400 228: c GLOBAL '__builtin__ object'
401 248: p PUT 7
402 251: N NONE
403 252: t TUPLE (MARK at 212)
404 253: p PUT 8
405 256: R REDUCE
406 257: p PUT 9
407 260: ( MARK
408 261: d DICT (MARK at 260)
409 262: p PUT 10
410 266: V UNICODE 'foo'
411 271: p PUT 11
412 275: L LONG 1
413 279: s SETITEM
414 280: V UNICODE 'bar'
415 285: p PUT 12
416 289: L LONG 2
417 293: s SETITEM
418 294: b BUILD
419 295: g GET 9
420 298: t TUPLE (MARK at 172)
421 299: p PUT 13
422 303: a APPEND
423 304: g GET 13
424 308: a APPEND
425 309: L LONG 5
426 313: a APPEND
427 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000428highest protocol among opcodes = 0
429"""
430
Guido van Rossum98297ee2007-11-06 21:34:58 +0000431DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200432 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
433 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000434 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
435 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
436 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
437 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200438 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000439 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200440 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000441 b'object\nq\x07Ntq\x08Rq\t}q\n('
442 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
443 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
444)
Tim Peters70b02d72003-02-02 17:26:40 +0000445
Guido van Rossum98297ee2007-11-06 21:34:58 +0000446# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000447DATA1_DIS = """\
448 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000449 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000450 3: ( MARK
451 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000452 6: K BININT1 1
453 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200454 17: c GLOBAL '__builtin__ complex'
455 38: q BINPUT 1
456 40: ( MARK
457 41: G BINFLOAT 3.0
458 50: G BINFLOAT 0.0
459 59: t TUPLE (MARK at 40)
460 60: q BINPUT 2
461 62: R REDUCE
462 63: q BINPUT 3
463 65: K BININT1 1
464 67: J BININT -1
465 72: K BININT1 255
466 74: J BININT -255
467 79: J BININT -256
468 84: M BININT2 65535
469 87: J BININT -65535
470 92: J BININT -65536
471 97: J BININT 2147483647
472 102: J BININT -2147483647
473 107: J BININT -2147483648
474 112: ( MARK
475 113: X BINUNICODE 'abc'
476 121: q BINPUT 4
477 123: h BINGET 4
478 125: c GLOBAL 'copy_reg _reconstructor'
479 150: q BINPUT 5
480 152: ( MARK
481 153: c GLOBAL '__main__ C'
482 165: q BINPUT 6
483 167: c GLOBAL '__builtin__ object'
484 187: q BINPUT 7
485 189: N NONE
486 190: t TUPLE (MARK at 152)
487 191: q BINPUT 8
488 193: R REDUCE
489 194: q BINPUT 9
490 196: } EMPTY_DICT
491 197: q BINPUT 10
492 199: ( MARK
493 200: X BINUNICODE 'foo'
494 208: q BINPUT 11
495 210: K BININT1 1
496 212: X BINUNICODE 'bar'
497 220: q BINPUT 12
498 222: K BININT1 2
499 224: u SETITEMS (MARK at 199)
500 225: b BUILD
501 226: h BINGET 9
502 228: t TUPLE (MARK at 112)
503 229: q BINPUT 13
504 231: h BINGET 13
505 233: K BININT1 5
506 235: e APPENDS (MARK at 3)
507 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000508highest protocol among opcodes = 1
509"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000510
Guido van Rossum98297ee2007-11-06 21:34:58 +0000511DATA2 = (
512 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200513 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000514 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
515 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
516 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
517 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
518 b'bcq\x04h\x04c__main__\nC\nq\x05'
519 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
520 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
521 b'\nK\x05e.'
522)
Tim Petersfc273752003-03-02 04:54:24 +0000523
Guido van Rossum98297ee2007-11-06 21:34:58 +0000524# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000525DATA2_DIS = """\
526 0: \x80 PROTO 2
527 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000528 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000529 5: ( MARK
530 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000531 8: K BININT1 1
532 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200533 19: c GLOBAL '__builtin__ complex'
534 40: q BINPUT 1
535 42: G BINFLOAT 3.0
536 51: G BINFLOAT 0.0
537 60: \x86 TUPLE2
538 61: q BINPUT 2
539 63: R REDUCE
540 64: q BINPUT 3
541 66: K BININT1 1
542 68: J BININT -1
543 73: K BININT1 255
544 75: J BININT -255
545 80: J BININT -256
546 85: M BININT2 65535
547 88: J BININT -65535
548 93: J BININT -65536
549 98: J BININT 2147483647
550 103: J BININT -2147483647
551 108: J BININT -2147483648
552 113: ( MARK
553 114: X BINUNICODE 'abc'
554 122: q BINPUT 4
555 124: h BINGET 4
556 126: c GLOBAL '__main__ C'
557 138: q BINPUT 5
558 140: ) EMPTY_TUPLE
559 141: \x81 NEWOBJ
560 142: q BINPUT 6
561 144: } EMPTY_DICT
562 145: q BINPUT 7
563 147: ( MARK
564 148: X BINUNICODE 'foo'
565 156: q BINPUT 8
566 158: K BININT1 1
567 160: X BINUNICODE 'bar'
568 168: q BINPUT 9
569 170: K BININT1 2
570 172: u SETITEMS (MARK at 147)
571 173: b BUILD
572 174: h BINGET 6
573 176: t TUPLE (MARK at 113)
574 177: q BINPUT 10
575 179: h BINGET 10
576 181: K BININT1 5
577 183: e APPENDS (MARK at 5)
578 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000579highest protocol among opcodes = 2
580"""
581
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300582DATA3 = (
583 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
584 b'builtins\ncomplex\nq\x01G'
585 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
586 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
587 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
588 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
589 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
590 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
591 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
592 b'e.'
593)
594
595# Disassembly of DATA3
596DATA3_DIS = """\
597 0: \x80 PROTO 3
598 2: ] EMPTY_LIST
599 3: q BINPUT 0
600 5: ( MARK
601 6: K BININT1 0
602 8: K BININT1 1
603 10: G BINFLOAT 2.0
604 19: c GLOBAL 'builtins complex'
605 37: q BINPUT 1
606 39: G BINFLOAT 3.0
607 48: G BINFLOAT 0.0
608 57: \x86 TUPLE2
609 58: q BINPUT 2
610 60: R REDUCE
611 61: q BINPUT 3
612 63: K BININT1 1
613 65: J BININT -1
614 70: K BININT1 255
615 72: J BININT -255
616 77: J BININT -256
617 82: M BININT2 65535
618 85: J BININT -65535
619 90: J BININT -65536
620 95: J BININT 2147483647
621 100: J BININT -2147483647
622 105: J BININT -2147483648
623 110: ( MARK
624 111: X BINUNICODE 'abc'
625 119: q BINPUT 4
626 121: h BINGET 4
627 123: c GLOBAL '__main__ C'
628 135: q BINPUT 5
629 137: ) EMPTY_TUPLE
630 138: \x81 NEWOBJ
631 139: q BINPUT 6
632 141: } EMPTY_DICT
633 142: q BINPUT 7
634 144: ( MARK
635 145: X BINUNICODE 'bar'
636 153: q BINPUT 8
637 155: K BININT1 2
638 157: X BINUNICODE 'foo'
639 165: q BINPUT 9
640 167: K BININT1 1
641 169: u SETITEMS (MARK at 144)
642 170: b BUILD
643 171: h BINGET 6
644 173: t TUPLE (MARK at 110)
645 174: q BINPUT 10
646 176: h BINGET 10
647 178: K BININT1 5
648 180: e APPENDS (MARK at 5)
649 181: . STOP
650highest protocol among opcodes = 2
651"""
652
653DATA4 = (
654 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
655 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
656 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
657 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
658 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
659 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
660 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
661 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
662 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
663)
664
665# Disassembly of DATA4
666DATA4_DIS = """\
667 0: \x80 PROTO 4
668 2: \x95 FRAME 168
669 11: ] EMPTY_LIST
670 12: \x94 MEMOIZE
671 13: ( MARK
672 14: K BININT1 0
673 16: K BININT1 1
674 18: G BINFLOAT 2.0
675 27: \x8c SHORT_BINUNICODE 'builtins'
676 37: \x94 MEMOIZE
677 38: \x8c SHORT_BINUNICODE 'complex'
678 47: \x94 MEMOIZE
679 48: \x93 STACK_GLOBAL
680 49: \x94 MEMOIZE
681 50: G BINFLOAT 3.0
682 59: G BINFLOAT 0.0
683 68: \x86 TUPLE2
684 69: \x94 MEMOIZE
685 70: R REDUCE
686 71: \x94 MEMOIZE
687 72: K BININT1 1
688 74: J BININT -1
689 79: K BININT1 255
690 81: J BININT -255
691 86: J BININT -256
692 91: M BININT2 65535
693 94: J BININT -65535
694 99: J BININT -65536
695 104: J BININT 2147483647
696 109: J BININT -2147483647
697 114: J BININT -2147483648
698 119: ( MARK
699 120: \x8c SHORT_BINUNICODE 'abc'
700 125: \x94 MEMOIZE
701 126: h BINGET 6
702 128: \x8c SHORT_BINUNICODE '__main__'
703 138: \x94 MEMOIZE
704 139: \x8c SHORT_BINUNICODE 'C'
705 142: \x94 MEMOIZE
706 143: \x93 STACK_GLOBAL
707 144: \x94 MEMOIZE
708 145: ) EMPTY_TUPLE
709 146: \x81 NEWOBJ
710 147: \x94 MEMOIZE
711 148: } EMPTY_DICT
712 149: \x94 MEMOIZE
713 150: ( MARK
714 151: \x8c SHORT_BINUNICODE 'bar'
715 156: \x94 MEMOIZE
716 157: K BININT1 2
717 159: \x8c SHORT_BINUNICODE 'foo'
718 164: \x94 MEMOIZE
719 165: K BININT1 1
720 167: u SETITEMS (MARK at 150)
721 168: b BUILD
722 169: h BINGET 10
723 171: t TUPLE (MARK at 119)
724 172: \x94 MEMOIZE
725 173: h BINGET 14
726 175: K BININT1 5
727 177: e APPENDS (MARK at 13)
728 178: . STOP
729highest protocol among opcodes = 4
730"""
731
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000732# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300733DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000734
735# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300736DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000737
738# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300739DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
740 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
741 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
742 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
743 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
744 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000745
746# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300747DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000748
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100749python2_exceptions_without_args = (
750 ArithmeticError,
751 AssertionError,
752 AttributeError,
753 BaseException,
754 BufferError,
755 BytesWarning,
756 DeprecationWarning,
757 EOFError,
758 EnvironmentError,
759 Exception,
760 FloatingPointError,
761 FutureWarning,
762 GeneratorExit,
763 IOError,
764 ImportError,
765 ImportWarning,
766 IndentationError,
767 IndexError,
768 KeyError,
769 KeyboardInterrupt,
770 LookupError,
771 MemoryError,
772 NameError,
773 NotImplementedError,
774 OSError,
775 OverflowError,
776 PendingDeprecationWarning,
777 ReferenceError,
778 RuntimeError,
779 RuntimeWarning,
780 # StandardError is gone in Python 3, we map it to Exception
781 StopIteration,
782 SyntaxError,
783 SyntaxWarning,
784 SystemError,
785 SystemExit,
786 TabError,
787 TypeError,
788 UnboundLocalError,
789 UnicodeError,
790 UnicodeWarning,
791 UserWarning,
792 ValueError,
793 Warning,
794 ZeroDivisionError,
795)
796
797exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
798
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100799# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300800DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
801 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
802 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100803
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000804
Jeremy Hylton66426532001-10-15 21:38:56 +0000805def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000806 c = C()
807 c.foo = 1
808 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000809 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000810 # Append some integer test cases at cPickle.c's internal size
811 # cutoffs.
812 uint1max = 0xff
813 uint2max = 0xffff
814 int4max = 0x7fffffff
815 x.extend([1, -1,
816 uint1max, -uint1max, -uint1max-1,
817 uint2max, -uint2max, -uint2max-1,
818 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000819 y = ('abc', 'abc', c, c)
820 x.append(y)
821 x.append(y)
822 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000823 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000824
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100825
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300826class AbstractUnpickleTests(unittest.TestCase):
827 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100828
Jeremy Hylton66426532001-10-15 21:38:56 +0000829 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000830
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100831 def assert_is_copy(self, obj, objcopy, msg=None):
832 """Utility method to verify if two objects are copies of each others.
833 """
834 if msg is None:
835 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
836 self.assertEqual(obj, objcopy, msg=msg)
837 self.assertIs(type(obj), type(objcopy), msg=msg)
838 if hasattr(obj, '__dict__'):
839 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
840 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
841 if hasattr(obj, '__slots__'):
842 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
843 for slot in obj.__slots__:
844 self.assertEqual(
845 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
846 self.assertEqual(getattr(obj, slot, None),
847 getattr(objcopy, slot, None), msg=msg)
848
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200849 def check_unpickling_error(self, errors, data):
850 with self.subTest(data=data), \
851 self.assertRaises(errors):
852 try:
853 self.loads(data)
854 except BaseException as exc:
855 if support.verbose > 1:
856 print('%-32r - %s: %s' %
857 (data, exc.__class__.__name__, exc))
858 raise
859
Guido van Rossum98297ee2007-11-06 21:34:58 +0000860 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100861 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000862
863 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100864 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000865
866 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100867 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000868
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300869 def test_load_from_data3(self):
870 self.assert_is_copy(self._testdata, self.loads(DATA3))
871
872 def test_load_from_data4(self):
873 self.assert_is_copy(self._testdata, self.loads(DATA4))
874
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000875 def test_load_classic_instance(self):
876 # See issue5180. Test loading 2.x pickles that
877 # contain an instance of old style class.
878 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
879 xname = X.__name__.encode('ascii')
880 # Protocol 0 (text mode pickle):
881 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200882 0: ( MARK
883 1: i INST '__main__ X' (MARK at 0)
884 13: p PUT 0
885 16: ( MARK
886 17: d DICT (MARK at 16)
887 18: p PUT 1
888 21: b BUILD
889 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000890 """
891 pickle0 = (b"(i__main__\n"
892 b"X\n"
893 b"p0\n"
894 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100895 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000896
897 # Protocol 1 (binary mode pickle)
898 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200899 0: ( MARK
900 1: c GLOBAL '__main__ X'
901 13: q BINPUT 0
902 15: o OBJ (MARK at 0)
903 16: q BINPUT 1
904 18: } EMPTY_DICT
905 19: q BINPUT 2
906 21: b BUILD
907 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000908 """
909 pickle1 = (b'(c__main__\n'
910 b'X\n'
911 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100912 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000913
914 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
915 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200916 0: \x80 PROTO 2
917 2: ( MARK
918 3: c GLOBAL '__main__ X'
919 15: q BINPUT 0
920 17: o OBJ (MARK at 2)
921 18: q BINPUT 1
922 20: } EMPTY_DICT
923 21: q BINPUT 2
924 23: b BUILD
925 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000926 """
927 pickle2 = (b'\x80\x02(c__main__\n'
928 b'X\n'
929 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100930 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000931
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300932 def test_maxint64(self):
933 maxint64 = (1 << 63) - 1
934 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
935 got = self.loads(data)
936 self.assert_is_copy(maxint64, got)
937
938 # Try too with a bogus literal.
939 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200940 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300941
942 def test_unpickle_from_2x(self):
943 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300944 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300945 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300946 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300947 self.assertEqual(type(loaded), type(range(0)))
948 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300949 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300950 self.assertEqual(type(loaded), SimpleCookie)
951 self.assertEqual(list(loaded.keys()), ["key"])
952 self.assertEqual(loaded["key"].value, "value")
953
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300954 # Exception objects without arguments pickled from 2.x with protocol 2
955 for exc in python2_exceptions_without_args:
956 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300957 loaded = self.loads(data)
958 self.assertIs(type(loaded), exc)
959
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300960 # StandardError is mapped to Exception, test that separately
961 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300962 self.assertIs(type(loaded), Exception)
963
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300964 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300965 self.assertIs(type(loaded), UnicodeEncodeError)
966 self.assertEqual(loaded.object, "foo")
967 self.assertEqual(loaded.encoding, "ascii")
968 self.assertEqual(loaded.start, 0)
969 self.assertEqual(loaded.end, 1)
970 self.assertEqual(loaded.reason, "bad")
971
972 def test_load_python2_str_as_bytes(self):
973 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
974 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
975 encoding="bytes"), b'a\x00\xa0')
976 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
977 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
978 encoding="bytes"), b'a\x00\xa0')
979 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
980 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
981 encoding="bytes"), b'a\x00\xa0')
982
983 def test_load_python2_unicode_as_str(self):
984 # From Python 2: pickle.dumps(u'π', protocol=0)
985 self.assertEqual(self.loads(b'V\\u03c0\n.',
986 encoding='bytes'), 'π')
987 # From Python 2: pickle.dumps(u'π', protocol=1)
988 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
989 encoding="bytes"), 'π')
990 # From Python 2: pickle.dumps(u'π', protocol=2)
991 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
992 encoding="bytes"), 'π')
993
994 def test_load_long_python2_str_as_bytes(self):
995 # From Python 2: pickle.dumps('x' * 300, protocol=1)
996 self.assertEqual(self.loads(pickle.BINSTRING +
997 struct.pack("<I", 300) +
998 b'x' * 300 + pickle.STOP,
999 encoding='bytes'), b'x' * 300)
1000
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001001 def test_constants(self):
1002 self.assertIsNone(self.loads(b'N.'))
1003 self.assertIs(self.loads(b'\x88.'), True)
1004 self.assertIs(self.loads(b'\x89.'), False)
1005 self.assertIs(self.loads(b'I01\n.'), True)
1006 self.assertIs(self.loads(b'I00\n.'), False)
1007
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001008 def test_empty_bytestring(self):
1009 # issue 11286
1010 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1011 self.assertEqual(empty, '')
1012
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001013 def test_short_binbytes(self):
1014 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
1015 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1016
1017 def test_binbytes(self):
1018 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1019 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1020
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001021 @requires_32b
1022 def test_negative_32b_binbytes(self):
1023 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1024 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001025 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1026 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001027
1028 @requires_32b
1029 def test_negative_32b_binunicode(self):
1030 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1031 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001032 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1033 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001034
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001035 def test_short_binunicode(self):
1036 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1037 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1038
1039 def test_misc_get(self):
Claudiu Popa6f03b232019-11-24 20:15:08 +01001040 self.check_unpickling_error(pickle.UnpicklingError, b'g0\np0')
1041 self.check_unpickling_error(pickle.UnpicklingError, b'jens:')
1042 self.check_unpickling_error(pickle.UnpicklingError, b'hens:')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001043 self.assert_is_copy([(100,), (100,)],
1044 self.loads(b'((Kdtp0\nh\x00l.))'))
1045
Serhiy Storchakae0606192015-09-29 22:10:07 +03001046 def test_binbytes8(self):
1047 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1048 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1049
1050 def test_binunicode8(self):
1051 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1052 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1053
Antoine Pitrou91f43802019-05-26 17:10:09 +02001054 def test_bytearray8(self):
1055 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1056 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1057
Serhiy Storchakae0606192015-09-29 22:10:07 +03001058 @requires_32b
1059 def test_large_32b_binbytes8(self):
1060 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001061 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1062 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001063
1064 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001065 def test_large_32b_bytearray8(self):
1066 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1067 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1068 dumped)
1069
1070 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001071 def test_large_32b_binunicode8(self):
1072 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001073 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1074 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001075
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001076 def test_get(self):
1077 pickled = b'((lp100000\ng100000\nt.'
1078 unpickled = self.loads(pickled)
1079 self.assertEqual(unpickled, ([],)*2)
1080 self.assertIs(unpickled[0], unpickled[1])
1081
1082 def test_binget(self):
1083 pickled = b'(]q\xffh\xfft.'
1084 unpickled = self.loads(pickled)
1085 self.assertEqual(unpickled, ([],)*2)
1086 self.assertIs(unpickled[0], unpickled[1])
1087
1088 def test_long_binget(self):
1089 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1090 unpickled = self.loads(pickled)
1091 self.assertEqual(unpickled, ([],)*2)
1092 self.assertIs(unpickled[0], unpickled[1])
1093
1094 def test_dup(self):
1095 pickled = b'((l2t.'
1096 unpickled = self.loads(pickled)
1097 self.assertEqual(unpickled, ([],)*2)
1098 self.assertIs(unpickled[0], unpickled[1])
1099
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001100 def test_negative_put(self):
1101 # Issue #12847
1102 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001103 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001104
1105 @requires_32b
1106 def test_negative_32b_binput(self):
1107 # Issue #12847
1108 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001109 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001110
1111 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001112 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001113
1114 def test_badly_quoted_string(self):
1115 # Issue #17710
1116 badpickles = [b"S'\n.",
1117 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.']
1129 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001130 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001131
1132 def test_correctly_quoted_string(self):
1133 goodpickles = [(b"S''\n.", ''),
1134 (b'S""\n.', ''),
1135 (b'S"\\n"\n.', '\n'),
1136 (b"S'\\n'\n.", '\n')]
1137 for p, expected in goodpickles:
1138 self.assertEqual(self.loads(p), expected)
1139
1140 def test_frame_readline(self):
1141 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1142 # 0: \x80 PROTO 4
1143 # 2: \x95 FRAME 5
1144 # 11: I INT 42
1145 # 15: . STOP
1146 self.assertEqual(self.loads(pickled), 42)
1147
1148 def test_compat_unpickle(self):
1149 # xrange(1, 7)
1150 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1151 unpickled = self.loads(pickled)
1152 self.assertIs(type(unpickled), range)
1153 self.assertEqual(unpickled, range(1, 7))
1154 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1155 # reduce
1156 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1157 self.assertIs(self.loads(pickled), functools.reduce)
1158 # whichdb.whichdb
1159 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1160 self.assertIs(self.loads(pickled), dbm.whichdb)
1161 # Exception(), StandardError()
1162 for name in (b'Exception', b'StandardError'):
1163 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1164 unpickled = self.loads(pickled)
1165 self.assertIs(type(unpickled), Exception)
1166 self.assertEqual(str(unpickled), 'ugh')
1167 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1168 for name in (b'UserDict', b'IterableUserDict'):
1169 pickled = (b'\x80\x02(cUserDict\n' + name +
1170 b'\no}U\x04data}K\x01K\x02ssb.')
1171 unpickled = self.loads(pickled)
1172 self.assertIs(type(unpickled), collections.UserDict)
1173 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1174
Miss Islington (bot)57c984f2020-07-13 06:09:27 -07001175 def test_bad_reduce(self):
1176 self.assertEqual(self.loads(b'cbuiltins\nint\n)R.'), 0)
1177 self.check_unpickling_error(TypeError, b'N)R.')
1178 self.check_unpickling_error(TypeError, b'cbuiltins\nint\nNR.')
1179
1180 def test_bad_newobj(self):
1181 error = (pickle.UnpicklingError, TypeError)
1182 self.assertEqual(self.loads(b'cbuiltins\nint\n)\x81.'), 0)
1183 self.check_unpickling_error(error, b'cbuiltins\nlen\n)\x81.')
1184 self.check_unpickling_error(error, b'cbuiltins\nint\nN\x81.')
1185
1186 def test_bad_newobj_ex(self):
1187 error = (pickle.UnpicklingError, TypeError)
1188 self.assertEqual(self.loads(b'cbuiltins\nint\n)}\x92.'), 0)
1189 self.check_unpickling_error(error, b'cbuiltins\nlen\n)}\x92.')
1190 self.check_unpickling_error(error, b'cbuiltins\nint\nN}\x92.')
1191 self.check_unpickling_error(error, b'cbuiltins\nint\n)N\x92.')
1192
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001193 def test_bad_stack(self):
1194 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001195 b'.', # STOP
1196 b'0', # POP
1197 b'1', # POP_MARK
1198 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001199 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001200 b'R', # REDUCE
1201 b')R',
1202 b'a', # APPEND
1203 b'Na',
1204 b'b', # BUILD
1205 b'Nb',
1206 b'd', # DICT
1207 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001208 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001209 b'ibuiltins\nlist\n', # INST
1210 b'l', # LIST
1211 b'o', # OBJ
1212 b'(o',
1213 b'p1\n', # PUT
1214 b'q\x00', # BINPUT
1215 b'r\x00\x00\x00\x00', # LONG_BINPUT
1216 b's', # SETITEM
1217 b'Ns',
1218 b'NNs',
1219 b't', # TUPLE
1220 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001221 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001222 b'}(Nu',
1223 b'\x81', # NEWOBJ
1224 b')\x81',
1225 b'\x85', # TUPLE1
1226 b'\x86', # TUPLE2
1227 b'N\x86',
1228 b'\x87', # TUPLE3
1229 b'N\x87',
1230 b'NN\x87',
1231 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001232 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001233 b'\x91', # FROZENSET
1234 b'\x92', # NEWOBJ_EX
1235 b')}\x92',
1236 b'\x93', # STACK_GLOBAL
1237 b'Vlist\n\x93',
1238 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001239 ]
1240 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001241 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001242
1243 def test_bad_mark(self):
1244 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001245 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001246 b'N(2', # DUP
1247 b'cbuiltins\nlist\n)(R', # REDUCE
1248 b'cbuiltins\nlist\n()R',
1249 b']N(a', # APPEND
1250 # BUILD
1251 b'cbuiltins\nValueError\n)R}(b',
1252 b'cbuiltins\nValueError\n)R(}b',
1253 b'(Nd', # DICT
1254 b'N(p1\n', # PUT
1255 b'N(q\x00', # BINPUT
1256 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1257 b'}NN(s', # SETITEM
1258 b'}N(Ns',
1259 b'}(NNs',
1260 b'}((u', # SETITEMS
1261 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1262 b'cbuiltins\nlist\n()\x81',
1263 b'N(\x85', # TUPLE1
1264 b'NN(\x86', # TUPLE2
1265 b'N(N\x86',
1266 b'NNN(\x87', # TUPLE3
1267 b'NN(N\x87',
1268 b'N(NN\x87',
1269 b']((\x90', # ADDITEMS
1270 # NEWOBJ_EX
1271 b'cbuiltins\nlist\n)}(\x92',
1272 b'cbuiltins\nlist\n)(}\x92',
1273 b'cbuiltins\nlist\n()}\x92',
1274 # STACK_GLOBAL
1275 b'Vbuiltins\n(Vlist\n\x93',
1276 b'Vbuiltins\nVlist\n(\x93',
1277 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001278 ]
1279 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001280 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001281
1282 def test_truncated_data(self):
1283 self.check_unpickling_error(EOFError, b'')
1284 self.check_unpickling_error(EOFError, b'N')
1285 badpickles = [
1286 b'B', # BINBYTES
1287 b'B\x03\x00\x00',
1288 b'B\x03\x00\x00\x00',
1289 b'B\x03\x00\x00\x00ab',
1290 b'C', # SHORT_BINBYTES
1291 b'C\x03',
1292 b'C\x03ab',
1293 b'F', # FLOAT
1294 b'F0.0',
1295 b'F0.00',
1296 b'G', # BINFLOAT
1297 b'G\x00\x00\x00\x00\x00\x00\x00',
1298 b'I', # INT
1299 b'I0',
1300 b'J', # BININT
1301 b'J\x00\x00\x00',
1302 b'K', # BININT1
1303 b'L', # LONG
1304 b'L0',
1305 b'L10',
1306 b'L0L',
1307 b'L10L',
1308 b'M', # BININT2
1309 b'M\x00',
1310 # b'P', # PERSID
1311 # b'Pabc',
1312 b'S', # STRING
1313 b"S'abc'",
1314 b'T', # BINSTRING
1315 b'T\x03\x00\x00',
1316 b'T\x03\x00\x00\x00',
1317 b'T\x03\x00\x00\x00ab',
1318 b'U', # SHORT_BINSTRING
1319 b'U\x03',
1320 b'U\x03ab',
1321 b'V', # UNICODE
1322 b'Vabc',
1323 b'X', # BINUNICODE
1324 b'X\x03\x00\x00',
1325 b'X\x03\x00\x00\x00',
1326 b'X\x03\x00\x00\x00ab',
1327 b'(c', # GLOBAL
1328 b'(cbuiltins',
1329 b'(cbuiltins\n',
1330 b'(cbuiltins\nlist',
1331 b'Ng', # GET
1332 b'Ng0',
1333 b'(i', # INST
1334 b'(ibuiltins',
1335 b'(ibuiltins\n',
1336 b'(ibuiltins\nlist',
1337 b'Nh', # BINGET
1338 b'Nj', # LONG_BINGET
1339 b'Nj\x00\x00\x00',
1340 b'Np', # PUT
1341 b'Np0',
1342 b'Nq', # BINPUT
1343 b'Nr', # LONG_BINPUT
1344 b'Nr\x00\x00\x00',
1345 b'\x80', # PROTO
1346 b'\x82', # EXT1
1347 b'\x83', # EXT2
1348 b'\x84\x01',
1349 b'\x84', # EXT4
1350 b'\x84\x01\x00\x00',
1351 b'\x8a', # LONG1
1352 b'\x8b', # LONG4
1353 b'\x8b\x00\x00\x00',
1354 b'\x8c', # SHORT_BINUNICODE
1355 b'\x8c\x03',
1356 b'\x8c\x03ab',
1357 b'\x8d', # BINUNICODE8
1358 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1359 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1360 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1361 b'\x8e', # BINBYTES8
1362 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1363 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1364 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001365 b'\x96', # BYTEARRAY8
1366 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1367 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1368 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001369 b'\x95', # FRAME
1370 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1371 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1372 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1373 ]
1374 for p in badpickles:
1375 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001376
tjb9004371c0a2019-02-18 23:30:51 +08001377 @reap_threads
1378 def test_unpickle_module_race(self):
1379 # https://bugs.python.org/issue34572
1380 locker_module = dedent("""
1381 import threading
1382 barrier = threading.Barrier(2)
1383 """)
1384 locking_import_module = dedent("""
1385 import locker
1386 locker.barrier.wait()
1387 class ToBeUnpickled(object):
1388 pass
1389 """)
1390
1391 os.mkdir(TESTFN)
1392 self.addCleanup(shutil.rmtree, TESTFN)
1393 sys.path.insert(0, TESTFN)
1394 self.addCleanup(sys.path.remove, TESTFN)
1395 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1396 f.write(locker_module.encode('utf-8'))
1397 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1398 f.write(locking_import_module.encode('utf-8'))
1399 self.addCleanup(forget, "locker")
1400 self.addCleanup(forget, "locking_import")
1401
1402 import locker
1403
1404 pickle_bytes = (
1405 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1406
1407 # Then try to unpickle two of these simultaneously
1408 # One of them will cause the module import, and we want it to block
1409 # until the other one either:
1410 # - fails (before the patch for this issue)
1411 # - blocks on the import lock for the module, as it should
1412 results = []
1413 barrier = threading.Barrier(3)
1414 def t():
1415 # This ensures the threads have all started
1416 # presumably barrier release is faster than thread startup
1417 barrier.wait()
1418 results.append(pickle.loads(pickle_bytes))
1419
1420 t1 = threading.Thread(target=t)
1421 t2 = threading.Thread(target=t)
1422 t1.start()
1423 t2.start()
1424
1425 barrier.wait()
1426 # could have delay here
1427 locker.barrier.wait()
1428
1429 t1.join()
1430 t2.join()
1431
1432 from locking_import import ToBeUnpickled
1433 self.assertEqual(
1434 [type(x) for x in results],
1435 [ToBeUnpickled] * 2)
1436
1437
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001438
1439class AbstractPickleTests(unittest.TestCase):
1440 # Subclass must define self.dumps, self.loads.
1441
1442 optimized = False
1443
1444 _testdata = AbstractUnpickleTests._testdata
1445
1446 def setUp(self):
1447 pass
1448
1449 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1450
1451 def test_misc(self):
1452 # test various datatypes not tested by testdata
1453 for proto in protocols:
1454 x = myint(4)
1455 s = self.dumps(x, proto)
1456 y = self.loads(s)
1457 self.assert_is_copy(x, y)
1458
1459 x = (1, ())
1460 s = self.dumps(x, proto)
1461 y = self.loads(s)
1462 self.assert_is_copy(x, y)
1463
1464 x = initarg(1, x)
1465 s = self.dumps(x, proto)
1466 y = self.loads(s)
1467 self.assert_is_copy(x, y)
1468
1469 # XXX test __reduce__ protocol?
1470
1471 def test_roundtrip_equality(self):
1472 expected = self._testdata
1473 for proto in protocols:
1474 s = self.dumps(expected, proto)
1475 got = self.loads(s)
1476 self.assert_is_copy(expected, got)
1477
Tim Peters70b02d72003-02-02 17:26:40 +00001478 # There are gratuitous differences between pickles produced by
1479 # pickle and cPickle, largely because cPickle starts PUT indices at
1480 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1481 # there's a comment with an exclamation point there whose meaning
1482 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1483 # of 1.
1484 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001485 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001486 from pickletools import dis
1487
1488 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1489 s = self.dumps(self._testdata, proto)
1490 filelike = StringIO()
1491 dis(s, out=filelike)
1492 got = filelike.getvalue()
1493 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001494
1495 def test_recursive_list(self):
1496 l = []
1497 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001498 for proto in protocols:
1499 s = self.dumps(l, proto)
1500 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001501 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001502 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001503 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001504
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001505 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001506 t = ([],)
1507 t[0].append(t)
1508 for proto in protocols:
1509 s = self.dumps(t, proto)
1510 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001511 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001512 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001513 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001514 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001515 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001516
Jeremy Hylton66426532001-10-15 21:38:56 +00001517 def test_recursive_dict(self):
1518 d = {}
1519 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001520 for proto in protocols:
1521 s = self.dumps(d, proto)
1522 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001523 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001524 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001525 self.assertIs(x[1], x)
1526
1527 def test_recursive_dict_key(self):
1528 d = {}
1529 k = K(d)
1530 d[k] = 1
1531 for proto in protocols:
1532 s = self.dumps(d, proto)
1533 x = self.loads(s)
1534 self.assertIsInstance(x, dict)
1535 self.assertEqual(len(x.keys()), 1)
1536 self.assertIsInstance(list(x.keys())[0], K)
1537 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001538
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001539 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001540 y = set()
1541 k = K(y)
1542 y.add(k)
1543 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001544 s = self.dumps(y, proto)
1545 x = self.loads(s)
1546 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001547 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001548 self.assertIsInstance(list(x)[0], K)
1549 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001550
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001551 def test_recursive_list_subclass(self):
1552 y = MyList()
1553 y.append(y)
1554 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001555 s = self.dumps(y, proto)
1556 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001557 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001558 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001559 self.assertIs(x[0], x)
1560
1561 def test_recursive_dict_subclass(self):
1562 d = MyDict()
1563 d[1] = d
1564 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1565 s = self.dumps(d, proto)
1566 x = self.loads(s)
1567 self.assertIsInstance(x, MyDict)
1568 self.assertEqual(list(x.keys()), [1])
1569 self.assertIs(x[1], x)
1570
1571 def test_recursive_dict_subclass_key(self):
1572 d = MyDict()
1573 k = K(d)
1574 d[k] = 1
1575 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1576 s = self.dumps(d, proto)
1577 x = self.loads(s)
1578 self.assertIsInstance(x, MyDict)
1579 self.assertEqual(len(list(x.keys())), 1)
1580 self.assertIsInstance(list(x.keys())[0], K)
1581 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001582
Jeremy Hylton66426532001-10-15 21:38:56 +00001583 def test_recursive_inst(self):
1584 i = C()
1585 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001586 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001587 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001588 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001589 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001590 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001591 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001592
1593 def test_recursive_multi(self):
1594 l = []
1595 d = {1:l}
1596 i = C()
1597 i.attr = d
1598 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001599 for proto in protocols:
1600 s = self.dumps(l, proto)
1601 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001602 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001603 self.assertEqual(len(x), 1)
1604 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001605 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001606 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001607
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001608 def check_recursive_collection_and_inst(self, factory):
1609 h = H()
1610 y = factory([h])
1611 h.attr = y
1612 for proto in protocols:
1613 s = self.dumps(y, proto)
1614 x = self.loads(s)
1615 self.assertIsInstance(x, type(y))
1616 self.assertEqual(len(x), 1)
1617 self.assertIsInstance(list(x)[0], H)
1618 self.assertIs(list(x)[0].attr, x)
1619
1620 def test_recursive_list_and_inst(self):
1621 self.check_recursive_collection_and_inst(list)
1622
1623 def test_recursive_tuple_and_inst(self):
1624 self.check_recursive_collection_and_inst(tuple)
1625
1626 def test_recursive_dict_and_inst(self):
1627 self.check_recursive_collection_and_inst(dict.fromkeys)
1628
1629 def test_recursive_set_and_inst(self):
1630 self.check_recursive_collection_and_inst(set)
1631
1632 def test_recursive_frozenset_and_inst(self):
1633 self.check_recursive_collection_and_inst(frozenset)
1634
1635 def test_recursive_list_subclass_and_inst(self):
1636 self.check_recursive_collection_and_inst(MyList)
1637
1638 def test_recursive_tuple_subclass_and_inst(self):
1639 self.check_recursive_collection_and_inst(MyTuple)
1640
1641 def test_recursive_dict_subclass_and_inst(self):
1642 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1643
1644 def test_recursive_set_subclass_and_inst(self):
1645 self.check_recursive_collection_and_inst(MySet)
1646
1647 def test_recursive_frozenset_subclass_and_inst(self):
1648 self.check_recursive_collection_and_inst(MyFrozenSet)
1649
Walter Dörwald9b775532007-06-08 14:30:53 +00001650 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001651 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001652 '<\\>', '<\\\U00012345>',
1653 # surrogates
1654 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001655 for proto in protocols:
1656 for u in endcases:
1657 p = self.dumps(u, proto)
1658 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001659 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001660
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001661 def test_unicode_high_plane(self):
1662 t = '\U00012345'
1663 for proto in protocols:
1664 p = self.dumps(t, proto)
1665 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001666 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001667
Guido van Rossumf4169812008-03-17 22:56:06 +00001668 def test_bytes(self):
1669 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001670 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001671 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001672 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001673 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001674 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001675 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001676 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001677 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001678 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001679
Antoine Pitrou91f43802019-05-26 17:10:09 +02001680 def test_bytearray(self):
1681 for proto in protocols:
1682 for s in b'', b'xyz', b'xyz'*100:
1683 b = bytearray(s)
1684 p = self.dumps(b, proto)
1685 bb = self.loads(p)
1686 self.assertIsNot(bb, b)
1687 self.assert_is_copy(b, bb)
1688 if proto <= 3:
1689 # bytearray is serialized using a global reference
1690 self.assertIn(b'bytearray', p)
1691 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1692 elif proto == 4:
1693 self.assertIn(b'bytearray', p)
1694 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1695 elif proto == 5:
1696 self.assertNotIn(b'bytearray', p)
1697 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1698
Jeremy Hylton66426532001-10-15 21:38:56 +00001699 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001700 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001701 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001702 while n:
1703 for expected in (-n, n):
1704 s = self.dumps(expected, proto)
1705 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001706 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001707 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001708
Tim Petersee1a53c2003-02-02 02:57:53 +00001709 def test_long(self):
1710 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001711 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001712 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001713 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001714 for npos in nbase-1, nbase, nbase+1:
1715 for n in npos, -npos:
1716 pickle = self.dumps(n, proto)
1717 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001718 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001719 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1720 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001721 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001722 nbase += nbase << 1000000
1723 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001724 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001725 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001726 # assert_is_copy is very expensive here as it precomputes
1727 # a failure message by computing the repr() of n and got,
1728 # we just do the check ourselves.
1729 self.assertIs(type(got), int)
1730 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001731
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001732 def test_float(self):
1733 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1734 3.14, 263.44582062374053, 6.022e23, 1e30]
1735 test_values = test_values + [-x for x in test_values]
1736 for proto in protocols:
1737 for value in test_values:
1738 pickle = self.dumps(value, proto)
1739 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001740 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001741
Thomas Wouters477c8d52006-05-27 19:21:47 +00001742 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1743 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001744 # make sure that floats are formatted locale independent with proto 0
1745 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001746
Jeremy Hylton66426532001-10-15 21:38:56 +00001747 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001748 for proto in protocols:
1749 inst = AAA()
1750 dumped = self.dumps(inst, proto)
1751 loaded = self.loads(dumped)
1752 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001753
1754 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001755 for proto in protocols:
1756 inst = initarg(1, 2)
1757 dumped = self.dumps(inst, proto)
1758 loaded = self.loads(dumped)
1759 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001760
Guido van Rossum04a86612001-12-19 16:58:54 +00001761 def test_metaclass(self):
1762 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001763 for proto in protocols:
1764 s = self.dumps(a, proto)
1765 b = self.loads(s)
1766 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001767
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001768 def test_dynamic_class(self):
1769 a = create_dynamic_class("my_dynamic_class", (object,))
1770 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1771 for proto in protocols:
1772 s = self.dumps(a, proto)
1773 b = self.loads(s)
1774 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001775 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001776
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001777 def test_structseq(self):
1778 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001779 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001780
1781 t = time.localtime()
1782 for proto in protocols:
1783 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001784 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001785 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001786 t = os.stat(os.curdir)
1787 s = self.dumps(t, proto)
1788 u = self.loads(s)
1789 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001790 if hasattr(os, "statvfs"):
1791 t = os.statvfs(os.curdir)
1792 s = self.dumps(t, proto)
1793 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001794 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001795
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001796 def test_ellipsis(self):
1797 for proto in protocols:
1798 s = self.dumps(..., proto)
1799 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001800 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001801
1802 def test_notimplemented(self):
1803 for proto in protocols:
1804 s = self.dumps(NotImplemented, proto)
1805 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001806 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001807
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001808 def test_singleton_types(self):
1809 # Issue #6477: Test that types of built-in singletons can be pickled.
1810 singletons = [None, ..., NotImplemented]
1811 for singleton in singletons:
1812 for proto in protocols:
1813 s = self.dumps(type(singleton), proto)
1814 u = self.loads(s)
1815 self.assertIs(type(singleton), u)
1816
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001817 # Tests for protocol 2
1818
Tim Peters4190fb82003-02-02 16:09:05 +00001819 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001820 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001821 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001822 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001823 proto_header = pickle.PROTO + bytes([proto])
1824 self.assertTrue(pickled.startswith(proto_header))
1825 else:
1826 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001827
1828 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001829 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001830 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001831 try:
1832 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001833 except ValueError as err:
1834 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001835 else:
1836 self.fail("expected bad protocol number to raise ValueError")
1837
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001838 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001839 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001840 for proto in protocols:
1841 s = self.dumps(x, proto)
1842 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001843 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001844 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001845
1846 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001847 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001848 for proto in protocols:
1849 s = self.dumps(x, proto)
1850 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001851 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001852 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001853
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001854 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001855 # Map (proto, len(tuple)) to expected opcode.
1856 expected_opcode = {(0, 0): pickle.TUPLE,
1857 (0, 1): pickle.TUPLE,
1858 (0, 2): pickle.TUPLE,
1859 (0, 3): pickle.TUPLE,
1860 (0, 4): pickle.TUPLE,
1861
1862 (1, 0): pickle.EMPTY_TUPLE,
1863 (1, 1): pickle.TUPLE,
1864 (1, 2): pickle.TUPLE,
1865 (1, 3): pickle.TUPLE,
1866 (1, 4): pickle.TUPLE,
1867
1868 (2, 0): pickle.EMPTY_TUPLE,
1869 (2, 1): pickle.TUPLE1,
1870 (2, 2): pickle.TUPLE2,
1871 (2, 3): pickle.TUPLE3,
1872 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001873
1874 (3, 0): pickle.EMPTY_TUPLE,
1875 (3, 1): pickle.TUPLE1,
1876 (3, 2): pickle.TUPLE2,
1877 (3, 3): pickle.TUPLE3,
1878 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001879 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001880 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001881 b = (1,)
1882 c = (1, 2)
1883 d = (1, 2, 3)
1884 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001885 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001886 for x in a, b, c, d, e:
1887 s = self.dumps(x, proto)
1888 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001889 self.assert_is_copy(x, y)
1890 expected = expected_opcode[min(proto, 3), len(x)]
1891 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001892
Guido van Rossum7d97d312003-01-28 04:25:27 +00001893 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001894 # Map (proto, singleton) to expected opcode.
1895 expected_opcode = {(0, None): pickle.NONE,
1896 (1, None): pickle.NONE,
1897 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001898 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001899
1900 (0, True): pickle.INT,
1901 (1, True): pickle.INT,
1902 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001903 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001904
1905 (0, False): pickle.INT,
1906 (1, False): pickle.INT,
1907 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001908 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001909 }
Tim Peters4190fb82003-02-02 16:09:05 +00001910 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001911 for x in None, False, True:
1912 s = self.dumps(x, proto)
1913 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001914 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001915 expected = expected_opcode[min(proto, 3), x]
1916 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001917
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001918 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001919 x = MyTuple([1, 2, 3])
1920 x.foo = 42
1921 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001922 for proto in protocols:
1923 s = self.dumps(x, proto)
1924 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001925 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001926
1927 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001928 x = MyList([1, 2, 3])
1929 x.foo = 42
1930 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001931 for proto in protocols:
1932 s = self.dumps(x, proto)
1933 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001934 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001935
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001936 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001937 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001938 for C in myclasses:
1939 B = C.__base__
1940 x = C(C.sample)
1941 x.foo = 42
1942 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001943 y = self.loads(s)
1944 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001945 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001946 self.assertEqual(B(x), B(y), detail)
1947 self.assertEqual(x.__dict__, y.__dict__, detail)
1948
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001949 def test_newobj_proxies(self):
1950 # NEWOBJ should use the __class__ rather than the raw type
1951 classes = myclasses[:]
1952 # Cannot create weakproxies to these classes
1953 for c in (MyInt, MyTuple):
1954 classes.remove(c)
1955 for proto in protocols:
1956 for C in classes:
1957 B = C.__base__
1958 x = C(C.sample)
1959 x.foo = 42
1960 p = weakref.proxy(x)
1961 s = self.dumps(p, proto)
1962 y = self.loads(s)
1963 self.assertEqual(type(y), type(x)) # rather than type(p)
1964 detail = (proto, C, B, x, y, type(y))
1965 self.assertEqual(B(x), B(y), detail)
1966 self.assertEqual(x.__dict__, y.__dict__, detail)
1967
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001968 def test_newobj_not_class(self):
1969 # Issue 24552
1970 global SimpleNewObj
1971 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001972 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001973 b = self.dumps(o, 4)
1974 try:
1975 SimpleNewObj = 42
1976 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1977 finally:
1978 SimpleNewObj = save
1979
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001980 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001981 # an object of that type. Check that the resulting pickle uses opcode
1982 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001983
Tim Peters22e71712003-02-03 22:27:38 +00001984 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001985 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001986 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001987 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001988 x = MyList([1, 2, 3])
1989 x.foo = 42
1990 x.bar = "hello"
1991
Tim Peters22e71712003-02-03 22:27:38 +00001992 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001993 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001994 self.assertIn(__name__.encode("utf-8"), s1)
1995 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001996 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001997
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001998 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001999 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002000
Tim Peters22e71712003-02-03 22:27:38 +00002001 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002002 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002003 self.assertNotIn(__name__.encode("utf-8"), s2)
2004 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00002005 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00002006
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002007 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002008 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002009 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00002010 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00002011
2012 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002013 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
2014 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002015
2016 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002017 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
2018 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
2019 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002020
2021 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002022 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
2023 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
2024 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
2025
Tim Peters8d2613a2003-02-11 16:40:16 +00002026 def test_list_chunking(self):
2027 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002028 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002029 for proto in protocols:
2030 s = self.dumps(x, proto)
2031 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002032 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002033 num_appends = count_opcode(pickle.APPENDS, s)
2034 self.assertEqual(num_appends, proto > 0)
2035
2036 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002037 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002038 for proto in protocols:
2039 s = self.dumps(x, proto)
2040 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002041 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002042 num_appends = count_opcode(pickle.APPENDS, s)
2043 if proto == 0:
2044 self.assertEqual(num_appends, 0)
2045 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002046 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002047
2048 def test_dict_chunking(self):
2049 n = 10 # too small to chunk
2050 x = dict.fromkeys(range(n))
2051 for proto in protocols:
2052 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002053 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002054 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002055 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002056 num_setitems = count_opcode(pickle.SETITEMS, s)
2057 self.assertEqual(num_setitems, proto > 0)
2058
2059 n = 2500 # expect at least two chunks when proto > 0
2060 x = dict.fromkeys(range(n))
2061 for proto in protocols:
2062 s = self.dumps(x, proto)
2063 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002064 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002065 num_setitems = count_opcode(pickle.SETITEMS, s)
2066 if proto == 0:
2067 self.assertEqual(num_setitems, 0)
2068 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002069 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002070
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002071 def test_set_chunking(self):
2072 n = 10 # too small to chunk
2073 x = set(range(n))
2074 for proto in protocols:
2075 s = self.dumps(x, proto)
2076 y = self.loads(s)
2077 self.assert_is_copy(x, y)
2078 num_additems = count_opcode(pickle.ADDITEMS, s)
2079 if proto < 4:
2080 self.assertEqual(num_additems, 0)
2081 else:
2082 self.assertEqual(num_additems, 1)
2083
2084 n = 2500 # expect at least two chunks when proto >= 4
2085 x = set(range(n))
2086 for proto in protocols:
2087 s = self.dumps(x, proto)
2088 y = self.loads(s)
2089 self.assert_is_copy(x, y)
2090 num_additems = count_opcode(pickle.ADDITEMS, s)
2091 if proto < 4:
2092 self.assertEqual(num_additems, 0)
2093 else:
2094 self.assertGreaterEqual(num_additems, 2)
2095
Tim Peterse9ef2032003-02-13 18:42:00 +00002096 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002097 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002098 x.abc = 666
2099 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002100 with self.subTest(proto=proto):
2101 s = self.dumps(x, proto)
2102 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002103 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002104 else:
2105 self.assertIn(b'M\xce\xfa', s) # BININT2
2106 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2107 2 <= proto)
2108 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2109 y = self.loads(s) # will raise TypeError if __init__ called
2110 self.assert_is_copy(x, y)
2111
2112 def test_complex_newobj(self):
2113 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2114 x.abc = 666
2115 for proto in protocols:
2116 with self.subTest(proto=proto):
2117 s = self.dumps(x, proto)
2118 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002119 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002120 elif proto < 2:
2121 self.assertIn(b'M\xce\xfa', s) # BININT2
2122 elif proto < 4:
2123 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2124 else:
2125 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2126 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2127 2 <= proto)
2128 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2129 y = self.loads(s) # will raise TypeError if __init__ called
2130 self.assert_is_copy(x, y)
2131
2132 def test_complex_newobj_ex(self):
2133 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2134 x.abc = 666
2135 for proto in protocols:
2136 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002137 s = self.dumps(x, proto)
2138 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002139 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002140 elif proto < 2:
2141 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002142 elif proto < 4:
2143 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002144 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002145 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2146 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2147 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2148 4 <= proto)
2149 y = self.loads(s) # will raise TypeError if __init__ called
2150 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002151
Tim Peters42f08ac2003-02-11 22:43:24 +00002152 def test_newobj_list_slots(self):
2153 x = SlotList([1, 2, 3])
2154 x.foo = 42
2155 x.bar = "hello"
2156 s = self.dumps(x, 2)
2157 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002158 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002159
Guido van Rossum2a30b212003-02-18 22:41:24 +00002160 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002161 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002162 x = REX_one()
2163 self.assertEqual(x._reduce_called, 0)
2164 s = self.dumps(x, proto)
2165 self.assertEqual(x._reduce_called, 1)
2166 y = self.loads(s)
2167 self.assertEqual(y._reduce_called, 0)
2168
2169 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002170 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002171 x = REX_two()
2172 self.assertEqual(x._proto, None)
2173 s = self.dumps(x, proto)
2174 self.assertEqual(x._proto, proto)
2175 y = self.loads(s)
2176 self.assertEqual(y._proto, None)
2177
2178 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002179 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002180 x = REX_three()
2181 self.assertEqual(x._proto, None)
2182 s = self.dumps(x, proto)
2183 self.assertEqual(x._proto, proto)
2184 y = self.loads(s)
2185 self.assertEqual(y._proto, None)
2186
Guido van Rossumd8faa362007-04-27 19:54:29 +00002187 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002188 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002189 x = REX_four()
2190 self.assertEqual(x._proto, None)
2191 s = self.dumps(x, proto)
2192 self.assertEqual(x._proto, proto)
2193 y = self.loads(s)
2194 self.assertEqual(y._proto, proto)
2195
2196 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002197 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002198 x = REX_five()
2199 self.assertEqual(x._reduce_called, 0)
2200 s = self.dumps(x, proto)
2201 self.assertEqual(x._reduce_called, 1)
2202 y = self.loads(s)
2203 self.assertEqual(y._reduce_called, 1)
2204
Brett Cannon31f59292011-02-21 19:29:56 +00002205 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002206 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002207 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002208 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002209 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002210 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002211
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002212 def test_reduce_bad_iterator(self):
2213 # Issue4176: crash when 4th and 5th items of __reduce__()
2214 # are not iterators
2215 class C(object):
2216 def __reduce__(self):
2217 # 4th item is not an iterator
2218 return list, (), None, [], None
2219 class D(object):
2220 def __reduce__(self):
2221 # 5th item is not an iterator
2222 return dict, (), None, None, []
2223
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002224 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002225 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002226 try:
2227 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002228 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002229 pass
2230 try:
2231 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002232 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002233 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002234
Collin Winter771d8342009-04-16 03:18:06 +00002235 def test_many_puts_and_gets(self):
2236 # Test that internal data structures correctly deal with lots of
2237 # puts/gets.
2238 keys = ("aaa" + str(i) for i in range(100))
2239 large_dict = dict((k, [4, 5, 6]) for k in keys)
2240 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2241
2242 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002243 with self.subTest(proto=proto):
2244 dumped = self.dumps(obj, proto)
2245 loaded = self.loads(dumped)
2246 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002247
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002248 def test_attribute_name_interning(self):
2249 # Test that attribute names of pickled objects are interned when
2250 # unpickling.
2251 for proto in protocols:
2252 x = C()
2253 x.foo = 42
2254 x.bar = "hello"
2255 s = self.dumps(x, proto)
2256 y = self.loads(s)
2257 x_keys = sorted(x.__dict__)
2258 y_keys = sorted(y.__dict__)
2259 for x_key, y_key in zip(x_keys, y_keys):
2260 self.assertIs(x_key, y_key)
2261
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002262 def test_pickle_to_2x(self):
2263 # Pickle non-trivial data with protocol 2, expecting that it yields
2264 # the same result as Python 2.x did.
2265 # NOTE: this test is a bit too strong since we can produce different
2266 # bytecode that 2.x will still understand.
2267 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002268 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002269 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002270 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002271
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002272 def test_large_pickles(self):
2273 # Test the correctness of internal buffering routines when handling
2274 # large data.
2275 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002276 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002277 dumped = self.dumps(data, proto)
2278 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002279 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002280 self.assertEqual(loaded, data)
2281
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002282 def test_int_pickling_efficiency(self):
2283 # Test compacity of int representation (see issue #12744)
2284 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002285 with self.subTest(proto=proto):
2286 pickles = [self.dumps(2**n, proto) for n in range(70)]
2287 sizes = list(map(len, pickles))
2288 # the size function is monotonic
2289 self.assertEqual(sorted(sizes), sizes)
2290 if proto >= 2:
2291 for p in pickles:
2292 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002293
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002294 def _check_pickling_with_opcode(self, obj, opcode, proto):
2295 pickled = self.dumps(obj, proto)
2296 self.assertTrue(opcode_in_pickle(opcode, pickled))
2297 unpickled = self.loads(pickled)
2298 self.assertEqual(obj, unpickled)
2299
2300 def test_appends_on_non_lists(self):
2301 # Issue #17720
2302 obj = REX_six([1, 2, 3])
2303 for proto in protocols:
2304 if proto == 0:
2305 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2306 else:
2307 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2308
2309 def test_setitems_on_non_dicts(self):
2310 obj = REX_seven({1: -1, 2: -2, 3: -3})
2311 for proto in protocols:
2312 if proto == 0:
2313 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2314 else:
2315 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2316
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002317 # Exercise framing (proto >= 4) for significant workloads
2318
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002319 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002320 FRAME_SIZE_TARGET = 64 * 1024
2321
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002322 def check_frame_opcodes(self, pickled):
2323 """
2324 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002325
2326 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2327 framed by default and are therefore considered a frame by themselves in
2328 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002329 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002330 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002331 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2332 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002333 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002334 if frame_end is not None:
2335 self.assertLessEqual(pos, frame_end)
2336 if pos == frame_end:
2337 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002338
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002339 if frame_end is not None: # framed
2340 self.assertNotEqual(op.name, 'FRAME')
2341 if op.name in frameless_opcodes:
2342 # Only short bytes and str objects should be written
2343 # in a frame
2344 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2345
2346 else: # not framed
2347 if (op.name == 'FRAME' or
2348 (op.name in frameless_opcodes and
2349 len(arg) > self.FRAME_SIZE_TARGET)):
2350 # Frame or large bytes or str object
2351 if frameless_start is not None:
2352 # Only short data should be written outside of a frame
2353 self.assertLess(pos - frameless_start,
2354 self.FRAME_SIZE_MIN)
2355 frameless_start = None
2356 elif frameless_start is None and op.name != 'PROTO':
2357 frameless_start = pos
2358
2359 if op.name == 'FRAME':
2360 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2361 frame_end = pos + 9 + arg
2362
2363 pos = len(pickled)
2364 if frame_end is not None:
2365 self.assertEqual(frame_end, pos)
2366 elif frameless_start is not None:
2367 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002368
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002369 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002370 def test_framing_many_objects(self):
2371 obj = list(range(10**5))
2372 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2373 with self.subTest(proto=proto):
2374 pickled = self.dumps(obj, proto)
2375 unpickled = self.loads(pickled)
2376 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002377 bytes_per_frame = (len(pickled) /
2378 count_opcode(pickle.FRAME, pickled))
2379 self.assertGreater(bytes_per_frame,
2380 self.FRAME_SIZE_TARGET / 2)
2381 self.assertLessEqual(bytes_per_frame,
2382 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002383 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002384
2385 def test_framing_large_objects(self):
2386 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002387 small_items = [[i] for i in range(10)]
2388 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002389 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002390 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002391 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002392 if not fast:
2393 # fast=False by default.
2394 # This covers in-memory pickling with pickle.dumps().
2395 pickled = self.dumps(obj, proto)
2396 else:
2397 # Pickler is required when fast=True.
2398 if not hasattr(self, 'pickler'):
2399 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002400 buf = io.BytesIO()
2401 pickler = self.pickler(buf, protocol=proto)
2402 pickler.fast = fast
2403 pickler.dump(obj)
2404 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002405 unpickled = self.loads(pickled)
2406 # More informative error message in case of failure.
2407 self.assertEqual([len(x) for x in obj],
2408 [len(x) for x in unpickled])
2409 # Perform full equality check if the lengths match.
2410 self.assertEqual(obj, unpickled)
2411 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002412 # A single frame for small objects between
2413 # first two large objects.
2414 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002415 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002416
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002417 def test_optional_frames(self):
2418 if pickle.HIGHEST_PROTOCOL < 4:
2419 return
2420
2421 def remove_frames(pickled, keep_frame=None):
2422 """Remove frame opcodes from the given pickle."""
2423 frame_starts = []
2424 # 1 byte for the opcode and 8 for the argument
2425 frame_opcode_size = 9
2426 for opcode, _, pos in pickletools.genops(pickled):
2427 if opcode.name == 'FRAME':
2428 frame_starts.append(pos)
2429
2430 newpickle = bytearray()
2431 last_frame_end = 0
2432 for i, pos in enumerate(frame_starts):
2433 if keep_frame and keep_frame(i):
2434 continue
2435 newpickle += pickled[last_frame_end:pos]
2436 last_frame_end = pos + frame_opcode_size
2437 newpickle += pickled[last_frame_end:]
2438 return newpickle
2439
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002440 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002441 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002442 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002443 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002444 for bytes_type in (bytes, bytearray):
2445 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002446
Antoine Pitrou91f43802019-05-26 17:10:09 +02002447 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2448 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002449
Antoine Pitrou91f43802019-05-26 17:10:09 +02002450 frameless_pickle = remove_frames(pickled)
2451 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2452 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002453
Antoine Pitrou91f43802019-05-26 17:10:09 +02002454 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2455 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2456 count_opcode(pickle.FRAME, pickled))
2457 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002458
Neil Schemenauer52a48e62019-07-30 11:08:18 -07002459 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002460 def test_framed_write_sizes_with_delayed_writer(self):
2461 class ChunkAccumulator:
2462 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002463 def __init__(self):
2464 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002465 def write(self, chunk):
2466 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002467 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002468 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002469
2470 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002471 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2472 for i in range(int(1e4))]
2473 # Add a large unique ASCII string
2474 objects.append('0123456789abcdef' *
2475 (self.FRAME_SIZE_TARGET // 16 + 1))
2476
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002477 # Protocol 4 packs groups of small objects into frames and issues
2478 # calls to write only once or twice per frame:
2479 # The C pickler issues one call to write per-frame (header and
2480 # contents) while Python pickler issues two calls to write: one for
2481 # the frame header and one for the frame binary contents.
2482 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002483 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002484
2485 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002486 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002487 # be released otherwise this delayed access would not be possible.
2488 pickled = writer.concatenate_chunks()
2489 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002490 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002491 self.assertGreater(len(writer.chunks), 1)
2492
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002493 # memoryviews should own the memory.
2494 del objects
2495 support.gc_collect()
2496 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002497
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002498 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002499 # There should be at least one call to write per frame
2500 self.assertGreaterEqual(len(writer.chunks), n_frames)
2501
2502 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002503 # one per-frame header, one per frame for the actual contents,
2504 # and two for the header.
2505 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002506
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002507 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002508 large_sizes = [s for s in chunk_sizes
2509 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002510 medium_sizes = [s for s in chunk_sizes
2511 if 9 < s < self.FRAME_SIZE_TARGET]
2512 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002513
2514 # Large chunks should not be too large:
2515 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002516 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2517 chunk_sizes)
2518 # There shouldn't bee too many small chunks: the protocol header,
2519 # the frame headers and the large string headers are written
2520 # in small chunks.
2521 self.assertLessEqual(len(small_sizes),
2522 len(large_sizes) + len(medium_sizes) + 3,
2523 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002524
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002525 def test_nested_names(self):
2526 global Nested
2527 class Nested:
2528 class A:
2529 class B:
2530 class C:
2531 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002532 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002533 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2534 with self.subTest(proto=proto, obj=obj):
2535 unpickled = self.loads(self.dumps(obj, proto))
2536 self.assertIs(obj, unpickled)
2537
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002538 def test_recursive_nested_names(self):
2539 global Recursive
2540 class Recursive:
2541 pass
2542 Recursive.mod = sys.modules[Recursive.__module__]
2543 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2544 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2545 with self.subTest(proto=proto):
2546 unpickled = self.loads(self.dumps(Recursive, proto))
2547 self.assertIs(unpickled, Recursive)
2548 del Recursive.mod # break reference loop
2549
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002550 def test_py_methods(self):
2551 global PyMethodsTest
2552 class PyMethodsTest:
2553 @staticmethod
2554 def cheese():
2555 return "cheese"
2556 @classmethod
2557 def wine(cls):
2558 assert cls is PyMethodsTest
2559 return "wine"
2560 def biscuits(self):
2561 assert isinstance(self, PyMethodsTest)
2562 return "biscuits"
2563 class Nested:
2564 "Nested class"
2565 @staticmethod
2566 def ketchup():
2567 return "ketchup"
2568 @classmethod
2569 def maple(cls):
2570 assert cls is PyMethodsTest.Nested
2571 return "maple"
2572 def pie(self):
2573 assert isinstance(self, PyMethodsTest.Nested)
2574 return "pie"
2575
2576 py_methods = (
2577 PyMethodsTest.cheese,
2578 PyMethodsTest.wine,
2579 PyMethodsTest().biscuits,
2580 PyMethodsTest.Nested.ketchup,
2581 PyMethodsTest.Nested.maple,
2582 PyMethodsTest.Nested().pie
2583 )
2584 py_unbound_methods = (
2585 (PyMethodsTest.biscuits, PyMethodsTest),
2586 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2587 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002588 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002589 for method in py_methods:
2590 with self.subTest(proto=proto, method=method):
2591 unpickled = self.loads(self.dumps(method, proto))
2592 self.assertEqual(method(), unpickled())
2593 for method, cls in py_unbound_methods:
2594 obj = cls()
2595 with self.subTest(proto=proto, method=method):
2596 unpickled = self.loads(self.dumps(method, proto))
2597 self.assertEqual(method(obj), unpickled(obj))
2598
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002599 def test_c_methods(self):
2600 global Subclass
2601 class Subclass(tuple):
2602 class Nested(str):
2603 pass
2604
2605 c_methods = (
2606 # bound built-in method
2607 ("abcd".index, ("c",)),
2608 # unbound built-in method
2609 (str.index, ("abcd", "c")),
2610 # bound "slot" method
2611 ([1, 2, 3].__len__, ()),
2612 # unbound "slot" method
2613 (list.__len__, ([1, 2, 3],)),
2614 # bound "coexist" method
2615 ({1, 2}.__contains__, (2,)),
2616 # unbound "coexist" method
2617 (set.__contains__, ({1, 2}, 2)),
2618 # built-in class method
2619 (dict.fromkeys, (("a", 1), ("b", 2))),
2620 # built-in static method
2621 (bytearray.maketrans, (b"abc", b"xyz")),
2622 # subclass methods
2623 (Subclass([1,2,2]).count, (2,)),
2624 (Subclass.count, (Subclass([1,2,2]), 2)),
2625 (Subclass.Nested("sweet").count, ("e",)),
2626 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2627 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002628 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002629 for method, args in c_methods:
2630 with self.subTest(proto=proto, method=method):
2631 unpickled = self.loads(self.dumps(method, proto))
2632 self.assertEqual(method(*args), unpickled(*args))
2633
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002634 def test_compat_pickle(self):
2635 tests = [
2636 (range(1, 7), '__builtin__', 'xrange'),
2637 (map(int, '123'), 'itertools', 'imap'),
2638 (functools.reduce, '__builtin__', 'reduce'),
2639 (dbm.whichdb, 'whichdb', 'whichdb'),
2640 (Exception(), 'exceptions', 'Exception'),
2641 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2642 (collections.UserList(), 'UserList', 'UserList'),
2643 (collections.defaultdict(), 'collections', 'defaultdict'),
2644 ]
2645 for val, mod, name in tests:
2646 for proto in range(3):
2647 with self.subTest(type=type(val), proto=proto):
2648 pickled = self.dumps(val, proto)
2649 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2650 self.assertIs(type(self.loads(pickled)), type(val))
2651
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002652 def test_local_lookup_error(self):
2653 # Test that whichmodule() errors out cleanly when looking up
2654 # an assumed globally-reachable object fails.
2655 def f():
2656 pass
2657 # Since the function is local, lookup will fail
2658 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2659 with self.assertRaises((AttributeError, pickle.PicklingError)):
2660 pickletools.dis(self.dumps(f, proto))
2661 # Same without a __module__ attribute (exercises a different path
2662 # in _pickle.c).
2663 del f.__module__
2664 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2665 with self.assertRaises((AttributeError, pickle.PicklingError)):
2666 pickletools.dis(self.dumps(f, proto))
2667 # Yet a different path.
2668 f.__name__ = f.__qualname__
2669 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2670 with self.assertRaises((AttributeError, pickle.PicklingError)):
2671 pickletools.dis(self.dumps(f, proto))
2672
Antoine Pitrou91f43802019-05-26 17:10:09 +02002673 #
2674 # PEP 574 tests below
2675 #
2676
2677 def buffer_like_objects(self):
2678 # Yield buffer-like objects with the bytestring "abcdef" in them
2679 bytestring = b"abcdefgh"
2680 yield ZeroCopyBytes(bytestring)
2681 yield ZeroCopyBytearray(bytestring)
2682 if _testbuffer is not None:
2683 items = list(bytestring)
2684 value = int.from_bytes(bytestring, byteorder='little')
2685 for flags in (0, _testbuffer.ND_WRITABLE):
2686 # 1-D, contiguous
2687 yield PicklableNDArray(items, format='B', shape=(8,),
2688 flags=flags)
2689 # 2-D, C-contiguous
2690 yield PicklableNDArray(items, format='B', shape=(4, 2),
2691 strides=(2, 1), flags=flags)
2692 # 2-D, Fortran-contiguous
2693 yield PicklableNDArray(items, format='B',
2694 shape=(4, 2), strides=(1, 4),
2695 flags=flags)
2696
2697 def test_in_band_buffers(self):
2698 # Test in-band buffers (PEP 574)
2699 for obj in self.buffer_like_objects():
2700 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2701 data = self.dumps(obj, proto)
2702 if obj.c_contiguous and proto >= 5:
2703 # The raw memory bytes are serialized in physical order
2704 self.assertIn(b"abcdefgh", data)
2705 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2706 if proto >= 5:
2707 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2708 1 if obj.readonly else 0)
2709 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2710 0 if obj.readonly else 1)
2711 # Return a true value from buffer_callback should have
2712 # the same effect
2713 def buffer_callback(obj):
2714 return True
2715 data2 = self.dumps(obj, proto,
2716 buffer_callback=buffer_callback)
2717 self.assertEqual(data2, data)
2718
2719 new = self.loads(data)
2720 # It's a copy
2721 self.assertIsNot(new, obj)
2722 self.assertIs(type(new), type(obj))
2723 self.assertEqual(new, obj)
2724
2725 # XXX Unfortunately cannot test non-contiguous array
2726 # (see comment in PicklableNDArray.__reduce_ex__)
2727
2728 def test_oob_buffers(self):
2729 # Test out-of-band buffers (PEP 574)
2730 for obj in self.buffer_like_objects():
2731 for proto in range(0, 5):
2732 # Need protocol >= 5 for buffer_callback
2733 with self.assertRaises(ValueError):
2734 self.dumps(obj, proto,
2735 buffer_callback=[].append)
2736 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2737 buffers = []
2738 buffer_callback = lambda pb: buffers.append(pb.raw())
2739 data = self.dumps(obj, proto,
2740 buffer_callback=buffer_callback)
2741 self.assertNotIn(b"abcdefgh", data)
2742 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2743 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2744 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2745 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2746 1 if obj.readonly else 0)
2747
2748 if obj.c_contiguous:
2749 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2750 # Need buffers argument to unpickle properly
2751 with self.assertRaises(pickle.UnpicklingError):
2752 self.loads(data)
2753
2754 new = self.loads(data, buffers=buffers)
2755 if obj.zero_copy_reconstruct:
2756 # Zero-copy achieved
2757 self.assertIs(new, obj)
2758 else:
2759 self.assertIs(type(new), type(obj))
2760 self.assertEqual(new, obj)
2761 # Non-sequence buffers accepted too
2762 new = self.loads(data, buffers=iter(buffers))
2763 if obj.zero_copy_reconstruct:
2764 # Zero-copy achieved
2765 self.assertIs(new, obj)
2766 else:
2767 self.assertIs(type(new), type(obj))
2768 self.assertEqual(new, obj)
2769
2770 def test_oob_buffers_writable_to_readonly(self):
2771 # Test reconstructing readonly object from writable buffer
2772 obj = ZeroCopyBytes(b"foobar")
2773 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2774 buffers = []
2775 buffer_callback = buffers.append
2776 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2777
2778 buffers = map(bytearray, buffers)
2779 new = self.loads(data, buffers=buffers)
2780 self.assertIs(type(new), type(obj))
2781 self.assertEqual(new, obj)
2782
2783 def test_picklebuffer_error(self):
2784 # PickleBuffer forbidden with protocol < 5
2785 pb = pickle.PickleBuffer(b"foobar")
2786 for proto in range(0, 5):
2787 with self.assertRaises(pickle.PickleError):
2788 self.dumps(pb, proto)
2789
2790 def test_buffer_callback_error(self):
2791 def buffer_callback(buffers):
2792 1/0
2793 pb = pickle.PickleBuffer(b"foobar")
2794 with self.assertRaises(ZeroDivisionError):
2795 self.dumps(pb, 5, buffer_callback=buffer_callback)
2796
2797 def test_buffers_error(self):
2798 pb = pickle.PickleBuffer(b"foobar")
2799 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2800 data = self.dumps(pb, proto, buffer_callback=[].append)
2801 # Non iterable buffers
2802 with self.assertRaises(TypeError):
2803 self.loads(data, buffers=object())
2804 # Buffer iterable exhausts too early
2805 with self.assertRaises(pickle.UnpicklingError):
2806 self.loads(data, buffers=[])
2807
Markus Mohrhard898318b2019-07-26 00:00:34 +08002808 def test_inband_accept_default_buffers_argument(self):
2809 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2810 data_pickled = self.dumps(1, proto, buffer_callback=None)
2811 data = self.loads(data_pickled, buffers=None)
2812
Antoine Pitrou91f43802019-05-26 17:10:09 +02002813 @unittest.skipIf(np is None, "Test needs Numpy")
2814 def test_buffers_numpy(self):
2815 def check_no_copy(x, y):
2816 np.testing.assert_equal(x, y)
2817 self.assertEqual(x.ctypes.data, y.ctypes.data)
2818
2819 def check_copy(x, y):
2820 np.testing.assert_equal(x, y)
2821 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2822
2823 def check_array(arr):
2824 # In-band
2825 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2826 data = self.dumps(arr, proto)
2827 new = self.loads(data)
2828 check_copy(arr, new)
2829 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2830 buffer_callback = lambda _: True
2831 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2832 new = self.loads(data)
2833 check_copy(arr, new)
2834 # Out-of-band
2835 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2836 buffers = []
2837 buffer_callback = buffers.append
2838 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2839 new = self.loads(data, buffers=buffers)
2840 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2841 check_no_copy(arr, new)
2842 else:
2843 check_copy(arr, new)
2844
2845 # 1-D
2846 arr = np.arange(6)
2847 check_array(arr)
2848 # 1-D, non-contiguous
2849 check_array(arr[::2])
2850 # 2-D, C-contiguous
2851 arr = np.arange(12).reshape((3, 4))
2852 check_array(arr)
2853 # 2-D, F-contiguous
2854 check_array(arr.T)
2855 # 2-D, non-contiguous
2856 check_array(arr[::2])
2857
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002858
2859class BigmemPickleTests(unittest.TestCase):
2860
Victor Stinner8c663fd2017-11-08 14:44:44 -08002861 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002862
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002863 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002864 def test_huge_long_32b(self, size):
2865 data = 1 << (8 * size)
2866 try:
2867 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002868 if proto < 2:
2869 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002870 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002871 with self.assertRaises((ValueError, OverflowError)):
2872 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002873 finally:
2874 data = None
2875
Victor Stinner8c663fd2017-11-08 14:44:44 -08002876 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002877 # (older protocols don't have a dedicated opcode for bytes and are
2878 # too inefficient)
2879
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002880 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002881 def test_huge_bytes_32b(self, size):
2882 data = b"abcd" * (size // 4)
2883 try:
2884 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002885 if proto < 3:
2886 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002887 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002888 try:
2889 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002890 header = (pickle.BINBYTES +
2891 struct.pack("<I", len(data)))
2892 data_start = pickled.index(data)
2893 self.assertEqual(
2894 header,
2895 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002896 finally:
2897 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002898 finally:
2899 data = None
2900
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002901 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002902 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002903 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002904 try:
2905 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002906 if proto < 3:
2907 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002908 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002909 if proto == 3:
2910 # Protocol 3 does not support large bytes objects.
2911 # Verify that we do not crash when processing one.
2912 with self.assertRaises((ValueError, OverflowError)):
2913 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002914 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002915 try:
2916 pickled = self.dumps(data, protocol=proto)
2917 header = (pickle.BINBYTES8 +
2918 struct.pack("<Q", len(data)))
2919 data_start = pickled.index(data)
2920 self.assertEqual(
2921 header,
2922 pickled[data_start-len(header):data_start])
2923 finally:
2924 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002925 finally:
2926 data = None
2927
2928 # All protocols use 1-byte per printable ASCII character; we add another
2929 # byte because the encoded form has to be copied into the internal buffer.
2930
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002931 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002932 def test_huge_str_32b(self, size):
2933 data = "abcd" * (size // 4)
2934 try:
2935 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002936 if proto == 0:
2937 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002938 with self.subTest(proto=proto):
2939 try:
2940 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002941 header = (pickle.BINUNICODE +
2942 struct.pack("<I", len(data)))
2943 data_start = pickled.index(b'abcd')
2944 self.assertEqual(
2945 header,
2946 pickled[data_start-len(header):data_start])
2947 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2948 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002949 finally:
2950 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002951 finally:
2952 data = None
2953
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002954 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2955 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2956 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002957
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002958 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002959 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002960 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002961 try:
2962 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002963 if proto == 0:
2964 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002965 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002966 if proto < 4:
2967 with self.assertRaises((ValueError, OverflowError)):
2968 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002969 continue
2970 try:
2971 pickled = self.dumps(data, protocol=proto)
2972 header = (pickle.BINUNICODE8 +
2973 struct.pack("<Q", len(data)))
2974 data_start = pickled.index(b'abcd')
2975 self.assertEqual(
2976 header,
2977 pickled[data_start-len(header):data_start])
2978 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2979 pickled.index(b"abcd")), len(data))
2980 finally:
2981 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002982 finally:
2983 data = None
2984
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002985
Guido van Rossum2a30b212003-02-18 22:41:24 +00002986# Test classes for reduce_ex
2987
2988class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002989 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002990 _reduce_called = 0
2991 def __reduce__(self):
2992 self._reduce_called = 1
2993 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002994
2995class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002996 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002997 _proto = None
2998 def __reduce_ex__(self, proto):
2999 self._proto = proto
3000 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00003001
3002class REX_three(object):
3003 _proto = None
3004 def __reduce_ex__(self, proto):
3005 self._proto = proto
3006 return REX_two, ()
3007 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00003008 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00003009
Guido van Rossumd8faa362007-04-27 19:54:29 +00003010class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003011 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003012 _proto = None
3013 def __reduce_ex__(self, proto):
3014 self._proto = proto
3015 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00003016
3017class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003018 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00003019 _reduce_called = 0
3020 def __reduce__(self):
3021 self._reduce_called = 1
3022 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003023
3024class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003025 """This class is used to check the 4th argument (list iterator) of
3026 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003027 """
3028 def __init__(self, items=None):
3029 self.items = items if items is not None else []
3030 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003031 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003032 def append(self, item):
3033 self.items.append(item)
3034 def __reduce__(self):
3035 return type(self), (), None, iter(self.items), None
3036
3037class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003038 """This class is used to check the 5th argument (dict iterator) of
3039 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003040 """
3041 def __init__(self, table=None):
3042 self.table = table if table is not None else {}
3043 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003044 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003045 def __setitem__(self, key, value):
3046 self.table[key] = value
3047 def __reduce__(self):
3048 return type(self), (), None, None, iter(self.table.items())
3049
Guido van Rossumd8faa362007-04-27 19:54:29 +00003050
Guido van Rossum2a30b212003-02-18 22:41:24 +00003051# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003052
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003053class MyInt(int):
3054 sample = 1
3055
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003056class MyFloat(float):
3057 sample = 1.0
3058
3059class MyComplex(complex):
3060 sample = 1.0 + 0.0j
3061
3062class MyStr(str):
3063 sample = "hello"
3064
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003065class MyUnicode(str):
3066 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003067
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003068class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003069 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003070
3071class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003072 sample = [1, 2, 3]
3073
3074class MyDict(dict):
3075 sample = {"a": 1, "b": 2}
3076
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003077class MySet(set):
3078 sample = {"a", "b"}
3079
3080class MyFrozenSet(frozenset):
3081 sample = frozenset({"a", "b"})
3082
Mark Dickinson5c2db372009-12-05 20:28:34 +00003083myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003084 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003085 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003086 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003087
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003088
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003089class SlotList(MyList):
3090 __slots__ = ["foo"]
3091
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003092class SimpleNewObj(int):
3093 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003094 # raise an error, to make sure this isn't called
3095 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003096 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003097 return int(self) == int(other) and self.__dict__ == other.__dict__
3098
3099class ComplexNewObj(SimpleNewObj):
3100 def __getnewargs__(self):
3101 return ('%X' % self, 16)
3102
3103class ComplexNewObjEx(SimpleNewObj):
3104 def __getnewargs_ex__(self):
3105 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003106
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003107class BadGetattr:
3108 def __getattr__(self, key):
3109 self.foo
3110
Collin Winter771d8342009-04-16 03:18:06 +00003111
Jeremy Hylton66426532001-10-15 21:38:56 +00003112class AbstractPickleModuleTests(unittest.TestCase):
3113
3114 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003115 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003116 try:
3117 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003118 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003119 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003120 support.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003121
3122 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003123 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003124 try:
3125 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003126 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003127 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003128 support.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003129
Collin Winter771d8342009-04-16 03:18:06 +00003130 def test_load_from_and_dump_to_file(self):
3131 stream = io.BytesIO()
3132 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003133 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003134 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003135 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003136 self.assertEqual(unpickled, data)
3137
Tim Petersc0c93702003-02-13 19:30:57 +00003138 def test_highest_protocol(self):
3139 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003140 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003141
Martin v. Löwis544f1192004-07-27 05:22:33 +00003142 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003143 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003144 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003145 self.dump(123, f, -1)
3146 self.dump(123, file=f, protocol=-1)
3147 self.dumps(123, -1)
3148 self.dumps(123, protocol=-1)
3149 self.Pickler(f, -1)
3150 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003151
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003152 def test_dump_text_file(self):
3153 f = open(TESTFN, "w")
3154 try:
3155 for proto in protocols:
3156 self.assertRaises(TypeError, self.dump, 123, f, proto)
3157 finally:
3158 f.close()
3159 support.unlink(TESTFN)
3160
3161 def test_incomplete_input(self):
3162 s = io.BytesIO(b"X''.")
3163 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3164
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003165 def test_bad_init(self):
3166 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003167 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003168 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003169 def __init__(self): pass
3170
Serhiy Storchaka65452562017-11-15 14:01:08 +02003171 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003172 def __init__(self): pass
3173
3174 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3175 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3176
Antoine Pitrou91f43802019-05-26 17:10:09 +02003177 def check_dumps_loads_oob_buffers(self, dumps, loads):
3178 # No need to do the full gamut of tests here, just enough to
3179 # check that dumps() and loads() redirect their arguments
3180 # to the underlying Pickler and Unpickler, respectively.
3181 obj = ZeroCopyBytes(b"foo")
3182
3183 for proto in range(0, 5):
3184 # Need protocol >= 5 for buffer_callback
3185 with self.assertRaises(ValueError):
3186 dumps(obj, protocol=proto,
3187 buffer_callback=[].append)
3188 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3189 buffers = []
3190 buffer_callback = buffers.append
3191 data = dumps(obj, protocol=proto,
3192 buffer_callback=buffer_callback)
3193 self.assertNotIn(b"foo", data)
3194 self.assertEqual(bytes(buffers[0]), b"foo")
3195 # Need buffers argument to unpickle properly
3196 with self.assertRaises(pickle.UnpicklingError):
3197 loads(data)
3198 new = loads(data, buffers=buffers)
3199 self.assertIs(new, obj)
3200
3201 def test_dumps_loads_oob_buffers(self):
3202 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3203 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3204
3205 def test_dump_load_oob_buffers(self):
3206 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3207 def dumps(obj, **kwargs):
3208 f = io.BytesIO()
3209 self.dump(obj, f, **kwargs)
3210 return f.getvalue()
3211
3212 def loads(data, **kwargs):
3213 f = io.BytesIO(data)
3214 return self.load(f, **kwargs)
3215
3216 self.check_dumps_loads_oob_buffers(dumps, loads)
3217
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003218
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003219class AbstractPersistentPicklerTests(unittest.TestCase):
3220
3221 # This class defines persistent_id() and persistent_load()
3222 # functions that should be used by the pickler. All even integers
3223 # are pickled using persistent ids.
3224
3225 def persistent_id(self, object):
3226 if isinstance(object, int) and object % 2 == 0:
3227 self.id_count += 1
3228 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003229 elif object == "test_false_value":
3230 self.false_count += 1
3231 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003232 else:
3233 return None
3234
3235 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003236 if not oid:
3237 self.load_false_count += 1
3238 return "test_false_value"
3239 else:
3240 self.load_count += 1
3241 object = int(oid)
3242 assert object % 2 == 0
3243 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003244
3245 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003246 L = list(range(10)) + ["test_false_value"]
3247 for proto in protocols:
3248 self.id_count = 0
3249 self.false_count = 0
3250 self.load_false_count = 0
3251 self.load_count = 0
3252 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3253 self.assertEqual(self.id_count, 5)
3254 self.assertEqual(self.false_count, 1)
3255 self.assertEqual(self.load_count, 5)
3256 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003257
Collin Winter771d8342009-04-16 03:18:06 +00003258
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003259class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3260
3261 def persistent_id(self, obj):
3262 return obj
3263
3264 def persistent_load(self, pid):
3265 return pid
3266
3267 def _check_return_correct_type(self, obj, proto):
3268 unpickled = self.loads(self.dumps(obj, proto))
3269 self.assertIsInstance(unpickled, type(obj))
3270 self.assertEqual(unpickled, obj)
3271
3272 def test_return_correct_type(self):
3273 for proto in protocols:
3274 # Protocol 0 supports only ASCII strings.
3275 if proto == 0:
3276 self._check_return_correct_type("abc", 0)
3277 else:
3278 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3279 self._check_return_correct_type(obj, proto)
3280
3281 def test_protocol0_is_ascii_only(self):
3282 non_ascii_str = "\N{EMPTY SET}"
3283 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3284 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3285 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3286
3287
Collin Winter771d8342009-04-16 03:18:06 +00003288class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3289
3290 pickler_class = None
3291 unpickler_class = None
3292
3293 def setUp(self):
3294 assert self.pickler_class
3295 assert self.unpickler_class
3296
3297 def test_clear_pickler_memo(self):
3298 # To test whether clear_memo() has any effect, we pickle an object,
3299 # then pickle it again without clearing the memo; the two serialized
3300 # forms should be different. If we clear_memo() and then pickle the
3301 # object again, the third serialized form should be identical to the
3302 # first one we obtained.
3303 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003304 for proto in protocols:
3305 f = io.BytesIO()
3306 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003307
Serhiy Storchakac8695292018-04-04 00:11:27 +03003308 pickler.dump(data)
3309 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003310
Serhiy Storchakac8695292018-04-04 00:11:27 +03003311 # Reset BytesIO object.
3312 f.seek(0)
3313 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003314
Serhiy Storchakac8695292018-04-04 00:11:27 +03003315 pickler.dump(data)
3316 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003317
Serhiy Storchakac8695292018-04-04 00:11:27 +03003318 # Reset the Pickler and BytesIO objects.
3319 pickler.clear_memo()
3320 f.seek(0)
3321 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003322
Serhiy Storchakac8695292018-04-04 00:11:27 +03003323 pickler.dump(data)
3324 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003325
Serhiy Storchakac8695292018-04-04 00:11:27 +03003326 self.assertNotEqual(first_pickled, second_pickled)
3327 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003328
3329 def test_priming_pickler_memo(self):
3330 # Verify that we can set the Pickler's memo attribute.
3331 data = ["abcdefg", "abcdefg", 44]
3332 f = io.BytesIO()
3333 pickler = self.pickler_class(f)
3334
3335 pickler.dump(data)
3336 first_pickled = f.getvalue()
3337
3338 f = io.BytesIO()
3339 primed = self.pickler_class(f)
3340 primed.memo = pickler.memo
3341
3342 primed.dump(data)
3343 primed_pickled = f.getvalue()
3344
3345 self.assertNotEqual(first_pickled, primed_pickled)
3346
3347 def test_priming_unpickler_memo(self):
3348 # Verify that we can set the Unpickler's memo attribute.
3349 data = ["abcdefg", "abcdefg", 44]
3350 f = io.BytesIO()
3351 pickler = self.pickler_class(f)
3352
3353 pickler.dump(data)
3354 first_pickled = f.getvalue()
3355
3356 f = io.BytesIO()
3357 primed = self.pickler_class(f)
3358 primed.memo = pickler.memo
3359
3360 primed.dump(data)
3361 primed_pickled = f.getvalue()
3362
3363 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3364 unpickled_data1 = unpickler.load()
3365
3366 self.assertEqual(unpickled_data1, data)
3367
3368 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3369 primed.memo = unpickler.memo
3370 unpickled_data2 = primed.load()
3371
3372 primed.memo.clear()
3373
3374 self.assertEqual(unpickled_data2, data)
3375 self.assertTrue(unpickled_data2 is unpickled_data1)
3376
3377 def test_reusing_unpickler_objects(self):
3378 data1 = ["abcdefg", "abcdefg", 44]
3379 f = io.BytesIO()
3380 pickler = self.pickler_class(f)
3381 pickler.dump(data1)
3382 pickled1 = f.getvalue()
3383
3384 data2 = ["abcdefg", 44, 44]
3385 f = io.BytesIO()
3386 pickler = self.pickler_class(f)
3387 pickler.dump(data2)
3388 pickled2 = f.getvalue()
3389
3390 f = io.BytesIO()
3391 f.write(pickled1)
3392 f.seek(0)
3393 unpickler = self.unpickler_class(f)
3394 self.assertEqual(unpickler.load(), data1)
3395
3396 f.seek(0)
3397 f.truncate()
3398 f.write(pickled2)
3399 f.seek(0)
3400 self.assertEqual(unpickler.load(), data2)
3401
Antoine Pitrou9f378722020-02-23 23:33:53 +01003402 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003403 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003404 with self.subTest(proto=proto):
3405 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3406 f = ioclass()
3407 pickler = self.pickler_class(f, protocol=proto)
3408 pickler.dump(data1)
3409 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003410
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003411 N = 5
3412 f = ioclass(pickled * N)
3413 unpickler = self.unpickler_class(f)
3414 for i in range(N):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003415 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003416 pos = f.tell()
3417 self.assertEqual(unpickler.load(), data1)
Antoine Pitrou9f378722020-02-23 23:33:53 +01003418 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003419 self.assertEqual(f.tell(), pos + len(pickled))
3420 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003421
3422 def test_multiple_unpicklings_seekable(self):
3423 self._check_multiple_unpicklings(io.BytesIO)
3424
3425 def test_multiple_unpicklings_unseekable(self):
Antoine Pitrou9f378722020-02-23 23:33:53 +01003426 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3427
3428 def test_multiple_unpicklings_minimal(self):
3429 # File-like object that doesn't support peek() and readinto()
3430 # (bpo-39681)
3431 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003432
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003433 def test_unpickling_buffering_readline(self):
3434 # Issue #12687: the unpickler's buffering logic could fail with
3435 # text mode opcodes.
3436 data = list(range(10))
3437 for proto in protocols:
3438 for buf_size in range(1, 11):
3439 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3440 pickler = self.pickler_class(f, protocol=proto)
3441 pickler.dump(data)
3442 f.seek(0)
3443 unpickler = self.unpickler_class(f)
3444 self.assertEqual(unpickler.load(), data)
3445
Collin Winter771d8342009-04-16 03:18:06 +00003446
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003447# Tests for dispatch_table attribute
3448
3449REDUCE_A = 'reduce_A'
3450
3451class AAA(object):
3452 def __reduce__(self):
3453 return str, (REDUCE_A,)
3454
3455class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003456 def __init__(self):
3457 # Add an instance attribute to enable state-saving routines at pickling
3458 # time.
3459 self.a = "some attribute"
3460
3461 def __setstate__(self, state):
3462 self.a = "BBB.__setstate__"
3463
3464
3465def setstate_bbb(obj, state):
3466 """Custom state setter for BBB objects
3467
3468 Such callable may be created by other persons than the ones who created the
3469 BBB class. If passed as the state_setter item of a custom reducer, this
3470 allows for custom state setting behavior of BBB objects. One can think of
3471 it as the analogous of list_setitems or dict_setitems but for foreign
3472 classes/functions.
3473 """
3474 obj.a = "custom state_setter"
3475
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003476
Pierre Glaser289f1f82019-05-08 23:08:25 +02003477
3478class AbstractCustomPicklerClass:
3479 """Pickler implementing a reducing hook using reducer_override."""
3480 def reducer_override(self, obj):
3481 obj_name = getattr(obj, "__name__", None)
3482
3483 if obj_name == 'f':
3484 # asking the pickler to save f as 5
3485 return int, (5, )
3486
3487 if obj_name == 'MyClass':
3488 return str, ('some str',)
3489
3490 elif obj_name == 'g':
3491 # in this case, the callback returns an invalid result (not a 2-5
3492 # tuple or a string), the pickler should raise a proper error.
3493 return False
3494
3495 elif obj_name == 'h':
3496 # Simulate a case when the reducer fails. The error should
3497 # be propagated to the original ``dump`` call.
3498 raise ValueError('The reducer just failed')
3499
3500 return NotImplemented
3501
3502class AbstractHookTests(unittest.TestCase):
3503 def test_pickler_hook(self):
3504 # test the ability of a custom, user-defined CPickler subclass to
3505 # override the default reducing routines of any type using the method
3506 # reducer_override
3507
3508 def f():
3509 pass
3510
3511 def g():
3512 pass
3513
3514 def h():
3515 pass
3516
3517 class MyClass:
3518 pass
3519
3520 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3521 with self.subTest(proto=proto):
3522 bio = io.BytesIO()
3523 p = self.pickler_class(bio, proto)
3524
3525 p.dump([f, MyClass, math.log])
3526 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3527
3528 self.assertEqual(new_f, 5)
3529 self.assertEqual(some_str, 'some str')
3530 # math.log does not have its usual reducer overriden, so the
3531 # custom reduction callback should silently direct the pickler
3532 # to the default pickling by attribute, by returning
3533 # NotImplemented
3534 self.assertIs(math_log, math.log)
3535
3536 with self.assertRaises(pickle.PicklingError):
3537 p.dump(g)
3538
3539 with self.assertRaisesRegex(
3540 ValueError, 'The reducer just failed'):
3541 p.dump(h)
3542
Pierre Glaser0f2f35e2020-02-02 19:55:21 +01003543 @support.cpython_only
3544 def test_reducer_override_no_reference_cycle(self):
3545 # bpo-39492: reducer_override used to induce a spurious reference cycle
3546 # inside the Pickler object, that could prevent all serialized objects
3547 # from being garbage-collected without explicity invoking gc.collect.
3548
3549 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3550 with self.subTest(proto=proto):
3551 def f():
3552 pass
3553
3554 wr = weakref.ref(f)
3555
3556 bio = io.BytesIO()
3557 p = self.pickler_class(bio, proto)
3558 p.dump(f)
3559 new_f = pickle.loads(bio.getvalue())
3560 assert new_f == 5
3561
3562 del p
3563 del f
3564
3565 self.assertIsNone(wr())
3566
Pierre Glaser289f1f82019-05-08 23:08:25 +02003567
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003568class AbstractDispatchTableTests(unittest.TestCase):
3569
3570 def test_default_dispatch_table(self):
3571 # No dispatch_table attribute by default
3572 f = io.BytesIO()
3573 p = self.pickler_class(f, 0)
3574 with self.assertRaises(AttributeError):
3575 p.dispatch_table
3576 self.assertFalse(hasattr(p, 'dispatch_table'))
3577
3578 def test_class_dispatch_table(self):
3579 # A dispatch_table attribute can be specified class-wide
3580 dt = self.get_dispatch_table()
3581
3582 class MyPickler(self.pickler_class):
3583 dispatch_table = dt
3584
3585 def dumps(obj, protocol=None):
3586 f = io.BytesIO()
3587 p = MyPickler(f, protocol)
3588 self.assertEqual(p.dispatch_table, dt)
3589 p.dump(obj)
3590 return f.getvalue()
3591
3592 self._test_dispatch_table(dumps, dt)
3593
3594 def test_instance_dispatch_table(self):
3595 # A dispatch_table attribute can also be specified instance-wide
3596 dt = self.get_dispatch_table()
3597
3598 def dumps(obj, protocol=None):
3599 f = io.BytesIO()
3600 p = self.pickler_class(f, protocol)
3601 p.dispatch_table = dt
3602 self.assertEqual(p.dispatch_table, dt)
3603 p.dump(obj)
3604 return f.getvalue()
3605
3606 self._test_dispatch_table(dumps, dt)
3607
3608 def _test_dispatch_table(self, dumps, dispatch_table):
3609 def custom_load_dump(obj):
3610 return pickle.loads(dumps(obj, 0))
3611
3612 def default_load_dump(obj):
3613 return pickle.loads(pickle.dumps(obj, 0))
3614
3615 # pickling complex numbers using protocol 0 relies on copyreg
3616 # so check pickling a complex number still works
3617 z = 1 + 2j
3618 self.assertEqual(custom_load_dump(z), z)
3619 self.assertEqual(default_load_dump(z), z)
3620
3621 # modify pickling of complex
3622 REDUCE_1 = 'reduce_1'
3623 def reduce_1(obj):
3624 return str, (REDUCE_1,)
3625 dispatch_table[complex] = reduce_1
3626 self.assertEqual(custom_load_dump(z), REDUCE_1)
3627 self.assertEqual(default_load_dump(z), z)
3628
3629 # check picklability of AAA and BBB
3630 a = AAA()
3631 b = BBB()
3632 self.assertEqual(custom_load_dump(a), REDUCE_A)
3633 self.assertIsInstance(custom_load_dump(b), BBB)
3634 self.assertEqual(default_load_dump(a), REDUCE_A)
3635 self.assertIsInstance(default_load_dump(b), BBB)
3636
3637 # modify pickling of BBB
3638 dispatch_table[BBB] = reduce_1
3639 self.assertEqual(custom_load_dump(a), REDUCE_A)
3640 self.assertEqual(custom_load_dump(b), REDUCE_1)
3641 self.assertEqual(default_load_dump(a), REDUCE_A)
3642 self.assertIsInstance(default_load_dump(b), BBB)
3643
3644 # revert pickling of BBB and modify pickling of AAA
3645 REDUCE_2 = 'reduce_2'
3646 def reduce_2(obj):
3647 return str, (REDUCE_2,)
3648 dispatch_table[AAA] = reduce_2
3649 del dispatch_table[BBB]
3650 self.assertEqual(custom_load_dump(a), REDUCE_2)
3651 self.assertIsInstance(custom_load_dump(b), BBB)
3652 self.assertEqual(default_load_dump(a), REDUCE_A)
3653 self.assertIsInstance(default_load_dump(b), BBB)
3654
Pierre Glaser65d98d02019-05-08 21:40:25 +02003655 # End-to-end testing of save_reduce with the state_setter keyword
3656 # argument. This is a dispatch_table test as the primary goal of
3657 # state_setter is to tweak objects reduction behavior.
3658 # In particular, state_setter is useful when the default __setstate__
3659 # behavior is not flexible enough.
3660
3661 # No custom reducer for b has been registered for now, so
3662 # BBB.__setstate__ should be used at unpickling time
3663 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3664
3665 def reduce_bbb(obj):
3666 return BBB, (), obj.__dict__, None, None, setstate_bbb
3667
3668 dispatch_table[BBB] = reduce_bbb
3669
3670 # The custom reducer reduce_bbb includes a state setter, that should
3671 # have priority over BBB.__setstate__
3672 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3673
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003674
Guido van Rossum98297ee2007-11-06 21:34:58 +00003675if __name__ == "__main__":
3676 # Print some stuff that can be used to rewrite DATA{0,1,2}
3677 from pickletools import dis
3678 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003679 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003680 p = pickle.dumps(x, i)
3681 print("DATA{0} = (".format(i))
3682 for j in range(0, len(p), 20):
3683 b = bytes(p[j:j+20])
3684 print(" {0!r}".format(b))
3685 print(")")
3686 print()
3687 print("# Disassembly of DATA{0}".format(i))
3688 print("DATA{0}_DIS = \"\"\"\\".format(i))
3689 dis(p)
3690 print("\"\"\"")
3691 print()