blob: 5cd08d9dded015ef01a6966fa3da97df3695d60e [file] [log] [blame]
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001import copyreg
Collin Winter771d8342009-04-16 03:18:06 +00002import io
Tim Peters4190fb82003-02-02 16:09:05 +00003import pickle
Tim Peters31f119e2003-02-03 16:20:13 +00004import pickletools
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01005import random
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08006import struct
Antoine Pitrou82be19f2011-08-29 23:09:33 +02007import sys
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01008import unittest
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01009import weakref
Antoine Pitroud9dfaa92009-06-04 20:32:06 +000010from http.cookies import SimpleCookie
Tim Peters4190fb82003-02-02 16:09:05 +000011
Antoine Pitrou82be19f2011-08-29 23:09:33 +020012from test.support import (
Antoine Pitrouee763e22011-08-29 23:14:53 +020013 TestFailed, TESTFN, run_with_locale, no_tracing,
Antoine Pitrou94190bb2011-10-04 10:22:36 +020014 _2G, _4G, bigmemtest,
Antoine Pitrou82be19f2011-08-29 23:09:33 +020015 )
Tim Peterse089c682001-04-10 03:41:41 +000016
Guido van Rossum98297ee2007-11-06 21:34:58 +000017from pickle import bytes_types
18
Tim Petersee1a53c2003-02-02 02:57:53 +000019# Tests that try a number of pickle protocols should have a
20# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000021# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000022protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000023
Tim Peters22e71712003-02-03 22:27:38 +000024
25# Return True if opcode code appears in the pickle, else False.
26def opcode_in_pickle(code, pickle):
27 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000028 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000029 return True
30 return False
31
Tim Peters8d2613a2003-02-11 16:40:16 +000032# Return the number of times opcode code appears in pickle.
33def count_opcode(code, pickle):
34 n = 0
35 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000036 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000037 n += 1
38 return n
39
Antoine Pitrou04248a82010-10-12 20:51:21 +000040
41class UnseekableIO(io.BytesIO):
42 def peek(self, *args):
43 raise NotImplementedError
44
45 def seekable(self):
46 return False
47
48 def seek(self, *args):
49 raise io.UnsupportedOperation
50
51 def tell(self):
52 raise io.UnsupportedOperation
53
54
Tim Peters3e667d52003-02-04 21:47:44 +000055# We can't very well test the extension registry without putting known stuff
56# in it, but we have to be careful to restore its original state. Code
57# should do this:
58#
59# e = ExtensionSaver(extension_code)
60# try:
61# fiddle w/ the extension registry's stuff for extension_code
62# finally:
63# e.restore()
64
65class ExtensionSaver:
66 # Remember current registration for code (if any), and remove it (if
67 # there is one).
68 def __init__(self, code):
69 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000070 if code in copyreg._inverted_registry:
71 self.pair = copyreg._inverted_registry[code]
72 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000073 else:
74 self.pair = None
75
76 # Restore previous registration for code.
77 def restore(self):
78 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000079 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +000080 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000081 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000082 pair = self.pair
83 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000084 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000085
Jeremy Hylton66426532001-10-15 21:38:56 +000086class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +000087 def __eq__(self, other):
88 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +000089
Alexander Belopolskyd92f0402010-07-17 22:50:45 +000090class D(C):
91 def __init__(self, arg):
92 pass
93
94class E(C):
95 def __getinitargs__(self):
96 return ()
97
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +010098class H(object):
99 pass
100
Jeremy Hylton66426532001-10-15 21:38:56 +0000101import __main__
102__main__.C = C
103C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000104__main__.D = D
105D.__module__ = "__main__"
106__main__.E = E
107E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100108__main__.H = H
109H.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000110
111class myint(int):
112 def __init__(self, x):
113 self.str = str(x)
114
115class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000116
Jeremy Hylton66426532001-10-15 21:38:56 +0000117 def __init__(self, a, b):
118 self.a = a
119 self.b = b
120
121 def __getinitargs__(self):
122 return self.a, self.b
123
Guido van Rossum04a86612001-12-19 16:58:54 +0000124class metaclass(type):
125 pass
126
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000127class use_metaclass(object, metaclass=metaclass):
128 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000129
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200130class pickling_metaclass(type):
131 def __eq__(self, other):
132 return (type(self) == type(other) and
133 self.reduce_args == other.reduce_args)
134
135 def __reduce__(self):
136 return (create_dynamic_class, self.reduce_args)
137
138def create_dynamic_class(name, bases):
139 result = pickling_metaclass(name, bases, dict())
140 result.reduce_args = (name, bases)
141 return result
142
Tim Peters70b02d72003-02-02 17:26:40 +0000143# DATA0 .. DATA2 are the pickles we expect under the various protocols, for
144# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000145
Guido van Rossum98297ee2007-11-06 21:34:58 +0000146DATA0 = (
Mark Dickinson8dd05142009-01-20 20:43:58 +0000147 b'(lp0\nL0L\naL1L\naF2.0\nac'
Georg Brandl1a3284e2007-12-02 09:40:06 +0000148 b'builtins\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000149 b'p1\n(F3.0\nF0.0\ntp2\nRp'
Mark Dickinson8dd05142009-01-20 20:43:58 +0000150 b'3\naL1L\naL-1L\naL255L\naL-'
151 b'255L\naL-256L\naL65535L\na'
152 b'L-65535L\naL-65536L\naL2'
153 b'147483647L\naL-2147483'
154 b'647L\naL-2147483648L\na('
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000155 b'Vabc\np4\ng4\nccopyreg'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000156 b'\n_reconstructor\np5\n('
Georg Brandl1a3284e2007-12-02 09:40:06 +0000157 b'c__main__\nC\np6\ncbu'
158 b'iltins\nobject\np7\nNt'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000159 b'p8\nRp9\n(dp10\nVfoo\np1'
Mark Dickinson8dd05142009-01-20 20:43:58 +0000160 b'1\nL1L\nsVbar\np12\nL2L\nsb'
161 b'g9\ntp13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000162)
Tim Peterse9358162001-01-22 22:05:20 +0000163
Guido van Rossum98297ee2007-11-06 21:34:58 +0000164# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000165DATA0_DIS = """\
166 0: ( MARK
167 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000168 2: p PUT 0
169 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000170 9: a APPEND
171 10: L LONG 1
172 14: a APPEND
173 15: F FLOAT 2.0
174 20: a APPEND
175 21: c GLOBAL 'builtins complex'
176 39: p PUT 1
177 42: ( MARK
178 43: F FLOAT 3.0
179 48: F FLOAT 0.0
180 53: t TUPLE (MARK at 42)
181 54: p PUT 2
182 57: R REDUCE
183 58: p PUT 3
184 61: a APPEND
185 62: L LONG 1
186 66: a APPEND
187 67: L LONG -1
188 72: a APPEND
189 73: L LONG 255
190 79: a APPEND
191 80: L LONG -255
192 87: a APPEND
193 88: L LONG -256
194 95: a APPEND
195 96: L LONG 65535
196 104: a APPEND
197 105: L LONG -65535
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000198 114: a APPEND
Mark Dickinson8dd05142009-01-20 20:43:58 +0000199 115: L LONG -65536
200 124: a APPEND
201 125: L LONG 2147483647
202 138: a APPEND
203 139: L LONG -2147483647
204 153: a APPEND
205 154: L LONG -2147483648
206 168: a APPEND
207 169: ( MARK
208 170: V UNICODE 'abc'
209 175: p PUT 4
210 178: g GET 4
211 181: c GLOBAL 'copyreg _reconstructor'
212 205: p PUT 5
213 208: ( MARK
214 209: c GLOBAL '__main__ C'
215 221: p PUT 6
216 224: c GLOBAL 'builtins object'
217 241: p PUT 7
218 244: N NONE
219 245: t TUPLE (MARK at 208)
220 246: p PUT 8
221 249: R REDUCE
222 250: p PUT 9
223 253: ( MARK
224 254: d DICT (MARK at 253)
225 255: p PUT 10
226 259: V UNICODE 'foo'
227 264: p PUT 11
228 268: L LONG 1
229 272: s SETITEM
230 273: V UNICODE 'bar'
231 278: p PUT 12
232 282: L LONG 2
233 286: s SETITEM
234 287: b BUILD
235 288: g GET 9
236 291: t TUPLE (MARK at 169)
237 292: p PUT 13
238 296: a APPEND
239 297: g GET 13
240 301: a APPEND
241 302: L LONG 5
242 306: a APPEND
243 307: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000244highest protocol among opcodes = 0
245"""
246
Guido van Rossum98297ee2007-11-06 21:34:58 +0000247DATA1 = (
Georg Brandl1a3284e2007-12-02 09:40:06 +0000248 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
249 b'builtins\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000250 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
251 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
252 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
253 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000254 b'cq\x04h\x04ccopyreg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000255 b'nstructor\nq\x05(c__main'
Georg Brandl1a3284e2007-12-02 09:40:06 +0000256 b'__\nC\nq\x06cbuiltins\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000257 b'object\nq\x07Ntq\x08Rq\t}q\n('
258 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
259 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
260)
Tim Peters70b02d72003-02-02 17:26:40 +0000261
Guido van Rossum98297ee2007-11-06 21:34:58 +0000262# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000263DATA1_DIS = """\
264 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000265 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000266 3: ( MARK
267 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000268 6: K BININT1 1
269 8: G BINFLOAT 2.0
Georg Brandl1a3284e2007-12-02 09:40:06 +0000270 17: c GLOBAL 'builtins complex'
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000271 35: q BINPUT 1
272 37: ( MARK
273 38: G BINFLOAT 3.0
274 47: G BINFLOAT 0.0
275 56: t TUPLE (MARK at 37)
276 57: q BINPUT 2
277 59: R REDUCE
278 60: q BINPUT 3
279 62: K BININT1 1
280 64: J BININT -1
281 69: K BININT1 255
282 71: J BININT -255
283 76: J BININT -256
284 81: M BININT2 65535
285 84: J BININT -65535
286 89: J BININT -65536
287 94: J BININT 2147483647
288 99: J BININT -2147483647
289 104: J BININT -2147483648
290 109: ( MARK
291 110: X BINUNICODE 'abc'
292 118: q BINPUT 4
293 120: h BINGET 4
294 122: c GLOBAL 'copyreg _reconstructor'
295 146: q BINPUT 5
296 148: ( MARK
297 149: c GLOBAL '__main__ C'
298 161: q BINPUT 6
299 163: c GLOBAL 'builtins object'
300 180: q BINPUT 7
301 182: N NONE
302 183: t TUPLE (MARK at 148)
303 184: q BINPUT 8
304 186: R REDUCE
305 187: q BINPUT 9
306 189: } EMPTY_DICT
307 190: q BINPUT 10
308 192: ( MARK
309 193: X BINUNICODE 'foo'
310 201: q BINPUT 11
311 203: K BININT1 1
312 205: X BINUNICODE 'bar'
313 213: q BINPUT 12
314 215: K BININT1 2
315 217: u SETITEMS (MARK at 192)
316 218: b BUILD
317 219: h BINGET 9
318 221: t TUPLE (MARK at 109)
319 222: q BINPUT 13
320 224: h BINGET 13
321 226: K BININT1 5
322 228: e APPENDS (MARK at 3)
323 229: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000324highest protocol among opcodes = 1
325"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000326
Guido van Rossum98297ee2007-11-06 21:34:58 +0000327DATA2 = (
328 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Georg Brandl1a3284e2007-12-02 09:40:06 +0000329 b'builtins\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000330 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
331 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
332 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
333 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
334 b'bcq\x04h\x04c__main__\nC\nq\x05'
335 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
336 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
337 b'\nK\x05e.'
338)
Tim Petersfc273752003-03-02 04:54:24 +0000339
Guido van Rossum98297ee2007-11-06 21:34:58 +0000340# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000341DATA2_DIS = """\
342 0: \x80 PROTO 2
343 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000344 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000345 5: ( MARK
346 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000347 8: K BININT1 1
348 10: G BINFLOAT 2.0
Georg Brandl1a3284e2007-12-02 09:40:06 +0000349 19: c GLOBAL 'builtins complex'
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000350 37: q BINPUT 1
351 39: G BINFLOAT 3.0
352 48: G BINFLOAT 0.0
353 57: \x86 TUPLE2
354 58: q BINPUT 2
355 60: R REDUCE
356 61: q BINPUT 3
357 63: K BININT1 1
358 65: J BININT -1
359 70: K BININT1 255
360 72: J BININT -255
361 77: J BININT -256
362 82: M BININT2 65535
363 85: J BININT -65535
364 90: J BININT -65536
365 95: J BININT 2147483647
366 100: J BININT -2147483647
367 105: J BININT -2147483648
368 110: ( MARK
369 111: X BINUNICODE 'abc'
370 119: q BINPUT 4
371 121: h BINGET 4
372 123: c GLOBAL '__main__ C'
373 135: q BINPUT 5
374 137: ) EMPTY_TUPLE
375 138: \x81 NEWOBJ
376 139: q BINPUT 6
377 141: } EMPTY_DICT
378 142: q BINPUT 7
379 144: ( MARK
380 145: X BINUNICODE 'foo'
381 153: q BINPUT 8
382 155: K BININT1 1
383 157: X BINUNICODE 'bar'
384 165: q BINPUT 9
385 167: K BININT1 2
386 169: u SETITEMS (MARK at 144)
387 170: b BUILD
388 171: h BINGET 6
389 173: t TUPLE (MARK at 110)
390 174: q BINPUT 10
391 176: h BINGET 10
392 178: K BININT1 5
393 180: e APPENDS (MARK at 5)
394 181: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000395highest protocol among opcodes = 2
396"""
397
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000398# set([1,2]) pickled from 2.x with protocol 2
399DATA3 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
400
401# xrange(5) pickled from 2.x with protocol 2
402DATA4 = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
403
404# a SimpleCookie() object pickled from 2.x with protocol 2
405DATA5 = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
406 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
407 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
408 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
409 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
410 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
411
412# set([3]) pickled from 2.x with protocol 2
413DATA6 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
414
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100415python2_exceptions_without_args = (
416 ArithmeticError,
417 AssertionError,
418 AttributeError,
419 BaseException,
420 BufferError,
421 BytesWarning,
422 DeprecationWarning,
423 EOFError,
424 EnvironmentError,
425 Exception,
426 FloatingPointError,
427 FutureWarning,
428 GeneratorExit,
429 IOError,
430 ImportError,
431 ImportWarning,
432 IndentationError,
433 IndexError,
434 KeyError,
435 KeyboardInterrupt,
436 LookupError,
437 MemoryError,
438 NameError,
439 NotImplementedError,
440 OSError,
441 OverflowError,
442 PendingDeprecationWarning,
443 ReferenceError,
444 RuntimeError,
445 RuntimeWarning,
446 # StandardError is gone in Python 3, we map it to Exception
447 StopIteration,
448 SyntaxError,
449 SyntaxWarning,
450 SystemError,
451 SystemExit,
452 TabError,
453 TypeError,
454 UnboundLocalError,
455 UnicodeError,
456 UnicodeWarning,
457 UserWarning,
458 ValueError,
459 Warning,
460 ZeroDivisionError,
461)
462
463exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
464
465# Exception objects without arguments pickled from 2.x with protocol 2
466DATA7 = {
467 exception :
468 exception_pickle.replace(b'?', exception.__name__.encode("ascii"))
469 for exception in python2_exceptions_without_args
470}
471
472# StandardError is mapped to Exception, test that separately
473DATA8 = exception_pickle.replace(b'?', b'StandardError')
474
475# UnicodeEncodeError object pickled from 2.x with protocol 2
476DATA9 = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
477 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
478 b'U\x03badq\x03tq\x04Rq\x05.')
479
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000480
Jeremy Hylton66426532001-10-15 21:38:56 +0000481def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000482 c = C()
483 c.foo = 1
484 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000485 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000486 # Append some integer test cases at cPickle.c's internal size
487 # cutoffs.
488 uint1max = 0xff
489 uint2max = 0xffff
490 int4max = 0x7fffffff
491 x.extend([1, -1,
492 uint1max, -uint1max, -uint1max-1,
493 uint2max, -uint2max, -uint2max-1,
494 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000495 y = ('abc', 'abc', c, c)
496 x.append(y)
497 x.append(y)
498 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000499 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000500
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100501
Jeremy Hylton66426532001-10-15 21:38:56 +0000502class AbstractPickleTests(unittest.TestCase):
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000503 # Subclass must define self.dumps, self.loads.
Tim Petersc58440f2001-04-09 17:16:31 +0000504
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100505 optimized = False
506
Jeremy Hylton66426532001-10-15 21:38:56 +0000507 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000508
Jeremy Hylton66426532001-10-15 21:38:56 +0000509 def setUp(self):
Tim Peterse9358162001-01-22 22:05:20 +0000510 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000511
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100512 def assert_is_copy(self, obj, objcopy, msg=None):
513 """Utility method to verify if two objects are copies of each others.
514 """
515 if msg is None:
516 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
517 self.assertEqual(obj, objcopy, msg=msg)
518 self.assertIs(type(obj), type(objcopy), msg=msg)
519 if hasattr(obj, '__dict__'):
520 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
521 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
522 if hasattr(obj, '__slots__'):
523 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
524 for slot in obj.__slots__:
525 self.assertEqual(
526 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
527 self.assertEqual(getattr(obj, slot, None),
528 getattr(objcopy, slot, None), msg=msg)
529
Jeremy Hylton66426532001-10-15 21:38:56 +0000530 def test_misc(self):
531 # test various datatypes not tested by testdata
Tim Peters70b02d72003-02-02 17:26:40 +0000532 for proto in protocols:
533 x = myint(4)
534 s = self.dumps(x, proto)
535 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100536 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000537
Tim Peters70b02d72003-02-02 17:26:40 +0000538 x = (1, ())
539 s = self.dumps(x, proto)
540 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100541 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000542
Tim Peters70b02d72003-02-02 17:26:40 +0000543 x = initarg(1, x)
544 s = self.dumps(x, proto)
545 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100546 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000547
Jeremy Hylton66426532001-10-15 21:38:56 +0000548 # XXX test __reduce__ protocol?
549
Tim Peters70b02d72003-02-02 17:26:40 +0000550 def test_roundtrip_equality(self):
551 expected = self._testdata
552 for proto in protocols:
553 s = self.dumps(expected, proto)
554 got = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100555 self.assert_is_copy(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000556
Guido van Rossum98297ee2007-11-06 21:34:58 +0000557 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100558 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000559
560 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100561 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000562
563 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100564 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000565
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000566 def test_load_classic_instance(self):
567 # See issue5180. Test loading 2.x pickles that
568 # contain an instance of old style class.
569 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
570 xname = X.__name__.encode('ascii')
571 # Protocol 0 (text mode pickle):
572 """
573 0: ( MARK
574 1: i INST '__main__ X' (MARK at 0)
575 15: p PUT 0
576 18: ( MARK
577 19: d DICT (MARK at 18)
578 20: p PUT 1
579 23: b BUILD
580 24: . STOP
581 """
582 pickle0 = (b"(i__main__\n"
583 b"X\n"
584 b"p0\n"
585 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100586 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000587
588 # Protocol 1 (binary mode pickle)
589 """
590 0: ( MARK
591 1: c GLOBAL '__main__ X'
592 15: q BINPUT 0
593 17: o OBJ (MARK at 0)
594 18: q BINPUT 1
595 20: } EMPTY_DICT
596 21: q BINPUT 2
597 23: b BUILD
598 24: . STOP
599 """
600 pickle1 = (b'(c__main__\n'
601 b'X\n'
602 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100603 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000604
605 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
606 """
607 0: \x80 PROTO 2
608 2: ( MARK
609 3: c GLOBAL '__main__ X'
610 17: q BINPUT 0
611 19: o OBJ (MARK at 2)
612 20: q BINPUT 1
613 22: } EMPTY_DICT
614 23: q BINPUT 2
615 25: b BUILD
616 26: . STOP
617 """
618 pickle2 = (b'\x80\x02(c__main__\n'
619 b'X\n'
620 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100621 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000622
Tim Peters70b02d72003-02-02 17:26:40 +0000623 # There are gratuitous differences between pickles produced by
624 # pickle and cPickle, largely because cPickle starts PUT indices at
625 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
626 # there's a comment with an exclamation point there whose meaning
627 # is a mystery. cPickle also suppresses PUT for objects with a refcount
628 # of 1.
629 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +0000630 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +0000631 from pickletools import dis
632
633 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
634 s = self.dumps(self._testdata, proto)
635 filelike = StringIO()
636 dis(s, out=filelike)
637 got = filelike.getvalue()
638 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000639
640 def test_recursive_list(self):
641 l = []
642 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +0000643 for proto in protocols:
644 s = self.dumps(l, proto)
645 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100646 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000647 self.assertEqual(len(x), 1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000648 self.assertTrue(x is x[0])
Jeremy Hylton66426532001-10-15 21:38:56 +0000649
Collin Winter8ca69de2009-05-26 16:53:41 +0000650 def test_recursive_tuple(self):
651 t = ([],)
652 t[0].append(t)
653 for proto in protocols:
654 s = self.dumps(t, proto)
655 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100656 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +0000657 self.assertEqual(len(x), 1)
658 self.assertEqual(len(x[0]), 1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000659 self.assertTrue(x is x[0][0])
Collin Winter8ca69de2009-05-26 16:53:41 +0000660
Jeremy Hylton66426532001-10-15 21:38:56 +0000661 def test_recursive_dict(self):
662 d = {}
663 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +0000664 for proto in protocols:
665 s = self.dumps(d, proto)
666 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100667 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000668 self.assertEqual(list(x.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000669 self.assertTrue(x[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000670
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100671 def test_recursive_set(self):
672 h = H()
673 y = set({h})
674 h.attr = y
675 for proto in protocols:
676 s = self.dumps(y, proto)
677 x = self.loads(s)
678 self.assertIsInstance(x, set)
679 self.assertIs(list(x)[0].attr, x)
680 self.assertEqual(len(x), 1)
681
682 def test_recursive_frozenset(self):
683 h = H()
684 y = frozenset({h})
685 h.attr = y
686 for proto in protocols:
687 s = self.dumps(y, proto)
688 x = self.loads(s)
689 self.assertIsInstance(x, frozenset)
690 self.assertIs(list(x)[0].attr, x)
691 self.assertEqual(len(x), 1)
692
Jeremy Hylton66426532001-10-15 21:38:56 +0000693 def test_recursive_inst(self):
694 i = C()
695 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +0000696 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200697 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +0000698 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100699 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000700 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +0200701 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000702
703 def test_recursive_multi(self):
704 l = []
705 d = {1:l}
706 i = C()
707 i.attr = d
708 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +0000709 for proto in protocols:
710 s = self.dumps(l, proto)
711 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100712 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000713 self.assertEqual(len(x), 1)
714 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000715 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000716 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000717
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000718 def test_get(self):
719 self.assertRaises(KeyError, self.loads, b'g0\np0')
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100720 self.assert_is_copy([(100,), (100,)],
721 self.loads(b'((Kdtp0\nh\x00l.))'))
Jeremy Hylton66426532001-10-15 21:38:56 +0000722
Walter Dörwald9b775532007-06-08 14:30:53 +0000723 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +0000724 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +0000725 '<\\>', '<\\\U00012345>',
726 # surrogates
727 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +0000728 for proto in protocols:
729 for u in endcases:
730 p = self.dumps(u, proto)
731 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100732 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +0000733
Alexandre Vassalotti554d8782008-12-27 07:32:41 +0000734 def test_unicode_high_plane(self):
735 t = '\U00012345'
736 for proto in protocols:
737 p = self.dumps(t, proto)
738 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100739 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +0000740
Guido van Rossumf4169812008-03-17 22:56:06 +0000741 def test_bytes(self):
742 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -0500743 for s in b'', b'xyz', b'xyz'*100:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200744 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100745 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -0500746 for s in [bytes([i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200747 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100748 self.assert_is_copy(s, self.loads(p))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -0500749 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200750 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100751 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +0000752
Jeremy Hylton66426532001-10-15 21:38:56 +0000753 def test_ints(self):
754 import sys
Tim Petersee1a53c2003-02-02 02:57:53 +0000755 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +0000756 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +0000757 while n:
758 for expected in (-n, n):
759 s = self.dumps(expected, proto)
760 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100761 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000762 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000763
Jeremy Hylton66426532001-10-15 21:38:56 +0000764 def test_maxint64(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000765 maxint64 = (1 << 63) - 1
Guido van Rossum39478e82007-08-27 17:23:59 +0000766 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
Jeremy Hylton66426532001-10-15 21:38:56 +0000767 got = self.loads(data)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100768 self.assert_is_copy(maxint64, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000769
770 # Try too with a bogus literal.
Guido van Rossum39478e82007-08-27 17:23:59 +0000771 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Jeremy Hylton66426532001-10-15 21:38:56 +0000772 self.assertRaises(ValueError, self.loads, data)
773
Tim Petersee1a53c2003-02-02 02:57:53 +0000774 def test_long(self):
775 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +0000776 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +0000777 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000778 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +0000779 for npos in nbase-1, nbase, nbase+1:
780 for n in npos, -npos:
781 pickle = self.dumps(n, proto)
782 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100783 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +0000784 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
785 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000786 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +0000787 nbase += nbase << 1000000
788 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +0000789 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000790 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +0100791 # assert_is_copy is very expensive here as it precomputes
792 # a failure message by computing the repr() of n and got,
793 # we just do the check ourselves.
794 self.assertIs(type(got), int)
795 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +0000796
Mark Dickinsoncddcf442009-01-24 21:46:33 +0000797 def test_float(self):
798 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
799 3.14, 263.44582062374053, 6.022e23, 1e30]
800 test_values = test_values + [-x for x in test_values]
801 for proto in protocols:
802 for value in test_values:
803 pickle = self.dumps(value, proto)
804 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100805 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +0000806
Thomas Wouters477c8d52006-05-27 19:21:47 +0000807 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
808 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +0000809 # make sure that floats are formatted locale independent with proto 0
810 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000811
Jeremy Hylton66426532001-10-15 21:38:56 +0000812 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +0100813 for proto in protocols:
814 inst = AAA()
815 dumped = self.dumps(inst, proto)
816 loaded = self.loads(dumped)
817 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +0000818
819 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +0100820 for proto in protocols:
821 inst = initarg(1, 2)
822 dumped = self.dumps(inst, proto)
823 loaded = self.loads(dumped)
824 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +0000825
Antoine Pitrou79035bd2012-06-26 23:04:48 +0200826 def test_pop_empty_stack(self):
827 # Test issue7455
828 s = b'0'
829 self.assertRaises((pickle.UnpicklingError, IndexError), self.loads, s)
830
Guido van Rossum04a86612001-12-19 16:58:54 +0000831 def test_metaclass(self):
832 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +0000833 for proto in protocols:
834 s = self.dumps(a, proto)
835 b = self.loads(s)
836 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +0000837
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200838 def test_dynamic_class(self):
839 a = create_dynamic_class("my_dynamic_class", (object,))
840 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
841 for proto in protocols:
842 s = self.dumps(a, proto)
843 b = self.loads(s)
844 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100845 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200846
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000847 def test_structseq(self):
848 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +0000849 import os
Tim Peters70b02d72003-02-02 17:26:40 +0000850
851 t = time.localtime()
852 for proto in protocols:
853 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000854 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100855 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000856 if hasattr(os, "stat"):
857 t = os.stat(os.curdir)
858 s = self.dumps(t, proto)
859 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100860 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000861 if hasattr(os, "statvfs"):
862 t = os.statvfs(os.curdir)
863 s = self.dumps(t, proto)
864 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100865 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000866
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100867 def test_ellipsis(self):
868 for proto in protocols:
869 s = self.dumps(..., proto)
870 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100871 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100872
873 def test_notimplemented(self):
874 for proto in protocols:
875 s = self.dumps(NotImplemented, proto)
876 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100877 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100878
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -0800879 def test_singleton_types(self):
880 # Issue #6477: Test that types of built-in singletons can be pickled.
881 singletons = [None, ..., NotImplemented]
882 for singleton in singletons:
883 for proto in protocols:
884 s = self.dumps(type(singleton), proto)
885 u = self.loads(s)
886 self.assertIs(type(singleton), u)
887
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000888 # Tests for protocol 2
889
Tim Peters4190fb82003-02-02 16:09:05 +0000890 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +0000891 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100892 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +0000893 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100894 proto_header = pickle.PROTO + bytes([proto])
895 self.assertTrue(pickled.startswith(proto_header))
896 else:
897 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +0000898
899 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100900 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +0000901 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +0000902 try:
903 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100904 except ValueError as err:
905 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +0000906 else:
907 self.fail("expected bad protocol number to raise ValueError")
908
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000909 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000910 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +0000911 for proto in protocols:
912 s = self.dumps(x, proto)
913 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100914 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000915 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000916
917 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000918 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +0000919 for proto in protocols:
920 s = self.dumps(x, proto)
921 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100922 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000923 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000924
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000925 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +0000926 # Map (proto, len(tuple)) to expected opcode.
927 expected_opcode = {(0, 0): pickle.TUPLE,
928 (0, 1): pickle.TUPLE,
929 (0, 2): pickle.TUPLE,
930 (0, 3): pickle.TUPLE,
931 (0, 4): pickle.TUPLE,
932
933 (1, 0): pickle.EMPTY_TUPLE,
934 (1, 1): pickle.TUPLE,
935 (1, 2): pickle.TUPLE,
936 (1, 3): pickle.TUPLE,
937 (1, 4): pickle.TUPLE,
938
939 (2, 0): pickle.EMPTY_TUPLE,
940 (2, 1): pickle.TUPLE1,
941 (2, 2): pickle.TUPLE2,
942 (2, 3): pickle.TUPLE3,
943 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000944
945 (3, 0): pickle.EMPTY_TUPLE,
946 (3, 1): pickle.TUPLE1,
947 (3, 2): pickle.TUPLE2,
948 (3, 3): pickle.TUPLE3,
949 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +0000950 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000951 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000952 b = (1,)
953 c = (1, 2)
954 d = (1, 2, 3)
955 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +0000956 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000957 for x in a, b, c, d, e:
958 s = self.dumps(x, proto)
959 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100960 self.assert_is_copy(x, y)
961 expected = expected_opcode[min(proto, 3), len(x)]
962 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +0000963
Guido van Rossum7d97d312003-01-28 04:25:27 +0000964 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +0000965 # Map (proto, singleton) to expected opcode.
966 expected_opcode = {(0, None): pickle.NONE,
967 (1, None): pickle.NONE,
968 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000969 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +0000970
971 (0, True): pickle.INT,
972 (1, True): pickle.INT,
973 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000974 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +0000975
976 (0, False): pickle.INT,
977 (1, False): pickle.INT,
978 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000979 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +0000980 }
Tim Peters4190fb82003-02-02 16:09:05 +0000981 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +0000982 for x in None, False, True:
983 s = self.dumps(x, proto)
984 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000985 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100986 expected = expected_opcode[min(proto, 3), x]
987 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +0000988
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000989 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000990 x = MyTuple([1, 2, 3])
991 x.foo = 42
992 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +0000993 for proto in protocols:
994 s = self.dumps(x, proto)
995 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100996 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000997
998 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000999 x = MyList([1, 2, 3])
1000 x.foo = 42
1001 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001002 for proto in protocols:
1003 s = self.dumps(x, proto)
1004 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001005 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001006
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001007 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001008 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001009 for C in myclasses:
1010 B = C.__base__
1011 x = C(C.sample)
1012 x.foo = 42
1013 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001014 y = self.loads(s)
1015 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001016 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001017 self.assertEqual(B(x), B(y), detail)
1018 self.assertEqual(x.__dict__, y.__dict__, detail)
1019
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001020 def test_newobj_proxies(self):
1021 # NEWOBJ should use the __class__ rather than the raw type
1022 classes = myclasses[:]
1023 # Cannot create weakproxies to these classes
1024 for c in (MyInt, MyTuple):
1025 classes.remove(c)
1026 for proto in protocols:
1027 for C in classes:
1028 B = C.__base__
1029 x = C(C.sample)
1030 x.foo = 42
1031 p = weakref.proxy(x)
1032 s = self.dumps(p, proto)
1033 y = self.loads(s)
1034 self.assertEqual(type(y), type(x)) # rather than type(p)
1035 detail = (proto, C, B, x, y, type(y))
1036 self.assertEqual(B(x), B(y), detail)
1037 self.assertEqual(x.__dict__, y.__dict__, detail)
1038
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001039 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001040 # an object of that type. Check that the resulting pickle uses opcode
1041 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001042
Tim Peters22e71712003-02-03 22:27:38 +00001043 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001044 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001045 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001046 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001047 x = MyList([1, 2, 3])
1048 x.foo = 42
1049 x.bar = "hello"
1050
Tim Peters22e71712003-02-03 22:27:38 +00001051 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001052 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001053 self.assertIn(__name__.encode("utf-8"), s1)
1054 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001055 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001056
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001057 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001058 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001059
Tim Peters22e71712003-02-03 22:27:38 +00001060 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001061 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001062 self.assertNotIn(__name__.encode("utf-8"), s2)
1063 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001064 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001065
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001066 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001067 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001068 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001069 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001070
1071 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001072 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1073 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001074
1075 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001076 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1077 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1078 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001079
1080 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001081 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1082 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
1083 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
1084
Tim Peters8d2613a2003-02-11 16:40:16 +00001085 def test_list_chunking(self):
1086 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00001087 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001088 for proto in protocols:
1089 s = self.dumps(x, proto)
1090 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001091 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001092 num_appends = count_opcode(pickle.APPENDS, s)
1093 self.assertEqual(num_appends, proto > 0)
1094
1095 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001096 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001097 for proto in protocols:
1098 s = self.dumps(x, proto)
1099 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001100 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001101 num_appends = count_opcode(pickle.APPENDS, s)
1102 if proto == 0:
1103 self.assertEqual(num_appends, 0)
1104 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001105 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00001106
1107 def test_dict_chunking(self):
1108 n = 10 # too small to chunk
1109 x = dict.fromkeys(range(n))
1110 for proto in protocols:
1111 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00001112 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00001113 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001114 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001115 num_setitems = count_opcode(pickle.SETITEMS, s)
1116 self.assertEqual(num_setitems, proto > 0)
1117
1118 n = 2500 # expect at least two chunks when proto > 0
1119 x = dict.fromkeys(range(n))
1120 for proto in protocols:
1121 s = self.dumps(x, proto)
1122 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001123 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001124 num_setitems = count_opcode(pickle.SETITEMS, s)
1125 if proto == 0:
1126 self.assertEqual(num_setitems, 0)
1127 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001128 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001129
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001130 def test_set_chunking(self):
1131 n = 10 # too small to chunk
1132 x = set(range(n))
1133 for proto in protocols:
1134 s = self.dumps(x, proto)
1135 y = self.loads(s)
1136 self.assert_is_copy(x, y)
1137 num_additems = count_opcode(pickle.ADDITEMS, s)
1138 if proto < 4:
1139 self.assertEqual(num_additems, 0)
1140 else:
1141 self.assertEqual(num_additems, 1)
1142
1143 n = 2500 # expect at least two chunks when proto >= 4
1144 x = set(range(n))
1145 for proto in protocols:
1146 s = self.dumps(x, proto)
1147 y = self.loads(s)
1148 self.assert_is_copy(x, y)
1149 num_additems = count_opcode(pickle.ADDITEMS, s)
1150 if proto < 4:
1151 self.assertEqual(num_additems, 0)
1152 else:
1153 self.assertGreaterEqual(num_additems, 2)
1154
Tim Peterse9ef2032003-02-13 18:42:00 +00001155 def test_simple_newobj(self):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001156 x = SimpleNewObj.__new__(SimpleNewObj, 0xface) # avoid __init__
Tim Peterse9ef2032003-02-13 18:42:00 +00001157 x.abc = 666
1158 for proto in protocols:
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001159 with self.subTest(proto=proto):
1160 s = self.dumps(x, proto)
1161 if proto < 1:
1162 self.assertIn(b'\nL64206', s) # LONG
1163 else:
1164 self.assertIn(b'M\xce\xfa', s) # BININT2
1165 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
1166 2 <= proto)
1167 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
1168 y = self.loads(s) # will raise TypeError if __init__ called
1169 self.assert_is_copy(x, y)
1170
1171 def test_complex_newobj(self):
1172 x = ComplexNewObj.__new__(ComplexNewObj, 0xface) # avoid __init__
1173 x.abc = 666
1174 for proto in protocols:
1175 with self.subTest(proto=proto):
1176 s = self.dumps(x, proto)
1177 if proto < 1:
1178 self.assertIn(b'\nL64206', s) # LONG
1179 elif proto < 2:
1180 self.assertIn(b'M\xce\xfa', s) # BININT2
1181 elif proto < 4:
1182 self.assertIn(b'X\x04\x00\x00\x00FACE', s) # BINUNICODE
1183 else:
1184 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
1185 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
1186 2 <= proto)
1187 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ_EX, s))
1188 y = self.loads(s) # will raise TypeError if __init__ called
1189 self.assert_is_copy(x, y)
1190
1191 def test_complex_newobj_ex(self):
1192 x = ComplexNewObjEx.__new__(ComplexNewObjEx, 0xface) # avoid __init__
1193 x.abc = 666
1194 for proto in protocols:
1195 with self.subTest(proto=proto):
1196 if 2 <= proto < 4:
1197 self.assertRaises(ValueError, self.dumps, x, proto)
1198 continue
1199 s = self.dumps(x, proto)
1200 if proto < 1:
1201 self.assertIn(b'\nL64206', s) # LONG
1202 elif proto < 2:
1203 self.assertIn(b'M\xce\xfa', s) # BININT2
1204 else:
1205 assert proto >= 4
1206 self.assertIn(b'\x8c\x04FACE', s) # SHORT_BINUNICODE
1207 self.assertFalse(opcode_in_pickle(pickle.NEWOBJ, s))
1208 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
1209 4 <= proto)
1210 y = self.loads(s) # will raise TypeError if __init__ called
1211 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00001212
Tim Peters42f08ac2003-02-11 22:43:24 +00001213 def test_newobj_list_slots(self):
1214 x = SlotList([1, 2, 3])
1215 x.foo = 42
1216 x.bar = "hello"
1217 s = self.dumps(x, 2)
1218 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001219 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00001220
Guido van Rossum2a30b212003-02-18 22:41:24 +00001221 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00001222 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001223 x = REX_one()
1224 self.assertEqual(x._reduce_called, 0)
1225 s = self.dumps(x, proto)
1226 self.assertEqual(x._reduce_called, 1)
1227 y = self.loads(s)
1228 self.assertEqual(y._reduce_called, 0)
1229
1230 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00001231 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001232 x = REX_two()
1233 self.assertEqual(x._proto, None)
1234 s = self.dumps(x, proto)
1235 self.assertEqual(x._proto, proto)
1236 y = self.loads(s)
1237 self.assertEqual(y._proto, None)
1238
1239 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00001240 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001241 x = REX_three()
1242 self.assertEqual(x._proto, None)
1243 s = self.dumps(x, proto)
1244 self.assertEqual(x._proto, proto)
1245 y = self.loads(s)
1246 self.assertEqual(y._proto, None)
1247
Guido van Rossumd8faa362007-04-27 19:54:29 +00001248 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00001249 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001250 x = REX_four()
1251 self.assertEqual(x._proto, None)
1252 s = self.dumps(x, proto)
1253 self.assertEqual(x._proto, proto)
1254 y = self.loads(s)
1255 self.assertEqual(y._proto, proto)
1256
1257 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00001258 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001259 x = REX_five()
1260 self.assertEqual(x._reduce_called, 0)
1261 s = self.dumps(x, proto)
1262 self.assertEqual(x._reduce_called, 1)
1263 y = self.loads(s)
1264 self.assertEqual(y._reduce_called, 1)
1265
Brett Cannon31f59292011-02-21 19:29:56 +00001266 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001267 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001268 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001269 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001270 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001271 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001272
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001273 def test_reduce_bad_iterator(self):
1274 # Issue4176: crash when 4th and 5th items of __reduce__()
1275 # are not iterators
1276 class C(object):
1277 def __reduce__(self):
1278 # 4th item is not an iterator
1279 return list, (), None, [], None
1280 class D(object):
1281 def __reduce__(self):
1282 # 5th item is not an iterator
1283 return dict, (), None, None, []
1284
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00001285 # Protocol 0 is less strict and also accept iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001286 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00001287 try:
1288 self.dumps(C(), proto)
1289 except (pickle.PickleError):
1290 pass
1291 try:
1292 self.dumps(D(), proto)
1293 except (pickle.PickleError):
1294 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001295
Collin Winter771d8342009-04-16 03:18:06 +00001296 def test_many_puts_and_gets(self):
1297 # Test that internal data structures correctly deal with lots of
1298 # puts/gets.
1299 keys = ("aaa" + str(i) for i in range(100))
1300 large_dict = dict((k, [4, 5, 6]) for k in keys)
1301 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
1302
1303 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001304 with self.subTest(proto=proto):
1305 dumped = self.dumps(obj, proto)
1306 loaded = self.loads(dumped)
1307 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00001308
Antoine Pitroua9f48a02009-05-02 21:41:14 +00001309 def test_attribute_name_interning(self):
1310 # Test that attribute names of pickled objects are interned when
1311 # unpickling.
1312 for proto in protocols:
1313 x = C()
1314 x.foo = 42
1315 x.bar = "hello"
1316 s = self.dumps(x, proto)
1317 y = self.loads(s)
1318 x_keys = sorted(x.__dict__)
1319 y_keys = sorted(y.__dict__)
1320 for x_key, y_key in zip(x_keys, y_keys):
1321 self.assertIs(x_key, y_key)
1322
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001323 def test_unpickle_from_2x(self):
1324 # Unpickle non-trivial data from Python 2.x.
1325 loaded = self.loads(DATA3)
1326 self.assertEqual(loaded, set([1, 2]))
1327 loaded = self.loads(DATA4)
1328 self.assertEqual(type(loaded), type(range(0)))
1329 self.assertEqual(list(loaded), list(range(5)))
1330 loaded = self.loads(DATA5)
1331 self.assertEqual(type(loaded), SimpleCookie)
1332 self.assertEqual(list(loaded.keys()), ["key"])
Serhiy Storchaka8cf7c1c2014-11-02 22:18:25 +02001333 self.assertEqual(loaded["key"].value, "value")
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001334
Walter Doerwald9d1dbca2013-12-02 11:41:01 +01001335 for (exc, data) in DATA7.items():
1336 loaded = self.loads(data)
1337 self.assertIs(type(loaded), exc)
1338
1339 loaded = self.loads(DATA8)
1340 self.assertIs(type(loaded), Exception)
1341
1342 loaded = self.loads(DATA9)
1343 self.assertIs(type(loaded), UnicodeEncodeError)
1344 self.assertEqual(loaded.object, "foo")
1345 self.assertEqual(loaded.encoding, "ascii")
1346 self.assertEqual(loaded.start, 0)
1347 self.assertEqual(loaded.end, 1)
1348 self.assertEqual(loaded.reason, "bad")
1349
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001350 def test_pickle_to_2x(self):
1351 # Pickle non-trivial data with protocol 2, expecting that it yields
1352 # the same result as Python 2.x did.
1353 # NOTE: this test is a bit too strong since we can produce different
1354 # bytecode that 2.x will still understand.
1355 dumped = self.dumps(range(5), 2)
1356 self.assertEqual(dumped, DATA4)
1357 dumped = self.dumps(set([3]), 2)
1358 self.assertEqual(dumped, DATA6)
1359
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -08001360 def test_load_python2_str_as_bytes(self):
1361 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
1362 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
1363 encoding="bytes"), b'a\x00\xa0')
1364 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
1365 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
1366 encoding="bytes"), b'a\x00\xa0')
1367 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
1368 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
1369 encoding="bytes"), b'a\x00\xa0')
1370
1371 def test_load_python2_unicode_as_str(self):
1372 # From Python 2: pickle.dumps(u'π', protocol=0)
1373 self.assertEqual(self.loads(b'V\\u03c0\n.',
1374 encoding='bytes'), 'π')
1375 # From Python 2: pickle.dumps(u'π', protocol=1)
1376 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
1377 encoding="bytes"), 'π')
1378 # From Python 2: pickle.dumps(u'π', protocol=2)
1379 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
1380 encoding="bytes"), 'π')
1381
1382 def test_load_long_python2_str_as_bytes(self):
1383 # From Python 2: pickle.dumps('x' * 300, protocol=1)
1384 self.assertEqual(self.loads(pickle.BINSTRING +
1385 struct.pack("<I", 300) +
1386 b'x' * 300 + pickle.STOP,
1387 encoding='bytes'), b'x' * 300)
1388
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001389 def test_large_pickles(self):
1390 # Test the correctness of internal buffering routines when handling
1391 # large data.
1392 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00001393 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001394 dumped = self.dumps(data, proto)
1395 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00001396 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001397 self.assertEqual(loaded, data)
1398
Alexander Belopolsky1ce92dc2011-02-24 19:40:09 +00001399 def test_empty_bytestring(self):
1400 # issue 11286
1401 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1402 self.assertEqual(empty, '')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001403
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001404 def test_int_pickling_efficiency(self):
1405 # Test compacity of int representation (see issue #12744)
1406 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001407 with self.subTest(proto=proto):
1408 pickles = [self.dumps(2**n, proto) for n in range(70)]
1409 sizes = list(map(len, pickles))
1410 # the size function is monotonic
1411 self.assertEqual(sorted(sizes), sizes)
1412 if proto >= 2:
1413 for p in pickles:
1414 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001415
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001416 def check_negative_32b_binXXX(self, dumped):
1417 if sys.maxsize > 2**32:
1418 self.skipTest("test is only meaningful on 32-bit builds")
1419 # XXX Pure Python pickle reads lengths as signed and passes
1420 # them directly to read() (hence the EOFError)
1421 with self.assertRaises((pickle.UnpicklingError, EOFError,
1422 ValueError, OverflowError)):
1423 self.loads(dumped)
1424
1425 def test_negative_32b_binbytes(self):
1426 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1427 self.check_negative_32b_binXXX(b'\x80\x03B\xff\xff\xff\xffxyzq\x00.')
1428
1429 def test_negative_32b_binunicode(self):
1430 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1431 self.check_negative_32b_binXXX(b'\x80\x03X\xff\xff\xff\xffxyzq\x00.')
1432
Antoine Pitrou55549ec2011-08-30 00:27:10 +02001433 def test_negative_put(self):
1434 # Issue #12847
1435 dumped = b'Va\np-1\n.'
1436 self.assertRaises(ValueError, self.loads, dumped)
1437
1438 def test_negative_32b_binput(self):
1439 # Issue #12847
1440 if sys.maxsize > 2**32:
1441 self.skipTest("test is only meaningful on 32-bit builds")
1442 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
1443 self.assertRaises(ValueError, self.loads, dumped)
1444
Alexandre Vassalotti7c5e0942013-04-15 23:14:55 -07001445 def test_badly_escaped_string(self):
1446 self.assertRaises(ValueError, self.loads, b"S'\\'\n.")
1447
1448 def test_badly_quoted_string(self):
1449 # Issue #17710
1450 badpickles = [b"S'\n.",
1451 b'S"\n.',
1452 b'S\' \n.',
1453 b'S" \n.',
1454 b'S\'"\n.',
1455 b'S"\'\n.',
1456 b"S' ' \n.",
1457 b'S" " \n.',
1458 b"S ''\n.",
1459 b'S ""\n.',
1460 b'S \n.',
1461 b'S\n.',
1462 b'S.']
1463 for p in badpickles:
1464 self.assertRaises(pickle.UnpicklingError, self.loads, p)
1465
1466 def test_correctly_quoted_string(self):
1467 goodpickles = [(b"S''\n.", ''),
1468 (b'S""\n.', ''),
1469 (b'S"\\n"\n.', '\n'),
1470 (b"S'\\n'\n.", '\n')]
1471 for p, expected in goodpickles:
1472 self.assertEqual(self.loads(p), expected)
1473
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001474 def _check_pickling_with_opcode(self, obj, opcode, proto):
1475 pickled = self.dumps(obj, proto)
1476 self.assertTrue(opcode_in_pickle(opcode, pickled))
1477 unpickled = self.loads(pickled)
1478 self.assertEqual(obj, unpickled)
1479
1480 def test_appends_on_non_lists(self):
1481 # Issue #17720
1482 obj = REX_six([1, 2, 3])
1483 for proto in protocols:
1484 if proto == 0:
1485 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
1486 else:
1487 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
1488
1489 def test_setitems_on_non_dicts(self):
1490 obj = REX_seven({1: -1, 2: -2, 3: -3})
1491 for proto in protocols:
1492 if proto == 0:
1493 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
1494 else:
1495 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
1496
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001497 # Exercise framing (proto >= 4) for significant workloads
1498
1499 FRAME_SIZE_TARGET = 64 * 1024
1500
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001501 def check_frame_opcodes(self, pickled):
1502 """
1503 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
1504 """
1505 frame_opcode_size = 9
1506 last_arg = last_pos = None
1507 for op, arg, pos in pickletools.genops(pickled):
1508 if op.name != 'FRAME':
1509 continue
1510 if last_pos is not None:
1511 # The previous frame's size should be equal to the number
1512 # of bytes up to the current frame.
1513 frame_size = pos - last_pos - frame_opcode_size
1514 self.assertEqual(frame_size, last_arg)
1515 last_arg, last_pos = arg, pos
1516 # The last frame's size should be equal to the number of bytes up
1517 # to the pickle's end.
1518 frame_size = len(pickled) - last_pos - frame_opcode_size
1519 self.assertEqual(frame_size, last_arg)
1520
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001521 def test_framing_many_objects(self):
1522 obj = list(range(10**5))
1523 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1524 with self.subTest(proto=proto):
1525 pickled = self.dumps(obj, proto)
1526 unpickled = self.loads(pickled)
1527 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01001528 bytes_per_frame = (len(pickled) /
1529 count_opcode(pickle.FRAME, pickled))
1530 self.assertGreater(bytes_per_frame,
1531 self.FRAME_SIZE_TARGET / 2)
1532 self.assertLessEqual(bytes_per_frame,
1533 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001534 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001535
1536 def test_framing_large_objects(self):
1537 N = 1024 * 1024
1538 obj = [b'x' * N, b'y' * N, b'z' * N]
1539 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1540 with self.subTest(proto=proto):
1541 pickled = self.dumps(obj, proto)
1542 unpickled = self.loads(pickled)
1543 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01001544 n_frames = count_opcode(pickle.FRAME, pickled)
Alexandre Vassalotti28d271e2013-12-01 16:27:46 -08001545 self.assertGreaterEqual(n_frames, len(obj))
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001546 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001547
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001548 def test_optional_frames(self):
1549 if pickle.HIGHEST_PROTOCOL < 4:
1550 return
1551
1552 def remove_frames(pickled, keep_frame=None):
1553 """Remove frame opcodes from the given pickle."""
1554 frame_starts = []
1555 # 1 byte for the opcode and 8 for the argument
1556 frame_opcode_size = 9
1557 for opcode, _, pos in pickletools.genops(pickled):
1558 if opcode.name == 'FRAME':
1559 frame_starts.append(pos)
1560
1561 newpickle = bytearray()
1562 last_frame_end = 0
1563 for i, pos in enumerate(frame_starts):
1564 if keep_frame and keep_frame(i):
1565 continue
1566 newpickle += pickled[last_frame_end:pos]
1567 last_frame_end = pos + frame_opcode_size
1568 newpickle += pickled[last_frame_end:]
1569 return newpickle
1570
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001571 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001572 num_frames = 20
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001573 obj = [bytes([i]) * frame_size for i in range(num_frames)]
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001574
1575 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1576 pickled = self.dumps(obj, proto)
1577
1578 frameless_pickle = remove_frames(pickled)
1579 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
1580 self.assertEqual(obj, self.loads(frameless_pickle))
1581
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001582 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001583 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
1584 count_opcode(pickle.FRAME, pickled))
1585 self.assertEqual(obj, self.loads(some_frames_pickle))
1586
Serhiy Storchaka21d75332015-01-26 10:37:01 +02001587 def test_frame_readline(self):
1588 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1589 # 0: \x80 PROTO 4
1590 # 2: \x95 FRAME 5
1591 # 11: I INT 42
1592 # 15: . STOP
1593 self.assertEqual(self.loads(pickled), 42)
1594
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001595 def test_nested_names(self):
1596 global Nested
1597 class Nested:
1598 class A:
1599 class B:
1600 class C:
1601 pass
1602
1603 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1604 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
1605 with self.subTest(proto=proto, obj=obj):
1606 unpickled = self.loads(self.dumps(obj, proto))
1607 self.assertIs(obj, unpickled)
1608
1609 def test_py_methods(self):
1610 global PyMethodsTest
1611 class PyMethodsTest:
1612 @staticmethod
1613 def cheese():
1614 return "cheese"
1615 @classmethod
1616 def wine(cls):
1617 assert cls is PyMethodsTest
1618 return "wine"
1619 def biscuits(self):
1620 assert isinstance(self, PyMethodsTest)
1621 return "biscuits"
1622 class Nested:
1623 "Nested class"
1624 @staticmethod
1625 def ketchup():
1626 return "ketchup"
1627 @classmethod
1628 def maple(cls):
1629 assert cls is PyMethodsTest.Nested
1630 return "maple"
1631 def pie(self):
1632 assert isinstance(self, PyMethodsTest.Nested)
1633 return "pie"
1634
1635 py_methods = (
1636 PyMethodsTest.cheese,
1637 PyMethodsTest.wine,
1638 PyMethodsTest().biscuits,
1639 PyMethodsTest.Nested.ketchup,
1640 PyMethodsTest.Nested.maple,
1641 PyMethodsTest.Nested().pie
1642 )
1643 py_unbound_methods = (
1644 (PyMethodsTest.biscuits, PyMethodsTest),
1645 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
1646 )
1647 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1648 for method in py_methods:
1649 with self.subTest(proto=proto, method=method):
1650 unpickled = self.loads(self.dumps(method, proto))
1651 self.assertEqual(method(), unpickled())
1652 for method, cls in py_unbound_methods:
1653 obj = cls()
1654 with self.subTest(proto=proto, method=method):
1655 unpickled = self.loads(self.dumps(method, proto))
1656 self.assertEqual(method(obj), unpickled(obj))
1657
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001658 def test_c_methods(self):
1659 global Subclass
1660 class Subclass(tuple):
1661 class Nested(str):
1662 pass
1663
1664 c_methods = (
1665 # bound built-in method
1666 ("abcd".index, ("c",)),
1667 # unbound built-in method
1668 (str.index, ("abcd", "c")),
1669 # bound "slot" method
1670 ([1, 2, 3].__len__, ()),
1671 # unbound "slot" method
1672 (list.__len__, ([1, 2, 3],)),
1673 # bound "coexist" method
1674 ({1, 2}.__contains__, (2,)),
1675 # unbound "coexist" method
1676 (set.__contains__, ({1, 2}, 2)),
1677 # built-in class method
1678 (dict.fromkeys, (("a", 1), ("b", 2))),
1679 # built-in static method
1680 (bytearray.maketrans, (b"abc", b"xyz")),
1681 # subclass methods
1682 (Subclass([1,2,2]).count, (2,)),
1683 (Subclass.count, (Subclass([1,2,2]), 2)),
1684 (Subclass.Nested("sweet").count, ("e",)),
1685 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
1686 )
1687 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1688 for method, args in c_methods:
1689 with self.subTest(proto=proto, method=method):
1690 unpickled = self.loads(self.dumps(method, proto))
1691 self.assertEqual(method(*args), unpickled(*args))
1692
Antoine Pitrou6cd5eda2014-12-02 00:20:03 +01001693 def test_local_lookup_error(self):
1694 # Test that whichmodule() errors out cleanly when looking up
1695 # an assumed globally-reachable object fails.
1696 def f():
1697 pass
1698 # Since the function is local, lookup will fail
1699 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
1700 with self.assertRaises((AttributeError, pickle.PicklingError)):
1701 pickletools.dis(self.dumps(f, proto))
1702 # Same without a __module__ attribute (exercises a different path
1703 # in _pickle.c).
1704 del f.__module__
1705 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
1706 with self.assertRaises((AttributeError, pickle.PicklingError)):
1707 pickletools.dis(self.dumps(f, proto))
1708 # Yet a different path.
1709 f.__name__ = f.__qualname__
1710 for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
1711 with self.assertRaises((AttributeError, pickle.PicklingError)):
1712 pickletools.dis(self.dumps(f, proto))
1713
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001714
1715class BigmemPickleTests(unittest.TestCase):
1716
1717 # Binary protocols can serialize longs of up to 2GB-1
1718
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001719 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001720 def test_huge_long_32b(self, size):
1721 data = 1 << (8 * size)
1722 try:
1723 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001724 if proto < 2:
1725 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001726 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001727 with self.assertRaises((ValueError, OverflowError)):
1728 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001729 finally:
1730 data = None
1731
1732 # Protocol 3 can serialize up to 4GB-1 as a bytes object
1733 # (older protocols don't have a dedicated opcode for bytes and are
1734 # too inefficient)
1735
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001736 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001737 def test_huge_bytes_32b(self, size):
1738 data = b"abcd" * (size // 4)
1739 try:
1740 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001741 if proto < 3:
1742 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001743 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001744 try:
1745 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001746 header = (pickle.BINBYTES +
1747 struct.pack("<I", len(data)))
1748 data_start = pickled.index(data)
1749 self.assertEqual(
1750 header,
1751 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001752 finally:
1753 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001754 finally:
1755 data = None
1756
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001757 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001758 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001759 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001760 try:
1761 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001762 if proto < 3:
1763 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001764 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001765 if proto == 3:
1766 # Protocol 3 does not support large bytes objects.
1767 # Verify that we do not crash when processing one.
1768 with self.assertRaises((ValueError, OverflowError)):
1769 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001770 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001771 try:
1772 pickled = self.dumps(data, protocol=proto)
1773 header = (pickle.BINBYTES8 +
1774 struct.pack("<Q", len(data)))
1775 data_start = pickled.index(data)
1776 self.assertEqual(
1777 header,
1778 pickled[data_start-len(header):data_start])
1779 finally:
1780 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001781 finally:
1782 data = None
1783
1784 # All protocols use 1-byte per printable ASCII character; we add another
1785 # byte because the encoded form has to be copied into the internal buffer.
1786
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001787 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001788 def test_huge_str_32b(self, size):
1789 data = "abcd" * (size // 4)
1790 try:
1791 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001792 if proto == 0:
1793 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001794 with self.subTest(proto=proto):
1795 try:
1796 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001797 header = (pickle.BINUNICODE +
1798 struct.pack("<I", len(data)))
1799 data_start = pickled.index(b'abcd')
1800 self.assertEqual(
1801 header,
1802 pickled[data_start-len(header):data_start])
1803 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
1804 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001805 finally:
1806 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001807 finally:
1808 data = None
1809
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001810 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
1811 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
1812 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02001813
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001814 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001815 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001816 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001817 try:
1818 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001819 if proto == 0:
1820 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001821 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001822 if proto < 4:
1823 with self.assertRaises((ValueError, OverflowError)):
1824 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001825 continue
1826 try:
1827 pickled = self.dumps(data, protocol=proto)
1828 header = (pickle.BINUNICODE8 +
1829 struct.pack("<Q", len(data)))
1830 data_start = pickled.index(b'abcd')
1831 self.assertEqual(
1832 header,
1833 pickled[data_start-len(header):data_start])
1834 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
1835 pickled.index(b"abcd")), len(data))
1836 finally:
1837 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001838 finally:
1839 data = None
1840
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001841
Guido van Rossum2a30b212003-02-18 22:41:24 +00001842# Test classes for reduce_ex
1843
1844class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001845 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00001846 _reduce_called = 0
1847 def __reduce__(self):
1848 self._reduce_called = 1
1849 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00001850
1851class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001852 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00001853 _proto = None
1854 def __reduce_ex__(self, proto):
1855 self._proto = proto
1856 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00001857
1858class REX_three(object):
1859 _proto = None
1860 def __reduce_ex__(self, proto):
1861 self._proto = proto
1862 return REX_two, ()
1863 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00001864 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00001865
Guido van Rossumd8faa362007-04-27 19:54:29 +00001866class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001867 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001868 _proto = None
1869 def __reduce_ex__(self, proto):
1870 self._proto = proto
1871 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001872
1873class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001874 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001875 _reduce_called = 0
1876 def __reduce__(self):
1877 self._reduce_called = 1
1878 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001879
1880class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001881 """This class is used to check the 4th argument (list iterator) of
1882 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001883 """
1884 def __init__(self, items=None):
1885 self.items = items if items is not None else []
1886 def __eq__(self, other):
1887 return type(self) is type(other) and self.items == self.items
1888 def append(self, item):
1889 self.items.append(item)
1890 def __reduce__(self):
1891 return type(self), (), None, iter(self.items), None
1892
1893class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001894 """This class is used to check the 5th argument (dict iterator) of
1895 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001896 """
1897 def __init__(self, table=None):
1898 self.table = table if table is not None else {}
1899 def __eq__(self, other):
1900 return type(self) is type(other) and self.table == self.table
1901 def __setitem__(self, key, value):
1902 self.table[key] = value
1903 def __reduce__(self):
1904 return type(self), (), None, None, iter(self.table.items())
1905
Guido van Rossumd8faa362007-04-27 19:54:29 +00001906
Guido van Rossum2a30b212003-02-18 22:41:24 +00001907# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00001908
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001909class MyInt(int):
1910 sample = 1
1911
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001912class MyFloat(float):
1913 sample = 1.0
1914
1915class MyComplex(complex):
1916 sample = 1.0 + 0.0j
1917
1918class MyStr(str):
1919 sample = "hello"
1920
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001921class MyUnicode(str):
1922 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001923
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001924class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001925 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001926
1927class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001928 sample = [1, 2, 3]
1929
1930class MyDict(dict):
1931 sample = {"a": 1, "b": 2}
1932
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001933class MySet(set):
1934 sample = {"a", "b"}
1935
1936class MyFrozenSet(frozenset):
1937 sample = frozenset({"a", "b"})
1938
Mark Dickinson5c2db372009-12-05 20:28:34 +00001939myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00001940 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001941 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001942 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001943
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001944
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00001945class SlotList(MyList):
1946 __slots__ = ["foo"]
1947
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001948class SimpleNewObj(int):
1949 def __init__(self, *args, **kwargs):
Tim Peterse9ef2032003-02-13 18:42:00 +00001950 # raise an error, to make sure this isn't called
1951 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001952 def __eq__(self, other):
Serhiy Storchaka707b5cc2014-12-16 19:43:46 +02001953 return int(self) == int(other) and self.__dict__ == other.__dict__
1954
1955class ComplexNewObj(SimpleNewObj):
1956 def __getnewargs__(self):
1957 return ('%X' % self, 16)
1958
1959class ComplexNewObjEx(SimpleNewObj):
1960 def __getnewargs_ex__(self):
1961 return ('%X' % self,), {'base': 16}
Tim Peterse9ef2032003-02-13 18:42:00 +00001962
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001963class BadGetattr:
1964 def __getattr__(self, key):
1965 self.foo
1966
Collin Winter771d8342009-04-16 03:18:06 +00001967
Jeremy Hylton66426532001-10-15 21:38:56 +00001968class AbstractPickleModuleTests(unittest.TestCase):
1969
1970 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001971 import os
Walter Dörwald11b41f62007-06-20 12:46:31 +00001972 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001973 try:
1974 f.close()
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00001975 self.assertRaises(ValueError, pickle.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001976 finally:
1977 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00001978
1979 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001980 import os
Walter Dörwald11b41f62007-06-20 12:46:31 +00001981 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001982 try:
1983 f.close()
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00001984 self.assertRaises(ValueError, pickle.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001985 finally:
1986 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00001987
Collin Winter771d8342009-04-16 03:18:06 +00001988 def test_load_from_and_dump_to_file(self):
1989 stream = io.BytesIO()
1990 data = [123, {}, 124]
1991 pickle.dump(data, stream)
1992 stream.seek(0)
1993 unpickled = pickle.load(stream)
1994 self.assertEqual(unpickled, data)
1995
Tim Petersc0c93702003-02-13 19:30:57 +00001996 def test_highest_protocol(self):
1997 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001998 self.assertEqual(pickle.HIGHEST_PROTOCOL, 4)
Tim Petersc0c93702003-02-13 19:30:57 +00001999
Martin v. Löwis544f1192004-07-27 05:22:33 +00002000 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00002001 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00002002 # With and without keyword arguments
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00002003 pickle.dump(123, f, -1)
2004 pickle.dump(123, file=f, protocol=-1)
2005 pickle.dumps(123, -1)
2006 pickle.dumps(123, protocol=-1)
2007 pickle.Pickler(f, -1)
2008 pickle.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00002009
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002010 def test_bad_init(self):
2011 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002012 # Override initialization without calling __init__() of the superclass.
2013 class BadPickler(pickle.Pickler):
2014 def __init__(self): pass
2015
2016 class BadUnpickler(pickle.Unpickler):
2017 def __init__(self): pass
2018
2019 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
2020 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
2021
Amaury Forgeot d'Arc3e4e72f2008-11-11 20:05:06 +00002022 def test_bad_input(self):
2023 # Test issue4298
2024 s = bytes([0x58, 0, 0, 0, 0x54])
2025 self.assertRaises(EOFError, pickle.loads, s)
2026
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002027
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002028class AbstractPersistentPicklerTests(unittest.TestCase):
2029
2030 # This class defines persistent_id() and persistent_load()
2031 # functions that should be used by the pickler. All even integers
2032 # are pickled using persistent ids.
2033
2034 def persistent_id(self, object):
2035 if isinstance(object, int) and object % 2 == 0:
2036 self.id_count += 1
2037 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002038 elif object == "test_false_value":
2039 self.false_count += 1
2040 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002041 else:
2042 return None
2043
2044 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002045 if not oid:
2046 self.load_false_count += 1
2047 return "test_false_value"
2048 else:
2049 self.load_count += 1
2050 object = int(oid)
2051 assert object % 2 == 0
2052 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002053
2054 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002055 L = list(range(10)) + ["test_false_value"]
2056 for proto in protocols:
2057 self.id_count = 0
2058 self.false_count = 0
2059 self.load_false_count = 0
2060 self.load_count = 0
2061 self.assertEqual(self.loads(self.dumps(L, proto)), L)
2062 self.assertEqual(self.id_count, 5)
2063 self.assertEqual(self.false_count, 1)
2064 self.assertEqual(self.load_count, 5)
2065 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00002066
Collin Winter771d8342009-04-16 03:18:06 +00002067
2068class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
2069
2070 pickler_class = None
2071 unpickler_class = None
2072
2073 def setUp(self):
2074 assert self.pickler_class
2075 assert self.unpickler_class
2076
2077 def test_clear_pickler_memo(self):
2078 # To test whether clear_memo() has any effect, we pickle an object,
2079 # then pickle it again without clearing the memo; the two serialized
2080 # forms should be different. If we clear_memo() and then pickle the
2081 # object again, the third serialized form should be identical to the
2082 # first one we obtained.
2083 data = ["abcdefg", "abcdefg", 44]
2084 f = io.BytesIO()
2085 pickler = self.pickler_class(f)
2086
2087 pickler.dump(data)
2088 first_pickled = f.getvalue()
2089
Serhiy Storchaka50254c52013-08-29 11:35:43 +03002090 # Reset BytesIO object.
Collin Winter771d8342009-04-16 03:18:06 +00002091 f.seek(0)
2092 f.truncate()
2093
2094 pickler.dump(data)
2095 second_pickled = f.getvalue()
2096
Serhiy Storchaka50254c52013-08-29 11:35:43 +03002097 # Reset the Pickler and BytesIO objects.
Collin Winter771d8342009-04-16 03:18:06 +00002098 pickler.clear_memo()
2099 f.seek(0)
2100 f.truncate()
2101
2102 pickler.dump(data)
2103 third_pickled = f.getvalue()
2104
2105 self.assertNotEqual(first_pickled, second_pickled)
2106 self.assertEqual(first_pickled, third_pickled)
2107
2108 def test_priming_pickler_memo(self):
2109 # Verify that we can set the Pickler's memo attribute.
2110 data = ["abcdefg", "abcdefg", 44]
2111 f = io.BytesIO()
2112 pickler = self.pickler_class(f)
2113
2114 pickler.dump(data)
2115 first_pickled = f.getvalue()
2116
2117 f = io.BytesIO()
2118 primed = self.pickler_class(f)
2119 primed.memo = pickler.memo
2120
2121 primed.dump(data)
2122 primed_pickled = f.getvalue()
2123
2124 self.assertNotEqual(first_pickled, primed_pickled)
2125
2126 def test_priming_unpickler_memo(self):
2127 # Verify that we can set the Unpickler's memo attribute.
2128 data = ["abcdefg", "abcdefg", 44]
2129 f = io.BytesIO()
2130 pickler = self.pickler_class(f)
2131
2132 pickler.dump(data)
2133 first_pickled = f.getvalue()
2134
2135 f = io.BytesIO()
2136 primed = self.pickler_class(f)
2137 primed.memo = pickler.memo
2138
2139 primed.dump(data)
2140 primed_pickled = f.getvalue()
2141
2142 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
2143 unpickled_data1 = unpickler.load()
2144
2145 self.assertEqual(unpickled_data1, data)
2146
2147 primed = self.unpickler_class(io.BytesIO(primed_pickled))
2148 primed.memo = unpickler.memo
2149 unpickled_data2 = primed.load()
2150
2151 primed.memo.clear()
2152
2153 self.assertEqual(unpickled_data2, data)
2154 self.assertTrue(unpickled_data2 is unpickled_data1)
2155
2156 def test_reusing_unpickler_objects(self):
2157 data1 = ["abcdefg", "abcdefg", 44]
2158 f = io.BytesIO()
2159 pickler = self.pickler_class(f)
2160 pickler.dump(data1)
2161 pickled1 = f.getvalue()
2162
2163 data2 = ["abcdefg", 44, 44]
2164 f = io.BytesIO()
2165 pickler = self.pickler_class(f)
2166 pickler.dump(data2)
2167 pickled2 = f.getvalue()
2168
2169 f = io.BytesIO()
2170 f.write(pickled1)
2171 f.seek(0)
2172 unpickler = self.unpickler_class(f)
2173 self.assertEqual(unpickler.load(), data1)
2174
2175 f.seek(0)
2176 f.truncate()
2177 f.write(pickled2)
2178 f.seek(0)
2179 self.assertEqual(unpickler.load(), data2)
2180
Antoine Pitrou04248a82010-10-12 20:51:21 +00002181 def _check_multiple_unpicklings(self, ioclass):
2182 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002183 with self.subTest(proto=proto):
2184 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
2185 f = ioclass()
2186 pickler = self.pickler_class(f, protocol=proto)
2187 pickler.dump(data1)
2188 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00002189
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002190 N = 5
2191 f = ioclass(pickled * N)
2192 unpickler = self.unpickler_class(f)
2193 for i in range(N):
2194 if f.seekable():
2195 pos = f.tell()
2196 self.assertEqual(unpickler.load(), data1)
2197 if f.seekable():
2198 self.assertEqual(f.tell(), pos + len(pickled))
2199 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002200
2201 def test_multiple_unpicklings_seekable(self):
2202 self._check_multiple_unpicklings(io.BytesIO)
2203
2204 def test_multiple_unpicklings_unseekable(self):
2205 self._check_multiple_unpicklings(UnseekableIO)
2206
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02002207 def test_unpickling_buffering_readline(self):
2208 # Issue #12687: the unpickler's buffering logic could fail with
2209 # text mode opcodes.
2210 data = list(range(10))
2211 for proto in protocols:
2212 for buf_size in range(1, 11):
2213 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
2214 pickler = self.pickler_class(f, protocol=proto)
2215 pickler.dump(data)
2216 f.seek(0)
2217 unpickler = self.unpickler_class(f)
2218 self.assertEqual(unpickler.load(), data)
2219
Collin Winter771d8342009-04-16 03:18:06 +00002220
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01002221# Tests for dispatch_table attribute
2222
2223REDUCE_A = 'reduce_A'
2224
2225class AAA(object):
2226 def __reduce__(self):
2227 return str, (REDUCE_A,)
2228
2229class BBB(object):
2230 pass
2231
2232class AbstractDispatchTableTests(unittest.TestCase):
2233
2234 def test_default_dispatch_table(self):
2235 # No dispatch_table attribute by default
2236 f = io.BytesIO()
2237 p = self.pickler_class(f, 0)
2238 with self.assertRaises(AttributeError):
2239 p.dispatch_table
2240 self.assertFalse(hasattr(p, 'dispatch_table'))
2241
2242 def test_class_dispatch_table(self):
2243 # A dispatch_table attribute can be specified class-wide
2244 dt = self.get_dispatch_table()
2245
2246 class MyPickler(self.pickler_class):
2247 dispatch_table = dt
2248
2249 def dumps(obj, protocol=None):
2250 f = io.BytesIO()
2251 p = MyPickler(f, protocol)
2252 self.assertEqual(p.dispatch_table, dt)
2253 p.dump(obj)
2254 return f.getvalue()
2255
2256 self._test_dispatch_table(dumps, dt)
2257
2258 def test_instance_dispatch_table(self):
2259 # A dispatch_table attribute can also be specified instance-wide
2260 dt = self.get_dispatch_table()
2261
2262 def dumps(obj, protocol=None):
2263 f = io.BytesIO()
2264 p = self.pickler_class(f, protocol)
2265 p.dispatch_table = dt
2266 self.assertEqual(p.dispatch_table, dt)
2267 p.dump(obj)
2268 return f.getvalue()
2269
2270 self._test_dispatch_table(dumps, dt)
2271
2272 def _test_dispatch_table(self, dumps, dispatch_table):
2273 def custom_load_dump(obj):
2274 return pickle.loads(dumps(obj, 0))
2275
2276 def default_load_dump(obj):
2277 return pickle.loads(pickle.dumps(obj, 0))
2278
2279 # pickling complex numbers using protocol 0 relies on copyreg
2280 # so check pickling a complex number still works
2281 z = 1 + 2j
2282 self.assertEqual(custom_load_dump(z), z)
2283 self.assertEqual(default_load_dump(z), z)
2284
2285 # modify pickling of complex
2286 REDUCE_1 = 'reduce_1'
2287 def reduce_1(obj):
2288 return str, (REDUCE_1,)
2289 dispatch_table[complex] = reduce_1
2290 self.assertEqual(custom_load_dump(z), REDUCE_1)
2291 self.assertEqual(default_load_dump(z), z)
2292
2293 # check picklability of AAA and BBB
2294 a = AAA()
2295 b = BBB()
2296 self.assertEqual(custom_load_dump(a), REDUCE_A)
2297 self.assertIsInstance(custom_load_dump(b), BBB)
2298 self.assertEqual(default_load_dump(a), REDUCE_A)
2299 self.assertIsInstance(default_load_dump(b), BBB)
2300
2301 # modify pickling of BBB
2302 dispatch_table[BBB] = reduce_1
2303 self.assertEqual(custom_load_dump(a), REDUCE_A)
2304 self.assertEqual(custom_load_dump(b), REDUCE_1)
2305 self.assertEqual(default_load_dump(a), REDUCE_A)
2306 self.assertIsInstance(default_load_dump(b), BBB)
2307
2308 # revert pickling of BBB and modify pickling of AAA
2309 REDUCE_2 = 'reduce_2'
2310 def reduce_2(obj):
2311 return str, (REDUCE_2,)
2312 dispatch_table[AAA] = reduce_2
2313 del dispatch_table[BBB]
2314 self.assertEqual(custom_load_dump(a), REDUCE_2)
2315 self.assertIsInstance(custom_load_dump(b), BBB)
2316 self.assertEqual(default_load_dump(a), REDUCE_A)
2317 self.assertIsInstance(default_load_dump(b), BBB)
2318
2319
Guido van Rossum98297ee2007-11-06 21:34:58 +00002320if __name__ == "__main__":
2321 # Print some stuff that can be used to rewrite DATA{0,1,2}
2322 from pickletools import dis
2323 x = create_data()
2324 for i in range(3):
2325 p = pickle.dumps(x, i)
2326 print("DATA{0} = (".format(i))
2327 for j in range(0, len(p), 20):
2328 b = bytes(p[j:j+20])
2329 print(" {0!r}".format(b))
2330 print(")")
2331 print()
2332 print("# Disassembly of DATA{0}".format(i))
2333 print("DATA{0}_DIS = \"\"\"\\".format(i))
2334 dis(p)
2335 print("\"\"\"")
2336 print()