blob: f8f3bc92e7fe6b632b505c3ef6e0de6505c8207b [file] [log] [blame]
Serhiy Storchakabfe18242015-03-31 13:12:37 +03001import collections
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002import copyreg
Serhiy Storchakabfe18242015-03-31 13:12:37 +03003import dbm
Collin Winter771d8342009-04-16 03:18:06 +00004import io
Serhiy Storchakabfe18242015-03-31 13:12:37 +03005import functools
tjb9004371c0a2019-02-18 23:30:51 +08006import os
Pierre Glaser289f1f82019-05-08 23:08:25 +02007import math
Tim Peters4190fb82003-02-02 16:09:05 +00008import pickle
Tim Peters31f119e2003-02-03 16:20:13 +00009import pickletools
tjb9004371c0a2019-02-18 23:30:51 +080010import shutil
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -080011import struct
Antoine Pitrou82be19f2011-08-29 23:09:33 +020012import sys
tjb9004371c0a2019-02-18 23:30:51 +080013import threading
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +010014import unittest
Antoine Pitrou16c4ce12011-03-11 21:30:43 +010015import weakref
tjb9004371c0a2019-02-18 23:30:51 +080016from textwrap import dedent
Antoine Pitroud9dfaa92009-06-04 20:32:06 +000017from http.cookies import SimpleCookie
Tim Peters4190fb82003-02-02 16:09:05 +000018
Antoine Pitrou91f43802019-05-26 17:10:09 +020019try:
20 import _testbuffer
21except ImportError:
22 _testbuffer = None
23
24try:
25 import numpy as np
26except ImportError:
27 np = None
28
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020029from test import support
Antoine Pitrou82be19f2011-08-29 23:09:33 +020030from test.support import (
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020031 TestFailed, TESTFN, run_with_locale, no_tracing,
tjb9004371c0a2019-02-18 23:30:51 +080032 _2G, _4G, bigmemtest, reap_threads, forget,
Antoine Pitrou82be19f2011-08-29 23:09:33 +020033 )
Tim Peterse089c682001-04-10 03:41:41 +000034
Guido van Rossum98297ee2007-11-06 21:34:58 +000035from pickle import bytes_types
36
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030037requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
38 "test is only meaningful on 32-bit builds")
39
Tim Petersee1a53c2003-02-02 02:57:53 +000040# Tests that try a number of pickle protocols should have a
41# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000042# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000043protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000044
Tim Peters22e71712003-02-03 22:27:38 +000045
46# Return True if opcode code appears in the pickle, else False.
47def opcode_in_pickle(code, pickle):
48 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000049 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000050 return True
51 return False
52
Tim Peters8d2613a2003-02-11 16:40:16 +000053# Return the number of times opcode code appears in pickle.
54def count_opcode(code, pickle):
55 n = 0
56 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000057 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000058 n += 1
59 return n
60
Antoine Pitrou04248a82010-10-12 20:51:21 +000061
62class UnseekableIO(io.BytesIO):
63 def peek(self, *args):
64 raise NotImplementedError
65
66 def seekable(self):
67 return False
68
69 def seek(self, *args):
70 raise io.UnsupportedOperation
71
72 def tell(self):
73 raise io.UnsupportedOperation
74
75
Tim Peters3e667d52003-02-04 21:47:44 +000076# We can't very well test the extension registry without putting known stuff
77# in it, but we have to be careful to restore its original state. Code
78# should do this:
79#
80# e = ExtensionSaver(extension_code)
81# try:
82# fiddle w/ the extension registry's stuff for extension_code
83# finally:
84# e.restore()
85
86class ExtensionSaver:
87 # Remember current registration for code (if any), and remove it (if
88 # there is one).
89 def __init__(self, code):
90 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000091 if code in copyreg._inverted_registry:
92 self.pair = copyreg._inverted_registry[code]
93 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000094 else:
95 self.pair = None
96
97 # Restore previous registration for code.
98 def restore(self):
99 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000100 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +0000101 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000102 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000103 pair = self.pair
104 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000105 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +0000106
Jeremy Hylton66426532001-10-15 21:38:56 +0000107class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000108 def __eq__(self, other):
109 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +0000110
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000111class D(C):
112 def __init__(self, arg):
113 pass
114
115class E(C):
116 def __getinitargs__(self):
117 return ()
118
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100119class H(object):
120 pass
121
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200122# Hashable mutable key
123class K(object):
124 def __init__(self, value):
125 self.value = value
126
127 def __reduce__(self):
128 # Shouldn't support the recursion itself
129 return K, (self.value,)
130
Jeremy Hylton66426532001-10-15 21:38:56 +0000131import __main__
132__main__.C = C
133C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000134__main__.D = D
135D.__module__ = "__main__"
136__main__.E = E
137E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100138__main__.H = H
139H.__module__ = "__main__"
Serhiy Storchaka608c2132015-11-07 11:16:10 +0200140__main__.K = K
141K.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000142
143class myint(int):
144 def __init__(self, x):
145 self.str = str(x)
146
147class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000148
Jeremy Hylton66426532001-10-15 21:38:56 +0000149 def __init__(self, a, b):
150 self.a = a
151 self.b = b
152
153 def __getinitargs__(self):
154 return self.a, self.b
155
Guido van Rossum04a86612001-12-19 16:58:54 +0000156class metaclass(type):
157 pass
158
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000159class use_metaclass(object, metaclass=metaclass):
160 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000161
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200162class pickling_metaclass(type):
163 def __eq__(self, other):
164 return (type(self) == type(other) and
165 self.reduce_args == other.reduce_args)
166
167 def __reduce__(self):
168 return (create_dynamic_class, self.reduce_args)
169
170def create_dynamic_class(name, bases):
171 result = pickling_metaclass(name, bases, dict())
172 result.reduce_args = (name, bases)
173 return result
174
Antoine Pitrou91f43802019-05-26 17:10:09 +0200175
176class ZeroCopyBytes(bytes):
177 readonly = True
178 c_contiguous = True
179 f_contiguous = True
180 zero_copy_reconstruct = True
181
182 def __reduce_ex__(self, protocol):
183 if protocol >= 5:
184 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
185 else:
186 return type(self)._reconstruct, (bytes(self),)
187
188 def __repr__(self):
189 return "{}({!r})".format(self.__class__.__name__, bytes(self))
190
191 __str__ = __repr__
192
193 @classmethod
194 def _reconstruct(cls, obj):
195 with memoryview(obj) as m:
196 obj = m.obj
197 if type(obj) is cls:
198 # Zero-copy
199 return obj
200 else:
201 return cls(obj)
202
203
204class ZeroCopyBytearray(bytearray):
205 readonly = False
206 c_contiguous = True
207 f_contiguous = True
208 zero_copy_reconstruct = True
209
210 def __reduce_ex__(self, protocol):
211 if protocol >= 5:
212 return type(self)._reconstruct, (pickle.PickleBuffer(self),), None
213 else:
214 return type(self)._reconstruct, (bytes(self),)
215
216 def __repr__(self):
217 return "{}({!r})".format(self.__class__.__name__, bytes(self))
218
219 __str__ = __repr__
220
221 @classmethod
222 def _reconstruct(cls, obj):
223 with memoryview(obj) as m:
224 obj = m.obj
225 if type(obj) is cls:
226 # Zero-copy
227 return obj
228 else:
229 return cls(obj)
230
231
232if _testbuffer is not None:
233
234 class PicklableNDArray:
235 # A not-really-zero-copy picklable ndarray, as the ndarray()
236 # constructor doesn't allow for it
237
238 zero_copy_reconstruct = False
239
240 def __init__(self, *args, **kwargs):
241 self.array = _testbuffer.ndarray(*args, **kwargs)
242
243 def __getitem__(self, idx):
244 cls = type(self)
245 new = cls.__new__(cls)
246 new.array = self.array[idx]
247 return new
248
249 @property
250 def readonly(self):
251 return self.array.readonly
252
253 @property
254 def c_contiguous(self):
255 return self.array.c_contiguous
256
257 @property
258 def f_contiguous(self):
259 return self.array.f_contiguous
260
261 def __eq__(self, other):
262 if not isinstance(other, PicklableNDArray):
263 return NotImplemented
264 return (other.array.format == self.array.format and
265 other.array.shape == self.array.shape and
266 other.array.strides == self.array.strides and
267 other.array.readonly == self.array.readonly and
268 other.array.tobytes() == self.array.tobytes())
269
270 def __ne__(self, other):
271 if not isinstance(other, PicklableNDArray):
272 return NotImplemented
273 return not (self == other)
274
275 def __repr__(self):
276 return (f"{type(self)}(shape={self.array.shape},"
277 f"strides={self.array.strides}, "
278 f"bytes={self.array.tobytes()})")
279
280 def __reduce_ex__(self, protocol):
281 if not self.array.contiguous:
282 raise NotImplementedError("Reconstructing a non-contiguous "
283 "ndarray does not seem possible")
284 ndarray_kwargs = {"shape": self.array.shape,
285 "strides": self.array.strides,
286 "format": self.array.format,
287 "flags": (0 if self.readonly
288 else _testbuffer.ND_WRITABLE)}
289 pb = pickle.PickleBuffer(self.array)
290 if protocol >= 5:
291 return (type(self)._reconstruct,
292 (pb, ndarray_kwargs))
293 else:
294 # Need to serialize the bytes in physical order
295 with pb.raw() as m:
296 return (type(self)._reconstruct,
297 (m.tobytes(), ndarray_kwargs))
298
299 @classmethod
300 def _reconstruct(cls, obj, kwargs):
301 with memoryview(obj) as m:
302 # For some reason, ndarray() wants a list of integers...
303 # XXX This only works if format == 'B'
304 items = list(m.tobytes())
305 return cls(items, **kwargs)
306
307
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300308# DATA0 .. DATA4 are the pickles we expect under the various protocols, for
Tim Peters70b02d72003-02-02 17:26:40 +0000309# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000310
Guido van Rossum98297ee2007-11-06 21:34:58 +0000311DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200312 b'(lp0\nL0L\naL1L\naF2.0\n'
313 b'ac__builtin__\ncomple'
314 b'x\np1\n(F3.0\nF0.0\ntp2\n'
315 b'Rp3\naL1L\naL-1L\naL255'
316 b'L\naL-255L\naL-256L\naL'
317 b'65535L\naL-65535L\naL-'
318 b'65536L\naL2147483647L'
319 b'\naL-2147483647L\naL-2'
320 b'147483648L\na(Vabc\np4'
321 b'\ng4\nccopy_reg\n_recon'
322 b'structor\np5\n(c__main'
323 b'__\nC\np6\nc__builtin__'
324 b'\nobject\np7\nNtp8\nRp9\n'
325 b'(dp10\nVfoo\np11\nL1L\ns'
326 b'Vbar\np12\nL2L\nsbg9\ntp'
327 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000328)
Tim Peterse9358162001-01-22 22:05:20 +0000329
Guido van Rossum98297ee2007-11-06 21:34:58 +0000330# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000331DATA0_DIS = """\
332 0: ( MARK
333 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000334 2: p PUT 0
335 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000336 9: a APPEND
337 10: L LONG 1
338 14: a APPEND
339 15: F FLOAT 2.0
340 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200341 21: c GLOBAL '__builtin__ complex'
342 42: p PUT 1
343 45: ( MARK
344 46: F FLOAT 3.0
345 51: F FLOAT 0.0
346 56: t TUPLE (MARK at 45)
347 57: p PUT 2
348 60: R REDUCE
349 61: p PUT 3
350 64: a APPEND
351 65: L LONG 1
352 69: a APPEND
353 70: L LONG -1
354 75: a APPEND
355 76: L LONG 255
356 82: a APPEND
357 83: L LONG -255
358 90: a APPEND
359 91: L LONG -256
360 98: a APPEND
361 99: L LONG 65535
362 107: a APPEND
363 108: L LONG -65535
364 117: a APPEND
365 118: L LONG -65536
366 127: a APPEND
367 128: L LONG 2147483647
368 141: a APPEND
369 142: L LONG -2147483647
370 156: a APPEND
371 157: L LONG -2147483648
372 171: a APPEND
373 172: ( MARK
374 173: V UNICODE 'abc'
375 178: p PUT 4
376 181: g GET 4
377 184: c GLOBAL 'copy_reg _reconstructor'
378 209: p PUT 5
379 212: ( MARK
380 213: c GLOBAL '__main__ C'
381 225: p PUT 6
382 228: c GLOBAL '__builtin__ object'
383 248: p PUT 7
384 251: N NONE
385 252: t TUPLE (MARK at 212)
386 253: p PUT 8
387 256: R REDUCE
388 257: p PUT 9
389 260: ( MARK
390 261: d DICT (MARK at 260)
391 262: p PUT 10
392 266: V UNICODE 'foo'
393 271: p PUT 11
394 275: L LONG 1
395 279: s SETITEM
396 280: V UNICODE 'bar'
397 285: p PUT 12
398 289: L LONG 2
399 293: s SETITEM
400 294: b BUILD
401 295: g GET 9
402 298: t TUPLE (MARK at 172)
403 299: p PUT 13
404 303: a APPEND
405 304: g GET 13
406 308: a APPEND
407 309: L LONG 5
408 313: a APPEND
409 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000410highest protocol among opcodes = 0
411"""
412
Guido van Rossum98297ee2007-11-06 21:34:58 +0000413DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200414 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
415 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000416 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
417 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
418 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
419 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200420 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000421 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200422 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000423 b'object\nq\x07Ntq\x08Rq\t}q\n('
424 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
425 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
426)
Tim Peters70b02d72003-02-02 17:26:40 +0000427
Guido van Rossum98297ee2007-11-06 21:34:58 +0000428# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000429DATA1_DIS = """\
430 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000431 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000432 3: ( MARK
433 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000434 6: K BININT1 1
435 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200436 17: c GLOBAL '__builtin__ complex'
437 38: q BINPUT 1
438 40: ( MARK
439 41: G BINFLOAT 3.0
440 50: G BINFLOAT 0.0
441 59: t TUPLE (MARK at 40)
442 60: q BINPUT 2
443 62: R REDUCE
444 63: q BINPUT 3
445 65: K BININT1 1
446 67: J BININT -1
447 72: K BININT1 255
448 74: J BININT -255
449 79: J BININT -256
450 84: M BININT2 65535
451 87: J BININT -65535
452 92: J BININT -65536
453 97: J BININT 2147483647
454 102: J BININT -2147483647
455 107: J BININT -2147483648
456 112: ( MARK
457 113: X BINUNICODE 'abc'
458 121: q BINPUT 4
459 123: h BINGET 4
460 125: c GLOBAL 'copy_reg _reconstructor'
461 150: q BINPUT 5
462 152: ( MARK
463 153: c GLOBAL '__main__ C'
464 165: q BINPUT 6
465 167: c GLOBAL '__builtin__ object'
466 187: q BINPUT 7
467 189: N NONE
468 190: t TUPLE (MARK at 152)
469 191: q BINPUT 8
470 193: R REDUCE
471 194: q BINPUT 9
472 196: } EMPTY_DICT
473 197: q BINPUT 10
474 199: ( MARK
475 200: X BINUNICODE 'foo'
476 208: q BINPUT 11
477 210: K BININT1 1
478 212: X BINUNICODE 'bar'
479 220: q BINPUT 12
480 222: K BININT1 2
481 224: u SETITEMS (MARK at 199)
482 225: b BUILD
483 226: h BINGET 9
484 228: t TUPLE (MARK at 112)
485 229: q BINPUT 13
486 231: h BINGET 13
487 233: K BININT1 5
488 235: e APPENDS (MARK at 3)
489 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000490highest protocol among opcodes = 1
491"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000492
Guido van Rossum98297ee2007-11-06 21:34:58 +0000493DATA2 = (
494 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200495 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000496 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
497 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
498 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
499 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
500 b'bcq\x04h\x04c__main__\nC\nq\x05'
501 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
502 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
503 b'\nK\x05e.'
504)
Tim Petersfc273752003-03-02 04:54:24 +0000505
Guido van Rossum98297ee2007-11-06 21:34:58 +0000506# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000507DATA2_DIS = """\
508 0: \x80 PROTO 2
509 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000510 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000511 5: ( MARK
512 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000513 8: K BININT1 1
514 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200515 19: c GLOBAL '__builtin__ complex'
516 40: q BINPUT 1
517 42: G BINFLOAT 3.0
518 51: G BINFLOAT 0.0
519 60: \x86 TUPLE2
520 61: q BINPUT 2
521 63: R REDUCE
522 64: q BINPUT 3
523 66: K BININT1 1
524 68: J BININT -1
525 73: K BININT1 255
526 75: J BININT -255
527 80: J BININT -256
528 85: M BININT2 65535
529 88: J BININT -65535
530 93: J BININT -65536
531 98: J BININT 2147483647
532 103: J BININT -2147483647
533 108: J BININT -2147483648
534 113: ( MARK
535 114: X BINUNICODE 'abc'
536 122: q BINPUT 4
537 124: h BINGET 4
538 126: c GLOBAL '__main__ C'
539 138: q BINPUT 5
540 140: ) EMPTY_TUPLE
541 141: \x81 NEWOBJ
542 142: q BINPUT 6
543 144: } EMPTY_DICT
544 145: q BINPUT 7
545 147: ( MARK
546 148: X BINUNICODE 'foo'
547 156: q BINPUT 8
548 158: K BININT1 1
549 160: X BINUNICODE 'bar'
550 168: q BINPUT 9
551 170: K BININT1 2
552 172: u SETITEMS (MARK at 147)
553 173: b BUILD
554 174: h BINGET 6
555 176: t TUPLE (MARK at 113)
556 177: q BINPUT 10
557 179: h BINGET 10
558 181: K BININT1 5
559 183: e APPENDS (MARK at 5)
560 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000561highest protocol among opcodes = 2
562"""
563
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300564DATA3 = (
565 b'\x80\x03]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
566 b'builtins\ncomplex\nq\x01G'
567 b'@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00\x86q\x02'
568 b'Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff'
569 b'\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7f'
570 b'J\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00abcq'
571 b'\x04h\x04c__main__\nC\nq\x05)\x81q'
572 b'\x06}q\x07(X\x03\x00\x00\x00barq\x08K\x02X\x03\x00'
573 b'\x00\x00fooq\tK\x01ubh\x06tq\nh\nK\x05'
574 b'e.'
575)
576
577# Disassembly of DATA3
578DATA3_DIS = """\
579 0: \x80 PROTO 3
580 2: ] EMPTY_LIST
581 3: q BINPUT 0
582 5: ( MARK
583 6: K BININT1 0
584 8: K BININT1 1
585 10: G BINFLOAT 2.0
586 19: c GLOBAL 'builtins complex'
587 37: q BINPUT 1
588 39: G BINFLOAT 3.0
589 48: G BINFLOAT 0.0
590 57: \x86 TUPLE2
591 58: q BINPUT 2
592 60: R REDUCE
593 61: q BINPUT 3
594 63: K BININT1 1
595 65: J BININT -1
596 70: K BININT1 255
597 72: J BININT -255
598 77: J BININT -256
599 82: M BININT2 65535
600 85: J BININT -65535
601 90: J BININT -65536
602 95: J BININT 2147483647
603 100: J BININT -2147483647
604 105: J BININT -2147483648
605 110: ( MARK
606 111: X BINUNICODE 'abc'
607 119: q BINPUT 4
608 121: h BINGET 4
609 123: c GLOBAL '__main__ C'
610 135: q BINPUT 5
611 137: ) EMPTY_TUPLE
612 138: \x81 NEWOBJ
613 139: q BINPUT 6
614 141: } EMPTY_DICT
615 142: q BINPUT 7
616 144: ( MARK
617 145: X BINUNICODE 'bar'
618 153: q BINPUT 8
619 155: K BININT1 2
620 157: X BINUNICODE 'foo'
621 165: q BINPUT 9
622 167: K BININT1 1
623 169: u SETITEMS (MARK at 144)
624 170: b BUILD
625 171: h BINGET 6
626 173: t TUPLE (MARK at 110)
627 174: q BINPUT 10
628 176: h BINGET 10
629 178: K BININT1 5
630 180: e APPENDS (MARK at 5)
631 181: . STOP
632highest protocol among opcodes = 2
633"""
634
635DATA4 = (
636 b'\x80\x04\x95\xa8\x00\x00\x00\x00\x00\x00\x00]\x94(K\x00K\x01G@'
637 b'\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x07'
638 b'complex\x94\x93\x94G@\x08\x00\x00\x00\x00\x00\x00G'
639 b'\x00\x00\x00\x00\x00\x00\x00\x00\x86\x94R\x94K\x01J\xff\xff\xff\xffK'
640 b'\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ'
641 b'\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80('
642 b'\x8c\x03abc\x94h\x06\x8c\x08__main__\x94\x8c'
643 b'\x01C\x94\x93\x94)\x81\x94}\x94(\x8c\x03bar\x94K\x02\x8c'
644 b'\x03foo\x94K\x01ubh\nt\x94h\x0eK\x05e.'
645)
646
647# Disassembly of DATA4
648DATA4_DIS = """\
649 0: \x80 PROTO 4
650 2: \x95 FRAME 168
651 11: ] EMPTY_LIST
652 12: \x94 MEMOIZE
653 13: ( MARK
654 14: K BININT1 0
655 16: K BININT1 1
656 18: G BINFLOAT 2.0
657 27: \x8c SHORT_BINUNICODE 'builtins'
658 37: \x94 MEMOIZE
659 38: \x8c SHORT_BINUNICODE 'complex'
660 47: \x94 MEMOIZE
661 48: \x93 STACK_GLOBAL
662 49: \x94 MEMOIZE
663 50: G BINFLOAT 3.0
664 59: G BINFLOAT 0.0
665 68: \x86 TUPLE2
666 69: \x94 MEMOIZE
667 70: R REDUCE
668 71: \x94 MEMOIZE
669 72: K BININT1 1
670 74: J BININT -1
671 79: K BININT1 255
672 81: J BININT -255
673 86: J BININT -256
674 91: M BININT2 65535
675 94: J BININT -65535
676 99: J BININT -65536
677 104: J BININT 2147483647
678 109: J BININT -2147483647
679 114: J BININT -2147483648
680 119: ( MARK
681 120: \x8c SHORT_BINUNICODE 'abc'
682 125: \x94 MEMOIZE
683 126: h BINGET 6
684 128: \x8c SHORT_BINUNICODE '__main__'
685 138: \x94 MEMOIZE
686 139: \x8c SHORT_BINUNICODE 'C'
687 142: \x94 MEMOIZE
688 143: \x93 STACK_GLOBAL
689 144: \x94 MEMOIZE
690 145: ) EMPTY_TUPLE
691 146: \x81 NEWOBJ
692 147: \x94 MEMOIZE
693 148: } EMPTY_DICT
694 149: \x94 MEMOIZE
695 150: ( MARK
696 151: \x8c SHORT_BINUNICODE 'bar'
697 156: \x94 MEMOIZE
698 157: K BININT1 2
699 159: \x8c SHORT_BINUNICODE 'foo'
700 164: \x94 MEMOIZE
701 165: K BININT1 1
702 167: u SETITEMS (MARK at 150)
703 168: b BUILD
704 169: h BINGET 10
705 171: t TUPLE (MARK at 119)
706 172: \x94 MEMOIZE
707 173: h BINGET 14
708 175: K BININT1 5
709 177: e APPENDS (MARK at 13)
710 178: . STOP
711highest protocol among opcodes = 4
712"""
713
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000714# set([1,2]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300715DATA_SET = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000716
717# xrange(5) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300718DATA_XRANGE = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000719
720# a SimpleCookie() object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300721DATA_COOKIE = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
722 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
723 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
724 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
725 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
726 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000727
728# set([3]) pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300729DATA_SET2 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000730
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100731python2_exceptions_without_args = (
732 ArithmeticError,
733 AssertionError,
734 AttributeError,
735 BaseException,
736 BufferError,
737 BytesWarning,
738 DeprecationWarning,
739 EOFError,
740 EnvironmentError,
741 Exception,
742 FloatingPointError,
743 FutureWarning,
744 GeneratorExit,
745 IOError,
746 ImportError,
747 ImportWarning,
748 IndentationError,
749 IndexError,
750 KeyError,
751 KeyboardInterrupt,
752 LookupError,
753 MemoryError,
754 NameError,
755 NotImplementedError,
756 OSError,
757 OverflowError,
758 PendingDeprecationWarning,
759 ReferenceError,
760 RuntimeError,
761 RuntimeWarning,
762 # StandardError is gone in Python 3, we map it to Exception
763 StopIteration,
764 SyntaxError,
765 SyntaxWarning,
766 SystemError,
767 SystemExit,
768 TabError,
769 TypeError,
770 UnboundLocalError,
771 UnicodeError,
772 UnicodeWarning,
773 UserWarning,
774 ValueError,
775 Warning,
776 ZeroDivisionError,
777)
778
779exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
780
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100781# UnicodeEncodeError object pickled from 2.x with protocol 2
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300782DATA_UEERR = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
783 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
784 b'U\x03badq\x03tq\x04Rq\x05.')
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100785
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000786
Jeremy Hylton66426532001-10-15 21:38:56 +0000787def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000788 c = C()
789 c.foo = 1
790 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000791 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000792 # Append some integer test cases at cPickle.c's internal size
793 # cutoffs.
794 uint1max = 0xff
795 uint2max = 0xffff
796 int4max = 0x7fffffff
797 x.extend([1, -1,
798 uint1max, -uint1max, -uint1max-1,
799 uint2max, -uint2max, -uint2max-1,
800 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000801 y = ('abc', 'abc', c, c)
802 x.append(y)
803 x.append(y)
804 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000805 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000806
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100807
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300808class AbstractUnpickleTests(unittest.TestCase):
809 # Subclass must define self.loads.
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100810
Jeremy Hylton66426532001-10-15 21:38:56 +0000811 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000812
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100813 def assert_is_copy(self, obj, objcopy, msg=None):
814 """Utility method to verify if two objects are copies of each others.
815 """
816 if msg is None:
817 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
818 self.assertEqual(obj, objcopy, msg=msg)
819 self.assertIs(type(obj), type(objcopy), msg=msg)
820 if hasattr(obj, '__dict__'):
821 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
822 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
823 if hasattr(obj, '__slots__'):
824 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
825 for slot in obj.__slots__:
826 self.assertEqual(
827 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
828 self.assertEqual(getattr(obj, slot, None),
829 getattr(objcopy, slot, None), msg=msg)
830
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200831 def check_unpickling_error(self, errors, data):
832 with self.subTest(data=data), \
833 self.assertRaises(errors):
834 try:
835 self.loads(data)
836 except BaseException as exc:
837 if support.verbose > 1:
838 print('%-32r - %s: %s' %
839 (data, exc.__class__.__name__, exc))
840 raise
841
Guido van Rossum98297ee2007-11-06 21:34:58 +0000842 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100843 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000844
845 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100846 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000847
848 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100849 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000850
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300851 def test_load_from_data3(self):
852 self.assert_is_copy(self._testdata, self.loads(DATA3))
853
854 def test_load_from_data4(self):
855 self.assert_is_copy(self._testdata, self.loads(DATA4))
856
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000857 def test_load_classic_instance(self):
858 # See issue5180. Test loading 2.x pickles that
859 # contain an instance of old style class.
860 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
861 xname = X.__name__.encode('ascii')
862 # Protocol 0 (text mode pickle):
863 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200864 0: ( MARK
865 1: i INST '__main__ X' (MARK at 0)
866 13: p PUT 0
867 16: ( MARK
868 17: d DICT (MARK at 16)
869 18: p PUT 1
870 21: b BUILD
871 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000872 """
873 pickle0 = (b"(i__main__\n"
874 b"X\n"
875 b"p0\n"
876 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100877 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000878
879 # Protocol 1 (binary mode pickle)
880 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200881 0: ( MARK
882 1: c GLOBAL '__main__ X'
883 13: q BINPUT 0
884 15: o OBJ (MARK at 0)
885 16: q BINPUT 1
886 18: } EMPTY_DICT
887 19: q BINPUT 2
888 21: b BUILD
889 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000890 """
891 pickle1 = (b'(c__main__\n'
892 b'X\n'
893 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100894 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000895
896 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
897 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200898 0: \x80 PROTO 2
899 2: ( MARK
900 3: c GLOBAL '__main__ X'
901 15: q BINPUT 0
902 17: o OBJ (MARK at 2)
903 18: q BINPUT 1
904 20: } EMPTY_DICT
905 21: q BINPUT 2
906 23: b BUILD
907 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000908 """
909 pickle2 = (b'\x80\x02(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(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000913
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300914 def test_maxint64(self):
915 maxint64 = (1 << 63) - 1
916 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
917 got = self.loads(data)
918 self.assert_is_copy(maxint64, got)
919
920 # Try too with a bogus literal.
921 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200922 self.check_unpickling_error(ValueError, data)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300923
924 def test_unpickle_from_2x(self):
925 # Unpickle non-trivial data from Python 2.x.
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300926 loaded = self.loads(DATA_SET)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300927 self.assertEqual(loaded, set([1, 2]))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300928 loaded = self.loads(DATA_XRANGE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300929 self.assertEqual(type(loaded), type(range(0)))
930 self.assertEqual(list(loaded), list(range(5)))
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300931 loaded = self.loads(DATA_COOKIE)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300932 self.assertEqual(type(loaded), SimpleCookie)
933 self.assertEqual(list(loaded.keys()), ["key"])
934 self.assertEqual(loaded["key"].value, "value")
935
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300936 # Exception objects without arguments pickled from 2.x with protocol 2
937 for exc in python2_exceptions_without_args:
938 data = exception_pickle.replace(b'?', exc.__name__.encode("ascii"))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300939 loaded = self.loads(data)
940 self.assertIs(type(loaded), exc)
941
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300942 # StandardError is mapped to Exception, test that separately
943 loaded = self.loads(exception_pickle.replace(b'?', b'StandardError'))
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300944 self.assertIs(type(loaded), Exception)
945
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300946 loaded = self.loads(DATA_UEERR)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300947 self.assertIs(type(loaded), UnicodeEncodeError)
948 self.assertEqual(loaded.object, "foo")
949 self.assertEqual(loaded.encoding, "ascii")
950 self.assertEqual(loaded.start, 0)
951 self.assertEqual(loaded.end, 1)
952 self.assertEqual(loaded.reason, "bad")
953
954 def test_load_python2_str_as_bytes(self):
955 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
956 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
957 encoding="bytes"), b'a\x00\xa0')
958 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
959 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
960 encoding="bytes"), b'a\x00\xa0')
961 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
962 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
963 encoding="bytes"), b'a\x00\xa0')
964
965 def test_load_python2_unicode_as_str(self):
966 # From Python 2: pickle.dumps(u'π', protocol=0)
967 self.assertEqual(self.loads(b'V\\u03c0\n.',
968 encoding='bytes'), 'π')
969 # From Python 2: pickle.dumps(u'π', protocol=1)
970 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
971 encoding="bytes"), 'π')
972 # From Python 2: pickle.dumps(u'π', protocol=2)
973 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
974 encoding="bytes"), 'π')
975
976 def test_load_long_python2_str_as_bytes(self):
977 # From Python 2: pickle.dumps('x' * 300, protocol=1)
978 self.assertEqual(self.loads(pickle.BINSTRING +
979 struct.pack("<I", 300) +
980 b'x' * 300 + pickle.STOP,
981 encoding='bytes'), b'x' * 300)
982
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300983 def test_constants(self):
984 self.assertIsNone(self.loads(b'N.'))
985 self.assertIs(self.loads(b'\x88.'), True)
986 self.assertIs(self.loads(b'\x89.'), False)
987 self.assertIs(self.loads(b'I01\n.'), True)
988 self.assertIs(self.loads(b'I00\n.'), False)
989
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300990 def test_empty_bytestring(self):
991 # issue 11286
992 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
993 self.assertEqual(empty, '')
994
Serhiy Storchakab8b951f2015-09-29 15:49:58 +0300995 def test_short_binbytes(self):
996 dumped = b'\x80\x03C\x04\xe2\x82\xac\x00.'
997 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
998
999 def test_binbytes(self):
1000 dumped = b'\x80\x03B\x04\x00\x00\x00\xe2\x82\xac\x00.'
1001 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1002
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001003 @requires_32b
1004 def test_negative_32b_binbytes(self):
1005 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1006 dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001007 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1008 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001009
1010 @requires_32b
1011 def test_negative_32b_binunicode(self):
1012 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1013 dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001014 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1015 dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001016
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001017 def test_short_binunicode(self):
1018 dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
1019 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1020
1021 def test_misc_get(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001022 self.check_unpickling_error(KeyError, b'g0\np0')
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001023 self.assert_is_copy([(100,), (100,)],
1024 self.loads(b'((Kdtp0\nh\x00l.))'))
1025
Serhiy Storchakae0606192015-09-29 22:10:07 +03001026 def test_binbytes8(self):
1027 dumped = b'\x80\x04\x8e\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1028 self.assertEqual(self.loads(dumped), b'\xe2\x82\xac\x00')
1029
1030 def test_binunicode8(self):
1031 dumped = b'\x80\x04\x8d\4\0\0\0\0\0\0\0\xe2\x82\xac\x00.'
1032 self.assertEqual(self.loads(dumped), '\u20ac\x00')
1033
Antoine Pitrou91f43802019-05-26 17:10:09 +02001034 def test_bytearray8(self):
1035 dumped = b'\x80\x05\x96\x03\x00\x00\x00\x00\x00\x00\x00xxx.'
1036 self.assertEqual(self.loads(dumped), bytearray(b'xxx'))
1037
Serhiy Storchakae0606192015-09-29 22:10:07 +03001038 @requires_32b
1039 def test_large_32b_binbytes8(self):
1040 dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001041 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1042 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001043
1044 @requires_32b
Antoine Pitrou91f43802019-05-26 17:10:09 +02001045 def test_large_32b_bytearray8(self):
1046 dumped = b'\x80\x05\x96\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
1047 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1048 dumped)
1049
1050 @requires_32b
Serhiy Storchakae0606192015-09-29 22:10:07 +03001051 def test_large_32b_binunicode8(self):
1052 dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001053 self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
1054 dumped)
Serhiy Storchakae0606192015-09-29 22:10:07 +03001055
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03001056 def test_get(self):
1057 pickled = b'((lp100000\ng100000\nt.'
1058 unpickled = self.loads(pickled)
1059 self.assertEqual(unpickled, ([],)*2)
1060 self.assertIs(unpickled[0], unpickled[1])
1061
1062 def test_binget(self):
1063 pickled = b'(]q\xffh\xfft.'
1064 unpickled = self.loads(pickled)
1065 self.assertEqual(unpickled, ([],)*2)
1066 self.assertIs(unpickled[0], unpickled[1])
1067
1068 def test_long_binget(self):
1069 pickled = b'(]r\x00\x00\x01\x00j\x00\x00\x01\x00t.'
1070 unpickled = self.loads(pickled)
1071 self.assertEqual(unpickled, ([],)*2)
1072 self.assertIs(unpickled[0], unpickled[1])
1073
1074 def test_dup(self):
1075 pickled = b'((l2t.'
1076 unpickled = self.loads(pickled)
1077 self.assertEqual(unpickled, ([],)*2)
1078 self.assertIs(unpickled[0], unpickled[1])
1079
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001080 def test_negative_put(self):
1081 # Issue #12847
1082 dumped = b'Va\np-1\n.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001083 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001084
1085 @requires_32b
1086 def test_negative_32b_binput(self):
1087 # Issue #12847
1088 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001089 self.check_unpickling_error(ValueError, dumped)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001090
1091 def test_badly_escaped_string(self):
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001092 self.check_unpickling_error(ValueError, b"S'\\'\n.")
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001093
1094 def test_badly_quoted_string(self):
1095 # Issue #17710
1096 badpickles = [b"S'\n.",
1097 b'S"\n.',
1098 b'S\' \n.',
1099 b'S" \n.',
1100 b'S\'"\n.',
1101 b'S"\'\n.',
1102 b"S' ' \n.",
1103 b'S" " \n.',
1104 b"S ''\n.",
1105 b'S ""\n.',
1106 b'S \n.',
1107 b'S\n.',
1108 b'S.']
1109 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001110 self.check_unpickling_error(pickle.UnpicklingError, p)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001111
1112 def test_correctly_quoted_string(self):
1113 goodpickles = [(b"S''\n.", ''),
1114 (b'S""\n.', ''),
1115 (b'S"\\n"\n.', '\n'),
1116 (b"S'\\n'\n.", '\n')]
1117 for p, expected in goodpickles:
1118 self.assertEqual(self.loads(p), expected)
1119
1120 def test_frame_readline(self):
1121 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1122 # 0: \x80 PROTO 4
1123 # 2: \x95 FRAME 5
1124 # 11: I INT 42
1125 # 15: . STOP
1126 self.assertEqual(self.loads(pickled), 42)
1127
1128 def test_compat_unpickle(self):
1129 # xrange(1, 7)
1130 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1131 unpickled = self.loads(pickled)
1132 self.assertIs(type(unpickled), range)
1133 self.assertEqual(unpickled, range(1, 7))
1134 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1135 # reduce
1136 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1137 self.assertIs(self.loads(pickled), functools.reduce)
1138 # whichdb.whichdb
1139 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1140 self.assertIs(self.loads(pickled), dbm.whichdb)
1141 # Exception(), StandardError()
1142 for name in (b'Exception', b'StandardError'):
1143 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1144 unpickled = self.loads(pickled)
1145 self.assertIs(type(unpickled), Exception)
1146 self.assertEqual(str(unpickled), 'ugh')
1147 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1148 for name in (b'UserDict', b'IterableUserDict'):
1149 pickled = (b'\x80\x02(cUserDict\n' + name +
1150 b'\no}U\x04data}K\x01K\x02ssb.')
1151 unpickled = self.loads(pickled)
1152 self.assertIs(type(unpickled), collections.UserDict)
1153 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1154
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001155 def test_bad_stack(self):
1156 badpickles = [
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001157 b'.', # STOP
1158 b'0', # POP
1159 b'1', # POP_MARK
1160 b'2', # DUP
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001161 b'(2',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001162 b'R', # REDUCE
1163 b')R',
1164 b'a', # APPEND
1165 b'Na',
1166 b'b', # BUILD
1167 b'Nb',
1168 b'd', # DICT
1169 b'e', # APPENDS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001170 b'(e',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001171 b'ibuiltins\nlist\n', # INST
1172 b'l', # LIST
1173 b'o', # OBJ
1174 b'(o',
1175 b'p1\n', # PUT
1176 b'q\x00', # BINPUT
1177 b'r\x00\x00\x00\x00', # LONG_BINPUT
1178 b's', # SETITEM
1179 b'Ns',
1180 b'NNs',
1181 b't', # TUPLE
1182 b'u', # SETITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001183 b'(u',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001184 b'}(Nu',
1185 b'\x81', # NEWOBJ
1186 b')\x81',
1187 b'\x85', # TUPLE1
1188 b'\x86', # TUPLE2
1189 b'N\x86',
1190 b'\x87', # TUPLE3
1191 b'N\x87',
1192 b'NN\x87',
1193 b'\x90', # ADDITEMS
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001194 b'(\x90',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001195 b'\x91', # FROZENSET
1196 b'\x92', # NEWOBJ_EX
1197 b')}\x92',
1198 b'\x93', # STACK_GLOBAL
1199 b'Vlist\n\x93',
1200 b'\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001201 ]
1202 for p in badpickles:
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001203 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001204
1205 def test_bad_mark(self):
1206 badpickles = [
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001207 b'N(.', # STOP
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001208 b'N(2', # DUP
1209 b'cbuiltins\nlist\n)(R', # REDUCE
1210 b'cbuiltins\nlist\n()R',
1211 b']N(a', # APPEND
1212 # BUILD
1213 b'cbuiltins\nValueError\n)R}(b',
1214 b'cbuiltins\nValueError\n)R(}b',
1215 b'(Nd', # DICT
1216 b'N(p1\n', # PUT
1217 b'N(q\x00', # BINPUT
1218 b'N(r\x00\x00\x00\x00', # LONG_BINPUT
1219 b'}NN(s', # SETITEM
1220 b'}N(Ns',
1221 b'}(NNs',
1222 b'}((u', # SETITEMS
1223 b'cbuiltins\nlist\n)(\x81', # NEWOBJ
1224 b'cbuiltins\nlist\n()\x81',
1225 b'N(\x85', # TUPLE1
1226 b'NN(\x86', # TUPLE2
1227 b'N(N\x86',
1228 b'NNN(\x87', # TUPLE3
1229 b'NN(N\x87',
1230 b'N(NN\x87',
1231 b']((\x90', # ADDITEMS
1232 # NEWOBJ_EX
1233 b'cbuiltins\nlist\n)}(\x92',
1234 b'cbuiltins\nlist\n)(}\x92',
1235 b'cbuiltins\nlist\n()}\x92',
1236 # STACK_GLOBAL
1237 b'Vbuiltins\n(Vlist\n\x93',
1238 b'Vbuiltins\nVlist\n(\x93',
1239 b'N(\x94', # MEMOIZE
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001240 ]
1241 for p in badpickles:
Serhiy Storchaka59fb6342015-12-06 22:01:35 +02001242 self.check_unpickling_error(self.bad_stack_errors, p)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001243
1244 def test_truncated_data(self):
1245 self.check_unpickling_error(EOFError, b'')
1246 self.check_unpickling_error(EOFError, b'N')
1247 badpickles = [
1248 b'B', # BINBYTES
1249 b'B\x03\x00\x00',
1250 b'B\x03\x00\x00\x00',
1251 b'B\x03\x00\x00\x00ab',
1252 b'C', # SHORT_BINBYTES
1253 b'C\x03',
1254 b'C\x03ab',
1255 b'F', # FLOAT
1256 b'F0.0',
1257 b'F0.00',
1258 b'G', # BINFLOAT
1259 b'G\x00\x00\x00\x00\x00\x00\x00',
1260 b'I', # INT
1261 b'I0',
1262 b'J', # BININT
1263 b'J\x00\x00\x00',
1264 b'K', # BININT1
1265 b'L', # LONG
1266 b'L0',
1267 b'L10',
1268 b'L0L',
1269 b'L10L',
1270 b'M', # BININT2
1271 b'M\x00',
1272 # b'P', # PERSID
1273 # b'Pabc',
1274 b'S', # STRING
1275 b"S'abc'",
1276 b'T', # BINSTRING
1277 b'T\x03\x00\x00',
1278 b'T\x03\x00\x00\x00',
1279 b'T\x03\x00\x00\x00ab',
1280 b'U', # SHORT_BINSTRING
1281 b'U\x03',
1282 b'U\x03ab',
1283 b'V', # UNICODE
1284 b'Vabc',
1285 b'X', # BINUNICODE
1286 b'X\x03\x00\x00',
1287 b'X\x03\x00\x00\x00',
1288 b'X\x03\x00\x00\x00ab',
1289 b'(c', # GLOBAL
1290 b'(cbuiltins',
1291 b'(cbuiltins\n',
1292 b'(cbuiltins\nlist',
1293 b'Ng', # GET
1294 b'Ng0',
1295 b'(i', # INST
1296 b'(ibuiltins',
1297 b'(ibuiltins\n',
1298 b'(ibuiltins\nlist',
1299 b'Nh', # BINGET
1300 b'Nj', # LONG_BINGET
1301 b'Nj\x00\x00\x00',
1302 b'Np', # PUT
1303 b'Np0',
1304 b'Nq', # BINPUT
1305 b'Nr', # LONG_BINPUT
1306 b'Nr\x00\x00\x00',
1307 b'\x80', # PROTO
1308 b'\x82', # EXT1
1309 b'\x83', # EXT2
1310 b'\x84\x01',
1311 b'\x84', # EXT4
1312 b'\x84\x01\x00\x00',
1313 b'\x8a', # LONG1
1314 b'\x8b', # LONG4
1315 b'\x8b\x00\x00\x00',
1316 b'\x8c', # SHORT_BINUNICODE
1317 b'\x8c\x03',
1318 b'\x8c\x03ab',
1319 b'\x8d', # BINUNICODE8
1320 b'\x8d\x03\x00\x00\x00\x00\x00\x00',
1321 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
1322 b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
1323 b'\x8e', # BINBYTES8
1324 b'\x8e\x03\x00\x00\x00\x00\x00\x00',
1325 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
1326 b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
Antoine Pitrou91f43802019-05-26 17:10:09 +02001327 b'\x96', # BYTEARRAY8
1328 b'\x96\x03\x00\x00\x00\x00\x00\x00',
1329 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00',
1330 b'\x96\x03\x00\x00\x00\x00\x00\x00\x00ab',
Serhiy Storchaka7279bef2015-11-29 13:12:10 +02001331 b'\x95', # FRAME
1332 b'\x95\x02\x00\x00\x00\x00\x00\x00',
1333 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
1334 b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
1335 ]
1336 for p in badpickles:
1337 self.check_unpickling_error(self.truncated_errors, p)
Serhiy Storchakae9b30742015-11-23 15:17:43 +02001338
tjb9004371c0a2019-02-18 23:30:51 +08001339 @reap_threads
1340 def test_unpickle_module_race(self):
1341 # https://bugs.python.org/issue34572
1342 locker_module = dedent("""
1343 import threading
1344 barrier = threading.Barrier(2)
1345 """)
1346 locking_import_module = dedent("""
1347 import locker
1348 locker.barrier.wait()
1349 class ToBeUnpickled(object):
1350 pass
1351 """)
1352
1353 os.mkdir(TESTFN)
1354 self.addCleanup(shutil.rmtree, TESTFN)
1355 sys.path.insert(0, TESTFN)
1356 self.addCleanup(sys.path.remove, TESTFN)
1357 with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
1358 f.write(locker_module.encode('utf-8'))
1359 with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
1360 f.write(locking_import_module.encode('utf-8'))
1361 self.addCleanup(forget, "locker")
1362 self.addCleanup(forget, "locking_import")
1363
1364 import locker
1365
1366 pickle_bytes = (
1367 b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
1368
1369 # Then try to unpickle two of these simultaneously
1370 # One of them will cause the module import, and we want it to block
1371 # until the other one either:
1372 # - fails (before the patch for this issue)
1373 # - blocks on the import lock for the module, as it should
1374 results = []
1375 barrier = threading.Barrier(3)
1376 def t():
1377 # This ensures the threads have all started
1378 # presumably barrier release is faster than thread startup
1379 barrier.wait()
1380 results.append(pickle.loads(pickle_bytes))
1381
1382 t1 = threading.Thread(target=t)
1383 t2 = threading.Thread(target=t)
1384 t1.start()
1385 t2.start()
1386
1387 barrier.wait()
1388 # could have delay here
1389 locker.barrier.wait()
1390
1391 t1.join()
1392 t2.join()
1393
1394 from locking_import import ToBeUnpickled
1395 self.assertEqual(
1396 [type(x) for x in results],
1397 [ToBeUnpickled] * 2)
1398
1399
Serhiy Storchakac6b54b42015-09-29 15:33:24 +03001400
1401class AbstractPickleTests(unittest.TestCase):
1402 # Subclass must define self.dumps, self.loads.
1403
1404 optimized = False
1405
1406 _testdata = AbstractUnpickleTests._testdata
1407
1408 def setUp(self):
1409 pass
1410
1411 assert_is_copy = AbstractUnpickleTests.assert_is_copy
1412
1413 def test_misc(self):
1414 # test various datatypes not tested by testdata
1415 for proto in protocols:
1416 x = myint(4)
1417 s = self.dumps(x, proto)
1418 y = self.loads(s)
1419 self.assert_is_copy(x, y)
1420
1421 x = (1, ())
1422 s = self.dumps(x, proto)
1423 y = self.loads(s)
1424 self.assert_is_copy(x, y)
1425
1426 x = initarg(1, x)
1427 s = self.dumps(x, proto)
1428 y = self.loads(s)
1429 self.assert_is_copy(x, y)
1430
1431 # XXX test __reduce__ protocol?
1432
1433 def test_roundtrip_equality(self):
1434 expected = self._testdata
1435 for proto in protocols:
1436 s = self.dumps(expected, proto)
1437 got = self.loads(s)
1438 self.assert_is_copy(expected, got)
1439
Tim Peters70b02d72003-02-02 17:26:40 +00001440 # There are gratuitous differences between pickles produced by
1441 # pickle and cPickle, largely because cPickle starts PUT indices at
1442 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
1443 # there's a comment with an exclamation point there whose meaning
1444 # is a mystery. cPickle also suppresses PUT for objects with a refcount
1445 # of 1.
1446 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +00001447 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +00001448 from pickletools import dis
1449
1450 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
1451 s = self.dumps(self._testdata, proto)
1452 filelike = StringIO()
1453 dis(s, out=filelike)
1454 got = filelike.getvalue()
1455 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +00001456
1457 def test_recursive_list(self):
1458 l = []
1459 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +00001460 for proto in protocols:
1461 s = self.dumps(l, proto)
1462 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001463 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001464 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001465 self.assertIs(x[0], x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001466
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001467 def test_recursive_tuple_and_list(self):
Collin Winter8ca69de2009-05-26 16:53:41 +00001468 t = ([],)
1469 t[0].append(t)
1470 for proto in protocols:
1471 s = self.dumps(t, proto)
1472 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001473 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +00001474 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001475 self.assertIsInstance(x[0], list)
Collin Winter8ca69de2009-05-26 16:53:41 +00001476 self.assertEqual(len(x[0]), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001477 self.assertIs(x[0][0], x)
Collin Winter8ca69de2009-05-26 16:53:41 +00001478
Jeremy Hylton66426532001-10-15 21:38:56 +00001479 def test_recursive_dict(self):
1480 d = {}
1481 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +00001482 for proto in protocols:
1483 s = self.dumps(d, proto)
1484 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001485 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001486 self.assertEqual(list(x.keys()), [1])
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001487 self.assertIs(x[1], x)
1488
1489 def test_recursive_dict_key(self):
1490 d = {}
1491 k = K(d)
1492 d[k] = 1
1493 for proto in protocols:
1494 s = self.dumps(d, proto)
1495 x = self.loads(s)
1496 self.assertIsInstance(x, dict)
1497 self.assertEqual(len(x.keys()), 1)
1498 self.assertIsInstance(list(x.keys())[0], K)
1499 self.assertIs(list(x.keys())[0].value, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001500
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001501 def test_recursive_set(self):
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001502 y = set()
1503 k = K(y)
1504 y.add(k)
1505 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001506 s = self.dumps(y, proto)
1507 x = self.loads(s)
1508 self.assertIsInstance(x, set)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001509 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001510 self.assertIsInstance(list(x)[0], K)
1511 self.assertIs(list(x)[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001512
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001513 def test_recursive_list_subclass(self):
1514 y = MyList()
1515 y.append(y)
1516 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001517 s = self.dumps(y, proto)
1518 x = self.loads(s)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001519 self.assertIsInstance(x, MyList)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001520 self.assertEqual(len(x), 1)
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001521 self.assertIs(x[0], x)
1522
1523 def test_recursive_dict_subclass(self):
1524 d = MyDict()
1525 d[1] = d
1526 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1527 s = self.dumps(d, proto)
1528 x = self.loads(s)
1529 self.assertIsInstance(x, MyDict)
1530 self.assertEqual(list(x.keys()), [1])
1531 self.assertIs(x[1], x)
1532
1533 def test_recursive_dict_subclass_key(self):
1534 d = MyDict()
1535 k = K(d)
1536 d[k] = 1
1537 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
1538 s = self.dumps(d, proto)
1539 x = self.loads(s)
1540 self.assertIsInstance(x, MyDict)
1541 self.assertEqual(len(list(x.keys())), 1)
1542 self.assertIsInstance(list(x.keys())[0], K)
1543 self.assertIs(list(x.keys())[0].value, x)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001544
Jeremy Hylton66426532001-10-15 21:38:56 +00001545 def test_recursive_inst(self):
1546 i = C()
1547 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +00001548 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001549 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +00001550 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001551 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001552 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +02001553 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001554
1555 def test_recursive_multi(self):
1556 l = []
1557 d = {1:l}
1558 i = C()
1559 i.attr = d
1560 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +00001561 for proto in protocols:
1562 s = self.dumps(l, proto)
1563 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001564 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +00001565 self.assertEqual(len(x), 1)
1566 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +00001567 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001568 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +00001569
Serhiy Storchaka608c2132015-11-07 11:16:10 +02001570 def check_recursive_collection_and_inst(self, factory):
1571 h = H()
1572 y = factory([h])
1573 h.attr = y
1574 for proto in protocols:
1575 s = self.dumps(y, proto)
1576 x = self.loads(s)
1577 self.assertIsInstance(x, type(y))
1578 self.assertEqual(len(x), 1)
1579 self.assertIsInstance(list(x)[0], H)
1580 self.assertIs(list(x)[0].attr, x)
1581
1582 def test_recursive_list_and_inst(self):
1583 self.check_recursive_collection_and_inst(list)
1584
1585 def test_recursive_tuple_and_inst(self):
1586 self.check_recursive_collection_and_inst(tuple)
1587
1588 def test_recursive_dict_and_inst(self):
1589 self.check_recursive_collection_and_inst(dict.fromkeys)
1590
1591 def test_recursive_set_and_inst(self):
1592 self.check_recursive_collection_and_inst(set)
1593
1594 def test_recursive_frozenset_and_inst(self):
1595 self.check_recursive_collection_and_inst(frozenset)
1596
1597 def test_recursive_list_subclass_and_inst(self):
1598 self.check_recursive_collection_and_inst(MyList)
1599
1600 def test_recursive_tuple_subclass_and_inst(self):
1601 self.check_recursive_collection_and_inst(MyTuple)
1602
1603 def test_recursive_dict_subclass_and_inst(self):
1604 self.check_recursive_collection_and_inst(MyDict.fromkeys)
1605
1606 def test_recursive_set_subclass_and_inst(self):
1607 self.check_recursive_collection_and_inst(MySet)
1608
1609 def test_recursive_frozenset_subclass_and_inst(self):
1610 self.check_recursive_collection_and_inst(MyFrozenSet)
1611
Walter Dörwald9b775532007-06-08 14:30:53 +00001612 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +00001613 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +00001614 '<\\>', '<\\\U00012345>',
1615 # surrogates
1616 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +00001617 for proto in protocols:
1618 for u in endcases:
1619 p = self.dumps(u, proto)
1620 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001621 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +00001622
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001623 def test_unicode_high_plane(self):
1624 t = '\U00012345'
1625 for proto in protocols:
1626 p = self.dumps(t, proto)
1627 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001628 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +00001629
Guido van Rossumf4169812008-03-17 22:56:06 +00001630 def test_bytes(self):
1631 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001632 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001633 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001634 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001635 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001636 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001637 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -05001638 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +02001639 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001640 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +00001641
Antoine Pitrou91f43802019-05-26 17:10:09 +02001642 def test_bytearray(self):
1643 for proto in protocols:
1644 for s in b'', b'xyz', b'xyz'*100:
1645 b = bytearray(s)
1646 p = self.dumps(b, proto)
1647 bb = self.loads(p)
1648 self.assertIsNot(bb, b)
1649 self.assert_is_copy(b, bb)
1650 if proto <= 3:
1651 # bytearray is serialized using a global reference
1652 self.assertIn(b'bytearray', p)
1653 self.assertTrue(opcode_in_pickle(pickle.GLOBAL, p))
1654 elif proto == 4:
1655 self.assertIn(b'bytearray', p)
1656 self.assertTrue(opcode_in_pickle(pickle.STACK_GLOBAL, p))
1657 elif proto == 5:
1658 self.assertNotIn(b'bytearray', p)
1659 self.assertTrue(opcode_in_pickle(pickle.BYTEARRAY8, p))
1660
Jeremy Hylton66426532001-10-15 21:38:56 +00001661 def test_ints(self):
Tim Petersee1a53c2003-02-02 02:57:53 +00001662 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +00001663 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +00001664 while n:
1665 for expected in (-n, n):
1666 s = self.dumps(expected, proto)
1667 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001668 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001669 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +00001670
Tim Petersee1a53c2003-02-02 02:57:53 +00001671 def test_long(self):
1672 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +00001673 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +00001674 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001675 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +00001676 for npos in nbase-1, nbase, nbase+1:
1677 for n in npos, -npos:
1678 pickle = self.dumps(n, proto)
1679 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001680 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001681 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
1682 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +00001683 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +00001684 nbase += nbase << 1000000
1685 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +00001686 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +00001687 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +01001688 # assert_is_copy is very expensive here as it precomputes
1689 # a failure message by computing the repr() of n and got,
1690 # we just do the check ourselves.
1691 self.assertIs(type(got), int)
1692 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +00001693
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001694 def test_float(self):
1695 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
1696 3.14, 263.44582062374053, 6.022e23, 1e30]
1697 test_values = test_values + [-x for x in test_values]
1698 for proto in protocols:
1699 for value in test_values:
1700 pickle = self.dumps(value, proto)
1701 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001702 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +00001703
Thomas Wouters477c8d52006-05-27 19:21:47 +00001704 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
1705 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +00001706 # make sure that floats are formatted locale independent with proto 0
1707 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +00001708
Jeremy Hylton66426532001-10-15 21:38:56 +00001709 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001710 for proto in protocols:
1711 inst = AAA()
1712 dumped = self.dumps(inst, proto)
1713 loaded = self.loads(dumped)
1714 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +00001715
1716 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +01001717 for proto in protocols:
1718 inst = initarg(1, 2)
1719 dumped = self.dumps(inst, proto)
1720 loaded = self.loads(dumped)
1721 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +00001722
Guido van Rossum04a86612001-12-19 16:58:54 +00001723 def test_metaclass(self):
1724 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +00001725 for proto in protocols:
1726 s = self.dumps(a, proto)
1727 b = self.loads(s)
1728 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +00001729
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001730 def test_dynamic_class(self):
1731 a = create_dynamic_class("my_dynamic_class", (object,))
1732 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
1733 for proto in protocols:
1734 s = self.dumps(a, proto)
1735 b = self.loads(s)
1736 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001737 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +02001738
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001739 def test_structseq(self):
1740 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +00001741 import os
Tim Peters70b02d72003-02-02 17:26:40 +00001742
1743 t = time.localtime()
1744 for proto in protocols:
1745 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +00001746 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001747 self.assert_is_copy(t, u)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001748 t = os.stat(os.curdir)
1749 s = self.dumps(t, proto)
1750 u = self.loads(s)
1751 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +00001752 if hasattr(os, "statvfs"):
1753 t = os.statvfs(os.curdir)
1754 s = self.dumps(t, proto)
1755 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001756 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +00001757
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001758 def test_ellipsis(self):
1759 for proto in protocols:
1760 s = self.dumps(..., proto)
1761 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001762 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001763
1764 def test_notimplemented(self):
1765 for proto in protocols:
1766 s = self.dumps(NotImplemented, proto)
1767 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001768 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +01001769
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -08001770 def test_singleton_types(self):
1771 # Issue #6477: Test that types of built-in singletons can be pickled.
1772 singletons = [None, ..., NotImplemented]
1773 for singleton in singletons:
1774 for proto in protocols:
1775 s = self.dumps(type(singleton), proto)
1776 u = self.loads(s)
1777 self.assertIs(type(singleton), u)
1778
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001779 # Tests for protocol 2
1780
Tim Peters4190fb82003-02-02 16:09:05 +00001781 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +00001782 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001783 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +00001784 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001785 proto_header = pickle.PROTO + bytes([proto])
1786 self.assertTrue(pickled.startswith(proto_header))
1787 else:
1788 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +00001789
1790 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001791 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001792 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +00001793 try:
1794 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001795 except ValueError as err:
1796 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +00001797 else:
1798 self.fail("expected bad protocol number to raise ValueError")
1799
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001800 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001801 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +00001802 for proto in protocols:
1803 s = self.dumps(x, proto)
1804 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001805 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001806 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001807
1808 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +00001809 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +00001810 for proto in protocols:
1811 s = self.dumps(x, proto)
1812 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001813 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +00001814 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +00001815
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001816 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +00001817 # Map (proto, len(tuple)) to expected opcode.
1818 expected_opcode = {(0, 0): pickle.TUPLE,
1819 (0, 1): pickle.TUPLE,
1820 (0, 2): pickle.TUPLE,
1821 (0, 3): pickle.TUPLE,
1822 (0, 4): pickle.TUPLE,
1823
1824 (1, 0): pickle.EMPTY_TUPLE,
1825 (1, 1): pickle.TUPLE,
1826 (1, 2): pickle.TUPLE,
1827 (1, 3): pickle.TUPLE,
1828 (1, 4): pickle.TUPLE,
1829
1830 (2, 0): pickle.EMPTY_TUPLE,
1831 (2, 1): pickle.TUPLE1,
1832 (2, 2): pickle.TUPLE2,
1833 (2, 3): pickle.TUPLE3,
1834 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001835
1836 (3, 0): pickle.EMPTY_TUPLE,
1837 (3, 1): pickle.TUPLE1,
1838 (3, 2): pickle.TUPLE2,
1839 (3, 3): pickle.TUPLE3,
1840 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +00001841 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001842 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +00001843 b = (1,)
1844 c = (1, 2)
1845 d = (1, 2, 3)
1846 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +00001847 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +00001848 for x in a, b, c, d, e:
1849 s = self.dumps(x, proto)
1850 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001851 self.assert_is_copy(x, y)
1852 expected = expected_opcode[min(proto, 3), len(x)]
1853 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +00001854
Guido van Rossum7d97d312003-01-28 04:25:27 +00001855 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +00001856 # Map (proto, singleton) to expected opcode.
1857 expected_opcode = {(0, None): pickle.NONE,
1858 (1, None): pickle.NONE,
1859 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001860 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +00001861
1862 (0, True): pickle.INT,
1863 (1, True): pickle.INT,
1864 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001865 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +00001866
1867 (0, False): pickle.INT,
1868 (1, False): pickle.INT,
1869 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +00001870 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +00001871 }
Tim Peters4190fb82003-02-02 16:09:05 +00001872 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +00001873 for x in None, False, True:
1874 s = self.dumps(x, proto)
1875 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001876 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001877 expected = expected_opcode[min(proto, 3), x]
1878 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +00001879
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001880 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001881 x = MyTuple([1, 2, 3])
1882 x.foo = 42
1883 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001884 for proto in protocols:
1885 s = self.dumps(x, proto)
1886 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001887 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001888
1889 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001890 x = MyList([1, 2, 3])
1891 x.foo = 42
1892 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001893 for proto in protocols:
1894 s = self.dumps(x, proto)
1895 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001896 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001897
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001898 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001899 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001900 for C in myclasses:
1901 B = C.__base__
1902 x = C(C.sample)
1903 x.foo = 42
1904 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001905 y = self.loads(s)
1906 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001907 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001908 self.assertEqual(B(x), B(y), detail)
1909 self.assertEqual(x.__dict__, y.__dict__, detail)
1910
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001911 def test_newobj_proxies(self):
1912 # NEWOBJ should use the __class__ rather than the raw type
1913 classes = myclasses[:]
1914 # Cannot create weakproxies to these classes
1915 for c in (MyInt, MyTuple):
1916 classes.remove(c)
1917 for proto in protocols:
1918 for C in classes:
1919 B = C.__base__
1920 x = C(C.sample)
1921 x.foo = 42
1922 p = weakref.proxy(x)
1923 s = self.dumps(p, proto)
1924 y = self.loads(s)
1925 self.assertEqual(type(y), type(x)) # rather than type(p)
1926 detail = (proto, C, B, x, y, type(y))
1927 self.assertEqual(B(x), B(y), detail)
1928 self.assertEqual(x.__dict__, y.__dict__, detail)
1929
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001930 def test_newobj_not_class(self):
1931 # Issue 24552
1932 global SimpleNewObj
1933 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001934 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001935 b = self.dumps(o, 4)
1936 try:
1937 SimpleNewObj = 42
1938 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1939 finally:
1940 SimpleNewObj = save
1941
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001942 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001943 # an object of that type. Check that the resulting pickle uses opcode
1944 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001945
Tim Peters22e71712003-02-03 22:27:38 +00001946 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001947 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001948 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001949 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001950 x = MyList([1, 2, 3])
1951 x.foo = 42
1952 x.bar = "hello"
1953
Tim Peters22e71712003-02-03 22:27:38 +00001954 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001955 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001956 self.assertIn(__name__.encode("utf-8"), s1)
1957 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001958 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001959
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001960 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001961 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001962
Tim Peters22e71712003-02-03 22:27:38 +00001963 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001964 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001965 self.assertNotIn(__name__.encode("utf-8"), s2)
1966 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001967 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001968
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001969 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001970 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001971 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001972 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001973
1974 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001975 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1976 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001977
1978 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001979 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1980 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1981 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001982
1983 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001984 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1985 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
1986 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
1987
Tim Peters8d2613a2003-02-11 16:40:16 +00001988 def test_list_chunking(self):
1989 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00001990 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001991 for proto in protocols:
1992 s = self.dumps(x, proto)
1993 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001994 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001995 num_appends = count_opcode(pickle.APPENDS, s)
1996 self.assertEqual(num_appends, proto > 0)
1997
1998 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001999 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00002000 for proto in protocols:
2001 s = self.dumps(x, proto)
2002 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002003 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002004 num_appends = count_opcode(pickle.APPENDS, s)
2005 if proto == 0:
2006 self.assertEqual(num_appends, 0)
2007 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002008 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00002009
2010 def test_dict_chunking(self):
2011 n = 10 # too small to chunk
2012 x = dict.fromkeys(range(n))
2013 for proto in protocols:
2014 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00002015 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00002016 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002017 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002018 num_setitems = count_opcode(pickle.SETITEMS, s)
2019 self.assertEqual(num_setitems, proto > 0)
2020
2021 n = 2500 # expect at least two chunks when proto > 0
2022 x = dict.fromkeys(range(n))
2023 for proto in protocols:
2024 s = self.dumps(x, proto)
2025 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002026 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00002027 num_setitems = count_opcode(pickle.SETITEMS, s)
2028 if proto == 0:
2029 self.assertEqual(num_setitems, 0)
2030 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002031 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00002032
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002033 def test_set_chunking(self):
2034 n = 10 # too small to chunk
2035 x = set(range(n))
2036 for proto in protocols:
2037 s = self.dumps(x, proto)
2038 y = self.loads(s)
2039 self.assert_is_copy(x, y)
2040 num_additems = count_opcode(pickle.ADDITEMS, s)
2041 if proto < 4:
2042 self.assertEqual(num_additems, 0)
2043 else:
2044 self.assertEqual(num_additems, 1)
2045
2046 n = 2500 # expect at least two chunks when proto >= 4
2047 x = set(range(n))
2048 for proto in protocols:
2049 s = self.dumps(x, proto)
2050 y = self.loads(s)
2051 self.assert_is_copy(x, y)
2052 num_additems = count_opcode(pickle.ADDITEMS, s)
2053 if proto < 4:
2054 self.assertEqual(num_additems, 0)
2055 else:
2056 self.assertGreaterEqual(num_additems, 2)
2057
Tim Peterse9ef2032003-02-13 18:42:00 +00002058 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002059 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00002060 x.abc = 666
2061 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002062 with self.subTest(proto=proto):
2063 s = self.dumps(x, proto)
2064 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002065 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002066 else:
2067 self.assertIn(b'M\xce\xfa', s) # BININT2
2068 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2069 2 <= proto)
2070 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2071 y = self.loads(s) # will raise TypeError if __init__ called
2072 self.assert_is_copy(x, y)
2073
2074 def test_complex_newobj(self):
2075 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
2076 x.abc = 666
2077 for proto in protocols:
2078 with self.subTest(proto=proto):
2079 s = self.dumps(x, proto)
2080 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002081 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002082 elif proto < 2:
2083 self.assertIn(b'M\xce\xfa', s) # BININT2
2084 elif proto < 4:
2085 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
2086 else:
2087 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2088 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
2089 2 <= proto)
2090 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
2091 y = self.loads(s) # will raise TypeError if __init__ called
2092 self.assert_is_copy(x, y)
2093
2094 def test_complex_newobj_ex(self):
2095 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
2096 x.abc = 666
2097 for proto in protocols:
2098 with self.subTest(proto=proto):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002099 s = self.dumps(x, proto)
2100 if proto < 1:
Serhiy Storchaka3daaafb2017-11-16 09:44:43 +02002101 self.assertIn(b'\nI64206', s) # INT
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002102 elif proto < 2:
2103 self.assertIn(b'M\xce\xfa', s) # BININT2
Serhiy Storchaka0d554d72015-10-10 22:42:18 +03002104 elif proto < 4:
2105 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002106 else:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02002107 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
2108 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
2109 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
2110 4 <= proto)
2111 y = self.loads(s) # will raise TypeError if __init__ called
2112 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00002113
Tim Peters42f08ac2003-02-11 22:43:24 +00002114 def test_newobj_list_slots(self):
2115 x = SlotList([1, 2, 3])
2116 x.foo = 42
2117 x.bar = "hello"
2118 s = self.dumps(x, 2)
2119 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002120 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00002121
Guido van Rossum2a30b212003-02-18 22:41:24 +00002122 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00002123 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002124 x = REX_one()
2125 self.assertEqual(x._reduce_called, 0)
2126 s = self.dumps(x, proto)
2127 self.assertEqual(x._reduce_called, 1)
2128 y = self.loads(s)
2129 self.assertEqual(y._reduce_called, 0)
2130
2131 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00002132 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002133 x = REX_two()
2134 self.assertEqual(x._proto, None)
2135 s = self.dumps(x, proto)
2136 self.assertEqual(x._proto, proto)
2137 y = self.loads(s)
2138 self.assertEqual(y._proto, None)
2139
2140 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00002141 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00002142 x = REX_three()
2143 self.assertEqual(x._proto, None)
2144 s = self.dumps(x, proto)
2145 self.assertEqual(x._proto, proto)
2146 y = self.loads(s)
2147 self.assertEqual(y._proto, None)
2148
Guido van Rossumd8faa362007-04-27 19:54:29 +00002149 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002150 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002151 x = REX_four()
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, proto)
2157
2158 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00002159 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002160 x = REX_five()
2161 self.assertEqual(x._reduce_called, 0)
2162 s = self.dumps(x, proto)
2163 self.assertEqual(x._reduce_called, 1)
2164 y = self.loads(s)
2165 self.assertEqual(y._reduce_called, 1)
2166
Brett Cannon31f59292011-02-21 19:29:56 +00002167 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002168 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002169 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002170 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002171 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002172 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00002173
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002174 def test_reduce_bad_iterator(self):
2175 # Issue4176: crash when 4th and 5th items of __reduce__()
2176 # are not iterators
2177 class C(object):
2178 def __reduce__(self):
2179 # 4th item is not an iterator
2180 return list, (), None, [], None
2181 class D(object):
2182 def __reduce__(self):
2183 # 5th item is not an iterator
2184 return dict, (), None, None, []
2185
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002186 # Python implementation is less strict and also accepts iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002187 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002188 try:
2189 self.dumps(C(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002190 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002191 pass
2192 try:
2193 self.dumps(D(), proto)
Serhiy Storchakabeb652c2015-12-30 21:00:08 +02002194 except pickle.PicklingError:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00002195 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00002196
Collin Winter771d8342009-04-16 03:18:06 +00002197 def test_many_puts_and_gets(self):
2198 # Test that internal data structures correctly deal with lots of
2199 # puts/gets.
2200 keys = ("aaa" + str(i) for i in range(100))
2201 large_dict = dict((k, [4, 5, 6]) for k in keys)
2202 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
2203
2204 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002205 with self.subTest(proto=proto):
2206 dumped = self.dumps(obj, proto)
2207 loaded = self.loads(dumped)
2208 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00002209
Antoine Pitroua9f48a02009-05-02 21:41:14 +00002210 def test_attribute_name_interning(self):
2211 # Test that attribute names of pickled objects are interned when
2212 # unpickling.
2213 for proto in protocols:
2214 x = C()
2215 x.foo = 42
2216 x.bar = "hello"
2217 s = self.dumps(x, proto)
2218 y = self.loads(s)
2219 x_keys = sorted(x.__dict__)
2220 y_keys = sorted(y.__dict__)
2221 for x_key, y_key in zip(x_keys, y_keys):
2222 self.assertIs(x_key, y_key)
2223
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002224 def test_pickle_to_2x(self):
2225 # Pickle non-trivial data with protocol 2, expecting that it yields
2226 # the same result as Python 2.x did.
2227 # NOTE: this test is a bit too strong since we can produce different
2228 # bytecode that 2.x will still understand.
2229 dumped = self.dumps(range(5), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002230 self.assertEqual(dumped, DATA_XRANGE)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002231 dumped = self.dumps(set([3]), 2)
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03002232 self.assertEqual(dumped, DATA_SET2)
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00002233
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002234 def test_large_pickles(self):
2235 # Test the correctness of internal buffering routines when handling
2236 # large data.
2237 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00002238 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002239 dumped = self.dumps(data, proto)
2240 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002241 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00002242 self.assertEqual(loaded, data)
2243
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002244 def test_int_pickling_efficiency(self):
2245 # Test compacity of int representation (see issue #12744)
2246 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002247 with self.subTest(proto=proto):
2248 pickles = [self.dumps(2**n, proto) for n in range(70)]
2249 sizes = list(map(len, pickles))
2250 # the size function is monotonic
2251 self.assertEqual(sorted(sizes), sizes)
2252 if proto >= 2:
2253 for p in pickles:
2254 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002255
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002256 def _check_pickling_with_opcode(self, obj, opcode, proto):
2257 pickled = self.dumps(obj, proto)
2258 self.assertTrue(opcode_in_pickle(opcode, pickled))
2259 unpickled = self.loads(pickled)
2260 self.assertEqual(obj, unpickled)
2261
2262 def test_appends_on_non_lists(self):
2263 # Issue #17720
2264 obj = REX_six([1, 2, 3])
2265 for proto in protocols:
2266 if proto == 0:
2267 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
2268 else:
2269 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
2270
2271 def test_setitems_on_non_dicts(self):
2272 obj = REX_seven({1: -1, 2: -2, 3: -3})
2273 for proto in protocols:
2274 if proto == 0:
2275 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
2276 else:
2277 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
2278
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002279 # Exercise framing (proto >= 4) for significant workloads
2280
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002281 FRAME_SIZE_MIN = 4
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002282 FRAME_SIZE_TARGET = 64 * 1024
2283
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002284 def check_frame_opcodes(self, pickled):
2285 """
2286 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002287
2288 Note that binary objects that are larger than FRAME_SIZE_TARGET are not
2289 framed by default and are therefore considered a frame by themselves in
2290 the following consistency check.
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002291 """
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002292 frame_end = frameless_start = None
Antoine Pitrou91f43802019-05-26 17:10:09 +02002293 frameless_opcodes = {'BINBYTES', 'BINUNICODE', 'BINBYTES8',
2294 'BINUNICODE8', 'BYTEARRAY8'}
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002295 for op, arg, pos in pickletools.genops(pickled):
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002296 if frame_end is not None:
2297 self.assertLessEqual(pos, frame_end)
2298 if pos == frame_end:
2299 frame_end = None
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002300
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002301 if frame_end is not None: # framed
2302 self.assertNotEqual(op.name, 'FRAME')
2303 if op.name in frameless_opcodes:
2304 # Only short bytes and str objects should be written
2305 # in a frame
2306 self.assertLessEqual(len(arg), self.FRAME_SIZE_TARGET)
2307
2308 else: # not framed
2309 if (op.name == 'FRAME' or
2310 (op.name in frameless_opcodes and
2311 len(arg) > self.FRAME_SIZE_TARGET)):
2312 # Frame or large bytes or str object
2313 if frameless_start is not None:
2314 # Only short data should be written outside of a frame
2315 self.assertLess(pos - frameless_start,
2316 self.FRAME_SIZE_MIN)
2317 frameless_start = None
2318 elif frameless_start is None and op.name != 'PROTO':
2319 frameless_start = pos
2320
2321 if op.name == 'FRAME':
2322 self.assertGreaterEqual(arg, self.FRAME_SIZE_MIN)
2323 frame_end = pos + 9 + arg
2324
2325 pos = len(pickled)
2326 if frame_end is not None:
2327 self.assertEqual(frame_end, pos)
2328 elif frameless_start is not None:
2329 self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002330
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002331 def test_framing_many_objects(self):
2332 obj = list(range(10**5))
2333 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2334 with self.subTest(proto=proto):
2335 pickled = self.dumps(obj, proto)
2336 unpickled = self.loads(pickled)
2337 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01002338 bytes_per_frame = (len(pickled) /
2339 count_opcode(pickle.FRAME, pickled))
2340 self.assertGreater(bytes_per_frame,
2341 self.FRAME_SIZE_TARGET / 2)
2342 self.assertLessEqual(bytes_per_frame,
2343 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01002344 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002345
2346 def test_framing_large_objects(self):
2347 N = 1024 * 1024
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002348 small_items = [[i] for i in range(10)]
2349 obj = [b'x' * N, *small_items, b'y' * N, 'z' * N]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002350 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002351 for fast in [False, True]:
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002352 with self.subTest(proto=proto, fast=fast):
Serhiy Storchaka0a2da502018-01-11 13:03:20 +02002353 if not fast:
2354 # fast=False by default.
2355 # This covers in-memory pickling with pickle.dumps().
2356 pickled = self.dumps(obj, proto)
2357 else:
2358 # Pickler is required when fast=True.
2359 if not hasattr(self, 'pickler'):
2360 continue
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002361 buf = io.BytesIO()
2362 pickler = self.pickler(buf, protocol=proto)
2363 pickler.fast = fast
2364 pickler.dump(obj)
2365 pickled = buf.getvalue()
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002366 unpickled = self.loads(pickled)
2367 # More informative error message in case of failure.
2368 self.assertEqual([len(x) for x in obj],
2369 [len(x) for x in unpickled])
2370 # Perform full equality check if the lengths match.
2371 self.assertEqual(obj, unpickled)
2372 n_frames = count_opcode(pickle.FRAME, pickled)
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002373 # A single frame for small objects between
2374 # first two large objects.
2375 self.assertEqual(n_frames, 1)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002376 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002377
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002378 def test_optional_frames(self):
2379 if pickle.HIGHEST_PROTOCOL < 4:
2380 return
2381
2382 def remove_frames(pickled, keep_frame=None):
2383 """Remove frame opcodes from the given pickle."""
2384 frame_starts = []
2385 # 1 byte for the opcode and 8 for the argument
2386 frame_opcode_size = 9
2387 for opcode, _, pos in pickletools.genops(pickled):
2388 if opcode.name == 'FRAME':
2389 frame_starts.append(pos)
2390
2391 newpickle = bytearray()
2392 last_frame_end = 0
2393 for i, pos in enumerate(frame_starts):
2394 if keep_frame and keep_frame(i):
2395 continue
2396 newpickle += pickled[last_frame_end:pos]
2397 last_frame_end = pos + frame_opcode_size
2398 newpickle += pickled[last_frame_end:]
2399 return newpickle
2400
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08002401 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002402 num_frames = 20
penguindustin96466302019-05-06 14:57:17 -04002403 # Large byte objects (dict values) intermittent with small objects
Serhiy Storchaka1211c9a2018-01-20 16:42:44 +02002404 # (dict keys)
Antoine Pitrou91f43802019-05-26 17:10:09 +02002405 for bytes_type in (bytes, bytearray):
2406 obj = {i: bytes_type([i]) * frame_size for i in range(num_frames)}
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002407
Antoine Pitrou91f43802019-05-26 17:10:09 +02002408 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
2409 pickled = self.dumps(obj, proto)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002410
Antoine Pitrou91f43802019-05-26 17:10:09 +02002411 frameless_pickle = remove_frames(pickled)
2412 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
2413 self.assertEqual(obj, self.loads(frameless_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002414
Antoine Pitrou91f43802019-05-26 17:10:09 +02002415 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
2416 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
2417 count_opcode(pickle.FRAME, pickled))
2418 self.assertEqual(obj, self.loads(some_frames_pickle))
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08002419
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002420 def test_framed_write_sizes_with_delayed_writer(self):
2421 class ChunkAccumulator:
2422 """Accumulate pickler output in a list of raw chunks."""
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002423 def __init__(self):
2424 self.chunks = []
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002425 def write(self, chunk):
2426 self.chunks.append(chunk)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002427 def concatenate_chunks(self):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002428 return b"".join(self.chunks)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002429
2430 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002431 objects = [(str(i).encode('ascii'), i % 42, {'i': str(i)})
2432 for i in range(int(1e4))]
2433 # Add a large unique ASCII string
2434 objects.append('0123456789abcdef' *
2435 (self.FRAME_SIZE_TARGET // 16 + 1))
2436
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002437 # Protocol 4 packs groups of small objects into frames and issues
2438 # calls to write only once or twice per frame:
2439 # The C pickler issues one call to write per-frame (header and
2440 # contents) while Python pickler issues two calls to write: one for
2441 # the frame header and one for the frame binary contents.
2442 writer = ChunkAccumulator()
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002443 self.pickler(writer, proto).dump(objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002444
2445 # Actually read the binary content of the chunks after the end
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002446 # of the call to dump: any memoryview passed to write should not
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002447 # be released otherwise this delayed access would not be possible.
2448 pickled = writer.concatenate_chunks()
2449 reconstructed = self.loads(pickled)
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002450 self.assertEqual(reconstructed, objects)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002451 self.assertGreater(len(writer.chunks), 1)
2452
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002453 # memoryviews should own the memory.
2454 del objects
2455 support.gc_collect()
2456 self.assertEqual(writer.concatenate_chunks(), pickled)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002457
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002458 n_frames = (len(pickled) - 1) // self.FRAME_SIZE_TARGET + 1
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002459 # There should be at least one call to write per frame
2460 self.assertGreaterEqual(len(writer.chunks), n_frames)
2461
2462 # but not too many either: there can be one for the proto,
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002463 # one per-frame header, one per frame for the actual contents,
2464 # and two for the header.
2465 self.assertLessEqual(len(writer.chunks), 2 * n_frames + 3)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002466
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002467 chunk_sizes = [len(c) for c in writer.chunks]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002468 large_sizes = [s for s in chunk_sizes
2469 if s >= self.FRAME_SIZE_TARGET]
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002470 medium_sizes = [s for s in chunk_sizes
2471 if 9 < s < self.FRAME_SIZE_TARGET]
2472 small_sizes = [s for s in chunk_sizes if s <= 9]
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002473
2474 # Large chunks should not be too large:
2475 for chunk_size in large_sizes:
Serhiy Storchaka5b76bdb2018-01-13 00:28:31 +02002476 self.assertLess(chunk_size, 2 * self.FRAME_SIZE_TARGET,
2477 chunk_sizes)
2478 # There shouldn't bee too many small chunks: the protocol header,
2479 # the frame headers and the large string headers are written
2480 # in small chunks.
2481 self.assertLessEqual(len(small_sizes),
2482 len(large_sizes) + len(medium_sizes) + 3,
2483 chunk_sizes)
Olivier Grisel3cd7c6e2018-01-06 16:18:54 +01002484
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002485 def test_nested_names(self):
2486 global Nested
2487 class Nested:
2488 class A:
2489 class B:
2490 class C:
2491 pass
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002492 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002493 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
2494 with self.subTest(proto=proto, obj=obj):
2495 unpickled = self.loads(self.dumps(obj, proto))
2496 self.assertIs(obj, unpickled)
2497
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002498 def test_recursive_nested_names(self):
2499 global Recursive
2500 class Recursive:
2501 pass
2502 Recursive.mod = sys.modules[Recursive.__module__]
2503 Recursive.__qualname__ = 'Recursive.mod.Recursive'
2504 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2505 with self.subTest(proto=proto):
2506 unpickled = self.loads(self.dumps(Recursive, proto))
2507 self.assertIs(unpickled, Recursive)
2508 del Recursive.mod # break reference loop
2509
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002510 def test_py_methods(self):
2511 global PyMethodsTest
2512 class PyMethodsTest:
2513 @staticmethod
2514 def cheese():
2515 return "cheese"
2516 @classmethod
2517 def wine(cls):
2518 assert cls is PyMethodsTest
2519 return "wine"
2520 def biscuits(self):
2521 assert isinstance(self, PyMethodsTest)
2522 return "biscuits"
2523 class Nested:
2524 "Nested class"
2525 @staticmethod
2526 def ketchup():
2527 return "ketchup"
2528 @classmethod
2529 def maple(cls):
2530 assert cls is PyMethodsTest.Nested
2531 return "maple"
2532 def pie(self):
2533 assert isinstance(self, PyMethodsTest.Nested)
2534 return "pie"
2535
2536 py_methods = (
2537 PyMethodsTest.cheese,
2538 PyMethodsTest.wine,
2539 PyMethodsTest().biscuits,
2540 PyMethodsTest.Nested.ketchup,
2541 PyMethodsTest.Nested.maple,
2542 PyMethodsTest.Nested().pie
2543 )
2544 py_unbound_methods = (
2545 (PyMethodsTest.biscuits, PyMethodsTest),
2546 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
2547 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002548 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002549 for method in py_methods:
2550 with self.subTest(proto=proto, method=method):
2551 unpickled = self.loads(self.dumps(method, proto))
2552 self.assertEqual(method(), unpickled())
2553 for method, cls in py_unbound_methods:
2554 obj = cls()
2555 with self.subTest(proto=proto, method=method):
2556 unpickled = self.loads(self.dumps(method, proto))
2557 self.assertEqual(method(obj), unpickled(obj))
2558
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002559 def test_c_methods(self):
2560 global Subclass
2561 class Subclass(tuple):
2562 class Nested(str):
2563 pass
2564
2565 c_methods = (
2566 # bound built-in method
2567 ("abcd".index, ("c",)),
2568 # unbound built-in method
2569 (str.index, ("abcd", "c")),
2570 # bound "slot" method
2571 ([1, 2, 3].__len__, ()),
2572 # unbound "slot" method
2573 (list.__len__, ([1, 2, 3],)),
2574 # bound "coexist" method
2575 ({1, 2}.__contains__, (2,)),
2576 # unbound "coexist" method
2577 (set.__contains__, ({1, 2}, 2)),
2578 # built-in class method
2579 (dict.fromkeys, (("a", 1), ("b", 2))),
2580 # built-in static method
2581 (bytearray.maketrans, (b"abc", b"xyz")),
2582 # subclass methods
2583 (Subclass([1,2,2]).count, (2,)),
2584 (Subclass.count, (Subclass([1,2,2]), 2)),
2585 (Subclass.Nested("sweet").count, ("e",)),
2586 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
2587 )
Serhiy Storchaka58e41342015-03-31 14:07:24 +03002588 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002589 for method, args in c_methods:
2590 with self.subTest(proto=proto, method=method):
2591 unpickled = self.loads(self.dumps(method, proto))
2592 self.assertEqual(method(*args), unpickled(*args))
2593
Serhiy Storchakabfe18242015-03-31 13:12:37 +03002594 def test_compat_pickle(self):
2595 tests = [
2596 (range(1, 7), '__builtin__', 'xrange'),
2597 (map(int, '123'), 'itertools', 'imap'),
2598 (functools.reduce, '__builtin__', 'reduce'),
2599 (dbm.whichdb, 'whichdb', 'whichdb'),
2600 (Exception(), 'exceptions', 'Exception'),
2601 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
2602 (collections.UserList(), 'UserList', 'UserList'),
2603 (collections.defaultdict(), 'collections', 'defaultdict'),
2604 ]
2605 for val, mod, name in tests:
2606 for proto in range(3):
2607 with self.subTest(type=type(val), proto=proto):
2608 pickled = self.dumps(val, proto)
2609 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
2610 self.assertIs(type(self.loads(pickled)), type(val))
2611
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01002612 def test_local_lookup_error(self):
2613 # Test that whichmodule() errors out cleanly when looking up
2614 # an assumed globally-reachable object fails.
2615 def f():
2616 pass
2617 # Since the function is local, lookup will fail
2618 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2619 with self.assertRaises((AttributeError, pickle.PicklingError)):
2620 pickletools.dis(self.dumps(f, proto))
2621 # Same without a __module__ attribute (exercises a different path
2622 # in _pickle.c).
2623 del f.__module__
2624 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2625 with self.assertRaises((AttributeError, pickle.PicklingError)):
2626 pickletools.dis(self.dumps(f, proto))
2627 # Yet a different path.
2628 f.__name__ = f.__qualname__
2629 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2630 with self.assertRaises((AttributeError, pickle.PicklingError)):
2631 pickletools.dis(self.dumps(f, proto))
2632
Antoine Pitrou91f43802019-05-26 17:10:09 +02002633 #
2634 # PEP 574 tests below
2635 #
2636
2637 def buffer_like_objects(self):
2638 # Yield buffer-like objects with the bytestring "abcdef" in them
2639 bytestring = b"abcdefgh"
2640 yield ZeroCopyBytes(bytestring)
2641 yield ZeroCopyBytearray(bytestring)
2642 if _testbuffer is not None:
2643 items = list(bytestring)
2644 value = int.from_bytes(bytestring, byteorder='little')
2645 for flags in (0, _testbuffer.ND_WRITABLE):
2646 # 1-D, contiguous
2647 yield PicklableNDArray(items, format='B', shape=(8,),
2648 flags=flags)
2649 # 2-D, C-contiguous
2650 yield PicklableNDArray(items, format='B', shape=(4, 2),
2651 strides=(2, 1), flags=flags)
2652 # 2-D, Fortran-contiguous
2653 yield PicklableNDArray(items, format='B',
2654 shape=(4, 2), strides=(1, 4),
2655 flags=flags)
2656
2657 def test_in_band_buffers(self):
2658 # Test in-band buffers (PEP 574)
2659 for obj in self.buffer_like_objects():
2660 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2661 data = self.dumps(obj, proto)
2662 if obj.c_contiguous and proto >= 5:
2663 # The raw memory bytes are serialized in physical order
2664 self.assertIn(b"abcdefgh", data)
2665 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 0)
2666 if proto >= 5:
2667 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data),
2668 1 if obj.readonly else 0)
2669 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data),
2670 0 if obj.readonly else 1)
2671 # Return a true value from buffer_callback should have
2672 # the same effect
2673 def buffer_callback(obj):
2674 return True
2675 data2 = self.dumps(obj, proto,
2676 buffer_callback=buffer_callback)
2677 self.assertEqual(data2, data)
2678
2679 new = self.loads(data)
2680 # It's a copy
2681 self.assertIsNot(new, obj)
2682 self.assertIs(type(new), type(obj))
2683 self.assertEqual(new, obj)
2684
2685 # XXX Unfortunately cannot test non-contiguous array
2686 # (see comment in PicklableNDArray.__reduce_ex__)
2687
2688 def test_oob_buffers(self):
2689 # Test out-of-band buffers (PEP 574)
2690 for obj in self.buffer_like_objects():
2691 for proto in range(0, 5):
2692 # Need protocol >= 5 for buffer_callback
2693 with self.assertRaises(ValueError):
2694 self.dumps(obj, proto,
2695 buffer_callback=[].append)
2696 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2697 buffers = []
2698 buffer_callback = lambda pb: buffers.append(pb.raw())
2699 data = self.dumps(obj, proto,
2700 buffer_callback=buffer_callback)
2701 self.assertNotIn(b"abcdefgh", data)
2702 self.assertEqual(count_opcode(pickle.SHORT_BINBYTES, data), 0)
2703 self.assertEqual(count_opcode(pickle.BYTEARRAY8, data), 0)
2704 self.assertEqual(count_opcode(pickle.NEXT_BUFFER, data), 1)
2705 self.assertEqual(count_opcode(pickle.READONLY_BUFFER, data),
2706 1 if obj.readonly else 0)
2707
2708 if obj.c_contiguous:
2709 self.assertEqual(bytes(buffers[0]), b"abcdefgh")
2710 # Need buffers argument to unpickle properly
2711 with self.assertRaises(pickle.UnpicklingError):
2712 self.loads(data)
2713
2714 new = self.loads(data, buffers=buffers)
2715 if obj.zero_copy_reconstruct:
2716 # Zero-copy achieved
2717 self.assertIs(new, obj)
2718 else:
2719 self.assertIs(type(new), type(obj))
2720 self.assertEqual(new, obj)
2721 # Non-sequence buffers accepted too
2722 new = self.loads(data, buffers=iter(buffers))
2723 if obj.zero_copy_reconstruct:
2724 # Zero-copy achieved
2725 self.assertIs(new, obj)
2726 else:
2727 self.assertIs(type(new), type(obj))
2728 self.assertEqual(new, obj)
2729
2730 def test_oob_buffers_writable_to_readonly(self):
2731 # Test reconstructing readonly object from writable buffer
2732 obj = ZeroCopyBytes(b"foobar")
2733 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2734 buffers = []
2735 buffer_callback = buffers.append
2736 data = self.dumps(obj, proto, buffer_callback=buffer_callback)
2737
2738 buffers = map(bytearray, buffers)
2739 new = self.loads(data, buffers=buffers)
2740 self.assertIs(type(new), type(obj))
2741 self.assertEqual(new, obj)
2742
2743 def test_picklebuffer_error(self):
2744 # PickleBuffer forbidden with protocol < 5
2745 pb = pickle.PickleBuffer(b"foobar")
2746 for proto in range(0, 5):
2747 with self.assertRaises(pickle.PickleError):
2748 self.dumps(pb, proto)
2749
2750 def test_buffer_callback_error(self):
2751 def buffer_callback(buffers):
2752 1/0
2753 pb = pickle.PickleBuffer(b"foobar")
2754 with self.assertRaises(ZeroDivisionError):
2755 self.dumps(pb, 5, buffer_callback=buffer_callback)
2756
2757 def test_buffers_error(self):
2758 pb = pickle.PickleBuffer(b"foobar")
2759 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2760 data = self.dumps(pb, proto, buffer_callback=[].append)
2761 # Non iterable buffers
2762 with self.assertRaises(TypeError):
2763 self.loads(data, buffers=object())
2764 # Buffer iterable exhausts too early
2765 with self.assertRaises(pickle.UnpicklingError):
2766 self.loads(data, buffers=[])
2767
2768 @unittest.skipIf(np is None, "Test needs Numpy")
2769 def test_buffers_numpy(self):
2770 def check_no_copy(x, y):
2771 np.testing.assert_equal(x, y)
2772 self.assertEqual(x.ctypes.data, y.ctypes.data)
2773
2774 def check_copy(x, y):
2775 np.testing.assert_equal(x, y)
2776 self.assertNotEqual(x.ctypes.data, y.ctypes.data)
2777
2778 def check_array(arr):
2779 # In-band
2780 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
2781 data = self.dumps(arr, proto)
2782 new = self.loads(data)
2783 check_copy(arr, new)
2784 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2785 buffer_callback = lambda _: True
2786 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2787 new = self.loads(data)
2788 check_copy(arr, new)
2789 # Out-of-band
2790 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
2791 buffers = []
2792 buffer_callback = buffers.append
2793 data = self.dumps(arr, proto, buffer_callback=buffer_callback)
2794 new = self.loads(data, buffers=buffers)
2795 if arr.flags.c_contiguous or arr.flags.f_contiguous:
2796 check_no_copy(arr, new)
2797 else:
2798 check_copy(arr, new)
2799
2800 # 1-D
2801 arr = np.arange(6)
2802 check_array(arr)
2803 # 1-D, non-contiguous
2804 check_array(arr[::2])
2805 # 2-D, C-contiguous
2806 arr = np.arange(12).reshape((3, 4))
2807 check_array(arr)
2808 # 2-D, F-contiguous
2809 check_array(arr.T)
2810 # 2-D, non-contiguous
2811 check_array(arr[::2])
2812
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002813
2814class BigmemPickleTests(unittest.TestCase):
2815
Victor Stinner8c663fd2017-11-08 14:44:44 -08002816 # Binary protocols can serialize longs of up to 2 GiB-1
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002817
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002818 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002819 def test_huge_long_32b(self, size):
2820 data = 1 << (8 * size)
2821 try:
2822 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002823 if proto < 2:
2824 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002825 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002826 with self.assertRaises((ValueError, OverflowError)):
2827 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002828 finally:
2829 data = None
2830
Victor Stinner8c663fd2017-11-08 14:44:44 -08002831 # Protocol 3 can serialize up to 4 GiB-1 as a bytes object
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002832 # (older protocols don't have a dedicated opcode for bytes and are
2833 # too inefficient)
2834
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002835 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002836 def test_huge_bytes_32b(self, size):
2837 data = b"abcd" * (size // 4)
2838 try:
2839 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002840 if proto < 3:
2841 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002842 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002843 try:
2844 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002845 header = (pickle.BINBYTES +
2846 struct.pack("<I", len(data)))
2847 data_start = pickled.index(data)
2848 self.assertEqual(
2849 header,
2850 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002851 finally:
2852 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002853 finally:
2854 data = None
2855
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002856 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002857 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002858 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002859 try:
2860 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002861 if proto < 3:
2862 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002863 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002864 if proto == 3:
2865 # Protocol 3 does not support large bytes objects.
2866 # Verify that we do not crash when processing one.
2867 with self.assertRaises((ValueError, OverflowError)):
2868 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002869 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002870 try:
2871 pickled = self.dumps(data, protocol=proto)
2872 header = (pickle.BINBYTES8 +
2873 struct.pack("<Q", len(data)))
2874 data_start = pickled.index(data)
2875 self.assertEqual(
2876 header,
2877 pickled[data_start-len(header):data_start])
2878 finally:
2879 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002880 finally:
2881 data = None
2882
2883 # All protocols use 1-byte per printable ASCII character; we add another
2884 # byte because the encoded form has to be copied into the internal buffer.
2885
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002886 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002887 def test_huge_str_32b(self, size):
2888 data = "abcd" * (size // 4)
2889 try:
2890 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002891 if proto == 0:
2892 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002893 with self.subTest(proto=proto):
2894 try:
2895 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002896 header = (pickle.BINUNICODE +
2897 struct.pack("<I", len(data)))
2898 data_start = pickled.index(b'abcd')
2899 self.assertEqual(
2900 header,
2901 pickled[data_start-len(header):data_start])
2902 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2903 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002904 finally:
2905 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002906 finally:
2907 data = None
2908
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002909 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
2910 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
2911 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02002912
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02002913 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002914 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002915 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002916 try:
2917 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002918 if proto == 0:
2919 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002920 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002921 if proto < 4:
2922 with self.assertRaises((ValueError, OverflowError)):
2923 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08002924 continue
2925 try:
2926 pickled = self.dumps(data, protocol=proto)
2927 header = (pickle.BINUNICODE8 +
2928 struct.pack("<Q", len(data)))
2929 data_start = pickled.index(b'abcd')
2930 self.assertEqual(
2931 header,
2932 pickled[data_start-len(header):data_start])
2933 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
2934 pickled.index(b"abcd")), len(data))
2935 finally:
2936 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02002937 finally:
2938 data = None
2939
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02002940
Guido van Rossum2a30b212003-02-18 22:41:24 +00002941# Test classes for reduce_ex
2942
2943class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002944 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002945 _reduce_called = 0
2946 def __reduce__(self):
2947 self._reduce_called = 1
2948 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002949
2950class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002951 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00002952 _proto = None
2953 def __reduce_ex__(self, proto):
2954 self._proto = proto
2955 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00002956
2957class REX_three(object):
2958 _proto = None
2959 def __reduce_ex__(self, proto):
2960 self._proto = proto
2961 return REX_two, ()
2962 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00002963 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00002964
Guido van Rossumd8faa362007-04-27 19:54:29 +00002965class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002966 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002967 _proto = None
2968 def __reduce_ex__(self, proto):
2969 self._proto = proto
2970 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002971
2972class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002973 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00002974 _reduce_called = 0
2975 def __reduce__(self):
2976 self._reduce_called = 1
2977 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002978
2979class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002980 """This class is used to check the 4th argument (list iterator) of
2981 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002982 """
2983 def __init__(self, items=None):
2984 self.items = items if items is not None else []
2985 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02002986 return type(self) is type(other) and self.items == other.items
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002987 def append(self, item):
2988 self.items.append(item)
2989 def __reduce__(self):
2990 return type(self), (), None, iter(self.items), None
2991
2992class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002993 """This class is used to check the 5th argument (dict iterator) of
2994 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07002995 """
2996 def __init__(self, table=None):
2997 self.table = table if table is not None else {}
2998 def __eq__(self, other):
Serhiy Storchakabe700022016-03-04 09:39:47 +02002999 return type(self) is type(other) and self.table == other.table
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07003000 def __setitem__(self, key, value):
3001 self.table[key] = value
3002 def __reduce__(self):
3003 return type(self), (), None, None, iter(self.table.items())
3004
Guido van Rossumd8faa362007-04-27 19:54:29 +00003005
Guido van Rossum2a30b212003-02-18 22:41:24 +00003006# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00003007
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003008class MyInt(int):
3009 sample = 1
3010
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003011class MyFloat(float):
3012 sample = 1.0
3013
3014class MyComplex(complex):
3015 sample = 1.0 + 0.0j
3016
3017class MyStr(str):
3018 sample = "hello"
3019
Guido van Rossumef87d6e2007-05-02 19:09:54 +00003020class MyUnicode(str):
3021 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003022
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003023class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003024 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003025
3026class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003027 sample = [1, 2, 3]
3028
3029class MyDict(dict):
3030 sample = {"a": 1, "b": 2}
3031
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003032class MySet(set):
3033 sample = {"a", "b"}
3034
3035class MyFrozenSet(frozenset):
3036 sample = frozenset({"a", "b"})
3037
Mark Dickinson5c2db372009-12-05 20:28:34 +00003038myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00003039 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003040 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003041 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00003042
Guido van Rossum533dbcf2003-01-28 17:55:05 +00003043
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00003044class SlotList(MyList):
3045 __slots__ = ["foo"]
3046
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003047class SimpleNewObj(int):
3048 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00003049 # raise an error, to make sure this isn't called
3050 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003051 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02003052 return int(self) == int(other) and self.__dict__ == other.__dict__
3053
3054class ComplexNewObj(SimpleNewObj):
3055 def __getnewargs__(self):
3056 return ('%X' % self, 16)
3057
3058class ComplexNewObjEx(SimpleNewObj):
3059 def __getnewargs_ex__(self):
3060 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00003061
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00003062class BadGetattr:
3063 def __getattr__(self, key):
3064 self.foo
3065
Collin Winter771d8342009-04-16 03:18:06 +00003066
Jeremy Hylton66426532001-10-15 21:38:56 +00003067class AbstractPickleModuleTests(unittest.TestCase):
3068
3069 def test_dump_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003070 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003071 try:
3072 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003073 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003074 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003075 support.unlink(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00003076
3077 def test_load_closed_file(self):
Walter Dörwald11b41f62007-06-20 12:46:31 +00003078 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003079 try:
3080 f.close()
Serhiy Storchaka65452562017-11-15 14:01:08 +02003081 self.assertRaises(ValueError, self.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00003082 finally:
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003083 support.unlink(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003084
Collin Winter771d8342009-04-16 03:18:06 +00003085 def test_load_from_and_dump_to_file(self):
3086 stream = io.BytesIO()
3087 data = [123, {}, 124]
Serhiy Storchaka65452562017-11-15 14:01:08 +02003088 self.dump(data, stream)
Collin Winter771d8342009-04-16 03:18:06 +00003089 stream.seek(0)
Serhiy Storchaka65452562017-11-15 14:01:08 +02003090 unpickled = self.load(stream)
Collin Winter771d8342009-04-16 03:18:06 +00003091 self.assertEqual(unpickled, data)
3092
Tim Petersc0c93702003-02-13 19:30:57 +00003093 def test_highest_protocol(self):
3094 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrou91f43802019-05-26 17:10:09 +02003095 self.assertEqual(pickle.HIGHEST_PROTOCOL, 5)
Tim Petersc0c93702003-02-13 19:30:57 +00003096
Martin v. Löwis544f1192004-07-27 05:22:33 +00003097 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00003098 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00003099 # With and without keyword arguments
Serhiy Storchaka65452562017-11-15 14:01:08 +02003100 self.dump(123, f, -1)
3101 self.dump(123, file=f, protocol=-1)
3102 self.dumps(123, -1)
3103 self.dumps(123, protocol=-1)
3104 self.Pickler(f, -1)
3105 self.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00003106
Serhiy Storchaka38ab7d42019-05-31 11:29:39 +03003107 def test_dump_text_file(self):
3108 f = open(TESTFN, "w")
3109 try:
3110 for proto in protocols:
3111 self.assertRaises(TypeError, self.dump, 123, f, proto)
3112 finally:
3113 f.close()
3114 support.unlink(TESTFN)
3115
3116 def test_incomplete_input(self):
3117 s = io.BytesIO(b"X''.")
3118 self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
3119
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003120 def test_bad_init(self):
3121 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003122 # Override initialization without calling __init__() of the superclass.
Serhiy Storchaka65452562017-11-15 14:01:08 +02003123 class BadPickler(self.Pickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003124 def __init__(self): pass
3125
Serhiy Storchaka65452562017-11-15 14:01:08 +02003126 class BadUnpickler(self.Unpickler):
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003127 def __init__(self): pass
3128
3129 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
3130 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
3131
Antoine Pitrou91f43802019-05-26 17:10:09 +02003132 def check_dumps_loads_oob_buffers(self, dumps, loads):
3133 # No need to do the full gamut of tests here, just enough to
3134 # check that dumps() and loads() redirect their arguments
3135 # to the underlying Pickler and Unpickler, respectively.
3136 obj = ZeroCopyBytes(b"foo")
3137
3138 for proto in range(0, 5):
3139 # Need protocol >= 5 for buffer_callback
3140 with self.assertRaises(ValueError):
3141 dumps(obj, protocol=proto,
3142 buffer_callback=[].append)
3143 for proto in range(5, pickle.HIGHEST_PROTOCOL + 1):
3144 buffers = []
3145 buffer_callback = buffers.append
3146 data = dumps(obj, protocol=proto,
3147 buffer_callback=buffer_callback)
3148 self.assertNotIn(b"foo", data)
3149 self.assertEqual(bytes(buffers[0]), b"foo")
3150 # Need buffers argument to unpickle properly
3151 with self.assertRaises(pickle.UnpicklingError):
3152 loads(data)
3153 new = loads(data, buffers=buffers)
3154 self.assertIs(new, obj)
3155
3156 def test_dumps_loads_oob_buffers(self):
3157 # Test out-of-band buffers (PEP 574) with top-level dumps() and loads()
3158 self.check_dumps_loads_oob_buffers(self.dumps, self.loads)
3159
3160 def test_dump_load_oob_buffers(self):
3161 # Test out-of-band buffers (PEP 574) with top-level dump() and load()
3162 def dumps(obj, **kwargs):
3163 f = io.BytesIO()
3164 self.dump(obj, f, **kwargs)
3165 return f.getvalue()
3166
3167 def loads(data, **kwargs):
3168 f = io.BytesIO(data)
3169 return self.load(f, **kwargs)
3170
3171 self.check_dumps_loads_oob_buffers(dumps, loads)
3172
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00003173
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003174class AbstractPersistentPicklerTests(unittest.TestCase):
3175
3176 # This class defines persistent_id() and persistent_load()
3177 # functions that should be used by the pickler. All even integers
3178 # are pickled using persistent ids.
3179
3180 def persistent_id(self, object):
3181 if isinstance(object, int) and object % 2 == 0:
3182 self.id_count += 1
3183 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003184 elif object == "test_false_value":
3185 self.false_count += 1
3186 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003187 else:
3188 return None
3189
3190 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003191 if not oid:
3192 self.load_false_count += 1
3193 return "test_false_value"
3194 else:
3195 self.load_count += 1
3196 object = int(oid)
3197 assert object % 2 == 0
3198 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00003199
3200 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08003201 L = list(range(10)) + ["test_false_value"]
3202 for proto in protocols:
3203 self.id_count = 0
3204 self.false_count = 0
3205 self.load_false_count = 0
3206 self.load_count = 0
3207 self.assertEqual(self.loads(self.dumps(L, proto)), L)
3208 self.assertEqual(self.id_count, 5)
3209 self.assertEqual(self.false_count, 1)
3210 self.assertEqual(self.load_count, 5)
3211 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00003212
Collin Winter771d8342009-04-16 03:18:06 +00003213
Serhiy Storchakadec25af2016-07-17 11:24:17 +03003214class AbstractIdentityPersistentPicklerTests(unittest.TestCase):
3215
3216 def persistent_id(self, obj):
3217 return obj
3218
3219 def persistent_load(self, pid):
3220 return pid
3221
3222 def _check_return_correct_type(self, obj, proto):
3223 unpickled = self.loads(self.dumps(obj, proto))
3224 self.assertIsInstance(unpickled, type(obj))
3225 self.assertEqual(unpickled, obj)
3226
3227 def test_return_correct_type(self):
3228 for proto in protocols:
3229 # Protocol 0 supports only ASCII strings.
3230 if proto == 0:
3231 self._check_return_correct_type("abc", 0)
3232 else:
3233 for obj in [b"abc\n", "abc\n", -1, -1.1 * 0.1, str]:
3234 self._check_return_correct_type(obj, proto)
3235
3236 def test_protocol0_is_ascii_only(self):
3237 non_ascii_str = "\N{EMPTY SET}"
3238 self.assertRaises(pickle.PicklingError, self.dumps, non_ascii_str, 0)
3239 pickled = pickle.PERSID + non_ascii_str.encode('utf-8') + b'\n.'
3240 self.assertRaises(pickle.UnpicklingError, self.loads, pickled)
3241
3242
Collin Winter771d8342009-04-16 03:18:06 +00003243class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
3244
3245 pickler_class = None
3246 unpickler_class = None
3247
3248 def setUp(self):
3249 assert self.pickler_class
3250 assert self.unpickler_class
3251
3252 def test_clear_pickler_memo(self):
3253 # To test whether clear_memo() has any effect, we pickle an object,
3254 # then pickle it again without clearing the memo; the two serialized
3255 # forms should be different. If we clear_memo() and then pickle the
3256 # object again, the third serialized form should be identical to the
3257 # first one we obtained.
3258 data = ["abcdefg", "abcdefg", 44]
Serhiy Storchakac8695292018-04-04 00:11:27 +03003259 for proto in protocols:
3260 f = io.BytesIO()
3261 pickler = self.pickler_class(f, proto)
Collin Winter771d8342009-04-16 03:18:06 +00003262
Serhiy Storchakac8695292018-04-04 00:11:27 +03003263 pickler.dump(data)
3264 first_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003265
Serhiy Storchakac8695292018-04-04 00:11:27 +03003266 # Reset BytesIO object.
3267 f.seek(0)
3268 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003269
Serhiy Storchakac8695292018-04-04 00:11:27 +03003270 pickler.dump(data)
3271 second_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003272
Serhiy Storchakac8695292018-04-04 00:11:27 +03003273 # Reset the Pickler and BytesIO objects.
3274 pickler.clear_memo()
3275 f.seek(0)
3276 f.truncate()
Collin Winter771d8342009-04-16 03:18:06 +00003277
Serhiy Storchakac8695292018-04-04 00:11:27 +03003278 pickler.dump(data)
3279 third_pickled = f.getvalue()
Collin Winter771d8342009-04-16 03:18:06 +00003280
Serhiy Storchakac8695292018-04-04 00:11:27 +03003281 self.assertNotEqual(first_pickled, second_pickled)
3282 self.assertEqual(first_pickled, third_pickled)
Collin Winter771d8342009-04-16 03:18:06 +00003283
3284 def test_priming_pickler_memo(self):
3285 # Verify that we can set the Pickler's memo attribute.
3286 data = ["abcdefg", "abcdefg", 44]
3287 f = io.BytesIO()
3288 pickler = self.pickler_class(f)
3289
3290 pickler.dump(data)
3291 first_pickled = f.getvalue()
3292
3293 f = io.BytesIO()
3294 primed = self.pickler_class(f)
3295 primed.memo = pickler.memo
3296
3297 primed.dump(data)
3298 primed_pickled = f.getvalue()
3299
3300 self.assertNotEqual(first_pickled, primed_pickled)
3301
3302 def test_priming_unpickler_memo(self):
3303 # Verify that we can set the Unpickler's memo attribute.
3304 data = ["abcdefg", "abcdefg", 44]
3305 f = io.BytesIO()
3306 pickler = self.pickler_class(f)
3307
3308 pickler.dump(data)
3309 first_pickled = f.getvalue()
3310
3311 f = io.BytesIO()
3312 primed = self.pickler_class(f)
3313 primed.memo = pickler.memo
3314
3315 primed.dump(data)
3316 primed_pickled = f.getvalue()
3317
3318 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
3319 unpickled_data1 = unpickler.load()
3320
3321 self.assertEqual(unpickled_data1, data)
3322
3323 primed = self.unpickler_class(io.BytesIO(primed_pickled))
3324 primed.memo = unpickler.memo
3325 unpickled_data2 = primed.load()
3326
3327 primed.memo.clear()
3328
3329 self.assertEqual(unpickled_data2, data)
3330 self.assertTrue(unpickled_data2 is unpickled_data1)
3331
3332 def test_reusing_unpickler_objects(self):
3333 data1 = ["abcdefg", "abcdefg", 44]
3334 f = io.BytesIO()
3335 pickler = self.pickler_class(f)
3336 pickler.dump(data1)
3337 pickled1 = f.getvalue()
3338
3339 data2 = ["abcdefg", 44, 44]
3340 f = io.BytesIO()
3341 pickler = self.pickler_class(f)
3342 pickler.dump(data2)
3343 pickled2 = f.getvalue()
3344
3345 f = io.BytesIO()
3346 f.write(pickled1)
3347 f.seek(0)
3348 unpickler = self.unpickler_class(f)
3349 self.assertEqual(unpickler.load(), data1)
3350
3351 f.seek(0)
3352 f.truncate()
3353 f.write(pickled2)
3354 f.seek(0)
3355 self.assertEqual(unpickler.load(), data2)
3356
Antoine Pitrou04248a82010-10-12 20:51:21 +00003357 def _check_multiple_unpicklings(self, ioclass):
3358 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003359 with self.subTest(proto=proto):
3360 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
3361 f = ioclass()
3362 pickler = self.pickler_class(f, protocol=proto)
3363 pickler.dump(data1)
3364 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00003365
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01003366 N = 5
3367 f = ioclass(pickled * N)
3368 unpickler = self.unpickler_class(f)
3369 for i in range(N):
3370 if f.seekable():
3371 pos = f.tell()
3372 self.assertEqual(unpickler.load(), data1)
3373 if f.seekable():
3374 self.assertEqual(f.tell(), pos + len(pickled))
3375 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00003376
3377 def test_multiple_unpicklings_seekable(self):
3378 self._check_multiple_unpicklings(io.BytesIO)
3379
3380 def test_multiple_unpicklings_unseekable(self):
3381 self._check_multiple_unpicklings(UnseekableIO)
3382
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02003383 def test_unpickling_buffering_readline(self):
3384 # Issue #12687: the unpickler's buffering logic could fail with
3385 # text mode opcodes.
3386 data = list(range(10))
3387 for proto in protocols:
3388 for buf_size in range(1, 11):
3389 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
3390 pickler = self.pickler_class(f, protocol=proto)
3391 pickler.dump(data)
3392 f.seek(0)
3393 unpickler = self.unpickler_class(f)
3394 self.assertEqual(unpickler.load(), data)
3395
Collin Winter771d8342009-04-16 03:18:06 +00003396
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003397# Tests for dispatch_table attribute
3398
3399REDUCE_A = 'reduce_A'
3400
3401class AAA(object):
3402 def __reduce__(self):
3403 return str, (REDUCE_A,)
3404
3405class BBB(object):
Pierre Glaser65d98d02019-05-08 21:40:25 +02003406 def __init__(self):
3407 # Add an instance attribute to enable state-saving routines at pickling
3408 # time.
3409 self.a = "some attribute"
3410
3411 def __setstate__(self, state):
3412 self.a = "BBB.__setstate__"
3413
3414
3415def setstate_bbb(obj, state):
3416 """Custom state setter for BBB objects
3417
3418 Such callable may be created by other persons than the ones who created the
3419 BBB class. If passed as the state_setter item of a custom reducer, this
3420 allows for custom state setting behavior of BBB objects. One can think of
3421 it as the analogous of list_setitems or dict_setitems but for foreign
3422 classes/functions.
3423 """
3424 obj.a = "custom state_setter"
3425
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003426
Pierre Glaser289f1f82019-05-08 23:08:25 +02003427
3428class AbstractCustomPicklerClass:
3429 """Pickler implementing a reducing hook using reducer_override."""
3430 def reducer_override(self, obj):
3431 obj_name = getattr(obj, "__name__", None)
3432
3433 if obj_name == 'f':
3434 # asking the pickler to save f as 5
3435 return int, (5, )
3436
3437 if obj_name == 'MyClass':
3438 return str, ('some str',)
3439
3440 elif obj_name == 'g':
3441 # in this case, the callback returns an invalid result (not a 2-5
3442 # tuple or a string), the pickler should raise a proper error.
3443 return False
3444
3445 elif obj_name == 'h':
3446 # Simulate a case when the reducer fails. The error should
3447 # be propagated to the original ``dump`` call.
3448 raise ValueError('The reducer just failed')
3449
3450 return NotImplemented
3451
3452class AbstractHookTests(unittest.TestCase):
3453 def test_pickler_hook(self):
3454 # test the ability of a custom, user-defined CPickler subclass to
3455 # override the default reducing routines of any type using the method
3456 # reducer_override
3457
3458 def f():
3459 pass
3460
3461 def g():
3462 pass
3463
3464 def h():
3465 pass
3466
3467 class MyClass:
3468 pass
3469
3470 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
3471 with self.subTest(proto=proto):
3472 bio = io.BytesIO()
3473 p = self.pickler_class(bio, proto)
3474
3475 p.dump([f, MyClass, math.log])
3476 new_f, some_str, math_log = pickle.loads(bio.getvalue())
3477
3478 self.assertEqual(new_f, 5)
3479 self.assertEqual(some_str, 'some str')
3480 # math.log does not have its usual reducer overriden, so the
3481 # custom reduction callback should silently direct the pickler
3482 # to the default pickling by attribute, by returning
3483 # NotImplemented
3484 self.assertIs(math_log, math.log)
3485
3486 with self.assertRaises(pickle.PicklingError):
3487 p.dump(g)
3488
3489 with self.assertRaisesRegex(
3490 ValueError, 'The reducer just failed'):
3491 p.dump(h)
3492
3493
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003494class AbstractDispatchTableTests(unittest.TestCase):
3495
3496 def test_default_dispatch_table(self):
3497 # No dispatch_table attribute by default
3498 f = io.BytesIO()
3499 p = self.pickler_class(f, 0)
3500 with self.assertRaises(AttributeError):
3501 p.dispatch_table
3502 self.assertFalse(hasattr(p, 'dispatch_table'))
3503
3504 def test_class_dispatch_table(self):
3505 # A dispatch_table attribute can be specified class-wide
3506 dt = self.get_dispatch_table()
3507
3508 class MyPickler(self.pickler_class):
3509 dispatch_table = dt
3510
3511 def dumps(obj, protocol=None):
3512 f = io.BytesIO()
3513 p = MyPickler(f, protocol)
3514 self.assertEqual(p.dispatch_table, dt)
3515 p.dump(obj)
3516 return f.getvalue()
3517
3518 self._test_dispatch_table(dumps, dt)
3519
3520 def test_instance_dispatch_table(self):
3521 # A dispatch_table attribute can also be specified instance-wide
3522 dt = self.get_dispatch_table()
3523
3524 def dumps(obj, protocol=None):
3525 f = io.BytesIO()
3526 p = self.pickler_class(f, protocol)
3527 p.dispatch_table = dt
3528 self.assertEqual(p.dispatch_table, dt)
3529 p.dump(obj)
3530 return f.getvalue()
3531
3532 self._test_dispatch_table(dumps, dt)
3533
3534 def _test_dispatch_table(self, dumps, dispatch_table):
3535 def custom_load_dump(obj):
3536 return pickle.loads(dumps(obj, 0))
3537
3538 def default_load_dump(obj):
3539 return pickle.loads(pickle.dumps(obj, 0))
3540
3541 # pickling complex numbers using protocol 0 relies on copyreg
3542 # so check pickling a complex number still works
3543 z = 1 + 2j
3544 self.assertEqual(custom_load_dump(z), z)
3545 self.assertEqual(default_load_dump(z), z)
3546
3547 # modify pickling of complex
3548 REDUCE_1 = 'reduce_1'
3549 def reduce_1(obj):
3550 return str, (REDUCE_1,)
3551 dispatch_table[complex] = reduce_1
3552 self.assertEqual(custom_load_dump(z), REDUCE_1)
3553 self.assertEqual(default_load_dump(z), z)
3554
3555 # check picklability of AAA and BBB
3556 a = AAA()
3557 b = BBB()
3558 self.assertEqual(custom_load_dump(a), REDUCE_A)
3559 self.assertIsInstance(custom_load_dump(b), BBB)
3560 self.assertEqual(default_load_dump(a), REDUCE_A)
3561 self.assertIsInstance(default_load_dump(b), BBB)
3562
3563 # modify pickling of BBB
3564 dispatch_table[BBB] = reduce_1
3565 self.assertEqual(custom_load_dump(a), REDUCE_A)
3566 self.assertEqual(custom_load_dump(b), REDUCE_1)
3567 self.assertEqual(default_load_dump(a), REDUCE_A)
3568 self.assertIsInstance(default_load_dump(b), BBB)
3569
3570 # revert pickling of BBB and modify pickling of AAA
3571 REDUCE_2 = 'reduce_2'
3572 def reduce_2(obj):
3573 return str, (REDUCE_2,)
3574 dispatch_table[AAA] = reduce_2
3575 del dispatch_table[BBB]
3576 self.assertEqual(custom_load_dump(a), REDUCE_2)
3577 self.assertIsInstance(custom_load_dump(b), BBB)
3578 self.assertEqual(default_load_dump(a), REDUCE_A)
3579 self.assertIsInstance(default_load_dump(b), BBB)
3580
Pierre Glaser65d98d02019-05-08 21:40:25 +02003581 # End-to-end testing of save_reduce with the state_setter keyword
3582 # argument. This is a dispatch_table test as the primary goal of
3583 # state_setter is to tweak objects reduction behavior.
3584 # In particular, state_setter is useful when the default __setstate__
3585 # behavior is not flexible enough.
3586
3587 # No custom reducer for b has been registered for now, so
3588 # BBB.__setstate__ should be used at unpickling time
3589 self.assertEqual(default_load_dump(b).a, "BBB.__setstate__")
3590
3591 def reduce_bbb(obj):
3592 return BBB, (), obj.__dict__, None, None, setstate_bbb
3593
3594 dispatch_table[BBB] = reduce_bbb
3595
3596 # The custom reducer reduce_bbb includes a state setter, that should
3597 # have priority over BBB.__setstate__
3598 self.assertEqual(custom_load_dump(b).a, "custom state_setter")
3599
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01003600
Guido van Rossum98297ee2007-11-06 21:34:58 +00003601if __name__ == "__main__":
3602 # Print some stuff that can be used to rewrite DATA{0,1,2}
3603 from pickletools import dis
3604 x = create_data()
Serhiy Storchakab8b951f2015-09-29 15:49:58 +03003605 for i in range(pickle.HIGHEST_PROTOCOL+1):
Guido van Rossum98297ee2007-11-06 21:34:58 +00003606 p = pickle.dumps(x, i)
3607 print("DATA{0} = (".format(i))
3608 for j in range(0, len(p), 20):
3609 b = bytes(p[j:j+20])
3610 print(" {0!r}".format(b))
3611 print(")")
3612 print()
3613 print("# Disassembly of DATA{0}".format(i))
3614 print("DATA{0}_DIS = \"\"\"\\".format(i))
3615 dis(p)
3616 print("\"\"\"")
3617 print()