blob: 9401043d78d18b122ca9845b322298b35f0a0afa [file] [log] [blame]
Serhiy Storchakabfe18242015-03-31 13:12:37 +03001import collections
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002import copyreg
Serhiy Storchakabfe18242015-03-31 13:12:37 +03003import dbm
Collin Winter771d8342009-04-16 03:18:06 +00004import io
Serhiy Storchakabfe18242015-03-31 13:12:37 +03005import functools
tjb9004371c0a2019-02-18 23:30:51 +08006import os
Pierre Glaser289f1f82019-05-08 23:08:25 +02007import math
Tim Peters4190fb82003-02-02 16:09:05 +00008import pickle
Tim Peters31f119e2003-02-03 16:20:13 +00009import pickletools
tjb9004371c0a2019-02-18 23:30:51 +080010import shutil
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -080011import struct
Antoine Pitrou82be19f2011-08-29 23:09:33 +020012import sys
tjb9004371c0a2019-02-18 23:30:51 +080013import threading
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +010014import unittest
Antoine Pitrou16c4ce12011-03-11 21:30:43 +010015import weakref
tjb9004371c0a2019-02-18 23:30:51 +080016from textwrap import dedent
Antoine Pitroud9dfaa92009-06-04 20:32:06 +000017from http.cookies import SimpleCookie
Tim Peters4190fb82003-02-02 16:09:05 +000018
Antoine Pitrou91f43802019-05-26 17:10:09 +020019try:
20 import _testbuffer
21except ImportError:
22 _testbuffer = None
23
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020024from test import support
Antoine Pitrou82be19f2011-08-29 23:09:33 +020025from test.support import (
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020026 TestFailed, TESTFN, run_with_locale, no_tracing,
tjb9004371c0a2019-02-18 23:30:51 +080027 _2G, _4G, bigmemtest, reap_threads, forget,
Victor Stinner3d974b22020-06-17 19:09:49 +020028 save_restore_warnings_filters
Antoine Pitrou82be19f2011-08-29 23:09:33 +020029 )
Tim Peterse089c682001-04-10 03:41:41 +000030
Guido van Rossum98297ee2007-11-06 21:34:58 +000031from pickle import bytes_types
32
Victor Stinner3d974b22020-06-17 19:09:49 +020033
34# bpo-41003: Save/restore warnings filters to leave them unchanged.
35# Ignore filters installed by numpy.
36try:
37 with save_restore_warnings_filters():
38 import numpy as np
39except ImportError:
40 np = None
41
42
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030043requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
44 "test is only meaningful on 32-bit builds")
45
Tim Petersee1a53c2003-02-02 02:57:53 +000046# Tests that try a number of pickle protocols should have a
47# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000048# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000049protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000050
Tim Peters22e71712003-02-03 22:27:38 +000051
52# Return True if opcode code appears in the pickle, else False.
53def opcode_in_pickle(code, pickle):
54 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000055 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000056 return True
57 return False
58
Tim Peters8d2613a2003-02-11 16:40:16 +000059# Return the number of times opcode code appears in pickle.
60def count_opcode(code, pickle):
61 n = 0
62 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000063 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000064 n += 1
65 return n
66
Antoine Pitrou04248a82010-10-12 20:51:21 +000067
68class UnseekableIO(io.BytesIO):
69 def peek(self, *args):
70 raise NotImplementedError
71
72 def seekable(self):
73 return False
74
75 def seek(self, *args):
76 raise io.UnsupportedOperation
77
78 def tell(self):
79 raise io.UnsupportedOperation
80
81
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -080082class MinimalIO(object):
83 """
84 A file-like object that doesn't support readinto().
85 """
86 def __init__(self, *args):
87 self._bio = io.BytesIO(*args)
88 self.getvalue = self._bio.getvalue
89 self.read = self._bio.read
90 self.readline = self._bio.readline
91 self.write = self._bio.write
92
93
Tim Peters3e667d52003-02-04 21:47:44 +000094# We can't very well test the extension registry without putting known stuff
95# in it, but we have to be careful to restore its original state. Code
96# should do this:
97#
98# e = ExtensionSaver(extension_code)
99# try:
100# fiddle w/ the extension registry's stuff for extension_code
101# finally:
102# e.restore()
103
104class ExtensionSaver:
105 # Remember current registration for code (if any), and remove it (if
106 # there is one).
107 def __init__(self, code):
108 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000109 if code in copyreg._inverted_registry:
110 self.pair = copyreg._inverted_registry[code]
111 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000112 else:
113 self.pair = None
114
115 # Restore previous registration for code.
116 def restore(self):
117 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000118 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000119 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000120 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000121 pair = self.pair
122 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000123 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000124
Jeremy Hylton66426532001-10-15 21:38:56 +0000125class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000126 def __eq__(self, other):
127 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000128
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000129class D(C):
130 def __init__(self, arg):
131 pass
132
133class E(C):
134 def __getinitargs__(self):
135 return ()
136
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100137class H(object):
138 pass
139
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200140# Hashable mutable key
141class K(object):
142 def __init__(self, value):
143 self.value = value
144
145 def __reduce__(self):
146 # Shouldn't support the recursion itself
147 return K, (self.value,)
148
Jeremy Hylton66426532001-10-15 21:38:56 +0000149import __main__
150__main__.C = C
151C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000152__main__.D = D
153D.__module__ = "__main__"
154__main__.E = E
155E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100156__main__.H = H
157H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200158__main__.K = K
159K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000160
161class myint(int):
162 def __init__(self, x):
163 self.str = str(x)
164
165class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000166
Jeremy Hylton66426532001-10-15 21:38:56 +0000167 def __init__(self, a, b):
168 self.a = a
169 self.b = b
170
171 def __getinitargs__(self):
172 return self.a, self.b
173
Guido van Rossum04a86612001-12-19 16:58:54 +0000174class metaclass(type):
175 pass
176
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000177class use_metaclass(object, metaclass=metaclass):
178 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000179
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200180class pickling_metaclass(type):
181 def __eq__(self, other):
182 return (type(self) == type(other) and
183 self.reduce_args == other.reduce_args)
184
185 def __reduce__(self):
186 return (create_dynamic_class, self.reduce_args)
187
188def create_dynamic_class(name, bases):
189 result = pickling_metaclass(name, bases, dict())
190 result.reduce_args = (name, bases)
191 return result
192
Antoine Pitrou91f43802019-05-26 17:10:09 +0200193
194class ZeroCopyBytes(bytes):
195 readonly = True
196 c_contiguous = True
197 f_contiguous = True
198 zero_copy_reconstruct = True
199
200 def __reduce_ex__(self, protocol):
201 if protocol >= 5:
202 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
203 else:
204 return type(self)._reconstruct, (bytes(self),)
205
206 def __repr__(self):
207 return "{}({!r})".format(self.__class__.__name__, bytes(self))
208
209 __str__ = __repr__
210
211 @classmethod
212 def _reconstruct(cls, obj):
213 with memoryview(obj) as m:
214 obj = m.obj
215 if type(obj) is cls:
216 # Zero-copy
217 return obj
218 else:
219 return cls(obj)
220
221
222class ZeroCopyBytearray(bytearray):
223 readonly = False
224 c_contiguous = True
225 f_contiguous = True
226 zero_copy_reconstruct = True
227
228 def __reduce_ex__(self, protocol):
229 if protocol >= 5:
230 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
231 else:
232 return type(self)._reconstruct, (bytes(self),)
233
234 def __repr__(self):
235 return "{}({!r})".format(self.__class__.__name__, bytes(self))
236
237 __str__ = __repr__
238
239 @classmethod
240 def _reconstruct(cls, obj):
241 with memoryview(obj) as m:
242 obj = m.obj
243 if type(obj) is cls:
244 # Zero-copy
245 return obj
246 else:
247 return cls(obj)
248
249
250if _testbuffer is not None:
251
252 class PicklableNDArray:
253 # A not-really-zero-copy picklable ndarray, as the ndarray()
254 # constructor doesn't allow for it
255
256 zero_copy_reconstruct = False
257
258 def __init__(self, *args, **kwargs):
259 self.array = _testbuffer.ndarray(*args, **kwargs)
260
261 def __getitem__(self, idx):
262 cls = type(self)
263 new = cls.__new__(cls)
264 new.array = self.array[idx]
265 return new
266
267 @property
268 def readonly(self):
269 return self.array.readonly
270
271 @property
272 def c_contiguous(self):
273 return self.array.c_contiguous
274
275 @property
276 def f_contiguous(self):
277 return self.array.f_contiguous
278
279 def __eq__(self, other):
280 if not isinstance(other, PicklableNDArray):
281 return NotImplemented
282 return (other.array.format == self.array.format and
283 other.array.shape == self.array.shape and
284 other.array.strides == self.array.strides and
285 other.array.readonly == self.array.readonly and
286 other.array.tobytes() == self.array.tobytes())
287
288 def __ne__(self, other):
289 if not isinstance(other, PicklableNDArray):
290 return NotImplemented
291 return not (self == other)
292
293 def __repr__(self):
294 return (f"{type(self)}(shape={self.array.shape},"
295 f"strides={self.array.strides}, "
296 f"bytes={self.array.tobytes()})")
297
298 def __reduce_ex__(self, protocol):
299 if not self.array.contiguous:
300 raise NotImplementedError("Reconstructing a non-contiguous "
301 "ndarray does not seem possible")
302 ndarray_kwargs = {"shape": self.array.shape,
303 "strides": self.array.strides,
304 "format": self.array.format,
305 "flags": (0 if self.readonly
306 else _testbuffer.ND_WRITABLE)}
307 pb = pickle.PickleBuffer(self.array)
308 if protocol >= 5:
309 return (type(self)._reconstruct,
310 (pb, ndarray_kwargs))
311 else:
312 # Need to serialize the bytes in physical order
313 with pb.raw() as m:
314 return (type(self)._reconstruct,
315 (m.tobytes(), ndarray_kwargs))
316
317 @classmethod
318 def _reconstruct(cls, obj, kwargs):
319 with memoryview(obj) as m:
320 # For some reason, ndarray() wants a list of integers...
321 # XXX This only works if format == 'B'
322 items = list(m.tobytes())
323 return cls(items, **kwargs)
324
325
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300326# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000327# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000328
Guido van Rossum98297ee2007-11-06 21:34:58 +0000329DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200330 b'(lp0\nL0L\naL1L\naF2.0\n'
331 b'ac__builtin__\ncomple'
332 b'x\np1\n(F3.0\nF0.0\ntp2\n'
333 b'Rp3\naL1L\naL-1L\naL255'
334 b'L\naL-255L\naL-256L\naL'
335 b'65535L\naL-65535L\naL-'
336 b'65536L\naL2147483647L'
337 b'\naL-2147483647L\naL-2'
338 b'147483648L\na(Vabc\np4'
339 b'\ng4\nccopy_reg\n_recon'
340 b'structor\np5\n(c__main'
341 b'__\nC\np6\nc__builtin__'
342 b'\nobject\np7\nNtp8\nRp9\n'
343 b'(dp10\nVfoo\np11\nL1L\ns'
344 b'Vbar\np12\nL2L\nsbg9\ntp'
345 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000346)
Tim Peterse9358162001-01-22 22:05:20 +0000347
Guido van Rossum98297ee2007-11-06 21:34:58 +0000348# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000349DATA0_DIS = """\
350 0: ( MARK
351 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000352 2: p PUT 0
353 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000354 9: a APPEND
355 10: L LONG 1
356 14: a APPEND
357 15: F FLOAT 2.0
358 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200359 21: c GLOBAL '__builtin__ complex'
360 42: p PUT 1
361 45: ( MARK
362 46: F FLOAT 3.0
363 51: F FLOAT 0.0
364 56: t TUPLE (MARK at 45)
365 57: p PUT 2
366 60: R REDUCE
367 61: p PUT 3
368 64: a APPEND
369 65: L LONG 1
370 69: a APPEND
371 70: L LONG -1
372 75: a APPEND
373 76: L LONG 255
374 82: a APPEND
375 83: L LONG -255
376 90: a APPEND
377 91: L LONG -256
378 98: a APPEND
379 99: L LONG 65535
380 107: a APPEND
381 108: L LONG -65535
382 117: a APPEND
383 118: L LONG -65536
384 127: a APPEND
385 128: L LONG 2147483647
386 141: a APPEND
387 142: L LONG -2147483647
388 156: a APPEND
389 157: L LONG -2147483648
390 171: a APPEND
391 172: ( MARK
392 173: V UNICODE 'abc'
393 178: p PUT 4
394 181: g GET 4
395 184: c GLOBAL 'copy_reg _reconstructor'
396 209: p PUT 5
397 212: ( MARK
398 213: c GLOBAL '__main__ C'
399 225: p PUT 6
400 228: c GLOBAL '__builtin__ object'
401 248: p PUT 7
402 251: N NONE
403 252: t TUPLE (MARK at 212)
404 253: p PUT 8
405 256: R REDUCE
406 257: p PUT 9
407 260: ( MARK
408 261: d DICT (MARK at 260)
409 262: p PUT 10
410 266: V UNICODE 'foo'
411 271: p PUT 11
412 275: L LONG 1
413 279: s SETITEM
414 280: V UNICODE 'bar'
415 285: p PUT 12
416 289: L LONG 2
417 293: s SETITEM
418 294: b BUILD
419 295: g GET 9
420 298: t TUPLE (MARK at 172)
421 299: p PUT 13
422 303: a APPEND
423 304: g GET 13
424 308: a APPEND
425 309: L LONG 5
426 313: a APPEND
427 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000428highest protocol among opcodes = 0
429"""
430
Guido van Rossum98297ee2007-11-06 21:34:58 +0000431DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200432 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
433 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000434 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
435 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
436 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
437 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200438 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000439 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200440 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000441 b'object\nq\x07Ntq\x08Rq\t}q\n('
442 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
443 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
444)
Tim Peters70b02d72003-02-02 17:26:40 +0000445
Guido van Rossum98297ee2007-11-06 21:34:58 +0000446# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000447DATA1_DIS = """\
448 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000449 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000450 3: ( MARK
451 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000452 6: K BININT1 1
453 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200454 17: c GLOBAL '__builtin__ complex'
455 38: q BINPUT 1
456 40: ( MARK
457 41: G BINFLOAT 3.0
458 50: G BINFLOAT 0.0
459 59: t TUPLE (MARK at 40)
460 60: q BINPUT 2
461 62: R REDUCE
462 63: q BINPUT 3
463 65: K BININT1 1
464 67: J BININT -1
465 72: K BININT1 255
466 74: J BININT -255
467 79: J BININT -256
468 84: M BININT2 65535
469 87: J BININT -65535
470 92: J BININT -65536
471 97: J BININT 2147483647
472 102: J BININT -2147483647
473 107: J BININT -2147483648
474 112: ( MARK
475 113: X BINUNICODE 'abc'
476 121: q BINPUT 4
477 123: h BINGET 4
478 125: c GLOBAL 'copy_reg _reconstructor'
479 150: q BINPUT 5
480 152: ( MARK
481 153: c GLOBAL '__main__ C'
482 165: q BINPUT 6
483 167: c GLOBAL '__builtin__ object'
484 187: q BINPUT 7
485 189: N NONE
486 190: t TUPLE (MARK at 152)
487 191: q BINPUT 8
488 193: R REDUCE
489 194: q BINPUT 9
490 196: } EMPTY_DICT
491 197: q BINPUT 10
492 199: ( MARK
493 200: X BINUNICODE 'foo'
494 208: q BINPUT 11
495 210: K BININT1 1
496 212: X BINUNICODE 'bar'
497 220: q BINPUT 12
498 222: K BININT1 2
499 224: u SETITEMS (MARK at 199)
500 225: b BUILD
501 226: h BINGET 9
502 228: t TUPLE (MARK at 112)
503 229: q BINPUT 13
504 231: h BINGET 13
505 233: K BININT1 5
506 235: e APPENDS (MARK at 3)
507 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000508highest protocol among opcodes = 1
509"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000510
Guido van Rossum98297ee2007-11-06 21:34:58 +0000511DATA2 = (
512 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200513 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000514 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
515 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
516 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
517 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
518 b'bcq\x04h\x04c__main__\nC\nq\x05'
519 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
520 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
521 b'\nK\x05e.'
522)
Tim Petersfc273752003-03-02 04:54:24 +0000523
Guido van Rossum98297ee2007-11-06 21:34:58 +0000524# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000525DATA2_DIS = """\
526 0: \x80 PROTO 2
527 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000528 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000529 5: ( MARK
530 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000531 8: K BININT1 1
532 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200533 19: c GLOBAL '__builtin__ complex'
534 40: q BINPUT 1
535 42: G BINFLOAT 3.0
536 51: G BINFLOAT 0.0
537 60: \x86 TUPLE2
538 61: q BINPUT 2
539 63: R REDUCE
540 64: q BINPUT 3
541 66: K BININT1 1
542 68: J BININT -1
543 73: K BININT1 255
544 75: J BININT -255
545 80: J BININT -256
546 85: M BININT2 65535
547 88: J BININT -65535
548 93: J BININT -65536
549 98: J BININT 2147483647
550 103: J BININT -2147483647
551 108: J BININT -2147483648
552 113: ( MARK
553 114: X BINUNICODE 'abc'
554 122: q BINPUT 4
555 124: h BINGET 4
556 126: c GLOBAL '__main__ C'
557 138: q BINPUT 5
558 140: ) EMPTY_TUPLE
559 141: \x81 NEWOBJ
560 142: q BINPUT 6
561 144: } EMPTY_DICT
562 145: q BINPUT 7
563 147: ( MARK
564 148: X BINUNICODE 'foo'
565 156: q BINPUT 8
566 158: K BININT1 1
567 160: X BINUNICODE 'bar'
568 168: q BINPUT 9
569 170: K BININT1 2
570 172: u SETITEMS (MARK at 147)
571 173: b BUILD
572 174: h BINGET 6
573 176: t TUPLE (MARK at 113)
574 177: q BINPUT 10
575 179: h BINGET 10
576 181: K BININT1 5
577 183: e APPENDS (MARK at 5)
578 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000579highest protocol among opcodes = 2
580"""
581
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300582DATA3 = (
583 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
584 b'builtins\ncomplex\nq\x01G'
585 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
586 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
587 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
588 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
589 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
590 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
591 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
592 b'e.'
593)
594
595# Disassembly of DATA3
596DATA3_DIS = """\
597 0: \x80 PROTO 3
598 2: ] EMPTY_LIST
599 3: q BINPUT 0
600 5: ( MARK
601 6: K BININT1 0
602 8: K BININT1 1
603 10: G BINFLOAT 2.0
604 19: c GLOBAL 'builtins complex'
605 37: q BINPUT 1
606 39: G BINFLOAT 3.0
607 48: G BINFLOAT 0.0
608 57: \x86 TUPLE2
609 58: q BINPUT 2
610 60: R REDUCE
611 61: q BINPUT 3
612 63: K BININT1 1
613 65: J BININT -1
614 70: K BININT1 255
615 72: J BININT -255
616 77: J BININT -256
617 82: M BININT2 65535
618 85: J BININT -65535
619 90: J BININT -65536
620 95: J BININT 2147483647
621 100: J BININT -2147483647
622 105: J BININT -2147483648
623 110: ( MARK
624 111: X BINUNICODE 'abc'
625 119: q BINPUT 4
626 121: h BINGET 4
627 123: c GLOBAL '__main__ C'
628 135: q BINPUT 5
629 137: ) EMPTY_TUPLE
630 138: \x81 NEWOBJ
631 139: q BINPUT 6
632 141: } EMPTY_DICT
633 142: q BINPUT 7
634 144: ( MARK
635 145: X BINUNICODE 'bar'
636 153: q BINPUT 8
637 155: K BININT1 2
638 157: X BINUNICODE 'foo'
639 165: q BINPUT 9
640 167: K BININT1 1
641 169: u SETITEMS (MARK at 144)
642 170: b BUILD
643 171: h BINGET 6
644 173: t TUPLE (MARK at 110)
645 174: q BINPUT 10
646 176: h BINGET 10
647 178: K BININT1 5
648 180: e APPENDS (MARK at 5)
649 181: . STOP
650highest protocol among opcodes = 2
651"""
652
653DATA4 = (
654 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
655 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
656 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
657 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
658 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
659 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
660 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
661 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
662 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
663)
664
665# Disassembly of DATA4
666DATA4_DIS = """\
667 0: \x80 PROTO 4
668 2: \x95 FRAME 168
669 11: ] EMPTY_LIST
670 12: \x94 MEMOIZE
671 13: ( MARK
672 14: K BININT1 0
673 16: K BININT1 1
674 18: G BINFLOAT 2.0
675 27: \x8c SHORT_BINUNICODE 'builtins'
676 37: \x94 MEMOIZE
677 38: \x8c SHORT_BINUNICODE 'complex'
678 47: \x94 MEMOIZE
679 48: \x93 STACK_GLOBAL
680 49: \x94 MEMOIZE
681 50: G BINFLOAT 3.0
682 59: G BINFLOAT 0.0
683 68: \x86 TUPLE2
684 69: \x94 MEMOIZE
685 70: R REDUCE
686 71: \x94 MEMOIZE
687 72: K BININT1 1
688 74: J BININT -1
689 79: K BININT1 255
690 81: J BININT -255
691 86: J BININT -256
692 91: M BININT2 65535
693 94: J BININT -65535
694 99: J BININT -65536
695 104: J BININT 2147483647
696 109: J BININT -2147483647
697 114: J BININT -2147483648
698 119: ( MARK
699 120: \x8c SHORT_BINUNICODE 'abc'
700 125: \x94 MEMOIZE
701 126: h BINGET 6
702 128: \x8c SHORT_BINUNICODE '__main__'
703 138: \x94 MEMOIZE
704 139: \x8c SHORT_BINUNICODE 'C'
705 142: \x94 MEMOIZE
706 143: \x93 STACK_GLOBAL
707 144: \x94 MEMOIZE
708 145: ) EMPTY_TUPLE
709 146: \x81 NEWOBJ
710 147: \x94 MEMOIZE
711 148: } EMPTY_DICT
712 149: \x94 MEMOIZE
713 150: ( MARK
714 151: \x8c SHORT_BINUNICODE 'bar'
715 156: \x94 MEMOIZE
716 157: K BININT1 2
717 159: \x8c SHORT_BINUNICODE 'foo'
718 164: \x94 MEMOIZE
719 165: K BININT1 1
720 167: u SETITEMS (MARK at 150)
721 168: b BUILD
722 169: h BINGET 10
723 171: t TUPLE (MARK at 119)
724 172: \x94 MEMOIZE
725 173: h BINGET 14
726 175: K BININT1 5
727 177: e APPENDS (MARK at 13)
728 178: . STOP
729highest protocol among opcodes = 4
730"""
731
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000732# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300733DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000734
735# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300736DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000737
738# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300739DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
740 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
741 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
742 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
743 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
744 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000745
746# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300747DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000748
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100749python2_exceptions_without_args = (
750 ArithmeticError,
751 AssertionError,
752 AttributeError,
753 BaseException,
754 BufferError,
755 BytesWarning,
756 DeprecationWarning,
757 EOFError,
758 EnvironmentError,
759 Exception,
760 FloatingPointError,
761 FutureWarning,
762 GeneratorExit,
763 IOError,
764 ImportError,
765 ImportWarning,
766 IndentationError,
767 IndexError,
768 KeyError,
769 KeyboardInterrupt,
770 LookupError,
771 MemoryError,
772 NameError,
773 NotImplementedError,
774 OSError,
775 OverflowError,
776 PendingDeprecationWarning,
777 ReferenceError,
778 RuntimeError,
779 RuntimeWarning,
780 # StandardError is gone in Python 3, we map it to Exception
781 StopIteration,
782 SyntaxError,
783 SyntaxWarning,
784 SystemError,
785 SystemExit,
786 TabError,
787 TypeError,
788 UnboundLocalError,
789 UnicodeError,
790 UnicodeWarning,
791 UserWarning,
792 ValueError,
793 Warning,
794 ZeroDivisionError,
795)
796
797exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
798
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100799# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300800DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
801 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
802 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100803
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000804
Jeremy Hylton66426532001-10-15 21:38:56 +0000805def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000806 c = C()
807 c.foo = 1
808 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000809 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000810 # Append some integer test cases at cPickle.c's internal size
811 # cutoffs.
812 uint1max = 0xff
813 uint2max = 0xffff
814 int4max = 0x7fffffff
815 x.extend([1, -1,
816 uint1max, -uint1max, -uint1max-1,
817 uint2max, -uint2max, -uint2max-1,
818 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000819 y = ('abc', 'abc', c, c)
820 x.append(y)
821 x.append(y)
822 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000823 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000824
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100825
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300826class AbstractUnpickleTests(unittest.TestCase):
827 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100828
Jeremy Hylton66426532001-10-15 21:38:56 +0000829 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000830
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100831 def assert_is_copy(self, obj, objcopy, msg=None):
832 """Utility method to verify if two objects are copies of each others.
833 """
834 if msg is None:
835 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
836 self.assertEqual(obj, objcopy, msg=msg)
837 self.assertIs(type(obj), type(objcopy), msg=msg)
838 if hasattr(obj, '__dict__'):
839 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
840 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
841 if hasattr(obj, '__slots__'):
842 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
843 for slot in obj.__slots__:
844 self.assertEqual(
845 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
846 self.assertEqual(getattr(obj, slot, None),
847 getattr(objcopy, slot, None), msg=msg)
848
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200849 def check_unpickling_error(self, errors, data):
850 with self.subTest(data=data), \
851 self.assertRaises(errors):
852 try:
853 self.loads(data)
854 except BaseException as exc:
855 if support.verbose > 1:
856 print('%-32r - %s: %s' %
857 (data, exc.__class__.__name__, exc))
858 raise
859
Guido van Rossum98297ee2007-11-06 21:34:58 +0000860 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100861 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000862
863 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100864 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000865
866 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100867 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000868
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300869 def test_load_from_data3(self):
870 self.assert_is_copy(self._testdata, self.loads(DATA3))
871
872 def test_load_from_data4(self):
873 self.assert_is_copy(self._testdata, self.loads(DATA4))
874
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000875 def test_load_classic_instance(self):
876 # See issue5180. Test loading 2.x pickles that
877 # contain an instance of old style class.
878 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
879 xname = X.__name__.encode('ascii')
880 # Protocol 0 (text mode pickle):
881 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200882 0: ( MARK
883 1: i INST '__main__ X' (MARK at 0)
884 13: p PUT 0
885 16: ( MARK
886 17: d DICT (MARK at 16)
887 18: p PUT 1
888 21: b BUILD
889 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000890 """
891 pickle0 = (b"(i__main__\n"
892 b"X\n"
893 b"p0\n"
894 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100895 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000896
897 # Protocol 1 (binary mode pickle)
898 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200899 0: ( MARK
900 1: c GLOBAL '__main__ X'
901 13: q BINPUT 0
902 15: o OBJ (MARK at 0)
903 16: q BINPUT 1
904 18: } EMPTY_DICT
905 19: q BINPUT 2
906 21: b BUILD
907 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000908 """
909 pickle1 = (b'(c__main__\n'
910 b'X\n'
911 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100912 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000913
914 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
915 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200916 0: \x80 PROTO 2
917 2: ( MARK
918 3: c GLOBAL '__main__ X'
919 15: q BINPUT 0
920 17: o OBJ (MARK at 2)
921 18: q BINPUT 1
922 20: } EMPTY_DICT
923 21: q BINPUT 2
924 23: b BUILD
925 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000926 """
927 pickle2 = (b'\x80\x02(c__main__\n'
928 b'X\n'
929 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100930 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000931
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300932 def test_maxint64(self):
933 maxint64 = (1 << 63) - 1
934 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
935 got = self.loads(data)
936 self.assert_is_copy(maxint64, got)
937
938 # Try too with a bogus literal.
939 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200940 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300941
942 def test_unpickle_from_2x(self):
943 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300944 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300945 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300946 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300947 self.assertEqual(type(loaded), type(range(0)))
948 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300949 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300950 self.assertEqual(type(loaded), SimpleCookie)
951 self.assertEqual(list(loaded.keys()), ["key"])
952 self.assertEqual(loaded["key"].value, "value")
953
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300954 # Exception objects without arguments pickled from 2.x with protocol 2
955 for exc in python2_exceptions_without_args:
956 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300957 loaded = self.loads(data)
958 self.assertIs(type(loaded), exc)
959
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300960 # StandardError is mapped to Exception, test that separately
961 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300962 self.assertIs(type(loaded), Exception)
963
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300964 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300965 self.assertIs(type(loaded), UnicodeEncodeError)
966 self.assertEqual(loaded.object, "foo")
967 self.assertEqual(loaded.encoding, "ascii")
968 self.assertEqual(loaded.start, 0)
969 self.assertEqual(loaded.end, 1)
970 self.assertEqual(loaded.reason, "bad")
971
972 def test_load_python2_str_as_bytes(self):
973 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
974 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
975 encoding="bytes"), b'a\x00\xa0')
976 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
977 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
978 encoding="bytes"), b'a\x00\xa0')
979 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
980 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
981 encoding="bytes"), b'a\x00\xa0')
982
983 def test_load_python2_unicode_as_str(self):
984 # From Python 2: pickle.dumps(u'π', protocol=0)
985 self.assertEqual(self.loads(b'V\\u03c0\n.',
986 encoding='bytes'), 'π')
987 # From Python 2: pickle.dumps(u'π', protocol=1)
988 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
989 encoding="bytes"), 'π')
990 # From Python 2: pickle.dumps(u'π', protocol=2)
991 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
992 encoding="bytes"), 'π')
993
994 def test_load_long_python2_str_as_bytes(self):
995 # From Python 2: pickle.dumps('x' * 300, protocol=1)
996 self.assertEqual(self.loads(pickle.BINSTRING +
997 struct.pack("<I", 300) +
998 b'x' * 300 + pickle.STOP,
999 encoding='bytes'), b'x' * 300)
1000
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001001 def test_constants(self):
1002 self.assertIsNone(self.loads(b'N.'))
1003 self.assertIs(self.loads(b'\x88.'), True)
1004 self.assertIs(self.loads(b'\x89.'), False)
1005 self.assertIs(self.loads(b'I01\n.'), True)
1006 self.assertIs(self.loads(b'I00\n.'), False)
1007
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001008 def test_empty_bytestring(self):
1009 # issue 11286
1010 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1011 self.assertEqual(empty, '')
1012
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001013 def test_short_binbytes(self):
1014 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
1015 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1016
1017 def test_binbytes(self):
1018 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1019 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1020
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001021 @requires_32b
1022 def test_negative_32b_binbytes(self):
1023 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1024 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001025 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1026 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001027
1028 @requires_32b
1029 def test_negative_32b_binunicode(self):
1030 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1031 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001032 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1033 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001034
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001035 def test_short_binunicode(self):
1036 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1037 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1038
1039 def test_misc_get(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001040 self.check_unpickling_error(KeyError, b'g0\np0')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001041 self.assert_is_copy([(100,), (100,)],
1042 self.loads(b'((Kdtp0\nh\x00l.))'))
1043
Serhiy Storchakae0606192015-09-29 22:10:07 +03001044 def test_binbytes8(self):
1045 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1046 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1047
1048 def test_binunicode8(self):
1049 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1050 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1051
Antoine Pitrou91f43802019-05-26 17:10:09 +02001052 def test_bytearray8(self):
1053 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1054 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1055
Serhiy Storchakae0606192015-09-29 22:10:07 +03001056 @requires_32b
1057 def test_large_32b_binbytes8(self):
1058 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001059 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1060 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001061
1062 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001063 def test_large_32b_bytearray8(self):
1064 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1065 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1066 dumped)
1067
1068 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001069 def test_large_32b_binunicode8(self):
1070 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001071 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1072 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001073
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001074 def test_get(self):
1075 pickled = b'((lp100000\ng100000\nt.'
1076 unpickled = self.loads(pickled)
1077 self.assertEqual(unpickled, ([],)*2)
1078 self.assertIs(unpickled[0], unpickled[1])
1079
1080 def test_binget(self):
1081 pickled = b'(]q\xffh\xfft.'
1082 unpickled = self.loads(pickled)
1083 self.assertEqual(unpickled, ([],)*2)
1084 self.assertIs(unpickled[0], unpickled[1])
1085
1086 def test_long_binget(self):
1087 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1088 unpickled = self.loads(pickled)
1089 self.assertEqual(unpickled, ([],)*2)
1090 self.assertIs(unpickled[0], unpickled[1])
1091
1092 def test_dup(self):
1093 pickled = b'((l2t.'
1094 unpickled = self.loads(pickled)
1095 self.assertEqual(unpickled, ([],)*2)
1096 self.assertIs(unpickled[0], unpickled[1])
1097
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001098 def test_negative_put(self):
1099 # Issue #12847
1100 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001101 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001102
1103 @requires_32b
1104 def test_negative_32b_binput(self):
1105 # Issue #12847
1106 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001107 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001108
1109 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001110 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001111
1112 def test_badly_quoted_string(self):
1113 # Issue #17710
1114 badpickles = [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' ' \n.",
1121 b'S" " \n.',
1122 b"S ''\n.",
1123 b'S ""\n.',
1124 b'S \n.',
1125 b'S\n.',
1126 b'S.']
1127 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001128 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001129
1130 def test_correctly_quoted_string(self):
1131 goodpickles = [(b"S''\n.", ''),
1132 (b'S""\n.', ''),
1133 (b'S"\\n"\n.', '\n'),
1134 (b"S'\\n'\n.", '\n')]
1135 for p, expected in goodpickles:
1136 self.assertEqual(self.loads(p), expected)
1137
1138 def test_frame_readline(self):
1139 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1140 # 0: \x80 PROTO 4
1141 # 2: \x95 FRAME 5
1142 # 11: I INT 42
1143 # 15: . STOP
1144 self.assertEqual(self.loads(pickled), 42)
1145
1146 def test_compat_unpickle(self):
1147 # xrange(1, 7)
1148 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1149 unpickled = self.loads(pickled)
1150 self.assertIs(type(unpickled), range)
1151 self.assertEqual(unpickled, range(1, 7))
1152 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1153 # reduce
1154 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1155 self.assertIs(self.loads(pickled), functools.reduce)
1156 # whichdb.whichdb
1157 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1158 self.assertIs(self.loads(pickled), dbm.whichdb)
1159 # Exception(), StandardError()
1160 for name in (b'Exception', b'StandardError'):
1161 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1162 unpickled = self.loads(pickled)
1163 self.assertIs(type(unpickled), Exception)
1164 self.assertEqual(str(unpickled), 'ugh')
1165 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1166 for name in (b'UserDict', b'IterableUserDict'):
1167 pickled = (b'\x80\x02(cUserDict\n' + name +
1168 b'\no}U\x04data}K\x01K\x02ssb.')
1169 unpickled = self.loads(pickled)
1170 self.assertIs(type(unpickled), collections.UserDict)
1171 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1172
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001173 def test_bad_stack(self):
1174 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001175 b'.', # STOP
1176 b'0', # POP
1177 b'1', # POP_MARK
1178 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001179 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001180 b'R', # REDUCE
1181 b')R',
1182 b'a', # APPEND
1183 b'Na',
1184 b'b', # BUILD
1185 b'Nb',
1186 b'd', # DICT
1187 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001188 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001189 b'ibuiltins\nlist\n', # INST
1190 b'l', # LIST
1191 b'o', # OBJ
1192 b'(o',
1193 b'p1\n', # PUT
1194 b'q\x00', # BINPUT
1195 b'r\x00\x00\x00\x00', # LONG_BINPUT
1196 b's', # SETITEM
1197 b'Ns',
1198 b'NNs',
1199 b't', # TUPLE
1200 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001201 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001202 b'}(Nu',
1203 b'\x81', # NEWOBJ
1204 b')\x81',
1205 b'\x85', # TUPLE1
1206 b'\x86', # TUPLE2
1207 b'N\x86',
1208 b'\x87', # TUPLE3
1209 b'N\x87',
1210 b'NN\x87',
1211 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001212 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001213 b'\x91', # FROZENSET
1214 b'\x92', # NEWOBJ_EX
1215 b')}\x92',
1216 b'\x93', # STACK_GLOBAL
1217 b'Vlist\n\x93',
1218 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001219 ]
1220 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001221 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001222
1223 def test_bad_mark(self):
1224 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001225 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001226 b'N(2', # DUP
1227 b'cbuiltins\nlist\n)(R', # REDUCE
1228 b'cbuiltins\nlist\n()R',
1229 b']N(a', # APPEND
1230 # BUILD
1231 b'cbuiltins\nValueError\n)R}(b',
1232 b'cbuiltins\nValueError\n)R(}b',
1233 b'(Nd', # DICT
1234 b'N(p1\n', # PUT
1235 b'N(q\x00', # BINPUT
1236 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1237 b'}NN(s', # SETITEM
1238 b'}N(Ns',
1239 b'}(NNs',
1240 b'}((u', # SETITEMS
1241 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1242 b'cbuiltins\nlist\n()\x81',
1243 b'N(\x85', # TUPLE1
1244 b'NN(\x86', # TUPLE2
1245 b'N(N\x86',
1246 b'NNN(\x87', # TUPLE3
1247 b'NN(N\x87',
1248 b'N(NN\x87',
1249 b']((\x90', # ADDITEMS
1250 # NEWOBJ_EX
1251 b'cbuiltins\nlist\n)}(\x92',
1252 b'cbuiltins\nlist\n)(}\x92',
1253 b'cbuiltins\nlist\n()}\x92',
1254 # STACK_GLOBAL
1255 b'Vbuiltins\n(Vlist\n\x93',
1256 b'Vbuiltins\nVlist\n(\x93',
1257 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001258 ]
1259 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001260 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001261
1262 def test_truncated_data(self):
1263 self.check_unpickling_error(EOFError, b'')
1264 self.check_unpickling_error(EOFError, b'N')
1265 badpickles = [
1266 b'B', # BINBYTES
1267 b'B\x03\x00\x00',
1268 b'B\x03\x00\x00\x00',
1269 b'B\x03\x00\x00\x00ab',
1270 b'C', # SHORT_BINBYTES
1271 b'C\x03',
1272 b'C\x03ab',
1273 b'F', # FLOAT
1274 b'F0.0',
1275 b'F0.00',
1276 b'G', # BINFLOAT
1277 b'G\x00\x00\x00\x00\x00\x00\x00',
1278 b'I', # INT
1279 b'I0',
1280 b'J', # BININT
1281 b'J\x00\x00\x00',
1282 b'K', # BININT1
1283 b'L', # LONG
1284 b'L0',
1285 b'L10',
1286 b'L0L',
1287 b'L10L',
1288 b'M', # BININT2
1289 b'M\x00',
1290 # b'P', # PERSID
1291 # b'Pabc',
1292 b'S', # STRING
1293 b"S'abc'",
1294 b'T', # BINSTRING
1295 b'T\x03\x00\x00',
1296 b'T\x03\x00\x00\x00',
1297 b'T\x03\x00\x00\x00ab',
1298 b'U', # SHORT_BINSTRING
1299 b'U\x03',
1300 b'U\x03ab',
1301 b'V', # UNICODE
1302 b'Vabc',
1303 b'X', # BINUNICODE
1304 b'X\x03\x00\x00',
1305 b'X\x03\x00\x00\x00',
1306 b'X\x03\x00\x00\x00ab',
1307 b'(c', # GLOBAL
1308 b'(cbuiltins',
1309 b'(cbuiltins\n',
1310 b'(cbuiltins\nlist',
1311 b'Ng', # GET
1312 b'Ng0',
1313 b'(i', # INST
1314 b'(ibuiltins',
1315 b'(ibuiltins\n',
1316 b'(ibuiltins\nlist',
1317 b'Nh', # BINGET
1318 b'Nj', # LONG_BINGET
1319 b'Nj\x00\x00\x00',
1320 b'Np', # PUT
1321 b'Np0',
1322 b'Nq', # BINPUT
1323 b'Nr', # LONG_BINPUT
1324 b'Nr\x00\x00\x00',
1325 b'\x80', # PROTO
1326 b'\x82', # EXT1
1327 b'\x83', # EXT2
1328 b'\x84\x01',
1329 b'\x84', # EXT4
1330 b'\x84\x01\x00\x00',
1331 b'\x8a', # LONG1
1332 b'\x8b', # LONG4
1333 b'\x8b\x00\x00\x00',
1334 b'\x8c', # SHORT_BINUNICODE
1335 b'\x8c\x03',
1336 b'\x8c\x03ab',
1337 b'\x8d', # BINUNICODE8
1338 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1339 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1340 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1341 b'\x8e', # BINBYTES8
1342 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1343 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1344 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001345 b'\x96', # BYTEARRAY8
1346 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1347 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1348 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001349 b'\x95', # FRAME
1350 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1351 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1352 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1353 ]
1354 for p in badpickles:
1355 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001356
tjb9004371c0a2019-02-18 23:30:51 +08001357 @reap_threads
1358 def test_unpickle_module_race(self):
1359 # https://bugs.python.org/issue34572
1360 locker_module = dedent("""
1361 import threading
1362 barrier = threading.Barrier(2)
1363 """)
1364 locking_import_module = dedent("""
1365 import locker
1366 locker.barrier.wait()
1367 class ToBeUnpickled(object):
1368 pass
1369 """)
1370
1371 os.mkdir(TESTFN)
1372 self.addCleanup(shutil.rmtree, TESTFN)
1373 sys.path.insert(0, TESTFN)
1374 self.addCleanup(sys.path.remove, TESTFN)
1375 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1376 f.write(locker_module.encode('utf-8'))
1377 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1378 f.write(locking_import_module.encode('utf-8'))
1379 self.addCleanup(forget, "locker")
1380 self.addCleanup(forget, "locking_import")
1381
1382 import locker
1383
1384 pickle_bytes = (
1385 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1386
1387 # Then try to unpickle two of these simultaneously
1388 # One of them will cause the module import, and we want it to block
1389 # until the other one either:
1390 # - fails (before the patch for this issue)
1391 # - blocks on the import lock for the module, as it should
1392 results = []
1393 barrier = threading.Barrier(3)
1394 def t():
1395 # This ensures the threads have all started
1396 # presumably barrier release is faster than thread startup
1397 barrier.wait()
1398 results.append(pickle.loads(pickle_bytes))
1399
1400 t1 = threading.Thread(target=t)
1401 t2 = threading.Thread(target=t)
1402 t1.start()
1403 t2.start()
1404
1405 barrier.wait()
1406 # could have delay here
1407 locker.barrier.wait()
1408
1409 t1.join()
1410 t2.join()
1411
1412 from locking_import import ToBeUnpickled
1413 self.assertEqual(
1414 [type(x) for x in results],
1415 [ToBeUnpickled] * 2)
1416
1417
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001418
1419class AbstractPickleTests(unittest.TestCase):
1420 # Subclass must define self.dumps, self.loads.
1421
1422 optimized = False
1423
1424 _testdata = AbstractUnpickleTests._testdata
1425
1426 def setUp(self):
1427 pass
1428
1429 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1430
1431 def test_misc(self):
1432 # test various datatypes not tested by testdata
1433 for proto in protocols:
1434 x = myint(4)
1435 s = self.dumps(x, proto)
1436 y = self.loads(s)
1437 self.assert_is_copy(x, y)
1438
1439 x = (1, ())
1440 s = self.dumps(x, proto)
1441 y = self.loads(s)
1442 self.assert_is_copy(x, y)
1443
1444 x = initarg(1, x)
1445 s = self.dumps(x, proto)
1446 y = self.loads(s)
1447 self.assert_is_copy(x, y)
1448
1449 # XXX test __reduce__ protocol?
1450
1451 def test_roundtrip_equality(self):
1452 expected = self._testdata
1453 for proto in protocols:
1454 s = self.dumps(expected, proto)
1455 got = self.loads(s)
1456 self.assert_is_copy(expected, got)
1457
Tim Peters70b02d72003-02-02 17:26:40 +00001458 # There are gratuitous differences between pickles produced by
1459 # pickle and cPickle, largely because cPickle starts PUT indices at
1460 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1461 # there's a comment with an exclamation point there whose meaning
1462 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1463 # of 1.
1464 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001465 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001466 from pickletools import dis
1467
1468 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1469 s = self.dumps(self._testdata, proto)
1470 filelike = StringIO()
1471 dis(s, out=filelike)
1472 got = filelike.getvalue()
1473 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001474
1475 def test_recursive_list(self):
1476 l = []
1477 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001478 for proto in protocols:
1479 s = self.dumps(l, proto)
1480 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001481 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001482 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001483 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001484
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001485 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001486 t = ([],)
1487 t[0].append(t)
1488 for proto in protocols:
1489 s = self.dumps(t, proto)
1490 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001491 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001492 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001493 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001494 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001495 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001496
Jeremy Hylton66426532001-10-15 21:38:56 +00001497 def test_recursive_dict(self):
1498 d = {}
1499 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001500 for proto in protocols:
1501 s = self.dumps(d, proto)
1502 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001503 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001504 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001505 self.assertIs(x[1], x)
1506
1507 def test_recursive_dict_key(self):
1508 d = {}
1509 k = K(d)
1510 d[k] = 1
1511 for proto in protocols:
1512 s = self.dumps(d, proto)
1513 x = self.loads(s)
1514 self.assertIsInstance(x, dict)
1515 self.assertEqual(len(x.keys()), 1)
1516 self.assertIsInstance(list(x.keys())[0], K)
1517 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001518
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001519 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001520 y = set()
1521 k = K(y)
1522 y.add(k)
1523 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001524 s = self.dumps(y, proto)
1525 x = self.loads(s)
1526 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001527 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001528 self.assertIsInstance(list(x)[0], K)
1529 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001530
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001531 def test_recursive_list_subclass(self):
1532 y = MyList()
1533 y.append(y)
1534 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001535 s = self.dumps(y, proto)
1536 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001537 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001538 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001539 self.assertIs(x[0], x)
1540
1541 def test_recursive_dict_subclass(self):
1542 d = MyDict()
1543 d[1] = d
1544 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1545 s = self.dumps(d, proto)
1546 x = self.loads(s)
1547 self.assertIsInstance(x, MyDict)
1548 self.assertEqual(list(x.keys()), [1])
1549 self.assertIs(x[1], x)
1550
1551 def test_recursive_dict_subclass_key(self):
1552 d = MyDict()
1553 k = K(d)
1554 d[k] = 1
1555 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1556 s = self.dumps(d, proto)
1557 x = self.loads(s)
1558 self.assertIsInstance(x, MyDict)
1559 self.assertEqual(len(list(x.keys())), 1)
1560 self.assertIsInstance(list(x.keys())[0], K)
1561 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001562
Jeremy Hylton66426532001-10-15 21:38:56 +00001563 def test_recursive_inst(self):
1564 i = C()
1565 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001566 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001567 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001568 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001569 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001570 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001571 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001572
1573 def test_recursive_multi(self):
1574 l = []
1575 d = {1:l}
1576 i = C()
1577 i.attr = d
1578 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001579 for proto in protocols:
1580 s = self.dumps(l, proto)
1581 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001582 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001583 self.assertEqual(len(x), 1)
1584 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001585 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001586 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001587
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001588 def check_recursive_collection_and_inst(self, factory):
1589 h = H()
1590 y = factory([h])
1591 h.attr = y
1592 for proto in protocols:
1593 s = self.dumps(y, proto)
1594 x = self.loads(s)
1595 self.assertIsInstance(x, type(y))
1596 self.assertEqual(len(x), 1)
1597 self.assertIsInstance(list(x)[0], H)
1598 self.assertIs(list(x)[0].attr, x)
1599
1600 def test_recursive_list_and_inst(self):
1601 self.check_recursive_collection_and_inst(list)
1602
1603 def test_recursive_tuple_and_inst(self):
1604 self.check_recursive_collection_and_inst(tuple)
1605
1606 def test_recursive_dict_and_inst(self):
1607 self.check_recursive_collection_and_inst(dict.fromkeys)
1608
1609 def test_recursive_set_and_inst(self):
1610 self.check_recursive_collection_and_inst(set)
1611
1612 def test_recursive_frozenset_and_inst(self):
1613 self.check_recursive_collection_and_inst(frozenset)
1614
1615 def test_recursive_list_subclass_and_inst(self):
1616 self.check_recursive_collection_and_inst(MyList)
1617
1618 def test_recursive_tuple_subclass_and_inst(self):
1619 self.check_recursive_collection_and_inst(MyTuple)
1620
1621 def test_recursive_dict_subclass_and_inst(self):
1622 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1623
1624 def test_recursive_set_subclass_and_inst(self):
1625 self.check_recursive_collection_and_inst(MySet)
1626
1627 def test_recursive_frozenset_subclass_and_inst(self):
1628 self.check_recursive_collection_and_inst(MyFrozenSet)
1629
Walter Dörwald9b775532007-06-08 14:30:53 +00001630 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001631 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001632 '<\\>', '<\\\U00012345>',
1633 # surrogates
1634 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001635 for proto in protocols:
1636 for u in endcases:
1637 p = self.dumps(u, proto)
1638 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001639 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001640
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001641 def test_unicode_high_plane(self):
1642 t = '\U00012345'
1643 for proto in protocols:
1644 p = self.dumps(t, proto)
1645 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001646 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001647
Guido van Rossumf4169812008-03-17 22:56:06 +00001648 def test_bytes(self):
1649 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001650 for s in b'', b'xyz', b'xyz'*100:
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))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001653 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001654 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001655 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001656 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001657 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001658 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001659
Antoine Pitrou91f43802019-05-26 17:10:09 +02001660 def test_bytearray(self):
1661 for proto in protocols:
1662 for s in b'', b'xyz', b'xyz'*100:
1663 b = bytearray(s)
1664 p = self.dumps(b, proto)
1665 bb = self.loads(p)
1666 self.assertIsNot(bb, b)
1667 self.assert_is_copy(b, bb)
1668 if proto <= 3:
1669 # bytearray is serialized using a global reference
1670 self.assertIn(b'bytearray', p)
1671 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1672 elif proto == 4:
1673 self.assertIn(b'bytearray', p)
1674 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1675 elif proto == 5:
1676 self.assertNotIn(b'bytearray', p)
1677 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1678
Jeremy Hylton66426532001-10-15 21:38:56 +00001679 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001680 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001681 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001682 while n:
1683 for expected in (-n, n):
1684 s = self.dumps(expected, proto)
1685 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001686 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001687 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001688
Tim Petersee1a53c2003-02-02 02:57:53 +00001689 def test_long(self):
1690 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001691 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001692 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001693 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001694 for npos in nbase-1, nbase, nbase+1:
1695 for n in npos, -npos:
1696 pickle = self.dumps(n, proto)
1697 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001698 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001699 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1700 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001701 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001702 nbase += nbase << 1000000
1703 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001704 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001705 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001706 # assert_is_copy is very expensive here as it precomputes
1707 # a failure message by computing the repr() of n and got,
1708 # we just do the check ourselves.
1709 self.assertIs(type(got), int)
1710 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001711
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001712 def test_float(self):
1713 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1714 3.14, 263.44582062374053, 6.022e23, 1e30]
1715 test_values = test_values + [-x for x in test_values]
1716 for proto in protocols:
1717 for value in test_values:
1718 pickle = self.dumps(value, proto)
1719 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001720 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001721
Thomas Wouters477c8d52006-05-27 19:21:47 +00001722 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1723 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001724 # make sure that floats are formatted locale independent with proto 0
1725 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001726
Jeremy Hylton66426532001-10-15 21:38:56 +00001727 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001728 for proto in protocols:
1729 inst = AAA()
1730 dumped = self.dumps(inst, proto)
1731 loaded = self.loads(dumped)
1732 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001733
1734 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001735 for proto in protocols:
1736 inst = initarg(1, 2)
1737 dumped = self.dumps(inst, proto)
1738 loaded = self.loads(dumped)
1739 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001740
Guido van Rossum04a86612001-12-19 16:58:54 +00001741 def test_metaclass(self):
1742 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001743 for proto in protocols:
1744 s = self.dumps(a, proto)
1745 b = self.loads(s)
1746 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001747
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001748 def test_dynamic_class(self):
1749 a = create_dynamic_class("my_dynamic_class", (object,))
1750 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1751 for proto in protocols:
1752 s = self.dumps(a, proto)
1753 b = self.loads(s)
1754 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001755 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001756
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001757 def test_structseq(self):
1758 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001759 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001760
1761 t = time.localtime()
1762 for proto in protocols:
1763 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001764 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001765 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001766 t = os.stat(os.curdir)
1767 s = self.dumps(t, proto)
1768 u = self.loads(s)
1769 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001770 if hasattr(os, "statvfs"):
1771 t = os.statvfs(os.curdir)
1772 s = self.dumps(t, proto)
1773 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001774 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001775
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001776 def test_ellipsis(self):
1777 for proto in protocols:
1778 s = self.dumps(..., proto)
1779 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001780 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001781
1782 def test_notimplemented(self):
1783 for proto in protocols:
1784 s = self.dumps(NotImplemented, proto)
1785 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001786 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001787
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001788 def test_singleton_types(self):
1789 # Issue #6477: Test that types of built-in singletons can be pickled.
1790 singletons = [None, ..., NotImplemented]
1791 for singleton in singletons:
1792 for proto in protocols:
1793 s = self.dumps(type(singleton), proto)
1794 u = self.loads(s)
1795 self.assertIs(type(singleton), u)
1796
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001797 # Tests for protocol 2
1798
Tim Peters4190fb82003-02-02 16:09:05 +00001799 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001800 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001801 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001802 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001803 proto_header = pickle.PROTO + bytes([proto])
1804 self.assertTrue(pickled.startswith(proto_header))
1805 else:
1806 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001807
1808 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001809 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001810 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001811 try:
1812 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001813 except ValueError as err:
1814 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001815 else:
1816 self.fail("expected bad protocol number to raise ValueError")
1817
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001818 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001819 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001820 for proto in protocols:
1821 s = self.dumps(x, proto)
1822 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001823 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001824 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001825
1826 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001827 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001828 for proto in protocols:
1829 s = self.dumps(x, proto)
1830 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001831 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001832 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001833
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001834 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001835 # Map (proto, len(tuple)) to expected opcode.
1836 expected_opcode = {(0, 0): pickle.TUPLE,
1837 (0, 1): pickle.TUPLE,
1838 (0, 2): pickle.TUPLE,
1839 (0, 3): pickle.TUPLE,
1840 (0, 4): pickle.TUPLE,
1841
1842 (1, 0): pickle.EMPTY_TUPLE,
1843 (1, 1): pickle.TUPLE,
1844 (1, 2): pickle.TUPLE,
1845 (1, 3): pickle.TUPLE,
1846 (1, 4): pickle.TUPLE,
1847
1848 (2, 0): pickle.EMPTY_TUPLE,
1849 (2, 1): pickle.TUPLE1,
1850 (2, 2): pickle.TUPLE2,
1851 (2, 3): pickle.TUPLE3,
1852 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001853
1854 (3, 0): pickle.EMPTY_TUPLE,
1855 (3, 1): pickle.TUPLE1,
1856 (3, 2): pickle.TUPLE2,
1857 (3, 3): pickle.TUPLE3,
1858 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001859 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001860 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001861 b = (1,)
1862 c = (1, 2)
1863 d = (1, 2, 3)
1864 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001865 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001866 for x in a, b, c, d, e:
1867 s = self.dumps(x, proto)
1868 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001869 self.assert_is_copy(x, y)
1870 expected = expected_opcode[min(proto, 3), len(x)]
1871 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001872
Guido van Rossum7d97d312003-01-28 04:25:27 +00001873 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001874 # Map (proto, singleton) to expected opcode.
1875 expected_opcode = {(0, None): pickle.NONE,
1876 (1, None): pickle.NONE,
1877 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001878 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001879
1880 (0, True): pickle.INT,
1881 (1, True): pickle.INT,
1882 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001883 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001884
1885 (0, False): pickle.INT,
1886 (1, False): pickle.INT,
1887 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001888 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001889 }
Tim Peters4190fb82003-02-02 16:09:05 +00001890 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001891 for x in None, False, True:
1892 s = self.dumps(x, proto)
1893 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001894 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001895 expected = expected_opcode[min(proto, 3), x]
1896 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001897
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001898 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001899 x = MyTuple([1, 2, 3])
1900 x.foo = 42
1901 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001902 for proto in protocols:
1903 s = self.dumps(x, proto)
1904 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001905 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001906
1907 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001908 x = MyList([1, 2, 3])
1909 x.foo = 42
1910 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001911 for proto in protocols:
1912 s = self.dumps(x, proto)
1913 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001914 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001915
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001916 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001917 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001918 for C in myclasses:
1919 B = C.__base__
1920 x = C(C.sample)
1921 x.foo = 42
1922 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001923 y = self.loads(s)
1924 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001925 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001926 self.assertEqual(B(x), B(y), detail)
1927 self.assertEqual(x.__dict__, y.__dict__, detail)
1928
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001929 def test_newobj_proxies(self):
1930 # NEWOBJ should use the __class__ rather than the raw type
1931 classes = myclasses[:]
1932 # Cannot create weakproxies to these classes
1933 for c in (MyInt, MyTuple):
1934 classes.remove(c)
1935 for proto in protocols:
1936 for C in classes:
1937 B = C.__base__
1938 x = C(C.sample)
1939 x.foo = 42
1940 p = weakref.proxy(x)
1941 s = self.dumps(p, proto)
1942 y = self.loads(s)
1943 self.assertEqual(type(y), type(x)) # rather than type(p)
1944 detail = (proto, C, B, x, y, type(y))
1945 self.assertEqual(B(x), B(y), detail)
1946 self.assertEqual(x.__dict__, y.__dict__, detail)
1947
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001948 def test_newobj_not_class(self):
1949 # Issue 24552
1950 global SimpleNewObj
1951 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001952 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001953 b = self.dumps(o, 4)
1954 try:
1955 SimpleNewObj = 42
1956 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1957 finally:
1958 SimpleNewObj = save
1959
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001960 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001961 # an object of that type. Check that the resulting pickle uses opcode
1962 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001963
Tim Peters22e71712003-02-03 22:27:38 +00001964 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001965 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001966 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001967 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001968 x = MyList([1, 2, 3])
1969 x.foo = 42
1970 x.bar = "hello"
1971
Tim Peters22e71712003-02-03 22:27:38 +00001972 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001973 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001974 self.assertIn(__name__.encode("utf-8"), s1)
1975 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001976 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001977
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001978 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001979 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001980
Tim Peters22e71712003-02-03 22:27:38 +00001981 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001982 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001983 self.assertNotIn(__name__.encode("utf-8"), s2)
1984 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001985 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001986
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001987 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001988 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001989 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001990 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001991
1992 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001993 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1994 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001995
1996 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001997 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1998 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1999 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002000
2001 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00002002 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
2003 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
2004 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
2005
Tim Peters8d2613a2003-02-11 16:40:16 +00002006 def test_list_chunking(self):
2007 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00002008 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002009 for proto in protocols:
2010 s = self.dumps(x, proto)
2011 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002012 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002013 num_appends = count_opcode(pickle.APPENDS, s)
2014 self.assertEqual(num_appends, proto > 0)
2015
2016 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00002017 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002018 for proto in protocols:
2019 s = self.dumps(x, proto)
2020 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002021 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002022 num_appends = count_opcode(pickle.APPENDS, s)
2023 if proto == 0:
2024 self.assertEqual(num_appends, 0)
2025 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002026 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002027
2028 def test_dict_chunking(self):
2029 n = 10 # too small to chunk
2030 x = dict.fromkeys(range(n))
2031 for proto in protocols:
2032 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002033 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002034 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002035 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002036 num_setitems = count_opcode(pickle.SETITEMS, s)
2037 self.assertEqual(num_setitems, proto > 0)
2038
2039 n = 2500 # expect at least two chunks when proto > 0
2040 x = dict.fromkeys(range(n))
2041 for proto in protocols:
2042 s = self.dumps(x, proto)
2043 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002044 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002045 num_setitems = count_opcode(pickle.SETITEMS, s)
2046 if proto == 0:
2047 self.assertEqual(num_setitems, 0)
2048 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002049 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002050
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002051 def test_set_chunking(self):
2052 n = 10 # too small to chunk
2053 x = set(range(n))
2054 for proto in protocols:
2055 s = self.dumps(x, proto)
2056 y = self.loads(s)
2057 self.assert_is_copy(x, y)
2058 num_additems = count_opcode(pickle.ADDITEMS, s)
2059 if proto < 4:
2060 self.assertEqual(num_additems, 0)
2061 else:
2062 self.assertEqual(num_additems, 1)
2063
2064 n = 2500 # expect at least two chunks when proto >= 4
2065 x = set(range(n))
2066 for proto in protocols:
2067 s = self.dumps(x, proto)
2068 y = self.loads(s)
2069 self.assert_is_copy(x, y)
2070 num_additems = count_opcode(pickle.ADDITEMS, s)
2071 if proto < 4:
2072 self.assertEqual(num_additems, 0)
2073 else:
2074 self.assertGreaterEqual(num_additems, 2)
2075
Tim Peterse9ef2032003-02-13 18:42:00 +00002076 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002077 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002078 x.abc = 666
2079 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002080 with self.subTest(proto=proto):
2081 s = self.dumps(x, proto)
2082 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002083 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002084 else:
2085 self.assertIn(b'M\xce\xfa', s) # BININT2
2086 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2087 2 <= proto)
2088 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2089 y = self.loads(s) # will raise TypeError if __init__ called
2090 self.assert_is_copy(x, y)
2091
2092 def test_complex_newobj(self):
2093 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2094 x.abc = 666
2095 for proto in protocols:
2096 with self.subTest(proto=proto):
2097 s = self.dumps(x, proto)
2098 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002099 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002100 elif proto < 2:
2101 self.assertIn(b'M\xce\xfa', s) # BININT2
2102 elif proto < 4:
2103 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2104 else:
2105 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2106 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2107 2 <= proto)
2108 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2109 y = self.loads(s) # will raise TypeError if __init__ called
2110 self.assert_is_copy(x, y)
2111
2112 def test_complex_newobj_ex(self):
2113 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2114 x.abc = 666
2115 for proto in protocols:
2116 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002117 s = self.dumps(x, proto)
2118 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002119 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002120 elif proto < 2:
2121 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002122 elif proto < 4:
2123 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002124 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002125 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2126 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2127 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2128 4 <= proto)
2129 y = self.loads(s) # will raise TypeError if __init__ called
2130 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002131
Tim Peters42f08ac2003-02-11 22:43:24 +00002132 def test_newobj_list_slots(self):
2133 x = SlotList([1, 2, 3])
2134 x.foo = 42
2135 x.bar = "hello"
2136 s = self.dumps(x, 2)
2137 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002138 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002139
Guido van Rossum2a30b212003-02-18 22:41:24 +00002140 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002141 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002142 x = REX_one()
2143 self.assertEqual(x._reduce_called, 0)
2144 s = self.dumps(x, proto)
2145 self.assertEqual(x._reduce_called, 1)
2146 y = self.loads(s)
2147 self.assertEqual(y._reduce_called, 0)
2148
2149 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002150 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002151 x = REX_two()
2152 self.assertEqual(x._proto, None)
2153 s = self.dumps(x, proto)
2154 self.assertEqual(x._proto, proto)
2155 y = self.loads(s)
2156 self.assertEqual(y._proto, None)
2157
2158 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002159 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002160 x = REX_three()
2161 self.assertEqual(x._proto, None)
2162 s = self.dumps(x, proto)
2163 self.assertEqual(x._proto, proto)
2164 y = self.loads(s)
2165 self.assertEqual(y._proto, None)
2166
Guido van Rossumd8faa362007-04-27 19:54:29 +00002167 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002168 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002169 x = REX_four()
2170 self.assertEqual(x._proto, None)
2171 s = self.dumps(x, proto)
2172 self.assertEqual(x._proto, proto)
2173 y = self.loads(s)
2174 self.assertEqual(y._proto, proto)
2175
2176 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002177 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002178 x = REX_five()
2179 self.assertEqual(x._reduce_called, 0)
2180 s = self.dumps(x, proto)
2181 self.assertEqual(x._reduce_called, 1)
2182 y = self.loads(s)
2183 self.assertEqual(y._reduce_called, 1)
2184
Brett Cannon31f59292011-02-21 19:29:56 +00002185 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002186 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002187 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002188 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002189 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002190 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002191
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002192 def test_reduce_bad_iterator(self):
2193 # Issue4176: crash when 4th and 5th items of __reduce__()
2194 # are not iterators
2195 class C(object):
2196 def __reduce__(self):
2197 # 4th item is not an iterator
2198 return list, (), None, [], None
2199 class D(object):
2200 def __reduce__(self):
2201 # 5th item is not an iterator
2202 return dict, (), None, None, []
2203
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002204 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002205 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002206 try:
2207 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002208 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002209 pass
2210 try:
2211 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002212 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002213 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002214
Collin Winter771d8342009-04-16 03:18:06 +00002215 def test_many_puts_and_gets(self):
2216 # Test that internal data structures correctly deal with lots of
2217 # puts/gets.
2218 keys = ("aaa" + str(i) for i in range(100))
2219 large_dict = dict((k, [4, 5, 6]) for k in keys)
2220 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2221
2222 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002223 with self.subTest(proto=proto):
2224 dumped = self.dumps(obj, proto)
2225 loaded = self.loads(dumped)
2226 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002227
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002228 def test_attribute_name_interning(self):
2229 # Test that attribute names of pickled objects are interned when
2230 # unpickling.
2231 for proto in protocols:
2232 x = C()
2233 x.foo = 42
2234 x.bar = "hello"
2235 s = self.dumps(x, proto)
2236 y = self.loads(s)
2237 x_keys = sorted(x.__dict__)
2238 y_keys = sorted(y.__dict__)
2239 for x_key, y_key in zip(x_keys, y_keys):
2240 self.assertIs(x_key, y_key)
2241
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002242 def test_pickle_to_2x(self):
2243 # Pickle non-trivial data with protocol 2, expecting that it yields
2244 # the same result as Python 2.x did.
2245 # NOTE: this test is a bit too strong since we can produce different
2246 # bytecode that 2.x will still understand.
2247 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002248 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002249 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002250 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002251
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002252 def test_large_pickles(self):
2253 # Test the correctness of internal buffering routines when handling
2254 # large data.
2255 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002256 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002257 dumped = self.dumps(data, proto)
2258 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002259 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002260 self.assertEqual(loaded, data)
2261
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002262 def test_int_pickling_efficiency(self):
2263 # Test compacity of int representation (see issue #12744)
2264 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002265 with self.subTest(proto=proto):
2266 pickles = [self.dumps(2**n, proto) for n in range(70)]
2267 sizes = list(map(len, pickles))
2268 # the size function is monotonic
2269 self.assertEqual(sorted(sizes), sizes)
2270 if proto >= 2:
2271 for p in pickles:
2272 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002273
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002274 def _check_pickling_with_opcode(self, obj, opcode, proto):
2275 pickled = self.dumps(obj, proto)
2276 self.assertTrue(opcode_in_pickle(opcode, pickled))
2277 unpickled = self.loads(pickled)
2278 self.assertEqual(obj, unpickled)
2279
2280 def test_appends_on_non_lists(self):
2281 # Issue #17720
2282 obj = REX_six([1, 2, 3])
2283 for proto in protocols:
2284 if proto == 0:
2285 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2286 else:
2287 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2288
2289 def test_setitems_on_non_dicts(self):
2290 obj = REX_seven({1: -1, 2: -2, 3: -3})
2291 for proto in protocols:
2292 if proto == 0:
2293 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2294 else:
2295 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2296
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002297 # Exercise framing (proto >= 4) for significant workloads
2298
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002299 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002300 FRAME_SIZE_TARGET = 64 * 1024
2301
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002302 def check_frame_opcodes(self, pickled):
2303 """
2304 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002305
2306 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2307 framed by default and are therefore considered a frame by themselves in
2308 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002309 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002310 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002311 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2312 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002313 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002314 if frame_end is not None:
2315 self.assertLessEqual(pos, frame_end)
2316 if pos == frame_end:
2317 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002318
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002319 if frame_end is not None: # framed
2320 self.assertNotEqual(op.name, 'FRAME')
2321 if op.name in frameless_opcodes:
2322 # Only short bytes and str objects should be written
2323 # in a frame
2324 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2325
2326 else: # not framed
2327 if (op.name == 'FRAME' or
2328 (op.name in frameless_opcodes and
2329 len(arg) > self.FRAME_SIZE_TARGET)):
2330 # Frame or large bytes or str object
2331 if frameless_start is not None:
2332 # Only short data should be written outside of a frame
2333 self.assertLess(pos - frameless_start,
2334 self.FRAME_SIZE_MIN)
2335 frameless_start = None
2336 elif frameless_start is None and op.name != 'PROTO':
2337 frameless_start = pos
2338
2339 if op.name == 'FRAME':
2340 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2341 frame_end = pos + 9 + arg
2342
2343 pos = len(pickled)
2344 if frame_end is not None:
2345 self.assertEqual(frame_end, pos)
2346 elif frameless_start is not None:
2347 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002348
Miss Islington (bot)382cb852019-07-30 11:34:33 -07002349 @support.skip_if_pgo_task
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002350 def test_framing_many_objects(self):
2351 obj = list(range(10**5))
2352 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2353 with self.subTest(proto=proto):
2354 pickled = self.dumps(obj, proto)
2355 unpickled = self.loads(pickled)
2356 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002357 bytes_per_frame = (len(pickled) /
2358 count_opcode(pickle.FRAME, pickled))
2359 self.assertGreater(bytes_per_frame,
2360 self.FRAME_SIZE_TARGET / 2)
2361 self.assertLessEqual(bytes_per_frame,
2362 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002363 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002364
2365 def test_framing_large_objects(self):
2366 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002367 small_items = [[i] for i in range(10)]
2368 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002369 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002370 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002371 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002372 if not fast:
2373 # fast=False by default.
2374 # This covers in-memory pickling with pickle.dumps().
2375 pickled = self.dumps(obj, proto)
2376 else:
2377 # Pickler is required when fast=True.
2378 if not hasattr(self, 'pickler'):
2379 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002380 buf = io.BytesIO()
2381 pickler = self.pickler(buf, protocol=proto)
2382 pickler.fast = fast
2383 pickler.dump(obj)
2384 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002385 unpickled = self.loads(pickled)
2386 # More informative error message in case of failure.
2387 self.assertEqual([len(x) for x in obj],
2388 [len(x) for x in unpickled])
2389 # Perform full equality check if the lengths match.
2390 self.assertEqual(obj, unpickled)
2391 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002392 # A single frame for small objects between
2393 # first two large objects.
2394 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002395 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002396
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002397 def test_optional_frames(self):
2398 if pickle.HIGHEST_PROTOCOL < 4:
2399 return
2400
2401 def remove_frames(pickled, keep_frame=None):
2402 """Remove frame opcodes from the given pickle."""
2403 frame_starts = []
2404 # 1 byte for the opcode and 8 for the argument
2405 frame_opcode_size = 9
2406 for opcode, _, pos in pickletools.genops(pickled):
2407 if opcode.name == 'FRAME':
2408 frame_starts.append(pos)
2409
2410 newpickle = bytearray()
2411 last_frame_end = 0
2412 for i, pos in enumerate(frame_starts):
2413 if keep_frame and keep_frame(i):
2414 continue
2415 newpickle += pickled[last_frame_end:pos]
2416 last_frame_end = pos + frame_opcode_size
2417 newpickle += pickled[last_frame_end:]
2418 return newpickle
2419
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002420 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002421 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002422 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002423 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002424 for bytes_type in (bytes, bytearray):
2425 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002426
Antoine Pitrou91f43802019-05-26 17:10:09 +02002427 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2428 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002429
Antoine Pitrou91f43802019-05-26 17:10:09 +02002430 frameless_pickle = remove_frames(pickled)
2431 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2432 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002433
Antoine Pitrou91f43802019-05-26 17:10:09 +02002434 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2435 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2436 count_opcode(pickle.FRAME, pickled))
2437 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002438
Miss Islington (bot)382cb852019-07-30 11:34:33 -07002439 @support.skip_if_pgo_task
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002440 def test_framed_write_sizes_with_delayed_writer(self):
2441 class ChunkAccumulator:
2442 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002443 def __init__(self):
2444 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002445 def write(self, chunk):
2446 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002447 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002448 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002449
2450 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002451 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2452 for i in range(int(1e4))]
2453 # Add a large unique ASCII string
2454 objects.append('0123456789abcdef' *
2455 (self.FRAME_SIZE_TARGET // 16 + 1))
2456
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002457 # Protocol 4 packs groups of small objects into frames and issues
2458 # calls to write only once or twice per frame:
2459 # The C pickler issues one call to write per-frame (header and
2460 # contents) while Python pickler issues two calls to write: one for
2461 # the frame header and one for the frame binary contents.
2462 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002463 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002464
2465 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002466 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002467 # be released otherwise this delayed access would not be possible.
2468 pickled = writer.concatenate_chunks()
2469 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002470 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002471 self.assertGreater(len(writer.chunks), 1)
2472
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002473 # memoryviews should own the memory.
2474 del objects
2475 support.gc_collect()
2476 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002477
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002478 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002479 # There should be at least one call to write per frame
2480 self.assertGreaterEqual(len(writer.chunks), n_frames)
2481
2482 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002483 # one per-frame header, one per frame for the actual contents,
2484 # and two for the header.
2485 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002486
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002487 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002488 large_sizes = [s for s in chunk_sizes
2489 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002490 medium_sizes = [s for s in chunk_sizes
2491 if 9 < s < self.FRAME_SIZE_TARGET]
2492 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002493
2494 # Large chunks should not be too large:
2495 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002496 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2497 chunk_sizes)
2498 # There shouldn't bee too many small chunks: the protocol header,
2499 # the frame headers and the large string headers are written
2500 # in small chunks.
2501 self.assertLessEqual(len(small_sizes),
2502 len(large_sizes) + len(medium_sizes) + 3,
2503 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002504
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002505 def test_nested_names(self):
2506 global Nested
2507 class Nested:
2508 class A:
2509 class B:
2510 class C:
2511 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002512 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002513 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2514 with self.subTest(proto=proto, obj=obj):
2515 unpickled = self.loads(self.dumps(obj, proto))
2516 self.assertIs(obj, unpickled)
2517
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002518 def test_recursive_nested_names(self):
2519 global Recursive
2520 class Recursive:
2521 pass
2522 Recursive.mod = sys.modules[Recursive.__module__]
2523 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2524 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2525 with self.subTest(proto=proto):
2526 unpickled = self.loads(self.dumps(Recursive, proto))
2527 self.assertIs(unpickled, Recursive)
2528 del Recursive.mod # break reference loop
2529
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002530 def test_py_methods(self):
2531 global PyMethodsTest
2532 class PyMethodsTest:
2533 @staticmethod
2534 def cheese():
2535 return "cheese"
2536 @classmethod
2537 def wine(cls):
2538 assert cls is PyMethodsTest
2539 return "wine"
2540 def biscuits(self):
2541 assert isinstance(self, PyMethodsTest)
2542 return "biscuits"
2543 class Nested:
2544 "Nested class"
2545 @staticmethod
2546 def ketchup():
2547 return "ketchup"
2548 @classmethod
2549 def maple(cls):
2550 assert cls is PyMethodsTest.Nested
2551 return "maple"
2552 def pie(self):
2553 assert isinstance(self, PyMethodsTest.Nested)
2554 return "pie"
2555
2556 py_methods = (
2557 PyMethodsTest.cheese,
2558 PyMethodsTest.wine,
2559 PyMethodsTest().biscuits,
2560 PyMethodsTest.Nested.ketchup,
2561 PyMethodsTest.Nested.maple,
2562 PyMethodsTest.Nested().pie
2563 )
2564 py_unbound_methods = (
2565 (PyMethodsTest.biscuits, PyMethodsTest),
2566 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2567 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002568 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002569 for method in py_methods:
2570 with self.subTest(proto=proto, method=method):
2571 unpickled = self.loads(self.dumps(method, proto))
2572 self.assertEqual(method(), unpickled())
2573 for method, cls in py_unbound_methods:
2574 obj = cls()
2575 with self.subTest(proto=proto, method=method):
2576 unpickled = self.loads(self.dumps(method, proto))
2577 self.assertEqual(method(obj), unpickled(obj))
2578
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002579 def test_c_methods(self):
2580 global Subclass
2581 class Subclass(tuple):
2582 class Nested(str):
2583 pass
2584
2585 c_methods = (
2586 # bound built-in method
2587 ("abcd".index, ("c",)),
2588 # unbound built-in method
2589 (str.index, ("abcd", "c")),
2590 # bound "slot" method
2591 ([1, 2, 3].__len__, ()),
2592 # unbound "slot" method
2593 (list.__len__, ([1, 2, 3],)),
2594 # bound "coexist" method
2595 ({1, 2}.__contains__, (2,)),
2596 # unbound "coexist" method
2597 (set.__contains__, ({1, 2}, 2)),
2598 # built-in class method
2599 (dict.fromkeys, (("a", 1), ("b", 2))),
2600 # built-in static method
2601 (bytearray.maketrans, (b"abc", b"xyz")),
2602 # subclass methods
2603 (Subclass([1,2,2]).count, (2,)),
2604 (Subclass.count, (Subclass([1,2,2]), 2)),
2605 (Subclass.Nested("sweet").count, ("e",)),
2606 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2607 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002608 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002609 for method, args in c_methods:
2610 with self.subTest(proto=proto, method=method):
2611 unpickled = self.loads(self.dumps(method, proto))
2612 self.assertEqual(method(*args), unpickled(*args))
2613
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002614 def test_compat_pickle(self):
2615 tests = [
2616 (range(1, 7), '__builtin__', 'xrange'),
2617 (map(int, '123'), 'itertools', 'imap'),
2618 (functools.reduce, '__builtin__', 'reduce'),
2619 (dbm.whichdb, 'whichdb', 'whichdb'),
2620 (Exception(), 'exceptions', 'Exception'),
2621 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2622 (collections.UserList(), 'UserList', 'UserList'),
2623 (collections.defaultdict(), 'collections', 'defaultdict'),
2624 ]
2625 for val, mod, name in tests:
2626 for proto in range(3):
2627 with self.subTest(type=type(val), proto=proto):
2628 pickled = self.dumps(val, proto)
2629 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2630 self.assertIs(type(self.loads(pickled)), type(val))
2631
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002632 def test_local_lookup_error(self):
2633 # Test that whichmodule() errors out cleanly when looking up
2634 # an assumed globally-reachable object fails.
2635 def f():
2636 pass
2637 # Since the function is local, lookup will fail
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 # Same without a __module__ attribute (exercises a different path
2642 # in _pickle.c).
2643 del f.__module__
2644 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2645 with self.assertRaises((AttributeError, pickle.PicklingError)):
2646 pickletools.dis(self.dumps(f, proto))
2647 # Yet a different path.
2648 f.__name__ = f.__qualname__
2649 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2650 with self.assertRaises((AttributeError, pickle.PicklingError)):
2651 pickletools.dis(self.dumps(f, proto))
2652
Antoine Pitrou91f43802019-05-26 17:10:09 +02002653 #
2654 # PEP 574 tests below
2655 #
2656
2657 def buffer_like_objects(self):
2658 # Yield buffer-like objects with the bytestring "abcdef" in them
2659 bytestring = b"abcdefgh"
2660 yield ZeroCopyBytes(bytestring)
2661 yield ZeroCopyBytearray(bytestring)
2662 if _testbuffer is not None:
2663 items = list(bytestring)
2664 value = int.from_bytes(bytestring, byteorder='little')
2665 for flags in (0, _testbuffer.ND_WRITABLE):
2666 # 1-D, contiguous
2667 yield PicklableNDArray(items, format='B', shape=(8,),
2668 flags=flags)
2669 # 2-D, C-contiguous
2670 yield PicklableNDArray(items, format='B', shape=(4, 2),
2671 strides=(2, 1), flags=flags)
2672 # 2-D, Fortran-contiguous
2673 yield PicklableNDArray(items, format='B',
2674 shape=(4, 2), strides=(1, 4),
2675 flags=flags)
2676
2677 def test_in_band_buffers(self):
2678 # Test in-band buffers (PEP 574)
2679 for obj in self.buffer_like_objects():
2680 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2681 data = self.dumps(obj, proto)
2682 if obj.c_contiguous and proto >= 5:
2683 # The raw memory bytes are serialized in physical order
2684 self.assertIn(b"abcdefgh", data)
2685 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2686 if proto >= 5:
2687 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2688 1 if obj.readonly else 0)
2689 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2690 0 if obj.readonly else 1)
2691 # Return a true value from buffer_callback should have
2692 # the same effect
2693 def buffer_callback(obj):
2694 return True
2695 data2 = self.dumps(obj, proto,
2696 buffer_callback=buffer_callback)
2697 self.assertEqual(data2, data)
2698
2699 new = self.loads(data)
2700 # It's a copy
2701 self.assertIsNot(new, obj)
2702 self.assertIs(type(new), type(obj))
2703 self.assertEqual(new, obj)
2704
2705 # XXX Unfortunately cannot test non-contiguous array
2706 # (see comment in PicklableNDArray.__reduce_ex__)
2707
2708 def test_oob_buffers(self):
2709 # Test out-of-band buffers (PEP 574)
2710 for obj in self.buffer_like_objects():
2711 for proto in range(0, 5):
2712 # Need protocol >= 5 for buffer_callback
2713 with self.assertRaises(ValueError):
2714 self.dumps(obj, proto,
2715 buffer_callback=[].append)
2716 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2717 buffers = []
2718 buffer_callback = lambda pb: buffers.append(pb.raw())
2719 data = self.dumps(obj, proto,
2720 buffer_callback=buffer_callback)
2721 self.assertNotIn(b"abcdefgh", data)
2722 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2723 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2724 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2725 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2726 1 if obj.readonly else 0)
2727
2728 if obj.c_contiguous:
2729 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2730 # Need buffers argument to unpickle properly
2731 with self.assertRaises(pickle.UnpicklingError):
2732 self.loads(data)
2733
2734 new = self.loads(data, buffers=buffers)
2735 if obj.zero_copy_reconstruct:
2736 # Zero-copy achieved
2737 self.assertIs(new, obj)
2738 else:
2739 self.assertIs(type(new), type(obj))
2740 self.assertEqual(new, obj)
2741 # Non-sequence buffers accepted too
2742 new = self.loads(data, buffers=iter(buffers))
2743 if obj.zero_copy_reconstruct:
2744 # Zero-copy achieved
2745 self.assertIs(new, obj)
2746 else:
2747 self.assertIs(type(new), type(obj))
2748 self.assertEqual(new, obj)
2749
2750 def test_oob_buffers_writable_to_readonly(self):
2751 # Test reconstructing readonly object from writable buffer
2752 obj = ZeroCopyBytes(b"foobar")
2753 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2754 buffers = []
2755 buffer_callback = buffers.append
2756 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2757
2758 buffers = map(bytearray, buffers)
2759 new = self.loads(data, buffers=buffers)
2760 self.assertIs(type(new), type(obj))
2761 self.assertEqual(new, obj)
2762
2763 def test_picklebuffer_error(self):
2764 # PickleBuffer forbidden with protocol < 5
2765 pb = pickle.PickleBuffer(b"foobar")
2766 for proto in range(0, 5):
2767 with self.assertRaises(pickle.PickleError):
2768 self.dumps(pb, proto)
2769
2770 def test_buffer_callback_error(self):
2771 def buffer_callback(buffers):
2772 1/0
2773 pb = pickle.PickleBuffer(b"foobar")
2774 with self.assertRaises(ZeroDivisionError):
2775 self.dumps(pb, 5, buffer_callback=buffer_callback)
2776
2777 def test_buffers_error(self):
2778 pb = pickle.PickleBuffer(b"foobar")
2779 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2780 data = self.dumps(pb, proto, buffer_callback=[].append)
2781 # Non iterable buffers
2782 with self.assertRaises(TypeError):
2783 self.loads(data, buffers=object())
2784 # Buffer iterable exhausts too early
2785 with self.assertRaises(pickle.UnpicklingError):
2786 self.loads(data, buffers=[])
2787
Miss Islington (bot)25cb4fd2019-07-25 09:18:20 -07002788 def test_inband_accept_default_buffers_argument(self):
2789 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2790 data_pickled = self.dumps(1, proto, buffer_callback=None)
2791 data = self.loads(data_pickled, buffers=None)
2792
Antoine Pitrou91f43802019-05-26 17:10:09 +02002793 @unittest.skipIf(np is None, "Test needs Numpy")
2794 def test_buffers_numpy(self):
2795 def check_no_copy(x, y):
2796 np.testing.assert_equal(x, y)
2797 self.assertEqual(x.ctypes.data, y.ctypes.data)
2798
2799 def check_copy(x, y):
2800 np.testing.assert_equal(x, y)
2801 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2802
2803 def check_array(arr):
2804 # In-band
2805 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2806 data = self.dumps(arr, proto)
2807 new = self.loads(data)
2808 check_copy(arr, new)
2809 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2810 buffer_callback = lambda _: True
2811 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2812 new = self.loads(data)
2813 check_copy(arr, new)
2814 # Out-of-band
2815 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2816 buffers = []
2817 buffer_callback = buffers.append
2818 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2819 new = self.loads(data, buffers=buffers)
2820 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2821 check_no_copy(arr, new)
2822 else:
2823 check_copy(arr, new)
2824
2825 # 1-D
2826 arr = np.arange(6)
2827 check_array(arr)
2828 # 1-D, non-contiguous
2829 check_array(arr[::2])
2830 # 2-D, C-contiguous
2831 arr = np.arange(12).reshape((3, 4))
2832 check_array(arr)
2833 # 2-D, F-contiguous
2834 check_array(arr.T)
2835 # 2-D, non-contiguous
2836 check_array(arr[::2])
2837
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002838
2839class BigmemPickleTests(unittest.TestCase):
2840
Victor Stinner8c663fd2017-11-08 14:44:44 -08002841 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002842
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002843 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002844 def test_huge_long_32b(self, size):
2845 data = 1 << (8 * size)
2846 try:
2847 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002848 if proto < 2:
2849 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002850 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002851 with self.assertRaises((ValueError, OverflowError)):
2852 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002853 finally:
2854 data = None
2855
Victor Stinner8c663fd2017-11-08 14:44:44 -08002856 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002857 # (older protocols don't have a dedicated opcode for bytes and are
2858 # too inefficient)
2859
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002860 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002861 def test_huge_bytes_32b(self, size):
2862 data = b"abcd" * (size // 4)
2863 try:
2864 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002865 if proto < 3:
2866 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002867 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002868 try:
2869 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002870 header = (pickle.BINBYTES +
2871 struct.pack("<I", len(data)))
2872 data_start = pickled.index(data)
2873 self.assertEqual(
2874 header,
2875 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002876 finally:
2877 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002878 finally:
2879 data = None
2880
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002881 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002882 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002883 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002884 try:
2885 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002886 if proto < 3:
2887 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002888 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002889 if proto == 3:
2890 # Protocol 3 does not support large bytes objects.
2891 # Verify that we do not crash when processing one.
2892 with self.assertRaises((ValueError, OverflowError)):
2893 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002894 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002895 try:
2896 pickled = self.dumps(data, protocol=proto)
2897 header = (pickle.BINBYTES8 +
2898 struct.pack("<Q", len(data)))
2899 data_start = pickled.index(data)
2900 self.assertEqual(
2901 header,
2902 pickled[data_start-len(header):data_start])
2903 finally:
2904 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002905 finally:
2906 data = None
2907
2908 # All protocols use 1-byte per printable ASCII character; we add another
2909 # byte because the encoded form has to be copied into the internal buffer.
2910
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002911 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002912 def test_huge_str_32b(self, size):
2913 data = "abcd" * (size // 4)
2914 try:
2915 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002916 if proto == 0:
2917 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002918 with self.subTest(proto=proto):
2919 try:
2920 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002921 header = (pickle.BINUNICODE +
2922 struct.pack("<I", len(data)))
2923 data_start = pickled.index(b'abcd')
2924 self.assertEqual(
2925 header,
2926 pickled[data_start-len(header):data_start])
2927 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2928 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002929 finally:
2930 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002931 finally:
2932 data = None
2933
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002934 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2935 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2936 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002937
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002938 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002939 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002940 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002941 try:
2942 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002943 if proto == 0:
2944 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002945 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002946 if proto < 4:
2947 with self.assertRaises((ValueError, OverflowError)):
2948 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002949 continue
2950 try:
2951 pickled = self.dumps(data, protocol=proto)
2952 header = (pickle.BINUNICODE8 +
2953 struct.pack("<Q", len(data)))
2954 data_start = pickled.index(b'abcd')
2955 self.assertEqual(
2956 header,
2957 pickled[data_start-len(header):data_start])
2958 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2959 pickled.index(b"abcd")), len(data))
2960 finally:
2961 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002962 finally:
2963 data = None
2964
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002965
Guido van Rossum2a30b212003-02-18 22:41:24 +00002966# Test classes for reduce_ex
2967
2968class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002969 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002970 _reduce_called = 0
2971 def __reduce__(self):
2972 self._reduce_called = 1
2973 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002974
2975class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002976 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002977 _proto = None
2978 def __reduce_ex__(self, proto):
2979 self._proto = proto
2980 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002981
2982class REX_three(object):
2983 _proto = None
2984 def __reduce_ex__(self, proto):
2985 self._proto = proto
2986 return REX_two, ()
2987 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002988 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002989
Guido van Rossumd8faa362007-04-27 19:54:29 +00002990class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002991 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002992 _proto = None
2993 def __reduce_ex__(self, proto):
2994 self._proto = proto
2995 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002996
2997class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002998 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002999 _reduce_called = 0
3000 def __reduce__(self):
3001 self._reduce_called = 1
3002 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003003
3004class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003005 """This class is used to check the 4th argument (list iterator) of
3006 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003007 """
3008 def __init__(self, items=None):
3009 self.items = items if items is not None else []
3010 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003011 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003012 def append(self, item):
3013 self.items.append(item)
3014 def __reduce__(self):
3015 return type(self), (), None, iter(self.items), None
3016
3017class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003018 """This class is used to check the 5th argument (dict iterator) of
3019 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003020 """
3021 def __init__(self, table=None):
3022 self.table = table if table is not None else {}
3023 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02003024 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003025 def __setitem__(self, key, value):
3026 self.table[key] = value
3027 def __reduce__(self):
3028 return type(self), (), None, None, iter(self.table.items())
3029
Guido van Rossumd8faa362007-04-27 19:54:29 +00003030
Guido van Rossum2a30b212003-02-18 22:41:24 +00003031# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003032
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003033class MyInt(int):
3034 sample = 1
3035
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003036class MyFloat(float):
3037 sample = 1.0
3038
3039class MyComplex(complex):
3040 sample = 1.0 + 0.0j
3041
3042class MyStr(str):
3043 sample = "hello"
3044
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003045class MyUnicode(str):
3046 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003047
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003048class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003049 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003050
3051class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003052 sample = [1, 2, 3]
3053
3054class MyDict(dict):
3055 sample = {"a": 1, "b": 2}
3056
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003057class MySet(set):
3058 sample = {"a", "b"}
3059
3060class MyFrozenSet(frozenset):
3061 sample = frozenset({"a", "b"})
3062
Mark Dickinson5c2db372009-12-05 20:28:34 +00003063myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003064 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003065 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003066 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003067
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003068
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003069class SlotList(MyList):
3070 __slots__ = ["foo"]
3071
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003072class SimpleNewObj(int):
3073 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003074 # raise an error, to make sure this isn't called
3075 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003076 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003077 return int(self) == int(other) and self.__dict__ == other.__dict__
3078
3079class ComplexNewObj(SimpleNewObj):
3080 def __getnewargs__(self):
3081 return ('%X' % self, 16)
3082
3083class ComplexNewObjEx(SimpleNewObj):
3084 def __getnewargs_ex__(self):
3085 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003086
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003087class BadGetattr:
3088 def __getattr__(self, key):
3089 self.foo
3090
Collin Winter771d8342009-04-16 03:18:06 +00003091
Jeremy Hylton66426532001-10-15 21:38:56 +00003092class AbstractPickleModuleTests(unittest.TestCase):
3093
3094 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003095 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003096 try:
3097 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003098 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003099 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003100 support.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003101
3102 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003103 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003104 try:
3105 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003106 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003107 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003108 support.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003109
Collin Winter771d8342009-04-16 03:18:06 +00003110 def test_load_from_and_dump_to_file(self):
3111 stream = io.BytesIO()
3112 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003113 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003114 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003115 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003116 self.assertEqual(unpickled, data)
3117
Tim Petersc0c93702003-02-13 19:30:57 +00003118 def test_highest_protocol(self):
3119 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003120 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003121
Martin v. Löwis544f1192004-07-27 05:22:33 +00003122 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003123 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003124 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003125 self.dump(123, f, -1)
3126 self.dump(123, file=f, protocol=-1)
3127 self.dumps(123, -1)
3128 self.dumps(123, protocol=-1)
3129 self.Pickler(f, -1)
3130 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003131
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003132 def test_dump_text_file(self):
3133 f = open(TESTFN, "w")
3134 try:
3135 for proto in protocols:
3136 self.assertRaises(TypeError, self.dump, 123, f, proto)
3137 finally:
3138 f.close()
3139 support.unlink(TESTFN)
3140
3141 def test_incomplete_input(self):
3142 s = io.BytesIO(b"X''.")
3143 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3144
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003145 def test_bad_init(self):
3146 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003147 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003148 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003149 def __init__(self): pass
3150
Serhiy Storchaka65452562017-11-15 14:01:08 +02003151 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003152 def __init__(self): pass
3153
3154 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3155 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3156
Antoine Pitrou91f43802019-05-26 17:10:09 +02003157 def check_dumps_loads_oob_buffers(self, dumps, loads):
3158 # No need to do the full gamut of tests here, just enough to
3159 # check that dumps() and loads() redirect their arguments
3160 # to the underlying Pickler and Unpickler, respectively.
3161 obj = ZeroCopyBytes(b"foo")
3162
3163 for proto in range(0, 5):
3164 # Need protocol >= 5 for buffer_callback
3165 with self.assertRaises(ValueError):
3166 dumps(obj, protocol=proto,
3167 buffer_callback=[].append)
3168 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3169 buffers = []
3170 buffer_callback = buffers.append
3171 data = dumps(obj, protocol=proto,
3172 buffer_callback=buffer_callback)
3173 self.assertNotIn(b"foo", data)
3174 self.assertEqual(bytes(buffers[0]), b"foo")
3175 # Need buffers argument to unpickle properly
3176 with self.assertRaises(pickle.UnpicklingError):
3177 loads(data)
3178 new = loads(data, buffers=buffers)
3179 self.assertIs(new, obj)
3180
3181 def test_dumps_loads_oob_buffers(self):
3182 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3183 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3184
3185 def test_dump_load_oob_buffers(self):
3186 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3187 def dumps(obj, **kwargs):
3188 f = io.BytesIO()
3189 self.dump(obj, f, **kwargs)
3190 return f.getvalue()
3191
3192 def loads(data, **kwargs):
3193 f = io.BytesIO(data)
3194 return self.load(f, **kwargs)
3195
3196 self.check_dumps_loads_oob_buffers(dumps, loads)
3197
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003198
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003199class AbstractPersistentPicklerTests(unittest.TestCase):
3200
3201 # This class defines persistent_id() and persistent_load()
3202 # functions that should be used by the pickler. All even integers
3203 # are pickled using persistent ids.
3204
3205 def persistent_id(self, object):
3206 if isinstance(object, int) and object % 2 == 0:
3207 self.id_count += 1
3208 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003209 elif object == "test_false_value":
3210 self.false_count += 1
3211 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003212 else:
3213 return None
3214
3215 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003216 if not oid:
3217 self.load_false_count += 1
3218 return "test_false_value"
3219 else:
3220 self.load_count += 1
3221 object = int(oid)
3222 assert object % 2 == 0
3223 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003224
3225 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003226 L = list(range(10)) + ["test_false_value"]
3227 for proto in protocols:
3228 self.id_count = 0
3229 self.false_count = 0
3230 self.load_false_count = 0
3231 self.load_count = 0
3232 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3233 self.assertEqual(self.id_count, 5)
3234 self.assertEqual(self.false_count, 1)
3235 self.assertEqual(self.load_count, 5)
3236 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003237
Collin Winter771d8342009-04-16 03:18:06 +00003238
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003239class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3240
3241 def persistent_id(self, obj):
3242 return obj
3243
3244 def persistent_load(self, pid):
3245 return pid
3246
3247 def _check_return_correct_type(self, obj, proto):
3248 unpickled = self.loads(self.dumps(obj, proto))
3249 self.assertIsInstance(unpickled, type(obj))
3250 self.assertEqual(unpickled, obj)
3251
3252 def test_return_correct_type(self):
3253 for proto in protocols:
3254 # Protocol 0 supports only ASCII strings.
3255 if proto == 0:
3256 self._check_return_correct_type("abc", 0)
3257 else:
3258 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3259 self._check_return_correct_type(obj, proto)
3260
3261 def test_protocol0_is_ascii_only(self):
3262 non_ascii_str = "\N{EMPTY SET}"
3263 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3264 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3265 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3266
3267
Collin Winter771d8342009-04-16 03:18:06 +00003268class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3269
3270 pickler_class = None
3271 unpickler_class = None
3272
3273 def setUp(self):
3274 assert self.pickler_class
3275 assert self.unpickler_class
3276
3277 def test_clear_pickler_memo(self):
3278 # To test whether clear_memo() has any effect, we pickle an object,
3279 # then pickle it again without clearing the memo; the two serialized
3280 # forms should be different. If we clear_memo() and then pickle the
3281 # object again, the third serialized form should be identical to the
3282 # first one we obtained.
3283 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003284 for proto in protocols:
3285 f = io.BytesIO()
3286 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003287
Serhiy Storchakac8695292018-04-04 00:11:27 +03003288 pickler.dump(data)
3289 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003290
Serhiy Storchakac8695292018-04-04 00:11:27 +03003291 # Reset BytesIO object.
3292 f.seek(0)
3293 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003294
Serhiy Storchakac8695292018-04-04 00:11:27 +03003295 pickler.dump(data)
3296 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003297
Serhiy Storchakac8695292018-04-04 00:11:27 +03003298 # Reset the Pickler and BytesIO objects.
3299 pickler.clear_memo()
3300 f.seek(0)
3301 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003302
Serhiy Storchakac8695292018-04-04 00:11:27 +03003303 pickler.dump(data)
3304 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003305
Serhiy Storchakac8695292018-04-04 00:11:27 +03003306 self.assertNotEqual(first_pickled, second_pickled)
3307 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003308
3309 def test_priming_pickler_memo(self):
3310 # Verify that we can set the Pickler's memo attribute.
3311 data = ["abcdefg", "abcdefg", 44]
3312 f = io.BytesIO()
3313 pickler = self.pickler_class(f)
3314
3315 pickler.dump(data)
3316 first_pickled = f.getvalue()
3317
3318 f = io.BytesIO()
3319 primed = self.pickler_class(f)
3320 primed.memo = pickler.memo
3321
3322 primed.dump(data)
3323 primed_pickled = f.getvalue()
3324
3325 self.assertNotEqual(first_pickled, primed_pickled)
3326
3327 def test_priming_unpickler_memo(self):
3328 # Verify that we can set the Unpickler's memo attribute.
3329 data = ["abcdefg", "abcdefg", 44]
3330 f = io.BytesIO()
3331 pickler = self.pickler_class(f)
3332
3333 pickler.dump(data)
3334 first_pickled = f.getvalue()
3335
3336 f = io.BytesIO()
3337 primed = self.pickler_class(f)
3338 primed.memo = pickler.memo
3339
3340 primed.dump(data)
3341 primed_pickled = f.getvalue()
3342
3343 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3344 unpickled_data1 = unpickler.load()
3345
3346 self.assertEqual(unpickled_data1, data)
3347
3348 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3349 primed.memo = unpickler.memo
3350 unpickled_data2 = primed.load()
3351
3352 primed.memo.clear()
3353
3354 self.assertEqual(unpickled_data2, data)
3355 self.assertTrue(unpickled_data2 is unpickled_data1)
3356
3357 def test_reusing_unpickler_objects(self):
3358 data1 = ["abcdefg", "abcdefg", 44]
3359 f = io.BytesIO()
3360 pickler = self.pickler_class(f)
3361 pickler.dump(data1)
3362 pickled1 = f.getvalue()
3363
3364 data2 = ["abcdefg", 44, 44]
3365 f = io.BytesIO()
3366 pickler = self.pickler_class(f)
3367 pickler.dump(data2)
3368 pickled2 = f.getvalue()
3369
3370 f = io.BytesIO()
3371 f.write(pickled1)
3372 f.seek(0)
3373 unpickler = self.unpickler_class(f)
3374 self.assertEqual(unpickler.load(), data1)
3375
3376 f.seek(0)
3377 f.truncate()
3378 f.write(pickled2)
3379 f.seek(0)
3380 self.assertEqual(unpickler.load(), data2)
3381
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -08003382 def _check_multiple_unpicklings(self, ioclass, *, seekable=True):
Antoine Pitrou04248a82010-10-12 20:51:21 +00003383 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003384 with self.subTest(proto=proto):
3385 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3386 f = ioclass()
3387 pickler = self.pickler_class(f, protocol=proto)
3388 pickler.dump(data1)
3389 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003390
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003391 N = 5
3392 f = ioclass(pickled * N)
3393 unpickler = self.unpickler_class(f)
3394 for i in range(N):
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -08003395 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003396 pos = f.tell()
3397 self.assertEqual(unpickler.load(), data1)
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -08003398 if seekable:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003399 self.assertEqual(f.tell(), pos + len(pickled))
3400 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003401
3402 def test_multiple_unpicklings_seekable(self):
3403 self._check_multiple_unpicklings(io.BytesIO)
3404
3405 def test_multiple_unpicklings_unseekable(self):
Miss Islington (bot)b19f7ec2020-02-23 14:53:24 -08003406 self._check_multiple_unpicklings(UnseekableIO, seekable=False)
3407
3408 def test_multiple_unpicklings_minimal(self):
3409 # File-like object that doesn't support peek() and readinto()
3410 # (bpo-39681)
3411 self._check_multiple_unpicklings(MinimalIO, seekable=False)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003412
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003413 def test_unpickling_buffering_readline(self):
3414 # Issue #12687: the unpickler's buffering logic could fail with
3415 # text mode opcodes.
3416 data = list(range(10))
3417 for proto in protocols:
3418 for buf_size in range(1, 11):
3419 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3420 pickler = self.pickler_class(f, protocol=proto)
3421 pickler.dump(data)
3422 f.seek(0)
3423 unpickler = self.unpickler_class(f)
3424 self.assertEqual(unpickler.load(), data)
3425
Collin Winter771d8342009-04-16 03:18:06 +00003426
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003427# Tests for dispatch_table attribute
3428
3429REDUCE_A = 'reduce_A'
3430
3431class AAA(object):
3432 def __reduce__(self):
3433 return str, (REDUCE_A,)
3434
3435class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003436 def __init__(self):
3437 # Add an instance attribute to enable state-saving routines at pickling
3438 # time.
3439 self.a = "some attribute"
3440
3441 def __setstate__(self, state):
3442 self.a = "BBB.__setstate__"
3443
3444
3445def setstate_bbb(obj, state):
3446 """Custom state setter for BBB objects
3447
3448 Such callable may be created by other persons than the ones who created the
3449 BBB class. If passed as the state_setter item of a custom reducer, this
3450 allows for custom state setting behavior of BBB objects. One can think of
3451 it as the analogous of list_setitems or dict_setitems but for foreign
3452 classes/functions.
3453 """
3454 obj.a = "custom state_setter"
3455
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003456
Pierre Glaser289f1f82019-05-08 23:08:25 +02003457
3458class AbstractCustomPicklerClass:
3459 """Pickler implementing a reducing hook using reducer_override."""
3460 def reducer_override(self, obj):
3461 obj_name = getattr(obj, "__name__", None)
3462
3463 if obj_name == 'f':
3464 # asking the pickler to save f as 5
3465 return int, (5, )
3466
3467 if obj_name == 'MyClass':
3468 return str, ('some str',)
3469
3470 elif obj_name == 'g':
3471 # in this case, the callback returns an invalid result (not a 2-5
3472 # tuple or a string), the pickler should raise a proper error.
3473 return False
3474
3475 elif obj_name == 'h':
3476 # Simulate a case when the reducer fails. The error should
3477 # be propagated to the original ``dump`` call.
3478 raise ValueError('The reducer just failed')
3479
3480 return NotImplemented
3481
3482class AbstractHookTests(unittest.TestCase):
3483 def test_pickler_hook(self):
3484 # test the ability of a custom, user-defined CPickler subclass to
3485 # override the default reducing routines of any type using the method
3486 # reducer_override
3487
3488 def f():
3489 pass
3490
3491 def g():
3492 pass
3493
3494 def h():
3495 pass
3496
3497 class MyClass:
3498 pass
3499
3500 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3501 with self.subTest(proto=proto):
3502 bio = io.BytesIO()
3503 p = self.pickler_class(bio, proto)
3504
3505 p.dump([f, MyClass, math.log])
3506 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3507
3508 self.assertEqual(new_f, 5)
3509 self.assertEqual(some_str, 'some str')
3510 # math.log does not have its usual reducer overriden, so the
3511 # custom reduction callback should silently direct the pickler
3512 # to the default pickling by attribute, by returning
3513 # NotImplemented
3514 self.assertIs(math_log, math.log)
3515
3516 with self.assertRaises(pickle.PicklingError):
3517 p.dump(g)
3518
3519 with self.assertRaisesRegex(
3520 ValueError, 'The reducer just failed'):
3521 p.dump(h)
3522
Antoine Pitrou17236872020-02-02 21:22:57 +01003523 @support.cpython_only
3524 def test_reducer_override_no_reference_cycle(self):
3525 # bpo-39492: reducer_override used to induce a spurious reference cycle
3526 # inside the Pickler object, that could prevent all serialized objects
3527 # from being garbage-collected without explicity invoking gc.collect.
3528
3529 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3530 with self.subTest(proto=proto):
3531 def f():
3532 pass
3533
3534 wr = weakref.ref(f)
3535
3536 bio = io.BytesIO()
3537 p = self.pickler_class(bio, proto)
3538 p.dump(f)
3539 new_f = pickle.loads(bio.getvalue())
3540 assert new_f == 5
3541
3542 del p
3543 del f
3544
3545 self.assertIsNone(wr())
3546
Pierre Glaser289f1f82019-05-08 23:08:25 +02003547
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003548class AbstractDispatchTableTests(unittest.TestCase):
3549
3550 def test_default_dispatch_table(self):
3551 # No dispatch_table attribute by default
3552 f = io.BytesIO()
3553 p = self.pickler_class(f, 0)
3554 with self.assertRaises(AttributeError):
3555 p.dispatch_table
3556 self.assertFalse(hasattr(p, 'dispatch_table'))
3557
3558 def test_class_dispatch_table(self):
3559 # A dispatch_table attribute can be specified class-wide
3560 dt = self.get_dispatch_table()
3561
3562 class MyPickler(self.pickler_class):
3563 dispatch_table = dt
3564
3565 def dumps(obj, protocol=None):
3566 f = io.BytesIO()
3567 p = MyPickler(f, protocol)
3568 self.assertEqual(p.dispatch_table, dt)
3569 p.dump(obj)
3570 return f.getvalue()
3571
3572 self._test_dispatch_table(dumps, dt)
3573
3574 def test_instance_dispatch_table(self):
3575 # A dispatch_table attribute can also be specified instance-wide
3576 dt = self.get_dispatch_table()
3577
3578 def dumps(obj, protocol=None):
3579 f = io.BytesIO()
3580 p = self.pickler_class(f, protocol)
3581 p.dispatch_table = dt
3582 self.assertEqual(p.dispatch_table, dt)
3583 p.dump(obj)
3584 return f.getvalue()
3585
3586 self._test_dispatch_table(dumps, dt)
3587
3588 def _test_dispatch_table(self, dumps, dispatch_table):
3589 def custom_load_dump(obj):
3590 return pickle.loads(dumps(obj, 0))
3591
3592 def default_load_dump(obj):
3593 return pickle.loads(pickle.dumps(obj, 0))
3594
3595 # pickling complex numbers using protocol 0 relies on copyreg
3596 # so check pickling a complex number still works
3597 z = 1 + 2j
3598 self.assertEqual(custom_load_dump(z), z)
3599 self.assertEqual(default_load_dump(z), z)
3600
3601 # modify pickling of complex
3602 REDUCE_1 = 'reduce_1'
3603 def reduce_1(obj):
3604 return str, (REDUCE_1,)
3605 dispatch_table[complex] = reduce_1
3606 self.assertEqual(custom_load_dump(z), REDUCE_1)
3607 self.assertEqual(default_load_dump(z), z)
3608
3609 # check picklability of AAA and BBB
3610 a = AAA()
3611 b = BBB()
3612 self.assertEqual(custom_load_dump(a), REDUCE_A)
3613 self.assertIsInstance(custom_load_dump(b), BBB)
3614 self.assertEqual(default_load_dump(a), REDUCE_A)
3615 self.assertIsInstance(default_load_dump(b), BBB)
3616
3617 # modify pickling of BBB
3618 dispatch_table[BBB] = reduce_1
3619 self.assertEqual(custom_load_dump(a), REDUCE_A)
3620 self.assertEqual(custom_load_dump(b), REDUCE_1)
3621 self.assertEqual(default_load_dump(a), REDUCE_A)
3622 self.assertIsInstance(default_load_dump(b), BBB)
3623
3624 # revert pickling of BBB and modify pickling of AAA
3625 REDUCE_2 = 'reduce_2'
3626 def reduce_2(obj):
3627 return str, (REDUCE_2,)
3628 dispatch_table[AAA] = reduce_2
3629 del dispatch_table[BBB]
3630 self.assertEqual(custom_load_dump(a), REDUCE_2)
3631 self.assertIsInstance(custom_load_dump(b), BBB)
3632 self.assertEqual(default_load_dump(a), REDUCE_A)
3633 self.assertIsInstance(default_load_dump(b), BBB)
3634
Pierre Glaser65d98d02019-05-08 21:40:25 +02003635 # End-to-end testing of save_reduce with the state_setter keyword
3636 # argument. This is a dispatch_table test as the primary goal of
3637 # state_setter is to tweak objects reduction behavior.
3638 # In particular, state_setter is useful when the default __setstate__
3639 # behavior is not flexible enough.
3640
3641 # No custom reducer for b has been registered for now, so
3642 # BBB.__setstate__ should be used at unpickling time
3643 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3644
3645 def reduce_bbb(obj):
3646 return BBB, (), obj.__dict__, None, None, setstate_bbb
3647
3648 dispatch_table[BBB] = reduce_bbb
3649
3650 # The custom reducer reduce_bbb includes a state setter, that should
3651 # have priority over BBB.__setstate__
3652 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3653
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003654
Guido van Rossum98297ee2007-11-06 21:34:58 +00003655if __name__ == "__main__":
3656 # Print some stuff that can be used to rewrite DATA{0,1,2}
3657 from pickletools import dis
3658 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003659 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003660 p = pickle.dumps(x, i)
3661 print("DATA{0} = (".format(i))
3662 for j in range(0, len(p), 20):
3663 b = bytes(p[j:j+20])
3664 print(" {0!r}".format(b))
3665 print(")")
3666 print()
3667 print("# Disassembly of DATA{0}".format(i))
3668 print("DATA{0}_DIS = \"\"\"\\".format(i))
3669 dis(p)
3670 print("\"\"\"")
3671 print()