blob: 7c8383f3eaac921196fc933404b19dabb4e49710 [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
24try:
25 import numpy as np
26except ImportError:
27 np = None
28
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020029from test import support
Antoine Pitrou82be19f2011-08-29 23:09:33 +020030from test.support import (
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020031 TestFailed, TESTFN, run_with_locale, no_tracing,
tjb9004371c0a2019-02-18 23:30:51 +080032 _2G, _4G, bigmemtest, reap_threads, forget,
Antoine Pitrou82be19f2011-08-29 23:09:33 +020033 )
Tim Peterse089c682001-04-10 03:41:41 +000034
Guido van Rossum98297ee2007-11-06 21:34:58 +000035from pickle import bytes_types
36
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030037requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
38 "test is only meaningful on 32-bit builds")
39
Tim Petersee1a53c2003-02-02 02:57:53 +000040# Tests that try a number of pickle protocols should have a
41# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000042# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000043protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000044
Tim Peters22e71712003-02-03 22:27:38 +000045
46# Return True if opcode code appears in the pickle, else False.
47def opcode_in_pickle(code, pickle):
48 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000049 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000050 return True
51 return False
52
Tim Peters8d2613a2003-02-11 16:40:16 +000053# Return the number of times opcode code appears in pickle.
54def count_opcode(code, pickle):
55 n = 0
56 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000057 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000058 n += 1
59 return n
60
Antoine Pitrou04248a82010-10-12 20:51:21 +000061
62class UnseekableIO(io.BytesIO):
63 def peek(self, *args):
64 raise NotImplementedError
65
66 def seekable(self):
67 return False
68
69 def seek(self, *args):
70 raise io.UnsupportedOperation
71
72 def tell(self):
73 raise io.UnsupportedOperation
74
75
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -080076class MinimalIO(object):
77 """
78 A file-like object that doesn't support readinto().
79 """
80 def __init__(self, *args):
81 self._bio = io.BytesIO(*args)
82 self.getvalue = self._bio.getvalue
83 self.read = self._bio.read
84 self.readline = self._bio.readline
85 self.write = self._bio.write
86
87
Tim Peters3e667d52003-02-04 21:47:44 +000088# We can't very well test the extension registry without putting known stuff
89# in it, but we have to be careful to restore its original state. Code
90# should do this:
91#
92# e = ExtensionSaver(extension_code)
93# try:
94# fiddle w/ the extension registry's stuff for extension_code
95# finally:
96# e.restore()
97
98class ExtensionSaver:
99 # Remember current registration for code (if any), and remove it (if
100 # there is one).
101 def __init__(self, code):
102 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000103 if code in copyreg._inverted_registry:
104 self.pair = copyreg._inverted_registry[code]
105 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000106 else:
107 self.pair = None
108
109 # Restore previous registration for code.
110 def restore(self):
111 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000112 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000113 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000114 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000115 pair = self.pair
116 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000117 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000118
Jeremy Hylton66426532001-10-15 21:38:56 +0000119class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000120 def __eq__(self, other):
121 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000122
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000123class D(C):
124 def __init__(self, arg):
125 pass
126
127class E(C):
128 def __getinitargs__(self):
129 return ()
130
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100131class H(object):
132 pass
133
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200134# Hashable mutable key
135class K(object):
136 def __init__(self, value):
137 self.value = value
138
139 def __reduce__(self):
140 # Shouldn't support the recursion itself
141 return K, (self.value,)
142
Jeremy Hylton66426532001-10-15 21:38:56 +0000143import __main__
144__main__.C = C
145C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000146__main__.D = D
147D.__module__ = "__main__"
148__main__.E = E
149E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100150__main__.H = H
151H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200152__main__.K = K
153K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000154
155class myint(int):
156 def __init__(self, x):
157 self.str = str(x)
158
159class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000160
Jeremy Hylton66426532001-10-15 21:38:56 +0000161 def __init__(self, a, b):
162 self.a = a
163 self.b = b
164
165 def __getinitargs__(self):
166 return self.a, self.b
167
Guido van Rossum04a86612001-12-19 16:58:54 +0000168class metaclass(type):
169 pass
170
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000171class use_metaclass(object, metaclass=metaclass):
172 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000173
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200174class pickling_metaclass(type):
175 def __eq__(self, other):
176 return (type(self) == type(other) and
177 self.reduce_args == other.reduce_args)
178
179 def __reduce__(self):
180 return (create_dynamic_class, self.reduce_args)
181
182def create_dynamic_class(name, bases):
183 result = pickling_metaclass(name, bases, dict())
184 result.reduce_args = (name, bases)
185 return result
186
Antoine Pitrou91f43802019-05-26 17:10:09 +0200187
188class ZeroCopyBytes(bytes):
189 readonly = True
190 c_contiguous = True
191 f_contiguous = True
192 zero_copy_reconstruct = True
193
194 def __reduce_ex__(self, protocol):
195 if protocol >= 5:
196 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
197 else:
198 return type(self)._reconstruct, (bytes(self),)
199
200 def __repr__(self):
201 return "{}({!r})".format(self.__class__.__name__, bytes(self))
202
203 __str__ = __repr__
204
205 @classmethod
206 def _reconstruct(cls, obj):
207 with memoryview(obj) as m:
208 obj = m.obj
209 if type(obj) is cls:
210 # Zero-copy
211 return obj
212 else:
213 return cls(obj)
214
215
216class ZeroCopyBytearray(bytearray):
217 readonly = False
218 c_contiguous = True
219 f_contiguous = True
220 zero_copy_reconstruct = True
221
222 def __reduce_ex__(self, protocol):
223 if protocol >= 5:
224 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
225 else:
226 return type(self)._reconstruct, (bytes(self),)
227
228 def __repr__(self):
229 return "{}({!r})".format(self.__class__.__name__, bytes(self))
230
231 __str__ = __repr__
232
233 @classmethod
234 def _reconstruct(cls, obj):
235 with memoryview(obj) as m:
236 obj = m.obj
237 if type(obj) is cls:
238 # Zero-copy
239 return obj
240 else:
241 return cls(obj)
242
243
244if _testbuffer is not None:
245
246 class PicklableNDArray:
247 # A not-really-zero-copy picklable ndarray, as the ndarray()
248 # constructor doesn't allow for it
249
250 zero_copy_reconstruct = False
251
252 def __init__(self, *args, **kwargs):
253 self.array = _testbuffer.ndarray(*args, **kwargs)
254
255 def __getitem__(self, idx):
256 cls = type(self)
257 new = cls.__new__(cls)
258 new.array = self.array[idx]
259 return new
260
261 @property
262 def readonly(self):
263 return self.array.readonly
264
265 @property
266 def c_contiguous(self):
267 return self.array.c_contiguous
268
269 @property
270 def f_contiguous(self):
271 return self.array.f_contiguous
272
273 def __eq__(self, other):
274 if not isinstance(other, PicklableNDArray):
275 return NotImplemented
276 return (other.array.format == self.array.format and
277 other.array.shape == self.array.shape and
278 other.array.strides == self.array.strides and
279 other.array.readonly == self.array.readonly and
280 other.array.tobytes() == self.array.tobytes())
281
282 def __ne__(self, other):
283 if not isinstance(other, PicklableNDArray):
284 return NotImplemented
285 return not (self == other)
286
287 def __repr__(self):
288 return (f"{type(self)}(shape={self.array.shape},"
289 f"strides={self.array.strides}, "
290 f"bytes={self.array.tobytes()})")
291
292 def __reduce_ex__(self, protocol):
293 if not self.array.contiguous:
294 raise NotImplementedError("Reconstructing a non-contiguous "
295 "ndarray does not seem possible")
296 ndarray_kwargs = {"shape": self.array.shape,
297 "strides": self.array.strides,
298 "format": self.array.format,
299 "flags": (0 if self.readonly
300 else _testbuffer.ND_WRITABLE)}
301 pb = pickle.PickleBuffer(self.array)
302 if protocol >= 5:
303 return (type(self)._reconstruct,
304 (pb, ndarray_kwargs))
305 else:
306 # Need to serialize the bytes in physical order
307 with pb.raw() as m:
308 return (type(self)._reconstruct,
309 (m.tobytes(), ndarray_kwargs))
310
311 @classmethod
312 def _reconstruct(cls, obj, kwargs):
313 with memoryview(obj) as m:
314 # For some reason, ndarray() wants a list of integers...
315 # XXX This only works if format == 'B'
316 items = list(m.tobytes())
317 return cls(items, **kwargs)
318
319
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300320# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000321# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000322
Guido van Rossum98297ee2007-11-06 21:34:58 +0000323DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200324 b'(lp0\nL0L\naL1L\naF2.0\n'
325 b'ac__builtin__\ncomple'
326 b'x\np1\n(F3.0\nF0.0\ntp2\n'
327 b'Rp3\naL1L\naL-1L\naL255'
328 b'L\naL-255L\naL-256L\naL'
329 b'65535L\naL-65535L\naL-'
330 b'65536L\naL2147483647L'
331 b'\naL-2147483647L\naL-2'
332 b'147483648L\na(Vabc\np4'
333 b'\ng4\nccopy_reg\n_recon'
334 b'structor\np5\n(c__main'
335 b'__\nC\np6\nc__builtin__'
336 b'\nobject\np7\nNtp8\nRp9\n'
337 b'(dp10\nVfoo\np11\nL1L\ns'
338 b'Vbar\np12\nL2L\nsbg9\ntp'
339 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000340)
Tim Peterse9358162001-01-22 22:05:20 +0000341
Guido van Rossum98297ee2007-11-06 21:34:58 +0000342# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000343DATA0_DIS = """\
344 0: ( MARK
345 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000346 2: p PUT 0
347 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000348 9: a APPEND
349 10: L LONG 1
350 14: a APPEND
351 15: F FLOAT 2.0
352 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200353 21: c GLOBAL '__builtin__ complex'
354 42: p PUT 1
355 45: ( MARK
356 46: F FLOAT 3.0
357 51: F FLOAT 0.0
358 56: t TUPLE (MARK at 45)
359 57: p PUT 2
360 60: R REDUCE
361 61: p PUT 3
362 64: a APPEND
363 65: L LONG 1
364 69: a APPEND
365 70: L LONG -1
366 75: a APPEND
367 76: L LONG 255
368 82: a APPEND
369 83: L LONG -255
370 90: a APPEND
371 91: L LONG -256
372 98: a APPEND
373 99: L LONG 65535
374 107: a APPEND
375 108: L LONG -65535
376 117: a APPEND
377 118: L LONG -65536
378 127: a APPEND
379 128: L LONG 2147483647
380 141: a APPEND
381 142: L LONG -2147483647
382 156: a APPEND
383 157: L LONG -2147483648
384 171: a APPEND
385 172: ( MARK
386 173: V UNICODE 'abc'
387 178: p PUT 4
388 181: g GET 4
389 184: c GLOBAL 'copy_reg _reconstructor'
390 209: p PUT 5
391 212: ( MARK
392 213: c GLOBAL '__main__ C'
393 225: p PUT 6
394 228: c GLOBAL '__builtin__ object'
395 248: p PUT 7
396 251: N NONE
397 252: t TUPLE (MARK at 212)
398 253: p PUT 8
399 256: R REDUCE
400 257: p PUT 9
401 260: ( MARK
402 261: d DICT (MARK at 260)
403 262: p PUT 10
404 266: V UNICODE 'foo'
405 271: p PUT 11
406 275: L LONG 1
407 279: s SETITEM
408 280: V UNICODE 'bar'
409 285: p PUT 12
410 289: L LONG 2
411 293: s SETITEM
412 294: b BUILD
413 295: g GET 9
414 298: t TUPLE (MARK at 172)
415 299: p PUT 13
416 303: a APPEND
417 304: g GET 13
418 308: a APPEND
419 309: L LONG 5
420 313: a APPEND
421 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000422highest protocol among opcodes = 0
423"""
424
Guido van Rossum98297ee2007-11-06 21:34:58 +0000425DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200426 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
427 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000428 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
429 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
430 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
431 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200432 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000433 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200434 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000435 b'object\nq\x07Ntq\x08Rq\t}q\n('
436 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
437 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
438)
Tim Peters70b02d72003-02-02 17:26:40 +0000439
Guido van Rossum98297ee2007-11-06 21:34:58 +0000440# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000441DATA1_DIS = """\
442 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000443 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000444 3: ( MARK
445 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000446 6: K BININT1 1
447 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200448 17: c GLOBAL '__builtin__ complex'
449 38: q BINPUT 1
450 40: ( MARK
451 41: G BINFLOAT 3.0
452 50: G BINFLOAT 0.0
453 59: t TUPLE (MARK at 40)
454 60: q BINPUT 2
455 62: R REDUCE
456 63: q BINPUT 3
457 65: K BININT1 1
458 67: J BININT -1
459 72: K BININT1 255
460 74: J BININT -255
461 79: J BININT -256
462 84: M BININT2 65535
463 87: J BININT -65535
464 92: J BININT -65536
465 97: J BININT 2147483647
466 102: J BININT -2147483647
467 107: J BININT -2147483648
468 112: ( MARK
469 113: X BINUNICODE 'abc'
470 121: q BINPUT 4
471 123: h BINGET 4
472 125: c GLOBAL 'copy_reg _reconstructor'
473 150: q BINPUT 5
474 152: ( MARK
475 153: c GLOBAL '__main__ C'
476 165: q BINPUT 6
477 167: c GLOBAL '__builtin__ object'
478 187: q BINPUT 7
479 189: N NONE
480 190: t TUPLE (MARK at 152)
481 191: q BINPUT 8
482 193: R REDUCE
483 194: q BINPUT 9
484 196: } EMPTY_DICT
485 197: q BINPUT 10
486 199: ( MARK
487 200: X BINUNICODE 'foo'
488 208: q BINPUT 11
489 210: K BININT1 1
490 212: X BINUNICODE 'bar'
491 220: q BINPUT 12
492 222: K BININT1 2
493 224: u SETITEMS (MARK at 199)
494 225: b BUILD
495 226: h BINGET 9
496 228: t TUPLE (MARK at 112)
497 229: q BINPUT 13
498 231: h BINGET 13
499 233: K BININT1 5
500 235: e APPENDS (MARK at 3)
501 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000502highest protocol among opcodes = 1
503"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000504
Guido van Rossum98297ee2007-11-06 21:34:58 +0000505DATA2 = (
506 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200507 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000508 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
509 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
510 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
511 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
512 b'bcq\x04h\x04c__main__\nC\nq\x05'
513 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
514 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
515 b'\nK\x05e.'
516)
Tim Petersfc273752003-03-02 04:54:24 +0000517
Guido van Rossum98297ee2007-11-06 21:34:58 +0000518# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000519DATA2_DIS = """\
520 0: \x80 PROTO 2
521 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000522 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000523 5: ( MARK
524 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000525 8: K BININT1 1
526 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200527 19: c GLOBAL '__builtin__ complex'
528 40: q BINPUT 1
529 42: G BINFLOAT 3.0
530 51: G BINFLOAT 0.0
531 60: \x86 TUPLE2
532 61: q BINPUT 2
533 63: R REDUCE
534 64: q BINPUT 3
535 66: K BININT1 1
536 68: J BININT -1
537 73: K BININT1 255
538 75: J BININT -255
539 80: J BININT -256
540 85: M BININT2 65535
541 88: J BININT -65535
542 93: J BININT -65536
543 98: J BININT 2147483647
544 103: J BININT -2147483647
545 108: J BININT -2147483648
546 113: ( MARK
547 114: X BINUNICODE 'abc'
548 122: q BINPUT 4
549 124: h BINGET 4
550 126: c GLOBAL '__main__ C'
551 138: q BINPUT 5
552 140: ) EMPTY_TUPLE
553 141: \x81 NEWOBJ
554 142: q BINPUT 6
555 144: } EMPTY_DICT
556 145: q BINPUT 7
557 147: ( MARK
558 148: X BINUNICODE 'foo'
559 156: q BINPUT 8
560 158: K BININT1 1
561 160: X BINUNICODE 'bar'
562 168: q BINPUT 9
563 170: K BININT1 2
564 172: u SETITEMS (MARK at 147)
565 173: b BUILD
566 174: h BINGET 6
567 176: t TUPLE (MARK at 113)
568 177: q BINPUT 10
569 179: h BINGET 10
570 181: K BININT1 5
571 183: e APPENDS (MARK at 5)
572 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000573highest protocol among opcodes = 2
574"""
575
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300576DATA3 = (
577 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
578 b'builtins\ncomplex\nq\x01G'
579 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
580 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
581 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
582 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
583 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
584 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
585 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
586 b'e.'
587)
588
589# Disassembly of DATA3
590DATA3_DIS = """\
591 0: \x80 PROTO 3
592 2: ] EMPTY_LIST
593 3: q BINPUT 0
594 5: ( MARK
595 6: K BININT1 0
596 8: K BININT1 1
597 10: G BINFLOAT 2.0
598 19: c GLOBAL 'builtins complex'
599 37: q BINPUT 1
600 39: G BINFLOAT 3.0
601 48: G BINFLOAT 0.0
602 57: \x86 TUPLE2
603 58: q BINPUT 2
604 60: R REDUCE
605 61: q BINPUT 3
606 63: K BININT1 1
607 65: J BININT -1
608 70: K BININT1 255
609 72: J BININT -255
610 77: J BININT -256
611 82: M BININT2 65535
612 85: J BININT -65535
613 90: J BININT -65536
614 95: J BININT 2147483647
615 100: J BININT -2147483647
616 105: J BININT -2147483648
617 110: ( MARK
618 111: X BINUNICODE 'abc'
619 119: q BINPUT 4
620 121: h BINGET 4
621 123: c GLOBAL '__main__ C'
622 135: q BINPUT 5
623 137: ) EMPTY_TUPLE
624 138: \x81 NEWOBJ
625 139: q BINPUT 6
626 141: } EMPTY_DICT
627 142: q BINPUT 7
628 144: ( MARK
629 145: X BINUNICODE 'bar'
630 153: q BINPUT 8
631 155: K BININT1 2
632 157: X BINUNICODE 'foo'
633 165: q BINPUT 9
634 167: K BININT1 1
635 169: u SETITEMS (MARK at 144)
636 170: b BUILD
637 171: h BINGET 6
638 173: t TUPLE (MARK at 110)
639 174: q BINPUT 10
640 176: h BINGET 10
641 178: K BININT1 5
642 180: e APPENDS (MARK at 5)
643 181: . STOP
644highest protocol among opcodes = 2
645"""
646
647DATA4 = (
648 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
649 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
650 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
651 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
652 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
653 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
654 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
655 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
656 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
657)
658
659# Disassembly of DATA4
660DATA4_DIS = """\
661 0: \x80 PROTO 4
662 2: \x95 FRAME 168
663 11: ] EMPTY_LIST
664 12: \x94 MEMOIZE
665 13: ( MARK
666 14: K BININT1 0
667 16: K BININT1 1
668 18: G BINFLOAT 2.0
669 27: \x8c SHORT_BINUNICODE 'builtins'
670 37: \x94 MEMOIZE
671 38: \x8c SHORT_BINUNICODE 'complex'
672 47: \x94 MEMOIZE
673 48: \x93 STACK_GLOBAL
674 49: \x94 MEMOIZE
675 50: G BINFLOAT 3.0
676 59: G BINFLOAT 0.0
677 68: \x86 TUPLE2
678 69: \x94 MEMOIZE
679 70: R REDUCE
680 71: \x94 MEMOIZE
681 72: K BININT1 1
682 74: J BININT -1
683 79: K BININT1 255
684 81: J BININT -255
685 86: J BININT -256
686 91: M BININT2 65535
687 94: J BININT -65535
688 99: J BININT -65536
689 104: J BININT 2147483647
690 109: J BININT -2147483647
691 114: J BININT -2147483648
692 119: ( MARK
693 120: \x8c SHORT_BINUNICODE 'abc'
694 125: \x94 MEMOIZE
695 126: h BINGET 6
696 128: \x8c SHORT_BINUNICODE '__main__'
697 138: \x94 MEMOIZE
698 139: \x8c SHORT_BINUNICODE 'C'
699 142: \x94 MEMOIZE
700 143: \x93 STACK_GLOBAL
701 144: \x94 MEMOIZE
702 145: ) EMPTY_TUPLE
703 146: \x81 NEWOBJ
704 147: \x94 MEMOIZE
705 148: } EMPTY_DICT
706 149: \x94 MEMOIZE
707 150: ( MARK
708 151: \x8c SHORT_BINUNICODE 'bar'
709 156: \x94 MEMOIZE
710 157: K BININT1 2
711 159: \x8c SHORT_BINUNICODE 'foo'
712 164: \x94 MEMOIZE
713 165: K BININT1 1
714 167: u SETITEMS (MARK at 150)
715 168: b BUILD
716 169: h BINGET 10
717 171: t TUPLE (MARK at 119)
718 172: \x94 MEMOIZE
719 173: h BINGET 14
720 175: K BININT1 5
721 177: e APPENDS (MARK at 13)
722 178: . STOP
723highest protocol among opcodes = 4
724"""
725
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000726# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300727DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000728
729# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300730DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000731
732# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300733DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
734 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
735 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
736 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
737 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
738 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000739
740# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300741DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000742
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100743python2_exceptions_without_args = (
744 ArithmeticError,
745 AssertionError,
746 AttributeError,
747 BaseException,
748 BufferError,
749 BytesWarning,
750 DeprecationWarning,
751 EOFError,
752 EnvironmentError,
753 Exception,
754 FloatingPointError,
755 FutureWarning,
756 GeneratorExit,
757 IOError,
758 ImportError,
759 ImportWarning,
760 IndentationError,
761 IndexError,
762 KeyError,
763 KeyboardInterrupt,
764 LookupError,
765 MemoryError,
766 NameError,
767 NotImplementedError,
768 OSError,
769 OverflowError,
770 PendingDeprecationWarning,
771 ReferenceError,
772 RuntimeError,
773 RuntimeWarning,
774 # StandardError is gone in Python 3, we map it to Exception
775 StopIteration,
776 SyntaxError,
777 SyntaxWarning,
778 SystemError,
779 SystemExit,
780 TabError,
781 TypeError,
782 UnboundLocalError,
783 UnicodeError,
784 UnicodeWarning,
785 UserWarning,
786 ValueError,
787 Warning,
788 ZeroDivisionError,
789)
790
791exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
792
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100793# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300794DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
795 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
796 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100797
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000798
Jeremy Hylton66426532001-10-15 21:38:56 +0000799def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000800 c = C()
801 c.foo = 1
802 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000803 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000804 # Append some integer test cases at cPickle.c's internal size
805 # cutoffs.
806 uint1max = 0xff
807 uint2max = 0xffff
808 int4max = 0x7fffffff
809 x.extend([1, -1,
810 uint1max, -uint1max, -uint1max-1,
811 uint2max, -uint2max, -uint2max-1,
812 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000813 y = ('abc', 'abc', c, c)
814 x.append(y)
815 x.append(y)
816 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000817 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000818
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100819
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300820class AbstractUnpickleTests(unittest.TestCase):
821 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100822
Jeremy Hylton66426532001-10-15 21:38:56 +0000823 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000824
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100825 def assert_is_copy(self, obj, objcopy, msg=None):
826 """Utility method to verify if two objects are copies of each others.
827 """
828 if msg is None:
829 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
830 self.assertEqual(obj, objcopy, msg=msg)
831 self.assertIs(type(obj), type(objcopy), msg=msg)
832 if hasattr(obj, '__dict__'):
833 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
834 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
835 if hasattr(obj, '__slots__'):
836 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
837 for slot in obj.__slots__:
838 self.assertEqual(
839 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
840 self.assertEqual(getattr(obj, slot, None),
841 getattr(objcopy, slot, None), msg=msg)
842
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200843 def check_unpickling_error(self, errors, data):
844 with self.subTest(data=data), \
845 self.assertRaises(errors):
846 try:
847 self.loads(data)
848 except BaseException as exc:
849 if support.verbose > 1:
850 print('%-32r - %s: %s' %
851 (data, exc.__class__.__name__, exc))
852 raise
853
Guido van Rossum98297ee2007-11-06 21:34:58 +0000854 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100855 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000856
857 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100858 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000859
860 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100861 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000862
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300863 def test_load_from_data3(self):
864 self.assert_is_copy(self._testdata, self.loads(DATA3))
865
866 def test_load_from_data4(self):
867 self.assert_is_copy(self._testdata, self.loads(DATA4))
868
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000869 def test_load_classic_instance(self):
870 # See issue5180. Test loading 2.x pickles that
871 # contain an instance of old style class.
872 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
873 xname = X.__name__.encode('ascii')
874 # Protocol 0 (text mode pickle):
875 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200876 0: ( MARK
877 1: i INST '__main__ X' (MARK at 0)
878 13: p PUT 0
879 16: ( MARK
880 17: d DICT (MARK at 16)
881 18: p PUT 1
882 21: b BUILD
883 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000884 """
885 pickle0 = (b"(i__main__\n"
886 b"X\n"
887 b"p0\n"
888 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100889 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000890
891 # Protocol 1 (binary mode pickle)
892 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200893 0: ( MARK
894 1: c GLOBAL '__main__ X'
895 13: q BINPUT 0
896 15: o OBJ (MARK at 0)
897 16: q BINPUT 1
898 18: } EMPTY_DICT
899 19: q BINPUT 2
900 21: b BUILD
901 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000902 """
903 pickle1 = (b'(c__main__\n'
904 b'X\n'
905 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100906 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000907
908 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
909 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200910 0: \x80 PROTO 2
911 2: ( MARK
912 3: c GLOBAL '__main__ X'
913 15: q BINPUT 0
914 17: o OBJ (MARK at 2)
915 18: q BINPUT 1
916 20: } EMPTY_DICT
917 21: q BINPUT 2
918 23: b BUILD
919 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000920 """
921 pickle2 = (b'\x80\x02(c__main__\n'
922 b'X\n'
923 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100924 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000925
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300926 def test_maxint64(self):
927 maxint64 = (1 << 63) - 1
928 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
929 got = self.loads(data)
930 self.assert_is_copy(maxint64, got)
931
932 # Try too with a bogus literal.
933 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200934 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300935
936 def test_unpickle_from_2x(self):
937 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300938 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300939 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300940 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300941 self.assertEqual(type(loaded), type(range(0)))
942 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300943 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300944 self.assertEqual(type(loaded), SimpleCookie)
945 self.assertEqual(list(loaded.keys()), ["key"])
946 self.assertEqual(loaded["key"].value, "value")
947
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300948 # Exception objects without arguments pickled from 2.x with protocol 2
949 for exc in python2_exceptions_without_args:
950 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300951 loaded = self.loads(data)
952 self.assertIs(type(loaded), exc)
953
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300954 # StandardError is mapped to Exception, test that separately
955 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300956 self.assertIs(type(loaded), Exception)
957
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300958 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300959 self.assertIs(type(loaded), UnicodeEncodeError)
960 self.assertEqual(loaded.object, "foo")
961 self.assertEqual(loaded.encoding, "ascii")
962 self.assertEqual(loaded.start, 0)
963 self.assertEqual(loaded.end, 1)
964 self.assertEqual(loaded.reason, "bad")
965
966 def test_load_python2_str_as_bytes(self):
967 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
968 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
969 encoding="bytes"), b'a\x00\xa0')
970 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
971 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
972 encoding="bytes"), b'a\x00\xa0')
973 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
974 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
975 encoding="bytes"), b'a\x00\xa0')
976
977 def test_load_python2_unicode_as_str(self):
978 # From Python 2: pickle.dumps(u'π', protocol=0)
979 self.assertEqual(self.loads(b'V\\u03c0\n.',
980 encoding='bytes'), 'π')
981 # From Python 2: pickle.dumps(u'π', protocol=1)
982 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
983 encoding="bytes"), 'π')
984 # From Python 2: pickle.dumps(u'π', protocol=2)
985 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
986 encoding="bytes"), 'π')
987
988 def test_load_long_python2_str_as_bytes(self):
989 # From Python 2: pickle.dumps('x' * 300, protocol=1)
990 self.assertEqual(self.loads(pickle.BINSTRING +
991 struct.pack("<I", 300) +
992 b'x' * 300 + pickle.STOP,
993 encoding='bytes'), b'x' * 300)
994
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300995 def test_constants(self):
996 self.assertIsNone(self.loads(b'N.'))
997 self.assertIs(self.loads(b'\x88.'), True)
998 self.assertIs(self.loads(b'\x89.'), False)
999 self.assertIs(self.loads(b'I01\n.'), True)
1000 self.assertIs(self.loads(b'I00\n.'), False)
1001
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001002 def test_empty_bytestring(self):
1003 # issue 11286
1004 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1005 self.assertEqual(empty, '')
1006
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001007 def test_short_binbytes(self):
1008 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
1009 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1010
1011 def test_binbytes(self):
1012 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1013 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1014
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001015 @requires_32b
1016 def test_negative_32b_binbytes(self):
1017 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1018 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001019 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1020 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001021
1022 @requires_32b
1023 def test_negative_32b_binunicode(self):
1024 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1025 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001026 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1027 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001028
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001029 def test_short_binunicode(self):
1030 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1031 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1032
1033 def test_misc_get(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001034 self.check_unpickling_error(KeyError, b'g0\np0')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001035 self.assert_is_copy([(100,), (100,)],
1036 self.loads(b'((Kdtp0\nh\x00l.))'))
1037
Serhiy Storchakae0606192015-09-29 22:10:07 +03001038 def test_binbytes8(self):
1039 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1040 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1041
1042 def test_binunicode8(self):
1043 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1044 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1045
Antoine Pitrou91f43802019-05-26 17:10:09 +02001046 def test_bytearray8(self):
1047 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1048 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1049
Serhiy Storchakae0606192015-09-29 22:10:07 +03001050 @requires_32b
1051 def test_large_32b_binbytes8(self):
1052 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001053 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1054 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001055
1056 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001057 def test_large_32b_bytearray8(self):
1058 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1059 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1060 dumped)
1061
1062 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001063 def test_large_32b_binunicode8(self):
1064 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001065 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1066 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001067
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001068 def test_get(self):
1069 pickled = b'((lp100000\ng100000\nt.'
1070 unpickled = self.loads(pickled)
1071 self.assertEqual(unpickled, ([],)*2)
1072 self.assertIs(unpickled[0], unpickled[1])
1073
1074 def test_binget(self):
1075 pickled = b'(]q\xffh\xfft.'
1076 unpickled = self.loads(pickled)
1077 self.assertEqual(unpickled, ([],)*2)
1078 self.assertIs(unpickled[0], unpickled[1])
1079
1080 def test_long_binget(self):
1081 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1082 unpickled = self.loads(pickled)
1083 self.assertEqual(unpickled, ([],)*2)
1084 self.assertIs(unpickled[0], unpickled[1])
1085
1086 def test_dup(self):
1087 pickled = b'((l2t.'
1088 unpickled = self.loads(pickled)
1089 self.assertEqual(unpickled, ([],)*2)
1090 self.assertIs(unpickled[0], unpickled[1])
1091
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001092 def test_negative_put(self):
1093 # Issue #12847
1094 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001095 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001096
1097 @requires_32b
1098 def test_negative_32b_binput(self):
1099 # Issue #12847
1100 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001101 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001102
1103 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001104 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001105
1106 def test_badly_quoted_string(self):
1107 # Issue #17710
1108 badpickles = [b"S'\n.",
1109 b'S"\n.',
1110 b'S\' \n.',
1111 b'S" \n.',
1112 b'S\'"\n.',
1113 b'S"\'\n.',
1114 b"S' ' \n.",
1115 b'S" " \n.',
1116 b"S ''\n.",
1117 b'S ""\n.',
1118 b'S \n.',
1119 b'S\n.',
1120 b'S.']
1121 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001122 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001123
1124 def test_correctly_quoted_string(self):
1125 goodpickles = [(b"S''\n.", ''),
1126 (b'S""\n.', ''),
1127 (b'S"\\n"\n.', '\n'),
1128 (b"S'\\n'\n.", '\n')]
1129 for p, expected in goodpickles:
1130 self.assertEqual(self.loads(p), expected)
1131
1132 def test_frame_readline(self):
1133 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1134 # 0: \x80 PROTO 4
1135 # 2: \x95 FRAME 5
1136 # 11: I INT 42
1137 # 15: . STOP
1138 self.assertEqual(self.loads(pickled), 42)
1139
1140 def test_compat_unpickle(self):
1141 # xrange(1, 7)
1142 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1143 unpickled = self.loads(pickled)
1144 self.assertIs(type(unpickled), range)
1145 self.assertEqual(unpickled, range(1, 7))
1146 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1147 # reduce
1148 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1149 self.assertIs(self.loads(pickled), functools.reduce)
1150 # whichdb.whichdb
1151 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1152 self.assertIs(self.loads(pickled), dbm.whichdb)
1153 # Exception(), StandardError()
1154 for name in (b'Exception', b'StandardError'):
1155 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1156 unpickled = self.loads(pickled)
1157 self.assertIs(type(unpickled), Exception)
1158 self.assertEqual(str(unpickled), 'ugh')
1159 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1160 for name in (b'UserDict', b'IterableUserDict'):
1161 pickled = (b'\x80\x02(cUserDict\n' + name +
1162 b'\no}U\x04data}K\x01K\x02ssb.')
1163 unpickled = self.loads(pickled)
1164 self.assertIs(type(unpickled), collections.UserDict)
1165 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1166
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001167 def test_bad_stack(self):
1168 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001169 b'.', # STOP
1170 b'0', # POP
1171 b'1', # POP_MARK
1172 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001173 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001174 b'R', # REDUCE
1175 b')R',
1176 b'a', # APPEND
1177 b'Na',
1178 b'b', # BUILD
1179 b'Nb',
1180 b'd', # DICT
1181 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001182 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001183 b'ibuiltins\nlist\n', # INST
1184 b'l', # LIST
1185 b'o', # OBJ
1186 b'(o',
1187 b'p1\n', # PUT
1188 b'q\x00', # BINPUT
1189 b'r\x00\x00\x00\x00', # LONG_BINPUT
1190 b's', # SETITEM
1191 b'Ns',
1192 b'NNs',
1193 b't', # TUPLE
1194 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001195 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001196 b'}(Nu',
1197 b'\x81', # NEWOBJ
1198 b')\x81',
1199 b'\x85', # TUPLE1
1200 b'\x86', # TUPLE2
1201 b'N\x86',
1202 b'\x87', # TUPLE3
1203 b'N\x87',
1204 b'NN\x87',
1205 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001206 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001207 b'\x91', # FROZENSET
1208 b'\x92', # NEWOBJ_EX
1209 b')}\x92',
1210 b'\x93', # STACK_GLOBAL
1211 b'Vlist\n\x93',
1212 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001213 ]
1214 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001215 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001216
1217 def test_bad_mark(self):
1218 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001219 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001220 b'N(2', # DUP
1221 b'cbuiltins\nlist\n)(R', # REDUCE
1222 b'cbuiltins\nlist\n()R',
1223 b']N(a', # APPEND
1224 # BUILD
1225 b'cbuiltins\nValueError\n)R}(b',
1226 b'cbuiltins\nValueError\n)R(}b',
1227 b'(Nd', # DICT
1228 b'N(p1\n', # PUT
1229 b'N(q\x00', # BINPUT
1230 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1231 b'}NN(s', # SETITEM
1232 b'}N(Ns',
1233 b'}(NNs',
1234 b'}((u', # SETITEMS
1235 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1236 b'cbuiltins\nlist\n()\x81',
1237 b'N(\x85', # TUPLE1
1238 b'NN(\x86', # TUPLE2
1239 b'N(N\x86',
1240 b'NNN(\x87', # TUPLE3
1241 b'NN(N\x87',
1242 b'N(NN\x87',
1243 b']((\x90', # ADDITEMS
1244 # NEWOBJ_EX
1245 b'cbuiltins\nlist\n)}(\x92',
1246 b'cbuiltins\nlist\n)(}\x92',
1247 b'cbuiltins\nlist\n()}\x92',
1248 # STACK_GLOBAL
1249 b'Vbuiltins\n(Vlist\n\x93',
1250 b'Vbuiltins\nVlist\n(\x93',
1251 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001252 ]
1253 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001254 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001255
1256 def test_truncated_data(self):
1257 self.check_unpickling_error(EOFError, b'')
1258 self.check_unpickling_error(EOFError, b'N')
1259 badpickles = [
1260 b'B', # BINBYTES
1261 b'B\x03\x00\x00',
1262 b'B\x03\x00\x00\x00',
1263 b'B\x03\x00\x00\x00ab',
1264 b'C', # SHORT_BINBYTES
1265 b'C\x03',
1266 b'C\x03ab',
1267 b'F', # FLOAT
1268 b'F0.0',
1269 b'F0.00',
1270 b'G', # BINFLOAT
1271 b'G\x00\x00\x00\x00\x00\x00\x00',
1272 b'I', # INT
1273 b'I0',
1274 b'J', # BININT
1275 b'J\x00\x00\x00',
1276 b'K', # BININT1
1277 b'L', # LONG
1278 b'L0',
1279 b'L10',
1280 b'L0L',
1281 b'L10L',
1282 b'M', # BININT2
1283 b'M\x00',
1284 # b'P', # PERSID
1285 # b'Pabc',
1286 b'S', # STRING
1287 b"S'abc'",
1288 b'T', # BINSTRING
1289 b'T\x03\x00\x00',
1290 b'T\x03\x00\x00\x00',
1291 b'T\x03\x00\x00\x00ab',
1292 b'U', # SHORT_BINSTRING
1293 b'U\x03',
1294 b'U\x03ab',
1295 b'V', # UNICODE
1296 b'Vabc',
1297 b'X', # BINUNICODE
1298 b'X\x03\x00\x00',
1299 b'X\x03\x00\x00\x00',
1300 b'X\x03\x00\x00\x00ab',
1301 b'(c', # GLOBAL
1302 b'(cbuiltins',
1303 b'(cbuiltins\n',
1304 b'(cbuiltins\nlist',
1305 b'Ng', # GET
1306 b'Ng0',
1307 b'(i', # INST
1308 b'(ibuiltins',
1309 b'(ibuiltins\n',
1310 b'(ibuiltins\nlist',
1311 b'Nh', # BINGET
1312 b'Nj', # LONG_BINGET
1313 b'Nj\x00\x00\x00',
1314 b'Np', # PUT
1315 b'Np0',
1316 b'Nq', # BINPUT
1317 b'Nr', # LONG_BINPUT
1318 b'Nr\x00\x00\x00',
1319 b'\x80', # PROTO
1320 b'\x82', # EXT1
1321 b'\x83', # EXT2
1322 b'\x84\x01',
1323 b'\x84', # EXT4
1324 b'\x84\x01\x00\x00',
1325 b'\x8a', # LONG1
1326 b'\x8b', # LONG4
1327 b'\x8b\x00\x00\x00',
1328 b'\x8c', # SHORT_BINUNICODE
1329 b'\x8c\x03',
1330 b'\x8c\x03ab',
1331 b'\x8d', # BINUNICODE8
1332 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1333 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1334 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1335 b'\x8e', # BINBYTES8
1336 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1337 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1338 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001339 b'\x96', # BYTEARRAY8
1340 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1341 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1342 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001343 b'\x95', # FRAME
1344 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1345 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1346 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1347 ]
1348 for p in badpickles:
1349 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001350
tjb9004371c0a2019-02-18 23:30:51 +08001351 @reap_threads
1352 def test_unpickle_module_race(self):
1353 # https://bugs.python.org/issue34572
1354 locker_module = dedent("""
1355 import threading
1356 barrier = threading.Barrier(2)
1357 """)
1358 locking_import_module = dedent("""
1359 import locker
1360 locker.barrier.wait()
1361 class ToBeUnpickled(object):
1362 pass
1363 """)
1364
1365 os.mkdir(TESTFN)
1366 self.addCleanup(shutil.rmtree, TESTFN)
1367 sys.path.insert(0, TESTFN)
1368 self.addCleanup(sys.path.remove, TESTFN)
1369 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1370 f.write(locker_module.encode('utf-8'))
1371 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1372 f.write(locking_import_module.encode('utf-8'))
1373 self.addCleanup(forget, "locker")
1374 self.addCleanup(forget, "locking_import")
1375
1376 import locker
1377
1378 pickle_bytes = (
1379 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1380
1381 # Then try to unpickle two of these simultaneously
1382 # One of them will cause the module import, and we want it to block
1383 # until the other one either:
1384 # - fails (before the patch for this issue)
1385 # - blocks on the import lock for the module, as it should
1386 results = []
1387 barrier = threading.Barrier(3)
1388 def t():
1389 # This ensures the threads have all started
1390 # presumably barrier release is faster than thread startup
1391 barrier.wait()
1392 results.append(pickle.loads(pickle_bytes))
1393
1394 t1 = threading.Thread(target=t)
1395 t2 = threading.Thread(target=t)
1396 t1.start()
1397 t2.start()
1398
1399 barrier.wait()
1400 # could have delay here
1401 locker.barrier.wait()
1402
1403 t1.join()
1404 t2.join()
1405
1406 from locking_import import ToBeUnpickled
1407 self.assertEqual(
1408 [type(x) for x in results],
1409 [ToBeUnpickled] * 2)
1410
1411
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001412
1413class AbstractPickleTests(unittest.TestCase):
1414 # Subclass must define self.dumps, self.loads.
1415
1416 optimized = False
1417
1418 _testdata = AbstractUnpickleTests._testdata
1419
1420 def setUp(self):
1421 pass
1422
1423 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1424
1425 def test_misc(self):
1426 # test various datatypes not tested by testdata
1427 for proto in protocols:
1428 x = myint(4)
1429 s = self.dumps(x, proto)
1430 y = self.loads(s)
1431 self.assert_is_copy(x, y)
1432
1433 x = (1, ())
1434 s = self.dumps(x, proto)
1435 y = self.loads(s)
1436 self.assert_is_copy(x, y)
1437
1438 x = initarg(1, x)
1439 s = self.dumps(x, proto)
1440 y = self.loads(s)
1441 self.assert_is_copy(x, y)
1442
1443 # XXX test __reduce__ protocol?
1444
1445 def test_roundtrip_equality(self):
1446 expected = self._testdata
1447 for proto in protocols:
1448 s = self.dumps(expected, proto)
1449 got = self.loads(s)
1450 self.assert_is_copy(expected, got)
1451
Tim Peters70b02d72003-02-02 17:26:40 +00001452 # There are gratuitous differences between pickles produced by
1453 # pickle and cPickle, largely because cPickle starts PUT indices at
1454 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1455 # there's a comment with an exclamation point there whose meaning
1456 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1457 # of 1.
1458 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001459 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001460 from pickletools import dis
1461
1462 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1463 s = self.dumps(self._testdata, proto)
1464 filelike = StringIO()
1465 dis(s, out=filelike)
1466 got = filelike.getvalue()
1467 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001468
1469 def test_recursive_list(self):
1470 l = []
1471 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001472 for proto in protocols:
1473 s = self.dumps(l, proto)
1474 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001475 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001476 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001477 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001478
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001479 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001480 t = ([],)
1481 t[0].append(t)
1482 for proto in protocols:
1483 s = self.dumps(t, proto)
1484 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001485 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001486 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001487 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001488 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001489 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001490
Jeremy Hylton66426532001-10-15 21:38:56 +00001491 def test_recursive_dict(self):
1492 d = {}
1493 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001494 for proto in protocols:
1495 s = self.dumps(d, proto)
1496 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001497 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001498 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001499 self.assertIs(x[1], x)
1500
1501 def test_recursive_dict_key(self):
1502 d = {}
1503 k = K(d)
1504 d[k] = 1
1505 for proto in protocols:
1506 s = self.dumps(d, proto)
1507 x = self.loads(s)
1508 self.assertIsInstance(x, dict)
1509 self.assertEqual(len(x.keys()), 1)
1510 self.assertIsInstance(list(x.keys())[0], K)
1511 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001512
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001513 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001514 y = set()
1515 k = K(y)
1516 y.add(k)
1517 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001518 s = self.dumps(y, proto)
1519 x = self.loads(s)
1520 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001521 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001522 self.assertIsInstance(list(x)[0], K)
1523 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001524
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001525 def test_recursive_list_subclass(self):
1526 y = MyList()
1527 y.append(y)
1528 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001529 s = self.dumps(y, proto)
1530 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001531 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001532 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001533 self.assertIs(x[0], x)
1534
1535 def test_recursive_dict_subclass(self):
1536 d = MyDict()
1537 d[1] = d
1538 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1539 s = self.dumps(d, proto)
1540 x = self.loads(s)
1541 self.assertIsInstance(x, MyDict)
1542 self.assertEqual(list(x.keys()), [1])
1543 self.assertIs(x[1], x)
1544
1545 def test_recursive_dict_subclass_key(self):
1546 d = MyDict()
1547 k = K(d)
1548 d[k] = 1
1549 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1550 s = self.dumps(d, proto)
1551 x = self.loads(s)
1552 self.assertIsInstance(x, MyDict)
1553 self.assertEqual(len(list(x.keys())), 1)
1554 self.assertIsInstance(list(x.keys())[0], K)
1555 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001556
Jeremy Hylton66426532001-10-15 21:38:56 +00001557 def test_recursive_inst(self):
1558 i = C()
1559 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001560 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001561 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001562 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001563 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001564 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001565 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001566
1567 def test_recursive_multi(self):
1568 l = []
1569 d = {1:l}
1570 i = C()
1571 i.attr = d
1572 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001573 for proto in protocols:
1574 s = self.dumps(l, proto)
1575 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001576 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001577 self.assertEqual(len(x), 1)
1578 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001579 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001580 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001581
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001582 def check_recursive_collection_and_inst(self, factory):
1583 h = H()
1584 y = factory([h])
1585 h.attr = y
1586 for proto in protocols:
1587 s = self.dumps(y, proto)
1588 x = self.loads(s)
1589 self.assertIsInstance(x, type(y))
1590 self.assertEqual(len(x), 1)
1591 self.assertIsInstance(list(x)[0], H)
1592 self.assertIs(list(x)[0].attr, x)
1593
1594 def test_recursive_list_and_inst(self):
1595 self.check_recursive_collection_and_inst(list)
1596
1597 def test_recursive_tuple_and_inst(self):
1598 self.check_recursive_collection_and_inst(tuple)
1599
1600 def test_recursive_dict_and_inst(self):
1601 self.check_recursive_collection_and_inst(dict.fromkeys)
1602
1603 def test_recursive_set_and_inst(self):
1604 self.check_recursive_collection_and_inst(set)
1605
1606 def test_recursive_frozenset_and_inst(self):
1607 self.check_recursive_collection_and_inst(frozenset)
1608
1609 def test_recursive_list_subclass_and_inst(self):
1610 self.check_recursive_collection_and_inst(MyList)
1611
1612 def test_recursive_tuple_subclass_and_inst(self):
1613 self.check_recursive_collection_and_inst(MyTuple)
1614
1615 def test_recursive_dict_subclass_and_inst(self):
1616 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1617
1618 def test_recursive_set_subclass_and_inst(self):
1619 self.check_recursive_collection_and_inst(MySet)
1620
1621 def test_recursive_frozenset_subclass_and_inst(self):
1622 self.check_recursive_collection_and_inst(MyFrozenSet)
1623
Walter Dörwald9b775532007-06-08 14:30:53 +00001624 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001625 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001626 '<\\>', '<\\\U00012345>',
1627 # surrogates
1628 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001629 for proto in protocols:
1630 for u in endcases:
1631 p = self.dumps(u, proto)
1632 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001633 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001634
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001635 def test_unicode_high_plane(self):
1636 t = '\U00012345'
1637 for proto in protocols:
1638 p = self.dumps(t, proto)
1639 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001640 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001641
Guido van Rossumf4169812008-03-17 22:56:06 +00001642 def test_bytes(self):
1643 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001644 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001645 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001646 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001647 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001648 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001649 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001650 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001651 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001652 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001653
Antoine Pitrou91f43802019-05-26 17:10:09 +02001654 def test_bytearray(self):
1655 for proto in protocols:
1656 for s in b'', b'xyz', b'xyz'*100:
1657 b = bytearray(s)
1658 p = self.dumps(b, proto)
1659 bb = self.loads(p)
1660 self.assertIsNot(bb, b)
1661 self.assert_is_copy(b, bb)
1662 if proto <= 3:
1663 # bytearray is serialized using a global reference
1664 self.assertIn(b'bytearray', p)
1665 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1666 elif proto == 4:
1667 self.assertIn(b'bytearray', p)
1668 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1669 elif proto == 5:
1670 self.assertNotIn(b'bytearray', p)
1671 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1672
Jeremy Hylton66426532001-10-15 21:38:56 +00001673 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001674 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001675 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001676 while n:
1677 for expected in (-n, n):
1678 s = self.dumps(expected, proto)
1679 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001680 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001681 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001682
Tim Petersee1a53c2003-02-02 02:57:53 +00001683 def test_long(self):
1684 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001685 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001686 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001687 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001688 for npos in nbase-1, nbase, nbase+1:
1689 for n in npos, -npos:
1690 pickle = self.dumps(n, proto)
1691 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001692 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001693 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1694 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001695 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001696 nbase += nbase << 1000000
1697 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001698 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001699 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001700 # assert_is_copy is very expensive here as it precomputes
1701 # a failure message by computing the repr() of n and got,
1702 # we just do the check ourselves.
1703 self.assertIs(type(got), int)
1704 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001705
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001706 def test_float(self):
1707 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1708 3.14, 263.44582062374053, 6.022e23, 1e30]
1709 test_values = test_values + [-x for x in test_values]
1710 for proto in protocols:
1711 for value in test_values:
1712 pickle = self.dumps(value, proto)
1713 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001714 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001715
Thomas Wouters477c8d52006-05-27 19:21:47 +00001716 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1717 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001718 # make sure that floats are formatted locale independent with proto 0
1719 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001720
Jeremy Hylton66426532001-10-15 21:38:56 +00001721 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001722 for proto in protocols:
1723 inst = AAA()
1724 dumped = self.dumps(inst, proto)
1725 loaded = self.loads(dumped)
1726 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001727
1728 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001729 for proto in protocols:
1730 inst = initarg(1, 2)
1731 dumped = self.dumps(inst, proto)
1732 loaded = self.loads(dumped)
1733 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001734
Guido van Rossum04a86612001-12-19 16:58:54 +00001735 def test_metaclass(self):
1736 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001737 for proto in protocols:
1738 s = self.dumps(a, proto)
1739 b = self.loads(s)
1740 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001741
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001742 def test_dynamic_class(self):
1743 a = create_dynamic_class("my_dynamic_class", (object,))
1744 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1745 for proto in protocols:
1746 s = self.dumps(a, proto)
1747 b = self.loads(s)
1748 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001749 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001750
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001751 def test_structseq(self):
1752 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001753 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001754
1755 t = time.localtime()
1756 for proto in protocols:
1757 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001758 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001759 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001760 t = os.stat(os.curdir)
1761 s = self.dumps(t, proto)
1762 u = self.loads(s)
1763 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001764 if hasattr(os, "statvfs"):
1765 t = os.statvfs(os.curdir)
1766 s = self.dumps(t, proto)
1767 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001768 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001769
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001770 def test_ellipsis(self):
1771 for proto in protocols:
1772 s = self.dumps(..., proto)
1773 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001774 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001775
1776 def test_notimplemented(self):
1777 for proto in protocols:
1778 s = self.dumps(NotImplemented, proto)
1779 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001780 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001781
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001782 def test_singleton_types(self):
1783 # Issue #6477: Test that types of built-in singletons can be pickled.
1784 singletons = [None, ..., NotImplemented]
1785 for singleton in singletons:
1786 for proto in protocols:
1787 s = self.dumps(type(singleton), proto)
1788 u = self.loads(s)
1789 self.assertIs(type(singleton), u)
1790
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001791 # Tests for protocol 2
1792
Tim Peters4190fb82003-02-02 16:09:05 +00001793 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001794 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001795 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001796 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001797 proto_header = pickle.PROTO + bytes([proto])
1798 self.assertTrue(pickled.startswith(proto_header))
1799 else:
1800 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001801
1802 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001803 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001804 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001805 try:
1806 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001807 except ValueError as err:
1808 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001809 else:
1810 self.fail("expected bad protocol number to raise ValueError")
1811
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001812 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001813 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001814 for proto in protocols:
1815 s = self.dumps(x, proto)
1816 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001817 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001818 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001819
1820 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001821 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001822 for proto in protocols:
1823 s = self.dumps(x, proto)
1824 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001825 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001826 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001827
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001828 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001829 # Map (proto, len(tuple)) to expected opcode.
1830 expected_opcode = {(0, 0): pickle.TUPLE,
1831 (0, 1): pickle.TUPLE,
1832 (0, 2): pickle.TUPLE,
1833 (0, 3): pickle.TUPLE,
1834 (0, 4): pickle.TUPLE,
1835
1836 (1, 0): pickle.EMPTY_TUPLE,
1837 (1, 1): pickle.TUPLE,
1838 (1, 2): pickle.TUPLE,
1839 (1, 3): pickle.TUPLE,
1840 (1, 4): pickle.TUPLE,
1841
1842 (2, 0): pickle.EMPTY_TUPLE,
1843 (2, 1): pickle.TUPLE1,
1844 (2, 2): pickle.TUPLE2,
1845 (2, 3): pickle.TUPLE3,
1846 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001847
1848 (3, 0): pickle.EMPTY_TUPLE,
1849 (3, 1): pickle.TUPLE1,
1850 (3, 2): pickle.TUPLE2,
1851 (3, 3): pickle.TUPLE3,
1852 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001853 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001854 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001855 b = (1,)
1856 c = (1, 2)
1857 d = (1, 2, 3)
1858 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001859 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001860 for x in a, b, c, d, e:
1861 s = self.dumps(x, proto)
1862 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001863 self.assert_is_copy(x, y)
1864 expected = expected_opcode[min(proto, 3), len(x)]
1865 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001866
Guido van Rossum7d97d312003-01-28 04:25:27 +00001867 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001868 # Map (proto, singleton) to expected opcode.
1869 expected_opcode = {(0, None): pickle.NONE,
1870 (1, None): pickle.NONE,
1871 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001872 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001873
1874 (0, True): pickle.INT,
1875 (1, True): pickle.INT,
1876 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001877 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001878
1879 (0, False): pickle.INT,
1880 (1, False): pickle.INT,
1881 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001882 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001883 }
Tim Peters4190fb82003-02-02 16:09:05 +00001884 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001885 for x in None, False, True:
1886 s = self.dumps(x, proto)
1887 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001888 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001889 expected = expected_opcode[min(proto, 3), x]
1890 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001891
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001892 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001893 x = MyTuple([1, 2, 3])
1894 x.foo = 42
1895 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001896 for proto in protocols:
1897 s = self.dumps(x, proto)
1898 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001899 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001900
1901 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001902 x = MyList([1, 2, 3])
1903 x.foo = 42
1904 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001905 for proto in protocols:
1906 s = self.dumps(x, proto)
1907 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001908 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001909
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001910 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001911 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001912 for C in myclasses:
1913 B = C.__base__
1914 x = C(C.sample)
1915 x.foo = 42
1916 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001917 y = self.loads(s)
1918 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001919 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001920 self.assertEqual(B(x), B(y), detail)
1921 self.assertEqual(x.__dict__, y.__dict__, detail)
1922
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001923 def test_newobj_proxies(self):
1924 # NEWOBJ should use the __class__ rather than the raw type
1925 classes = myclasses[:]
1926 # Cannot create weakproxies to these classes
1927 for c in (MyInt, MyTuple):
1928 classes.remove(c)
1929 for proto in protocols:
1930 for C in classes:
1931 B = C.__base__
1932 x = C(C.sample)
1933 x.foo = 42
1934 p = weakref.proxy(x)
1935 s = self.dumps(p, proto)
1936 y = self.loads(s)
1937 self.assertEqual(type(y), type(x)) # rather than type(p)
1938 detail = (proto, C, B, x, y, type(y))
1939 self.assertEqual(B(x), B(y), detail)
1940 self.assertEqual(x.__dict__, y.__dict__, detail)
1941
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001942 def test_newobj_not_class(self):
1943 # Issue 24552
1944 global SimpleNewObj
1945 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001946 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001947 b = self.dumps(o, 4)
1948 try:
1949 SimpleNewObj = 42
1950 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1951 finally:
1952 SimpleNewObj = save
1953
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001954 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001955 # an object of that type. Check that the resulting pickle uses opcode
1956 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001957
Tim Peters22e71712003-02-03 22:27:38 +00001958 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001959 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001960 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001961 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001962 x = MyList([1, 2, 3])
1963 x.foo = 42
1964 x.bar = "hello"
1965
Tim Peters22e71712003-02-03 22:27:38 +00001966 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001967 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001968 self.assertIn(__name__.encode("utf-8"), s1)
1969 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001970 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001971
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001972 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001973 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001974
Tim Peters22e71712003-02-03 22:27:38 +00001975 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001976 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001977 self.assertNotIn(__name__.encode("utf-8"), s2)
1978 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001979 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001980
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001981 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001982 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001983 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001984 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001985
1986 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001987 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1988 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001989
1990 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001991 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1992 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1993 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001994
1995 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001996 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1997 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
1998 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
1999
Tim Peters8d2613a2003-02-11 16:40:16 +00002000 def test_list_chunking(self):
2001 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002002 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002003 for proto in protocols:
2004 s = self.dumps(x, proto)
2005 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002006 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002007 num_appends = count_opcode(pickle.APPENDS, s)
2008 self.assertEqual(num_appends, proto > 0)
2009
2010 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002011 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002012 for proto in protocols:
2013 s = self.dumps(x, proto)
2014 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002015 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002016 num_appends = count_opcode(pickle.APPENDS, s)
2017 if proto == 0:
2018 self.assertEqual(num_appends, 0)
2019 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002020 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002021
2022 def test_dict_chunking(self):
2023 n = 10 # too small to chunk
2024 x = dict.fromkeys(range(n))
2025 for proto in protocols:
2026 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002027 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002028 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002029 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002030 num_setitems = count_opcode(pickle.SETITEMS, s)
2031 self.assertEqual(num_setitems, proto > 0)
2032
2033 n = 2500 # expect at least two chunks when proto > 0
2034 x = dict.fromkeys(range(n))
2035 for proto in protocols:
2036 s = self.dumps(x, proto)
2037 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002038 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002039 num_setitems = count_opcode(pickle.SETITEMS, s)
2040 if proto == 0:
2041 self.assertEqual(num_setitems, 0)
2042 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002043 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002044
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002045 def test_set_chunking(self):
2046 n = 10 # too small to chunk
2047 x = set(range(n))
2048 for proto in protocols:
2049 s = self.dumps(x, proto)
2050 y = self.loads(s)
2051 self.assert_is_copy(x, y)
2052 num_additems = count_opcode(pickle.ADDITEMS, s)
2053 if proto < 4:
2054 self.assertEqual(num_additems, 0)
2055 else:
2056 self.assertEqual(num_additems, 1)
2057
2058 n = 2500 # expect at least two chunks when proto >= 4
2059 x = set(range(n))
2060 for proto in protocols:
2061 s = self.dumps(x, proto)
2062 y = self.loads(s)
2063 self.assert_is_copy(x, y)
2064 num_additems = count_opcode(pickle.ADDITEMS, s)
2065 if proto < 4:
2066 self.assertEqual(num_additems, 0)
2067 else:
2068 self.assertGreaterEqual(num_additems, 2)
2069
Tim Peterse9ef2032003-02-13 18:42:00 +00002070 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002071 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002072 x.abc = 666
2073 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002074 with self.subTest(proto=proto):
2075 s = self.dumps(x, proto)
2076 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002077 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002078 else:
2079 self.assertIn(b'M\xce\xfa', s) # BININT2
2080 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2081 2 <= proto)
2082 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2083 y = self.loads(s) # will raise TypeError if __init__ called
2084 self.assert_is_copy(x, y)
2085
2086 def test_complex_newobj(self):
2087 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2088 x.abc = 666
2089 for proto in protocols:
2090 with self.subTest(proto=proto):
2091 s = self.dumps(x, proto)
2092 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002093 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002094 elif proto < 2:
2095 self.assertIn(b'M\xce\xfa', s) # BININT2
2096 elif proto < 4:
2097 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2098 else:
2099 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2100 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2101 2 <= proto)
2102 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2103 y = self.loads(s) # will raise TypeError if __init__ called
2104 self.assert_is_copy(x, y)
2105
2106 def test_complex_newobj_ex(self):
2107 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2108 x.abc = 666
2109 for proto in protocols:
2110 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002111 s = self.dumps(x, proto)
2112 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002113 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002114 elif proto < 2:
2115 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002116 elif proto < 4:
2117 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002118 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002119 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2120 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2121 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2122 4 <= proto)
2123 y = self.loads(s) # will raise TypeError if __init__ called
2124 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002125
Tim Peters42f08ac2003-02-11 22:43:24 +00002126 def test_newobj_list_slots(self):
2127 x = SlotList([1, 2, 3])
2128 x.foo = 42
2129 x.bar = "hello"
2130 s = self.dumps(x, 2)
2131 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002132 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002133
Guido van Rossum2a30b212003-02-18 22:41:24 +00002134 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002135 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002136 x = REX_one()
2137 self.assertEqual(x._reduce_called, 0)
2138 s = self.dumps(x, proto)
2139 self.assertEqual(x._reduce_called, 1)
2140 y = self.loads(s)
2141 self.assertEqual(y._reduce_called, 0)
2142
2143 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002144 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002145 x = REX_two()
2146 self.assertEqual(x._proto, None)
2147 s = self.dumps(x, proto)
2148 self.assertEqual(x._proto, proto)
2149 y = self.loads(s)
2150 self.assertEqual(y._proto, None)
2151
2152 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002153 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002154 x = REX_three()
2155 self.assertEqual(x._proto, None)
2156 s = self.dumps(x, proto)
2157 self.assertEqual(x._proto, proto)
2158 y = self.loads(s)
2159 self.assertEqual(y._proto, None)
2160
Guido van Rossumd8faa362007-04-27 19:54:29 +00002161 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002162 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002163 x = REX_four()
2164 self.assertEqual(x._proto, None)
2165 s = self.dumps(x, proto)
2166 self.assertEqual(x._proto, proto)
2167 y = self.loads(s)
2168 self.assertEqual(y._proto, proto)
2169
2170 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002171 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002172 x = REX_five()
2173 self.assertEqual(x._reduce_called, 0)
2174 s = self.dumps(x, proto)
2175 self.assertEqual(x._reduce_called, 1)
2176 y = self.loads(s)
2177 self.assertEqual(y._reduce_called, 1)
2178
Brett Cannon31f59292011-02-21 19:29:56 +00002179 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002180 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002181 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002182 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002183 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002184 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002185
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002186 def test_reduce_bad_iterator(self):
2187 # Issue4176: crash when 4th and 5th items of __reduce__()
2188 # are not iterators
2189 class C(object):
2190 def __reduce__(self):
2191 # 4th item is not an iterator
2192 return list, (), None, [], None
2193 class D(object):
2194 def __reduce__(self):
2195 # 5th item is not an iterator
2196 return dict, (), None, None, []
2197
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002198 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002199 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002200 try:
2201 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002202 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002203 pass
2204 try:
2205 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002206 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002207 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002208
Collin Winter771d8342009-04-16 03:18:06 +00002209 def test_many_puts_and_gets(self):
2210 # Test that internal data structures correctly deal with lots of
2211 # puts/gets.
2212 keys = ("aaa" + str(i) for i in range(100))
2213 large_dict = dict((k, [4, 5, 6]) for k in keys)
2214 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2215
2216 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002217 with self.subTest(proto=proto):
2218 dumped = self.dumps(obj, proto)
2219 loaded = self.loads(dumped)
2220 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002221
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002222 def test_attribute_name_interning(self):
2223 # Test that attribute names of pickled objects are interned when
2224 # unpickling.
2225 for proto in protocols:
2226 x = C()
2227 x.foo = 42
2228 x.bar = "hello"
2229 s = self.dumps(x, proto)
2230 y = self.loads(s)
2231 x_keys = sorted(x.__dict__)
2232 y_keys = sorted(y.__dict__)
2233 for x_key, y_key in zip(x_keys, y_keys):
2234 self.assertIs(x_key, y_key)
2235
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002236 def test_pickle_to_2x(self):
2237 # Pickle non-trivial data with protocol 2, expecting that it yields
2238 # the same result as Python 2.x did.
2239 # NOTE: this test is a bit too strong since we can produce different
2240 # bytecode that 2.x will still understand.
2241 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002242 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002243 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002244 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002245
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002246 def test_large_pickles(self):
2247 # Test the correctness of internal buffering routines when handling
2248 # large data.
2249 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002250 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002251 dumped = self.dumps(data, proto)
2252 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002253 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002254 self.assertEqual(loaded, data)
2255
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002256 def test_int_pickling_efficiency(self):
2257 # Test compacity of int representation (see issue #12744)
2258 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002259 with self.subTest(proto=proto):
2260 pickles = [self.dumps(2**n, proto) for n in range(70)]
2261 sizes = list(map(len, pickles))
2262 # the size function is monotonic
2263 self.assertEqual(sorted(sizes), sizes)
2264 if proto >= 2:
2265 for p in pickles:
2266 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002267
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002268 def _check_pickling_with_opcode(self, obj, opcode, proto):
2269 pickled = self.dumps(obj, proto)
2270 self.assertTrue(opcode_in_pickle(opcode, pickled))
2271 unpickled = self.loads(pickled)
2272 self.assertEqual(obj, unpickled)
2273
2274 def test_appends_on_non_lists(self):
2275 # Issue #17720
2276 obj = REX_six([1, 2, 3])
2277 for proto in protocols:
2278 if proto == 0:
2279 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2280 else:
2281 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2282
2283 def test_setitems_on_non_dicts(self):
2284 obj = REX_seven({1: -1, 2: -2, 3: -3})
2285 for proto in protocols:
2286 if proto == 0:
2287 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2288 else:
2289 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2290
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002291 # Exercise framing (proto >= 4) for significant workloads
2292
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002293 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002294 FRAME_SIZE_TARGET = 64 * 1024
2295
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002296 def check_frame_opcodes(self, pickled):
2297 """
2298 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002299
2300 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2301 framed by default and are therefore considered a frame by themselves in
2302 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002303 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002304 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002305 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2306 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002307 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002308 if frame_end is not None:
2309 self.assertLessEqual(pos, frame_end)
2310 if pos == frame_end:
2311 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002312
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002313 if frame_end is not None: # framed
2314 self.assertNotEqual(op.name, 'FRAME')
2315 if op.name in frameless_opcodes:
2316 # Only short bytes and str objects should be written
2317 # in a frame
2318 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2319
2320 else: # not framed
2321 if (op.name == 'FRAME' or
2322 (op.name in frameless_opcodes and
2323 len(arg) > self.FRAME_SIZE_TARGET)):
2324 # Frame or large bytes or str object
2325 if frameless_start is not None:
2326 # Only short data should be written outside of a frame
2327 self.assertLess(pos - frameless_start,
2328 self.FRAME_SIZE_MIN)
2329 frameless_start = None
2330 elif frameless_start is None and op.name != 'PROTO':
2331 frameless_start = pos
2332
2333 if op.name == 'FRAME':
2334 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2335 frame_end = pos + 9 + arg
2336
2337 pos = len(pickled)
2338 if frame_end is not None:
2339 self.assertEqual(frame_end, pos)
2340 elif frameless_start is not None:
2341 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002342
Miss Islington (bot)382cb852019-07-30 11:34:33 -07002343 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002344 def test_framing_many_objects(self):
2345 obj = list(range(10**5))
2346 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2347 with self.subTest(proto=proto):
2348 pickled = self.dumps(obj, proto)
2349 unpickled = self.loads(pickled)
2350 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002351 bytes_per_frame = (len(pickled) /
2352 count_opcode(pickle.FRAME, pickled))
2353 self.assertGreater(bytes_per_frame,
2354 self.FRAME_SIZE_TARGET / 2)
2355 self.assertLessEqual(bytes_per_frame,
2356 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002357 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002358
2359 def test_framing_large_objects(self):
2360 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002361 small_items = [[i] for i in range(10)]
2362 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002363 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002364 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002365 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002366 if not fast:
2367 # fast=False by default.
2368 # This covers in-memory pickling with pickle.dumps().
2369 pickled = self.dumps(obj, proto)
2370 else:
2371 # Pickler is required when fast=True.
2372 if not hasattr(self, 'pickler'):
2373 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002374 buf = io.BytesIO()
2375 pickler = self.pickler(buf, protocol=proto)
2376 pickler.fast = fast
2377 pickler.dump(obj)
2378 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002379 unpickled = self.loads(pickled)
2380 # More informative error message in case of failure.
2381 self.assertEqual([len(x) for x in obj],
2382 [len(x) for x in unpickled])
2383 # Perform full equality check if the lengths match.
2384 self.assertEqual(obj, unpickled)
2385 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002386 # A single frame for small objects between
2387 # first two large objects.
2388 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002389 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002390
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002391 def test_optional_frames(self):
2392 if pickle.HIGHEST_PROTOCOL < 4:
2393 return
2394
2395 def remove_frames(pickled, keep_frame=None):
2396 """Remove frame opcodes from the given pickle."""
2397 frame_starts = []
2398 # 1 byte for the opcode and 8 for the argument
2399 frame_opcode_size = 9
2400 for opcode, _, pos in pickletools.genops(pickled):
2401 if opcode.name == 'FRAME':
2402 frame_starts.append(pos)
2403
2404 newpickle = bytearray()
2405 last_frame_end = 0
2406 for i, pos in enumerate(frame_starts):
2407 if keep_frame and keep_frame(i):
2408 continue
2409 newpickle += pickled[last_frame_end:pos]
2410 last_frame_end = pos + frame_opcode_size
2411 newpickle += pickled[last_frame_end:]
2412 return newpickle
2413
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002414 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002415 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002416 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002417 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002418 for bytes_type in (bytes, bytearray):
2419 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002420
Antoine Pitrou91f43802019-05-26 17:10:09 +02002421 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2422 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002423
Antoine Pitrou91f43802019-05-26 17:10:09 +02002424 frameless_pickle = remove_frames(pickled)
2425 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2426 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002427
Antoine Pitrou91f43802019-05-26 17:10:09 +02002428 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2429 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2430 count_opcode(pickle.FRAME, pickled))
2431 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002432
Miss Islington (bot)382cb852019-07-30 11:34:33 -07002433 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002434 def test_framed_write_sizes_with_delayed_writer(self):
2435 class ChunkAccumulator:
2436 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002437 def __init__(self):
2438 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002439 def write(self, chunk):
2440 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002441 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002442 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002443
2444 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002445 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2446 for i in range(int(1e4))]
2447 # Add a large unique ASCII string
2448 objects.append('0123456789abcdef' *
2449 (self.FRAME_SIZE_TARGET // 16 + 1))
2450
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002451 # Protocol 4 packs groups of small objects into frames and issues
2452 # calls to write only once or twice per frame:
2453 # The C pickler issues one call to write per-frame (header and
2454 # contents) while Python pickler issues two calls to write: one for
2455 # the frame header and one for the frame binary contents.
2456 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002457 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002458
2459 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002460 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002461 # be released otherwise this delayed access would not be possible.
2462 pickled = writer.concatenate_chunks()
2463 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002464 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002465 self.assertGreater(len(writer.chunks), 1)
2466
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002467 # memoryviews should own the memory.
2468 del objects
2469 support.gc_collect()
2470 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002471
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002472 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002473 # There should be at least one call to write per frame
2474 self.assertGreaterEqual(len(writer.chunks), n_frames)
2475
2476 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002477 # one per-frame header, one per frame for the actual contents,
2478 # and two for the header.
2479 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002480
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002481 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002482 large_sizes = [s for s in chunk_sizes
2483 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002484 medium_sizes = [s for s in chunk_sizes
2485 if 9 < s < self.FRAME_SIZE_TARGET]
2486 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002487
2488 # Large chunks should not be too large:
2489 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002490 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2491 chunk_sizes)
2492 # There shouldn't bee too many small chunks: the protocol header,
2493 # the frame headers and the large string headers are written
2494 # in small chunks.
2495 self.assertLessEqual(len(small_sizes),
2496 len(large_sizes) + len(medium_sizes) + 3,
2497 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002498
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002499 def test_nested_names(self):
2500 global Nested
2501 class Nested:
2502 class A:
2503 class B:
2504 class C:
2505 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002506 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002507 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2508 with self.subTest(proto=proto, obj=obj):
2509 unpickled = self.loads(self.dumps(obj, proto))
2510 self.assertIs(obj, unpickled)
2511
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002512 def test_recursive_nested_names(self):
2513 global Recursive
2514 class Recursive:
2515 pass
2516 Recursive.mod = sys.modules[Recursive.__module__]
2517 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2518 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2519 with self.subTest(proto=proto):
2520 unpickled = self.loads(self.dumps(Recursive, proto))
2521 self.assertIs(unpickled, Recursive)
2522 del Recursive.mod # break reference loop
2523
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002524 def test_py_methods(self):
2525 global PyMethodsTest
2526 class PyMethodsTest:
2527 @staticmethod
2528 def cheese():
2529 return "cheese"
2530 @classmethod
2531 def wine(cls):
2532 assert cls is PyMethodsTest
2533 return "wine"
2534 def biscuits(self):
2535 assert isinstance(self, PyMethodsTest)
2536 return "biscuits"
2537 class Nested:
2538 "Nested class"
2539 @staticmethod
2540 def ketchup():
2541 return "ketchup"
2542 @classmethod
2543 def maple(cls):
2544 assert cls is PyMethodsTest.Nested
2545 return "maple"
2546 def pie(self):
2547 assert isinstance(self, PyMethodsTest.Nested)
2548 return "pie"
2549
2550 py_methods = (
2551 PyMethodsTest.cheese,
2552 PyMethodsTest.wine,
2553 PyMethodsTest().biscuits,
2554 PyMethodsTest.Nested.ketchup,
2555 PyMethodsTest.Nested.maple,
2556 PyMethodsTest.Nested().pie
2557 )
2558 py_unbound_methods = (
2559 (PyMethodsTest.biscuits, PyMethodsTest),
2560 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2561 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002562 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002563 for method in py_methods:
2564 with self.subTest(proto=proto, method=method):
2565 unpickled = self.loads(self.dumps(method, proto))
2566 self.assertEqual(method(), unpickled())
2567 for method, cls in py_unbound_methods:
2568 obj = cls()
2569 with self.subTest(proto=proto, method=method):
2570 unpickled = self.loads(self.dumps(method, proto))
2571 self.assertEqual(method(obj), unpickled(obj))
2572
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002573 def test_c_methods(self):
2574 global Subclass
2575 class Subclass(tuple):
2576 class Nested(str):
2577 pass
2578
2579 c_methods = (
2580 # bound built-in method
2581 ("abcd".index, ("c",)),
2582 # unbound built-in method
2583 (str.index, ("abcd", "c")),
2584 # bound "slot" method
2585 ([1, 2, 3].__len__, ()),
2586 # unbound "slot" method
2587 (list.__len__, ([1, 2, 3],)),
2588 # bound "coexist" method
2589 ({1, 2}.__contains__, (2,)),
2590 # unbound "coexist" method
2591 (set.__contains__, ({1, 2}, 2)),
2592 # built-in class method
2593 (dict.fromkeys, (("a", 1), ("b", 2))),
2594 # built-in static method
2595 (bytearray.maketrans, (b"abc", b"xyz")),
2596 # subclass methods
2597 (Subclass([1,2,2]).count, (2,)),
2598 (Subclass.count, (Subclass([1,2,2]), 2)),
2599 (Subclass.Nested("sweet").count, ("e",)),
2600 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2601 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002602 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002603 for method, args in c_methods:
2604 with self.subTest(proto=proto, method=method):
2605 unpickled = self.loads(self.dumps(method, proto))
2606 self.assertEqual(method(*args), unpickled(*args))
2607
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002608 def test_compat_pickle(self):
2609 tests = [
2610 (range(1, 7), '__builtin__', 'xrange'),
2611 (map(int, '123'), 'itertools', 'imap'),
2612 (functools.reduce, '__builtin__', 'reduce'),
2613 (dbm.whichdb, 'whichdb', 'whichdb'),
2614 (Exception(), 'exceptions', 'Exception'),
2615 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2616 (collections.UserList(), 'UserList', 'UserList'),
2617 (collections.defaultdict(), 'collections', 'defaultdict'),
2618 ]
2619 for val, mod, name in tests:
2620 for proto in range(3):
2621 with self.subTest(type=type(val), proto=proto):
2622 pickled = self.dumps(val, proto)
2623 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2624 self.assertIs(type(self.loads(pickled)), type(val))
2625
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002626 def test_local_lookup_error(self):
2627 # Test that whichmodule() errors out cleanly when looking up
2628 # an assumed globally-reachable object fails.
2629 def f():
2630 pass
2631 # Since the function is local, lookup will fail
2632 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2633 with self.assertRaises((AttributeError, pickle.PicklingError)):
2634 pickletools.dis(self.dumps(f, proto))
2635 # Same without a __module__ attribute (exercises a different path
2636 # in _pickle.c).
2637 del f.__module__
2638 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2639 with self.assertRaises((AttributeError, pickle.PicklingError)):
2640 pickletools.dis(self.dumps(f, proto))
2641 # Yet a different path.
2642 f.__name__ = f.__qualname__
2643 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2644 with self.assertRaises((AttributeError, pickle.PicklingError)):
2645 pickletools.dis(self.dumps(f, proto))
2646
Antoine Pitrou91f43802019-05-26 17:10:09 +02002647 #
2648 # PEP 574 tests below
2649 #
2650
2651 def buffer_like_objects(self):
2652 # Yield buffer-like objects with the bytestring "abcdef" in them
2653 bytestring = b"abcdefgh"
2654 yield ZeroCopyBytes(bytestring)
2655 yield ZeroCopyBytearray(bytestring)
2656 if _testbuffer is not None:
2657 items = list(bytestring)
2658 value = int.from_bytes(bytestring, byteorder='little')
2659 for flags in (0, _testbuffer.ND_WRITABLE):
2660 # 1-D, contiguous
2661 yield PicklableNDArray(items, format='B', shape=(8,),
2662 flags=flags)
2663 # 2-D, C-contiguous
2664 yield PicklableNDArray(items, format='B', shape=(4, 2),
2665 strides=(2, 1), flags=flags)
2666 # 2-D, Fortran-contiguous
2667 yield PicklableNDArray(items, format='B',
2668 shape=(4, 2), strides=(1, 4),
2669 flags=flags)
2670
2671 def test_in_band_buffers(self):
2672 # Test in-band buffers (PEP 574)
2673 for obj in self.buffer_like_objects():
2674 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2675 data = self.dumps(obj, proto)
2676 if obj.c_contiguous and proto >= 5:
2677 # The raw memory bytes are serialized in physical order
2678 self.assertIn(b"abcdefgh", data)
2679 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2680 if proto >= 5:
2681 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2682 1 if obj.readonly else 0)
2683 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2684 0 if obj.readonly else 1)
2685 # Return a true value from buffer_callback should have
2686 # the same effect
2687 def buffer_callback(obj):
2688 return True
2689 data2 = self.dumps(obj, proto,
2690 buffer_callback=buffer_callback)
2691 self.assertEqual(data2, data)
2692
2693 new = self.loads(data)
2694 # It's a copy
2695 self.assertIsNot(new, obj)
2696 self.assertIs(type(new), type(obj))
2697 self.assertEqual(new, obj)
2698
2699 # XXX Unfortunately cannot test non-contiguous array
2700 # (see comment in PicklableNDArray.__reduce_ex__)
2701
2702 def test_oob_buffers(self):
2703 # Test out-of-band buffers (PEP 574)
2704 for obj in self.buffer_like_objects():
2705 for proto in range(0, 5):
2706 # Need protocol >= 5 for buffer_callback
2707 with self.assertRaises(ValueError):
2708 self.dumps(obj, proto,
2709 buffer_callback=[].append)
2710 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2711 buffers = []
2712 buffer_callback = lambda pb: buffers.append(pb.raw())
2713 data = self.dumps(obj, proto,
2714 buffer_callback=buffer_callback)
2715 self.assertNotIn(b"abcdefgh", data)
2716 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2717 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2718 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2719 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2720 1 if obj.readonly else 0)
2721
2722 if obj.c_contiguous:
2723 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2724 # Need buffers argument to unpickle properly
2725 with self.assertRaises(pickle.UnpicklingError):
2726 self.loads(data)
2727
2728 new = self.loads(data, buffers=buffers)
2729 if obj.zero_copy_reconstruct:
2730 # Zero-copy achieved
2731 self.assertIs(new, obj)
2732 else:
2733 self.assertIs(type(new), type(obj))
2734 self.assertEqual(new, obj)
2735 # Non-sequence buffers accepted too
2736 new = self.loads(data, buffers=iter(buffers))
2737 if obj.zero_copy_reconstruct:
2738 # Zero-copy achieved
2739 self.assertIs(new, obj)
2740 else:
2741 self.assertIs(type(new), type(obj))
2742 self.assertEqual(new, obj)
2743
2744 def test_oob_buffers_writable_to_readonly(self):
2745 # Test reconstructing readonly object from writable buffer
2746 obj = ZeroCopyBytes(b"foobar")
2747 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2748 buffers = []
2749 buffer_callback = buffers.append
2750 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2751
2752 buffers = map(bytearray, buffers)
2753 new = self.loads(data, buffers=buffers)
2754 self.assertIs(type(new), type(obj))
2755 self.assertEqual(new, obj)
2756
2757 def test_picklebuffer_error(self):
2758 # PickleBuffer forbidden with protocol < 5
2759 pb = pickle.PickleBuffer(b"foobar")
2760 for proto in range(0, 5):
2761 with self.assertRaises(pickle.PickleError):
2762 self.dumps(pb, proto)
2763
2764 def test_buffer_callback_error(self):
2765 def buffer_callback(buffers):
2766 1/0
2767 pb = pickle.PickleBuffer(b"foobar")
2768 with self.assertRaises(ZeroDivisionError):
2769 self.dumps(pb, 5, buffer_callback=buffer_callback)
2770
2771 def test_buffers_error(self):
2772 pb = pickle.PickleBuffer(b"foobar")
2773 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2774 data = self.dumps(pb, proto, buffer_callback=[].append)
2775 # Non iterable buffers
2776 with self.assertRaises(TypeError):
2777 self.loads(data, buffers=object())
2778 # Buffer iterable exhausts too early
2779 with self.assertRaises(pickle.UnpicklingError):
2780 self.loads(data, buffers=[])
2781
Miss Islington (bot)25cb4fd2019-07-25 09:18:20 -07002782 def test_inband_accept_default_buffers_argument(self):
2783 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2784 data_pickled = self.dumps(1, proto, buffer_callback=None)
2785 data = self.loads(data_pickled, buffers=None)
2786
Antoine Pitrou91f43802019-05-26 17:10:09 +02002787 @unittest.skipIf(np is None, "Test needs Numpy")
2788 def test_buffers_numpy(self):
2789 def check_no_copy(x, y):
2790 np.testing.assert_equal(x, y)
2791 self.assertEqual(x.ctypes.data, y.ctypes.data)
2792
2793 def check_copy(x, y):
2794 np.testing.assert_equal(x, y)
2795 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2796
2797 def check_array(arr):
2798 # In-band
2799 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2800 data = self.dumps(arr, proto)
2801 new = self.loads(data)
2802 check_copy(arr, new)
2803 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2804 buffer_callback = lambda _: True
2805 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2806 new = self.loads(data)
2807 check_copy(arr, new)
2808 # Out-of-band
2809 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2810 buffers = []
2811 buffer_callback = buffers.append
2812 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2813 new = self.loads(data, buffers=buffers)
2814 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2815 check_no_copy(arr, new)
2816 else:
2817 check_copy(arr, new)
2818
2819 # 1-D
2820 arr = np.arange(6)
2821 check_array(arr)
2822 # 1-D, non-contiguous
2823 check_array(arr[::2])
2824 # 2-D, C-contiguous
2825 arr = np.arange(12).reshape((3, 4))
2826 check_array(arr)
2827 # 2-D, F-contiguous
2828 check_array(arr.T)
2829 # 2-D, non-contiguous
2830 check_array(arr[::2])
2831
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002832
2833class BigmemPickleTests(unittest.TestCase):
2834
Victor Stinner8c663fd2017-11-08 14:44:44 -08002835 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002836
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002837 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002838 def test_huge_long_32b(self, size):
2839 data = 1 << (8 * size)
2840 try:
2841 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002842 if proto < 2:
2843 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002844 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002845 with self.assertRaises((ValueError, OverflowError)):
2846 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002847 finally:
2848 data = None
2849
Victor Stinner8c663fd2017-11-08 14:44:44 -08002850 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002851 # (older protocols don't have a dedicated opcode for bytes and are
2852 # too inefficient)
2853
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002854 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002855 def test_huge_bytes_32b(self, size):
2856 data = b"abcd" * (size // 4)
2857 try:
2858 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002859 if proto < 3:
2860 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002861 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002862 try:
2863 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002864 header = (pickle.BINBYTES +
2865 struct.pack("<I", len(data)))
2866 data_start = pickled.index(data)
2867 self.assertEqual(
2868 header,
2869 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002870 finally:
2871 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002872 finally:
2873 data = None
2874
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002875 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002876 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002877 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002878 try:
2879 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002880 if proto < 3:
2881 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002882 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002883 if proto == 3:
2884 # Protocol 3 does not support large bytes objects.
2885 # Verify that we do not crash when processing one.
2886 with self.assertRaises((ValueError, OverflowError)):
2887 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002888 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002889 try:
2890 pickled = self.dumps(data, protocol=proto)
2891 header = (pickle.BINBYTES8 +
2892 struct.pack("<Q", len(data)))
2893 data_start = pickled.index(data)
2894 self.assertEqual(
2895 header,
2896 pickled[data_start-len(header):data_start])
2897 finally:
2898 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002899 finally:
2900 data = None
2901
2902 # All protocols use 1-byte per printable ASCII character; we add another
2903 # byte because the encoded form has to be copied into the internal buffer.
2904
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002905 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002906 def test_huge_str_32b(self, size):
2907 data = "abcd" * (size // 4)
2908 try:
2909 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002910 if proto == 0:
2911 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002912 with self.subTest(proto=proto):
2913 try:
2914 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002915 header = (pickle.BINUNICODE +
2916 struct.pack("<I", len(data)))
2917 data_start = pickled.index(b'abcd')
2918 self.assertEqual(
2919 header,
2920 pickled[data_start-len(header):data_start])
2921 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2922 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002923 finally:
2924 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002925 finally:
2926 data = None
2927
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002928 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2929 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2930 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002931
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002932 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002933 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002934 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002935 try:
2936 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002937 if proto == 0:
2938 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002939 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002940 if proto < 4:
2941 with self.assertRaises((ValueError, OverflowError)):
2942 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002943 continue
2944 try:
2945 pickled = self.dumps(data, protocol=proto)
2946 header = (pickle.BINUNICODE8 +
2947 struct.pack("<Q", len(data)))
2948 data_start = pickled.index(b'abcd')
2949 self.assertEqual(
2950 header,
2951 pickled[data_start-len(header):data_start])
2952 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2953 pickled.index(b"abcd")), len(data))
2954 finally:
2955 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002956 finally:
2957 data = None
2958
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002959
Guido van Rossum2a30b212003-02-18 22:41:24 +00002960# Test classes for reduce_ex
2961
2962class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002963 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002964 _reduce_called = 0
2965 def __reduce__(self):
2966 self._reduce_called = 1
2967 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002968
2969class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002970 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002971 _proto = None
2972 def __reduce_ex__(self, proto):
2973 self._proto = proto
2974 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002975
2976class REX_three(object):
2977 _proto = None
2978 def __reduce_ex__(self, proto):
2979 self._proto = proto
2980 return REX_two, ()
2981 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002982 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002983
Guido van Rossumd8faa362007-04-27 19:54:29 +00002984class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002985 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002986 _proto = None
2987 def __reduce_ex__(self, proto):
2988 self._proto = proto
2989 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002990
2991class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002992 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002993 _reduce_called = 0
2994 def __reduce__(self):
2995 self._reduce_called = 1
2996 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002997
2998class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002999 """This class is used to check the 4th argument (list iterator) of
3000 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003001 """
3002 def __init__(self, items=None):
3003 self.items = items if items is not None else []
3004 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003005 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003006 def append(self, item):
3007 self.items.append(item)
3008 def __reduce__(self):
3009 return type(self), (), None, iter(self.items), None
3010
3011class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003012 """This class is used to check the 5th argument (dict iterator) of
3013 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003014 """
3015 def __init__(self, table=None):
3016 self.table = table if table is not None else {}
3017 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003018 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003019 def __setitem__(self, key, value):
3020 self.table[key] = value
3021 def __reduce__(self):
3022 return type(self), (), None, None, iter(self.table.items())
3023
Guido van Rossumd8faa362007-04-27 19:54:29 +00003024
Guido van Rossum2a30b212003-02-18 22:41:24 +00003025# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003026
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003027class MyInt(int):
3028 sample = 1
3029
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003030class MyFloat(float):
3031 sample = 1.0
3032
3033class MyComplex(complex):
3034 sample = 1.0 + 0.0j
3035
3036class MyStr(str):
3037 sample = "hello"
3038
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003039class MyUnicode(str):
3040 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003041
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003042class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003043 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003044
3045class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003046 sample = [1, 2, 3]
3047
3048class MyDict(dict):
3049 sample = {"a": 1, "b": 2}
3050
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003051class MySet(set):
3052 sample = {"a", "b"}
3053
3054class MyFrozenSet(frozenset):
3055 sample = frozenset({"a", "b"})
3056
Mark Dickinson5c2db372009-12-05 20:28:34 +00003057myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003058 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003059 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003060 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003061
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003062
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003063class SlotList(MyList):
3064 __slots__ = ["foo"]
3065
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003066class SimpleNewObj(int):
3067 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003068 # raise an error, to make sure this isn't called
3069 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003070 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003071 return int(self) == int(other) and self.__dict__ == other.__dict__
3072
3073class ComplexNewObj(SimpleNewObj):
3074 def __getnewargs__(self):
3075 return ('%X' % self, 16)
3076
3077class ComplexNewObjEx(SimpleNewObj):
3078 def __getnewargs_ex__(self):
3079 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003080
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003081class BadGetattr:
3082 def __getattr__(self, key):
3083 self.foo
3084
Collin Winter771d8342009-04-16 03:18:06 +00003085
Jeremy Hylton66426532001-10-15 21:38:56 +00003086class AbstractPickleModuleTests(unittest.TestCase):
3087
3088 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003089 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003090 try:
3091 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003092 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003093 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003094 support.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003095
3096 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003097 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003098 try:
3099 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003100 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003101 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003102 support.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003103
Collin Winter771d8342009-04-16 03:18:06 +00003104 def test_load_from_and_dump_to_file(self):
3105 stream = io.BytesIO()
3106 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003107 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003108 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003109 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003110 self.assertEqual(unpickled, data)
3111
Tim Petersc0c93702003-02-13 19:30:57 +00003112 def test_highest_protocol(self):
3113 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003114 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003115
Martin v. Löwis544f1192004-07-27 05:22:33 +00003116 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003117 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003118 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003119 self.dump(123, f, -1)
3120 self.dump(123, file=f, protocol=-1)
3121 self.dumps(123, -1)
3122 self.dumps(123, protocol=-1)
3123 self.Pickler(f, -1)
3124 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003125
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003126 def test_dump_text_file(self):
3127 f = open(TESTFN, "w")
3128 try:
3129 for proto in protocols:
3130 self.assertRaises(TypeError, self.dump, 123, f, proto)
3131 finally:
3132 f.close()
3133 support.unlink(TESTFN)
3134
3135 def test_incomplete_input(self):
3136 s = io.BytesIO(b"X''.")
3137 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3138
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003139 def test_bad_init(self):
3140 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003141 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003142 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003143 def __init__(self): pass
3144
Serhiy Storchaka65452562017-11-15 14:01:08 +02003145 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003146 def __init__(self): pass
3147
3148 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3149 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3150
Antoine Pitrou91f43802019-05-26 17:10:09 +02003151 def check_dumps_loads_oob_buffers(self, dumps, loads):
3152 # No need to do the full gamut of tests here, just enough to
3153 # check that dumps() and loads() redirect their arguments
3154 # to the underlying Pickler and Unpickler, respectively.
3155 obj = ZeroCopyBytes(b"foo")
3156
3157 for proto in range(0, 5):
3158 # Need protocol >= 5 for buffer_callback
3159 with self.assertRaises(ValueError):
3160 dumps(obj, protocol=proto,
3161 buffer_callback=[].append)
3162 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3163 buffers = []
3164 buffer_callback = buffers.append
3165 data = dumps(obj, protocol=proto,
3166 buffer_callback=buffer_callback)
3167 self.assertNotIn(b"foo", data)
3168 self.assertEqual(bytes(buffers[0]), b"foo")
3169 # Need buffers argument to unpickle properly
3170 with self.assertRaises(pickle.UnpicklingError):
3171 loads(data)
3172 new = loads(data, buffers=buffers)
3173 self.assertIs(new, obj)
3174
3175 def test_dumps_loads_oob_buffers(self):
3176 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3177 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3178
3179 def test_dump_load_oob_buffers(self):
3180 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3181 def dumps(obj, **kwargs):
3182 f = io.BytesIO()
3183 self.dump(obj, f, **kwargs)
3184 return f.getvalue()
3185
3186 def loads(data, **kwargs):
3187 f = io.BytesIO(data)
3188 return self.load(f, **kwargs)
3189
3190 self.check_dumps_loads_oob_buffers(dumps, loads)
3191
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003192
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003193class AbstractPersistentPicklerTests(unittest.TestCase):
3194
3195 # This class defines persistent_id() and persistent_load()
3196 # functions that should be used by the pickler. All even integers
3197 # are pickled using persistent ids.
3198
3199 def persistent_id(self, object):
3200 if isinstance(object, int) and object % 2 == 0:
3201 self.id_count += 1
3202 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003203 elif object == "test_false_value":
3204 self.false_count += 1
3205 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003206 else:
3207 return None
3208
3209 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003210 if not oid:
3211 self.load_false_count += 1
3212 return "test_false_value"
3213 else:
3214 self.load_count += 1
3215 object = int(oid)
3216 assert object % 2 == 0
3217 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003218
3219 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003220 L = list(range(10)) + ["test_false_value"]
3221 for proto in protocols:
3222 self.id_count = 0
3223 self.false_count = 0
3224 self.load_false_count = 0
3225 self.load_count = 0
3226 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3227 self.assertEqual(self.id_count, 5)
3228 self.assertEqual(self.false_count, 1)
3229 self.assertEqual(self.load_count, 5)
3230 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003231
Collin Winter771d8342009-04-16 03:18:06 +00003232
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003233class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3234
3235 def persistent_id(self, obj):
3236 return obj
3237
3238 def persistent_load(self, pid):
3239 return pid
3240
3241 def _check_return_correct_type(self, obj, proto):
3242 unpickled = self.loads(self.dumps(obj, proto))
3243 self.assertIsInstance(unpickled, type(obj))
3244 self.assertEqual(unpickled, obj)
3245
3246 def test_return_correct_type(self):
3247 for proto in protocols:
3248 # Protocol 0 supports only ASCII strings.
3249 if proto == 0:
3250 self._check_return_correct_type("abc", 0)
3251 else:
3252 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3253 self._check_return_correct_type(obj, proto)
3254
3255 def test_protocol0_is_ascii_only(self):
3256 non_ascii_str = "\N{EMPTY SET}"
3257 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3258 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3259 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3260
3261
Collin Winter771d8342009-04-16 03:18:06 +00003262class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3263
3264 pickler_class = None
3265 unpickler_class = None
3266
3267 def setUp(self):
3268 assert self.pickler_class
3269 assert self.unpickler_class
3270
3271 def test_clear_pickler_memo(self):
3272 # To test whether clear_memo() has any effect, we pickle an object,
3273 # then pickle it again without clearing the memo; the two serialized
3274 # forms should be different. If we clear_memo() and then pickle the
3275 # object again, the third serialized form should be identical to the
3276 # first one we obtained.
3277 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003278 for proto in protocols:
3279 f = io.BytesIO()
3280 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003281
Serhiy Storchakac8695292018-04-04 00:11:27 +03003282 pickler.dump(data)
3283 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003284
Serhiy Storchakac8695292018-04-04 00:11:27 +03003285 # Reset BytesIO object.
3286 f.seek(0)
3287 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003288
Serhiy Storchakac8695292018-04-04 00:11:27 +03003289 pickler.dump(data)
3290 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003291
Serhiy Storchakac8695292018-04-04 00:11:27 +03003292 # Reset the Pickler and BytesIO objects.
3293 pickler.clear_memo()
3294 f.seek(0)
3295 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003296
Serhiy Storchakac8695292018-04-04 00:11:27 +03003297 pickler.dump(data)
3298 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003299
Serhiy Storchakac8695292018-04-04 00:11:27 +03003300 self.assertNotEqual(first_pickled, second_pickled)
3301 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003302
3303 def test_priming_pickler_memo(self):
3304 # Verify that we can set the Pickler's memo attribute.
3305 data = ["abcdefg", "abcdefg", 44]
3306 f = io.BytesIO()
3307 pickler = self.pickler_class(f)
3308
3309 pickler.dump(data)
3310 first_pickled = f.getvalue()
3311
3312 f = io.BytesIO()
3313 primed = self.pickler_class(f)
3314 primed.memo = pickler.memo
3315
3316 primed.dump(data)
3317 primed_pickled = f.getvalue()
3318
3319 self.assertNotEqual(first_pickled, primed_pickled)
3320
3321 def test_priming_unpickler_memo(self):
3322 # Verify that we can set the Unpickler's memo attribute.
3323 data = ["abcdefg", "abcdefg", 44]
3324 f = io.BytesIO()
3325 pickler = self.pickler_class(f)
3326
3327 pickler.dump(data)
3328 first_pickled = f.getvalue()
3329
3330 f = io.BytesIO()
3331 primed = self.pickler_class(f)
3332 primed.memo = pickler.memo
3333
3334 primed.dump(data)
3335 primed_pickled = f.getvalue()
3336
3337 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3338 unpickled_data1 = unpickler.load()
3339
3340 self.assertEqual(unpickled_data1, data)
3341
3342 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3343 primed.memo = unpickler.memo
3344 unpickled_data2 = primed.load()
3345
3346 primed.memo.clear()
3347
3348 self.assertEqual(unpickled_data2, data)
3349 self.assertTrue(unpickled_data2 is unpickled_data1)
3350
3351 def test_reusing_unpickler_objects(self):
3352 data1 = ["abcdefg", "abcdefg", 44]
3353 f = io.BytesIO()
3354 pickler = self.pickler_class(f)
3355 pickler.dump(data1)
3356 pickled1 = f.getvalue()
3357
3358 data2 = ["abcdefg", 44, 44]
3359 f = io.BytesIO()
3360 pickler = self.pickler_class(f)
3361 pickler.dump(data2)
3362 pickled2 = f.getvalue()
3363
3364 f = io.BytesIO()
3365 f.write(pickled1)
3366 f.seek(0)
3367 unpickler = self.unpickler_class(f)
3368 self.assertEqual(unpickler.load(), data1)
3369
3370 f.seek(0)
3371 f.truncate()
3372 f.write(pickled2)
3373 f.seek(0)
3374 self.assertEqual(unpickler.load(), data2)
3375
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -08003376 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003377 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003378 with self.subTest(proto=proto):
3379 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3380 f = ioclass()
3381 pickler = self.pickler_class(f, protocol=proto)
3382 pickler.dump(data1)
3383 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003384
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003385 N = 5
3386 f = ioclass(pickled * N)
3387 unpickler = self.unpickler_class(f)
3388 for i in range(N):
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -08003389 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003390 pos = f.tell()
3391 self.assertEqual(unpickler.load(), data1)
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -08003392 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003393 self.assertEqual(f.tell(), pos + len(pickled))
3394 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003395
3396 def test_multiple_unpicklings_seekable(self):
3397 self._check_multiple_unpicklings(io.BytesIO)
3398
3399 def test_multiple_unpicklings_unseekable(self):
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -08003400 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3401
3402 def test_multiple_unpicklings_minimal(self):
3403 # File-like object that doesn't support peek() and readinto()
3404 # (bpo-39681)
3405 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003406
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003407 def test_unpickling_buffering_readline(self):
3408 # Issue #12687: the unpickler's buffering logic could fail with
3409 # text mode opcodes.
3410 data = list(range(10))
3411 for proto in protocols:
3412 for buf_size in range(1, 11):
3413 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3414 pickler = self.pickler_class(f, protocol=proto)
3415 pickler.dump(data)
3416 f.seek(0)
3417 unpickler = self.unpickler_class(f)
3418 self.assertEqual(unpickler.load(), data)
3419
Collin Winter771d8342009-04-16 03:18:06 +00003420
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003421# Tests for dispatch_table attribute
3422
3423REDUCE_A = 'reduce_A'
3424
3425class AAA(object):
3426 def __reduce__(self):
3427 return str, (REDUCE_A,)
3428
3429class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003430 def __init__(self):
3431 # Add an instance attribute to enable state-saving routines at pickling
3432 # time.
3433 self.a = "some attribute"
3434
3435 def __setstate__(self, state):
3436 self.a = "BBB.__setstate__"
3437
3438
3439def setstate_bbb(obj, state):
3440 """Custom state setter for BBB objects
3441
3442 Such callable may be created by other persons than the ones who created the
3443 BBB class. If passed as the state_setter item of a custom reducer, this
3444 allows for custom state setting behavior of BBB objects. One can think of
3445 it as the analogous of list_setitems or dict_setitems but for foreign
3446 classes/functions.
3447 """
3448 obj.a = "custom state_setter"
3449
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003450
Pierre Glaser289f1f82019-05-08 23:08:25 +02003451
3452class AbstractCustomPicklerClass:
3453 """Pickler implementing a reducing hook using reducer_override."""
3454 def reducer_override(self, obj):
3455 obj_name = getattr(obj, "__name__", None)
3456
3457 if obj_name == 'f':
3458 # asking the pickler to save f as 5
3459 return int, (5, )
3460
3461 if obj_name == 'MyClass':
3462 return str, ('some str',)
3463
3464 elif obj_name == 'g':
3465 # in this case, the callback returns an invalid result (not a 2-5
3466 # tuple or a string), the pickler should raise a proper error.
3467 return False
3468
3469 elif obj_name == 'h':
3470 # Simulate a case when the reducer fails. The error should
3471 # be propagated to the original ``dump`` call.
3472 raise ValueError('The reducer just failed')
3473
3474 return NotImplemented
3475
3476class AbstractHookTests(unittest.TestCase):
3477 def test_pickler_hook(self):
3478 # test the ability of a custom, user-defined CPickler subclass to
3479 # override the default reducing routines of any type using the method
3480 # reducer_override
3481
3482 def f():
3483 pass
3484
3485 def g():
3486 pass
3487
3488 def h():
3489 pass
3490
3491 class MyClass:
3492 pass
3493
3494 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3495 with self.subTest(proto=proto):
3496 bio = io.BytesIO()
3497 p = self.pickler_class(bio, proto)
3498
3499 p.dump([f, MyClass, math.log])
3500 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3501
3502 self.assertEqual(new_f, 5)
3503 self.assertEqual(some_str, 'some str')
3504 # math.log does not have its usual reducer overriden, so the
3505 # custom reduction callback should silently direct the pickler
3506 # to the default pickling by attribute, by returning
3507 # NotImplemented
3508 self.assertIs(math_log, math.log)
3509
3510 with self.assertRaises(pickle.PicklingError):
3511 p.dump(g)
3512
3513 with self.assertRaisesRegex(
3514 ValueError, 'The reducer just failed'):
3515 p.dump(h)
3516
Antoine Pitrou17236872020-02-02 21:22:57 +01003517 @support.cpython_only
3518 def test_reducer_override_no_reference_cycle(self):
3519 # bpo-39492: reducer_override used to induce a spurious reference cycle
3520 # inside the Pickler object, that could prevent all serialized objects
3521 # from being garbage-collected without explicity invoking gc.collect.
3522
3523 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3524 with self.subTest(proto=proto):
3525 def f():
3526 pass
3527
3528 wr = weakref.ref(f)
3529
3530 bio = io.BytesIO()
3531 p = self.pickler_class(bio, proto)
3532 p.dump(f)
3533 new_f = pickle.loads(bio.getvalue())
3534 assert new_f == 5
3535
3536 del p
3537 del f
3538
3539 self.assertIsNone(wr())
3540
Pierre Glaser289f1f82019-05-08 23:08:25 +02003541
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003542class AbstractDispatchTableTests(unittest.TestCase):
3543
3544 def test_default_dispatch_table(self):
3545 # No dispatch_table attribute by default
3546 f = io.BytesIO()
3547 p = self.pickler_class(f, 0)
3548 with self.assertRaises(AttributeError):
3549 p.dispatch_table
3550 self.assertFalse(hasattr(p, 'dispatch_table'))
3551
3552 def test_class_dispatch_table(self):
3553 # A dispatch_table attribute can be specified class-wide
3554 dt = self.get_dispatch_table()
3555
3556 class MyPickler(self.pickler_class):
3557 dispatch_table = dt
3558
3559 def dumps(obj, protocol=None):
3560 f = io.BytesIO()
3561 p = MyPickler(f, protocol)
3562 self.assertEqual(p.dispatch_table, dt)
3563 p.dump(obj)
3564 return f.getvalue()
3565
3566 self._test_dispatch_table(dumps, dt)
3567
3568 def test_instance_dispatch_table(self):
3569 # A dispatch_table attribute can also be specified instance-wide
3570 dt = self.get_dispatch_table()
3571
3572 def dumps(obj, protocol=None):
3573 f = io.BytesIO()
3574 p = self.pickler_class(f, protocol)
3575 p.dispatch_table = dt
3576 self.assertEqual(p.dispatch_table, dt)
3577 p.dump(obj)
3578 return f.getvalue()
3579
3580 self._test_dispatch_table(dumps, dt)
3581
3582 def _test_dispatch_table(self, dumps, dispatch_table):
3583 def custom_load_dump(obj):
3584 return pickle.loads(dumps(obj, 0))
3585
3586 def default_load_dump(obj):
3587 return pickle.loads(pickle.dumps(obj, 0))
3588
3589 # pickling complex numbers using protocol 0 relies on copyreg
3590 # so check pickling a complex number still works
3591 z = 1 + 2j
3592 self.assertEqual(custom_load_dump(z), z)
3593 self.assertEqual(default_load_dump(z), z)
3594
3595 # modify pickling of complex
3596 REDUCE_1 = 'reduce_1'
3597 def reduce_1(obj):
3598 return str, (REDUCE_1,)
3599 dispatch_table[complex] = reduce_1
3600 self.assertEqual(custom_load_dump(z), REDUCE_1)
3601 self.assertEqual(default_load_dump(z), z)
3602
3603 # check picklability of AAA and BBB
3604 a = AAA()
3605 b = BBB()
3606 self.assertEqual(custom_load_dump(a), REDUCE_A)
3607 self.assertIsInstance(custom_load_dump(b), BBB)
3608 self.assertEqual(default_load_dump(a), REDUCE_A)
3609 self.assertIsInstance(default_load_dump(b), BBB)
3610
3611 # modify pickling of BBB
3612 dispatch_table[BBB] = reduce_1
3613 self.assertEqual(custom_load_dump(a), REDUCE_A)
3614 self.assertEqual(custom_load_dump(b), REDUCE_1)
3615 self.assertEqual(default_load_dump(a), REDUCE_A)
3616 self.assertIsInstance(default_load_dump(b), BBB)
3617
3618 # revert pickling of BBB and modify pickling of AAA
3619 REDUCE_2 = 'reduce_2'
3620 def reduce_2(obj):
3621 return str, (REDUCE_2,)
3622 dispatch_table[AAA] = reduce_2
3623 del dispatch_table[BBB]
3624 self.assertEqual(custom_load_dump(a), REDUCE_2)
3625 self.assertIsInstance(custom_load_dump(b), BBB)
3626 self.assertEqual(default_load_dump(a), REDUCE_A)
3627 self.assertIsInstance(default_load_dump(b), BBB)
3628
Pierre Glaser65d98d02019-05-08 21:40:25 +02003629 # End-to-end testing of save_reduce with the state_setter keyword
3630 # argument. This is a dispatch_table test as the primary goal of
3631 # state_setter is to tweak objects reduction behavior.
3632 # In particular, state_setter is useful when the default __setstate__
3633 # behavior is not flexible enough.
3634
3635 # No custom reducer for b has been registered for now, so
3636 # BBB.__setstate__ should be used at unpickling time
3637 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3638
3639 def reduce_bbb(obj):
3640 return BBB, (), obj.__dict__, None, None, setstate_bbb
3641
3642 dispatch_table[BBB] = reduce_bbb
3643
3644 # The custom reducer reduce_bbb includes a state setter, that should
3645 # have priority over BBB.__setstate__
3646 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3647
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003648
Guido van Rossum98297ee2007-11-06 21:34:58 +00003649if __name__ == "__main__":
3650 # Print some stuff that can be used to rewrite DATA{0,1,2}
3651 from pickletools import dis
3652 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003653 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003654 p = pickle.dumps(x, i)
3655 print("DATA{0} = (".format(i))
3656 for j in range(0, len(p), 20):
3657 b = bytes(p[j:j+20])
3658 print(" {0!r}".format(b))
3659 print(")")
3660 print()
3661 print("# Disassembly of DATA{0}".format(i))
3662 print("DATA{0}_DIS = \"\"\"\\".format(i))
3663 dis(p)
3664 print("\"\"\"")
3665 print()