blob: af34d23d37567c9fa88316d90f3f3407d38290b8 [file] [log] [blame]
Serhiy Storchakabfe18242015-03-31 13:12:37 +03001import collections
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002import copyreg
Serhiy Storchakabfe18242015-03-31 13:12:37 +03003import dbm
Collin Winter771d8342009-04-16 03:18:06 +00004import io
Serhiy Storchakabfe18242015-03-31 13:12:37 +03005import functools
Tim Peters4190fb82003-02-02 16:09:05 +00006import pickle
Tim Peters31f119e2003-02-03 16:20:13 +00007import pickletools
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08008import struct
Antoine Pitrou82be19f2011-08-29 23:09:33 +02009import sys
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +010010import unittest
Antoine Pitrou16c4ce12011-03-11 21:30:43 +010011import weakref
Antoine Pitroud9dfaa92009-06-04 20:32:06 +000012from http.cookies import SimpleCookie
Tim Peters4190fb82003-02-02 16:09:05 +000013
Antoine Pitrou82be19f2011-08-29 23:09:33 +020014from test.support import (
Antoine Pitrouee763e22011-08-29 23:14:53 +020015 TestFailed, TESTFN, run_with_locale, no_tracing,
Antoine Pitrou94190bb2011-10-04 10:22:36 +020016 _2G, _4G, bigmemtest,
Antoine Pitrou82be19f2011-08-29 23:09:33 +020017 )
Tim Peterse089c682001-04-10 03:41:41 +000018
Guido van Rossum98297ee2007-11-06 21:34:58 +000019from pickle import bytes_types
20
Tim Petersee1a53c2003-02-02 02:57:53 +000021# Tests that try a number of pickle protocols should have a
22# for proto in protocols:
Tim Peters8587b3c2003-02-13 15:44:41 +000023# kind of outer loop.
Tim Peters8587b3c2003-02-13 15:44:41 +000024protocols = range(pickle.HIGHEST_PROTOCOL + 1)
Tim Petersee1a53c2003-02-02 02:57:53 +000025
Tim Peters22e71712003-02-03 22:27:38 +000026
27# Return True if opcode code appears in the pickle, else False.
28def opcode_in_pickle(code, pickle):
29 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000030 if op.code == code.decode("latin-1"):
Tim Peters22e71712003-02-03 22:27:38 +000031 return True
32 return False
33
Tim Peters8d2613a2003-02-11 16:40:16 +000034# Return the number of times opcode code appears in pickle.
35def count_opcode(code, pickle):
36 n = 0
37 for op, dummy, dummy in pickletools.genops(pickle):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000038 if op.code == code.decode("latin-1"):
Tim Peters8d2613a2003-02-11 16:40:16 +000039 n += 1
40 return n
41
Antoine Pitrou04248a82010-10-12 20:51:21 +000042
43class UnseekableIO(io.BytesIO):
44 def peek(self, *args):
45 raise NotImplementedError
46
47 def seekable(self):
48 return False
49
50 def seek(self, *args):
51 raise io.UnsupportedOperation
52
53 def tell(self):
54 raise io.UnsupportedOperation
55
56
Tim Peters3e667d52003-02-04 21:47:44 +000057# We can't very well test the extension registry without putting known stuff
58# in it, but we have to be careful to restore its original state. Code
59# should do this:
60#
61# e = ExtensionSaver(extension_code)
62# try:
63# fiddle w/ the extension registry's stuff for extension_code
64# finally:
65# e.restore()
66
67class ExtensionSaver:
68 # Remember current registration for code (if any), and remove it (if
69 # there is one).
70 def __init__(self, code):
71 self.code = code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000072 if code in copyreg._inverted_registry:
73 self.pair = copyreg._inverted_registry[code]
74 copyreg.remove_extension(self.pair[0], self.pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000075 else:
76 self.pair = None
77
78 # Restore previous registration for code.
79 def restore(self):
80 code = self.code
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000081 curpair = copyreg._inverted_registry.get(code)
Tim Peters3e667d52003-02-04 21:47:44 +000082 if curpair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000083 copyreg.remove_extension(curpair[0], curpair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000084 pair = self.pair
85 if pair is not None:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +000086 copyreg.add_extension(pair[0], pair[1], code)
Tim Peters3e667d52003-02-04 21:47:44 +000087
Jeremy Hylton66426532001-10-15 21:38:56 +000088class C:
Guido van Rossum47b9ff62006-08-24 00:41:19 +000089 def __eq__(self, other):
90 return self.__dict__ == other.__dict__
Jeremy Hylton66426532001-10-15 21:38:56 +000091
Alexander Belopolskyd92f0402010-07-17 22:50:45 +000092class D(C):
93 def __init__(self, arg):
94 pass
95
96class E(C):
97 def __getinitargs__(self):
98 return ()
99
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100100class H(object):
101 pass
102
Jeremy Hylton66426532001-10-15 21:38:56 +0000103import __main__
104__main__.C = C
105C.__module__ = "__main__"
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000106__main__.D = D
107D.__module__ = "__main__"
108__main__.E = E
109E.__module__ = "__main__"
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100110__main__.H = H
111H.__module__ = "__main__"
Jeremy Hylton66426532001-10-15 21:38:56 +0000112
113class myint(int):
114 def __init__(self, x):
115 self.str = str(x)
116
117class initarg(C):
Guido van Rossum1444f672001-12-19 16:38:29 +0000118
Jeremy Hylton66426532001-10-15 21:38:56 +0000119 def __init__(self, a, b):
120 self.a = a
121 self.b = b
122
123 def __getinitargs__(self):
124 return self.a, self.b
125
Guido van Rossum04a86612001-12-19 16:58:54 +0000126class metaclass(type):
127 pass
128
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000129class use_metaclass(object, metaclass=metaclass):
130 pass
Guido van Rossum04a86612001-12-19 16:58:54 +0000131
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200132class pickling_metaclass(type):
133 def __eq__(self, other):
134 return (type(self) == type(other) and
135 self.reduce_args == other.reduce_args)
136
137 def __reduce__(self):
138 return (create_dynamic_class, self.reduce_args)
139
140def create_dynamic_class(name, bases):
141 result = pickling_metaclass(name, bases, dict())
142 result.reduce_args = (name, bases)
143 return result
144
Tim Peters70b02d72003-02-02 17:26:40 +0000145# DATA0 .. DATA2 are the pickles we expect under the various protocols, for
146# the object returned by create_data().
Tim Petersee1a53c2003-02-02 02:57:53 +0000147
Guido van Rossum98297ee2007-11-06 21:34:58 +0000148DATA0 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200149 b'(lp0\nL0L\naL1L\naF2.0\n'
150 b'ac__builtin__\ncomple'
151 b'x\np1\n(F3.0\nF0.0\ntp2\n'
152 b'Rp3\naL1L\naL-1L\naL255'
153 b'L\naL-255L\naL-256L\naL'
154 b'65535L\naL-65535L\naL-'
155 b'65536L\naL2147483647L'
156 b'\naL-2147483647L\naL-2'
157 b'147483648L\na(Vabc\np4'
158 b'\ng4\nccopy_reg\n_recon'
159 b'structor\np5\n(c__main'
160 b'__\nC\np6\nc__builtin__'
161 b'\nobject\np7\nNtp8\nRp9\n'
162 b'(dp10\nVfoo\np11\nL1L\ns'
163 b'Vbar\np12\nL2L\nsbg9\ntp'
164 b'13\nag13\naL5L\na.'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000165)
Tim Peterse9358162001-01-22 22:05:20 +0000166
Guido van Rossum98297ee2007-11-06 21:34:58 +0000167# Disassembly of DATA0
Tim Peters70b02d72003-02-02 17:26:40 +0000168DATA0_DIS = """\
169 0: ( MARK
170 1: l LIST (MARK at 0)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000171 2: p PUT 0
172 5: L LONG 0
Mark Dickinson8dd05142009-01-20 20:43:58 +0000173 9: a APPEND
174 10: L LONG 1
175 14: a APPEND
176 15: F FLOAT 2.0
177 20: a APPEND
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200178 21: c GLOBAL '__builtin__ complex'
179 42: p PUT 1
180 45: ( MARK
181 46: F FLOAT 3.0
182 51: F FLOAT 0.0
183 56: t TUPLE (MARK at 45)
184 57: p PUT 2
185 60: R REDUCE
186 61: p PUT 3
187 64: a APPEND
188 65: L LONG 1
189 69: a APPEND
190 70: L LONG -1
191 75: a APPEND
192 76: L LONG 255
193 82: a APPEND
194 83: L LONG -255
195 90: a APPEND
196 91: L LONG -256
197 98: a APPEND
198 99: L LONG 65535
199 107: a APPEND
200 108: L LONG -65535
201 117: a APPEND
202 118: L LONG -65536
203 127: a APPEND
204 128: L LONG 2147483647
205 141: a APPEND
206 142: L LONG -2147483647
207 156: a APPEND
208 157: L LONG -2147483648
209 171: a APPEND
210 172: ( MARK
211 173: V UNICODE 'abc'
212 178: p PUT 4
213 181: g GET 4
214 184: c GLOBAL 'copy_reg _reconstructor'
215 209: p PUT 5
216 212: ( MARK
217 213: c GLOBAL '__main__ C'
218 225: p PUT 6
219 228: c GLOBAL '__builtin__ object'
220 248: p PUT 7
221 251: N NONE
222 252: t TUPLE (MARK at 212)
223 253: p PUT 8
224 256: R REDUCE
225 257: p PUT 9
226 260: ( MARK
227 261: d DICT (MARK at 260)
228 262: p PUT 10
229 266: V UNICODE 'foo'
230 271: p PUT 11
231 275: L LONG 1
232 279: s SETITEM
233 280: V UNICODE 'bar'
234 285: p PUT 12
235 289: L LONG 2
236 293: s SETITEM
237 294: b BUILD
238 295: g GET 9
239 298: t TUPLE (MARK at 172)
240 299: p PUT 13
241 303: a APPEND
242 304: g GET 13
243 308: a APPEND
244 309: L LONG 5
245 313: a APPEND
246 314: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000247highest protocol among opcodes = 0
248"""
249
Guido van Rossum98297ee2007-11-06 21:34:58 +0000250DATA1 = (
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200251 b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c__'
252 b'builtin__\ncomplex\nq\x01'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000253 b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
254 b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
255 b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
256 b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200257 b'cq\x04h\x04ccopy_reg\n_reco'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000258 b'nstructor\nq\x05(c__main'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200259 b'__\nC\nq\x06c__builtin__\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000260 b'object\nq\x07Ntq\x08Rq\t}q\n('
261 b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
262 b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
263)
Tim Peters70b02d72003-02-02 17:26:40 +0000264
Guido van Rossum98297ee2007-11-06 21:34:58 +0000265# Disassembly of DATA1
Tim Peters70b02d72003-02-02 17:26:40 +0000266DATA1_DIS = """\
267 0: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000268 1: q BINPUT 0
Tim Peters70b02d72003-02-02 17:26:40 +0000269 3: ( MARK
270 4: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000271 6: K BININT1 1
272 8: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200273 17: c GLOBAL '__builtin__ complex'
274 38: q BINPUT 1
275 40: ( MARK
276 41: G BINFLOAT 3.0
277 50: G BINFLOAT 0.0
278 59: t TUPLE (MARK at 40)
279 60: q BINPUT 2
280 62: R REDUCE
281 63: q BINPUT 3
282 65: K BININT1 1
283 67: J BININT -1
284 72: K BININT1 255
285 74: J BININT -255
286 79: J BININT -256
287 84: M BININT2 65535
288 87: J BININT -65535
289 92: J BININT -65536
290 97: J BININT 2147483647
291 102: J BININT -2147483647
292 107: J BININT -2147483648
293 112: ( MARK
294 113: X BINUNICODE 'abc'
295 121: q BINPUT 4
296 123: h BINGET 4
297 125: c GLOBAL 'copy_reg _reconstructor'
298 150: q BINPUT 5
299 152: ( MARK
300 153: c GLOBAL '__main__ C'
301 165: q BINPUT 6
302 167: c GLOBAL '__builtin__ object'
303 187: q BINPUT 7
304 189: N NONE
305 190: t TUPLE (MARK at 152)
306 191: q BINPUT 8
307 193: R REDUCE
308 194: q BINPUT 9
309 196: } EMPTY_DICT
310 197: q BINPUT 10
311 199: ( MARK
312 200: X BINUNICODE 'foo'
313 208: q BINPUT 11
314 210: K BININT1 1
315 212: X BINUNICODE 'bar'
316 220: q BINPUT 12
317 222: K BININT1 2
318 224: u SETITEMS (MARK at 199)
319 225: b BUILD
320 226: h BINGET 9
321 228: t TUPLE (MARK at 112)
322 229: q BINPUT 13
323 231: h BINGET 13
324 233: K BININT1 5
325 235: e APPENDS (MARK at 3)
326 236: . STOP
Tim Peters70b02d72003-02-02 17:26:40 +0000327highest protocol among opcodes = 1
328"""
Tim Peterse0c446b2001-10-18 21:57:37 +0000329
Guido van Rossum98297ee2007-11-06 21:34:58 +0000330DATA2 = (
331 b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200332 b'__builtin__\ncomplex\n'
Guido van Rossum98297ee2007-11-06 21:34:58 +0000333 b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
334 b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
335 b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
336 b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
337 b'bcq\x04h\x04c__main__\nC\nq\x05'
338 b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
339 b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
340 b'\nK\x05e.'
341)
Tim Petersfc273752003-03-02 04:54:24 +0000342
Guido van Rossum98297ee2007-11-06 21:34:58 +0000343# Disassembly of DATA2
Tim Petersfc273752003-03-02 04:54:24 +0000344DATA2_DIS = """\
345 0: \x80 PROTO 2
346 2: ] EMPTY_LIST
Guido van Rossum98297ee2007-11-06 21:34:58 +0000347 3: q BINPUT 0
Tim Petersfc273752003-03-02 04:54:24 +0000348 5: ( MARK
349 6: K BININT1 0
Guido van Rossum98297ee2007-11-06 21:34:58 +0000350 8: K BININT1 1
351 10: G BINFLOAT 2.0
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200352 19: c GLOBAL '__builtin__ complex'
353 40: q BINPUT 1
354 42: G BINFLOAT 3.0
355 51: G BINFLOAT 0.0
356 60: \x86 TUPLE2
357 61: q BINPUT 2
358 63: R REDUCE
359 64: q BINPUT 3
360 66: K BININT1 1
361 68: J BININT -1
362 73: K BININT1 255
363 75: J BININT -255
364 80: J BININT -256
365 85: M BININT2 65535
366 88: J BININT -65535
367 93: J BININT -65536
368 98: J BININT 2147483647
369 103: J BININT -2147483647
370 108: J BININT -2147483648
371 113: ( MARK
372 114: X BINUNICODE 'abc'
373 122: q BINPUT 4
374 124: h BINGET 4
375 126: c GLOBAL '__main__ C'
376 138: q BINPUT 5
377 140: ) EMPTY_TUPLE
378 141: \x81 NEWOBJ
379 142: q BINPUT 6
380 144: } EMPTY_DICT
381 145: q BINPUT 7
382 147: ( MARK
383 148: X BINUNICODE 'foo'
384 156: q BINPUT 8
385 158: K BININT1 1
386 160: X BINUNICODE 'bar'
387 168: q BINPUT 9
388 170: K BININT1 2
389 172: u SETITEMS (MARK at 147)
390 173: b BUILD
391 174: h BINGET 6
392 176: t TUPLE (MARK at 113)
393 177: q BINPUT 10
394 179: h BINGET 10
395 181: K BININT1 5
396 183: e APPENDS (MARK at 5)
397 184: . STOP
Tim Petersfc273752003-03-02 04:54:24 +0000398highest protocol among opcodes = 2
399"""
400
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000401# set([1,2]) pickled from 2.x with protocol 2
402DATA3 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
403
404# xrange(5) pickled from 2.x with protocol 2
405DATA4 = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
406
407# a SimpleCookie() object pickled from 2.x with protocol 2
408DATA5 = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
409 b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
410 b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
411 b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
412 b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
413 b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
414
415# set([3]) pickled from 2.x with protocol 2
416DATA6 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
417
Walter Doerwald9d1dbca2013-12-02 11:41:01 +0100418python2_exceptions_without_args = (
419 ArithmeticError,
420 AssertionError,
421 AttributeError,
422 BaseException,
423 BufferError,
424 BytesWarning,
425 DeprecationWarning,
426 EOFError,
427 EnvironmentError,
428 Exception,
429 FloatingPointError,
430 FutureWarning,
431 GeneratorExit,
432 IOError,
433 ImportError,
434 ImportWarning,
435 IndentationError,
436 IndexError,
437 KeyError,
438 KeyboardInterrupt,
439 LookupError,
440 MemoryError,
441 NameError,
442 NotImplementedError,
443 OSError,
444 OverflowError,
445 PendingDeprecationWarning,
446 ReferenceError,
447 RuntimeError,
448 RuntimeWarning,
449 # StandardError is gone in Python 3, we map it to Exception
450 StopIteration,
451 SyntaxError,
452 SyntaxWarning,
453 SystemError,
454 SystemExit,
455 TabError,
456 TypeError,
457 UnboundLocalError,
458 UnicodeError,
459 UnicodeWarning,
460 UserWarning,
461 ValueError,
462 Warning,
463 ZeroDivisionError,
464)
465
466exception_pickle = b'\x80\x02cexceptions\n?\nq\x00)Rq\x01.'
467
468# Exception objects without arguments pickled from 2.x with protocol 2
469DATA7 = {
470 exception :
471 exception_pickle.replace(b'?', exception.__name__.encode("ascii"))
472 for exception in python2_exceptions_without_args
473}
474
475# StandardError is mapped to Exception, test that separately
476DATA8 = exception_pickle.replace(b'?', b'StandardError')
477
478# UnicodeEncodeError object pickled from 2.x with protocol 2
479DATA9 = (b'\x80\x02cexceptions\nUnicodeEncodeError\n'
480 b'q\x00(U\x05asciiq\x01X\x03\x00\x00\x00fooq\x02K\x00K\x01'
481 b'U\x03badq\x03tq\x04Rq\x05.')
482
Antoine Pitroud9dfaa92009-06-04 20:32:06 +0000483
Jeremy Hylton66426532001-10-15 21:38:56 +0000484def create_data():
Tim Peterse9358162001-01-22 22:05:20 +0000485 c = C()
486 c.foo = 1
487 c.bar = 2
Guido van Rossume2a383d2007-01-15 16:59:06 +0000488 x = [0, 1, 2.0, 3.0+0j]
Tim Peters461922a2001-04-09 20:07:05 +0000489 # Append some integer test cases at cPickle.c's internal size
490 # cutoffs.
491 uint1max = 0xff
492 uint2max = 0xffff
493 int4max = 0x7fffffff
494 x.extend([1, -1,
495 uint1max, -uint1max, -uint1max-1,
496 uint2max, -uint2max, -uint2max-1,
497 int4max, -int4max, -int4max-1])
Tim Peterse9358162001-01-22 22:05:20 +0000498 y = ('abc', 'abc', c, c)
499 x.append(y)
500 x.append(y)
501 x.append(5)
Jeremy Hylton66426532001-10-15 21:38:56 +0000502 return x
Tim Petersc58440f2001-04-09 17:16:31 +0000503
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100504
Jeremy Hylton66426532001-10-15 21:38:56 +0000505class AbstractPickleTests(unittest.TestCase):
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000506 # Subclass must define self.dumps, self.loads.
Tim Petersc58440f2001-04-09 17:16:31 +0000507
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +0100508 optimized = False
509
Jeremy Hylton66426532001-10-15 21:38:56 +0000510 _testdata = create_data()
Tim Petersc58440f2001-04-09 17:16:31 +0000511
Jeremy Hylton66426532001-10-15 21:38:56 +0000512 def setUp(self):
Tim Peterse9358162001-01-22 22:05:20 +0000513 pass
Tim Petersc58440f2001-04-09 17:16:31 +0000514
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100515 def assert_is_copy(self, obj, objcopy, msg=None):
516 """Utility method to verify if two objects are copies of each others.
517 """
518 if msg is None:
519 msg = "{!r} is not a copy of {!r}".format(obj, objcopy)
520 self.assertEqual(obj, objcopy, msg=msg)
521 self.assertIs(type(obj), type(objcopy), msg=msg)
522 if hasattr(obj, '__dict__'):
523 self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg)
524 self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg)
525 if hasattr(obj, '__slots__'):
526 self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg)
527 for slot in obj.__slots__:
528 self.assertEqual(
529 hasattr(obj, slot), hasattr(objcopy, slot), msg=msg)
530 self.assertEqual(getattr(obj, slot, None),
531 getattr(objcopy, slot, None), msg=msg)
532
Jeremy Hylton66426532001-10-15 21:38:56 +0000533 def test_misc(self):
534 # test various datatypes not tested by testdata
Tim Peters70b02d72003-02-02 17:26:40 +0000535 for proto in protocols:
536 x = myint(4)
537 s = self.dumps(x, proto)
538 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100539 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000540
Tim Peters70b02d72003-02-02 17:26:40 +0000541 x = (1, ())
542 s = self.dumps(x, proto)
543 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100544 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000545
Tim Peters70b02d72003-02-02 17:26:40 +0000546 x = initarg(1, x)
547 s = self.dumps(x, proto)
548 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100549 self.assert_is_copy(x, y)
Tim Peterse9358162001-01-22 22:05:20 +0000550
Jeremy Hylton66426532001-10-15 21:38:56 +0000551 # XXX test __reduce__ protocol?
552
Tim Peters70b02d72003-02-02 17:26:40 +0000553 def test_roundtrip_equality(self):
554 expected = self._testdata
555 for proto in protocols:
556 s = self.dumps(expected, proto)
557 got = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100558 self.assert_is_copy(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000559
Guido van Rossum98297ee2007-11-06 21:34:58 +0000560 def test_load_from_data0(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100561 self.assert_is_copy(self._testdata, self.loads(DATA0))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000562
563 def test_load_from_data1(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100564 self.assert_is_copy(self._testdata, self.loads(DATA1))
Guido van Rossum98297ee2007-11-06 21:34:58 +0000565
566 def test_load_from_data2(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100567 self.assert_is_copy(self._testdata, self.loads(DATA2))
Jeremy Hylton66426532001-10-15 21:38:56 +0000568
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000569 def test_load_classic_instance(self):
570 # See issue5180. Test loading 2.x pickles that
571 # contain an instance of old style class.
572 for X, args in [(C, ()), (D, ('x',)), (E, ())]:
573 xname = X.__name__.encode('ascii')
574 # Protocol 0 (text mode pickle):
575 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200576 0: ( MARK
577 1: i INST '__main__ X' (MARK at 0)
578 13: p PUT 0
579 16: ( MARK
580 17: d DICT (MARK at 16)
581 18: p PUT 1
582 21: b BUILD
583 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000584 """
585 pickle0 = (b"(i__main__\n"
586 b"X\n"
587 b"p0\n"
588 b"(dp1\nb.").replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100589 self.assert_is_copy(X(*args), self.loads(pickle0))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000590
591 # Protocol 1 (binary mode pickle)
592 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200593 0: ( MARK
594 1: c GLOBAL '__main__ X'
595 13: q BINPUT 0
596 15: o OBJ (MARK at 0)
597 16: q BINPUT 1
598 18: } EMPTY_DICT
599 19: q BINPUT 2
600 21: b BUILD
601 22: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000602 """
603 pickle1 = (b'(c__main__\n'
604 b'X\n'
605 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100606 self.assert_is_copy(X(*args), self.loads(pickle1))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000607
608 # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
609 """
Serhiy Storchakafa310ee2015-02-15 14:10:03 +0200610 0: \x80 PROTO 2
611 2: ( MARK
612 3: c GLOBAL '__main__ X'
613 15: q BINPUT 0
614 17: o OBJ (MARK at 2)
615 18: q BINPUT 1
616 20: } EMPTY_DICT
617 21: q BINPUT 2
618 23: b BUILD
619 24: . STOP
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000620 """
621 pickle2 = (b'\x80\x02(c__main__\n'
622 b'X\n'
623 b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100624 self.assert_is_copy(X(*args), self.loads(pickle2))
Alexander Belopolskyd92f0402010-07-17 22:50:45 +0000625
Tim Peters70b02d72003-02-02 17:26:40 +0000626 # There are gratuitous differences between pickles produced by
627 # pickle and cPickle, largely because cPickle starts PUT indices at
628 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
629 # there's a comment with an exclamation point there whose meaning
630 # is a mystery. cPickle also suppresses PUT for objects with a refcount
631 # of 1.
632 def dont_test_disassembly(self):
Guido van Rossum34d19282007-08-09 01:03:29 +0000633 from io import StringIO
Tim Peters70b02d72003-02-02 17:26:40 +0000634 from pickletools import dis
635
636 for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
637 s = self.dumps(self._testdata, proto)
638 filelike = StringIO()
639 dis(s, out=filelike)
640 got = filelike.getvalue()
641 self.assertEqual(expected, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000642
643 def test_recursive_list(self):
644 l = []
645 l.append(l)
Tim Peters70b02d72003-02-02 17:26:40 +0000646 for proto in protocols:
647 s = self.dumps(l, proto)
648 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100649 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000650 self.assertEqual(len(x), 1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000651 self.assertTrue(x is x[0])
Jeremy Hylton66426532001-10-15 21:38:56 +0000652
Collin Winter8ca69de2009-05-26 16:53:41 +0000653 def test_recursive_tuple(self):
654 t = ([],)
655 t[0].append(t)
656 for proto in protocols:
657 s = self.dumps(t, proto)
658 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100659 self.assertIsInstance(x, tuple)
Collin Winter8ca69de2009-05-26 16:53:41 +0000660 self.assertEqual(len(x), 1)
661 self.assertEqual(len(x[0]), 1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000662 self.assertTrue(x is x[0][0])
Collin Winter8ca69de2009-05-26 16:53:41 +0000663
Jeremy Hylton66426532001-10-15 21:38:56 +0000664 def test_recursive_dict(self):
665 d = {}
666 d[1] = d
Tim Peters70b02d72003-02-02 17:26:40 +0000667 for proto in protocols:
668 s = self.dumps(d, proto)
669 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100670 self.assertIsInstance(x, dict)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000671 self.assertEqual(list(x.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000672 self.assertTrue(x[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000673
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100674 def test_recursive_set(self):
675 h = H()
676 y = set({h})
677 h.attr = y
678 for proto in protocols:
679 s = self.dumps(y, proto)
680 x = self.loads(s)
681 self.assertIsInstance(x, set)
682 self.assertIs(list(x)[0].attr, x)
683 self.assertEqual(len(x), 1)
684
685 def test_recursive_frozenset(self):
686 h = H()
687 y = frozenset({h})
688 h.attr = y
689 for proto in protocols:
690 s = self.dumps(y, proto)
691 x = self.loads(s)
692 self.assertIsInstance(x, frozenset)
693 self.assertIs(list(x)[0].attr, x)
694 self.assertEqual(len(x), 1)
695
Jeremy Hylton66426532001-10-15 21:38:56 +0000696 def test_recursive_inst(self):
697 i = C()
698 i.attr = i
Tim Peters70b02d72003-02-02 17:26:40 +0000699 for proto in protocols:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200700 s = self.dumps(i, proto)
Tim Peters70b02d72003-02-02 17:26:40 +0000701 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100702 self.assertIsInstance(x, C)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000703 self.assertEqual(dir(x), dir(i))
Ezio Melottiaaef3442013-03-04 15:17:56 +0200704 self.assertIs(x.attr, x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000705
706 def test_recursive_multi(self):
707 l = []
708 d = {1:l}
709 i = C()
710 i.attr = d
711 l.append(i)
Tim Peters70b02d72003-02-02 17:26:40 +0000712 for proto in protocols:
713 s = self.dumps(l, proto)
714 x = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100715 self.assertIsInstance(x, list)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000716 self.assertEqual(len(x), 1)
717 self.assertEqual(dir(x[0]), dir(i))
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000718 self.assertEqual(list(x[0].attr.keys()), [1])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000719 self.assertTrue(x[0].attr[1] is x)
Jeremy Hylton66426532001-10-15 21:38:56 +0000720
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000721 def test_get(self):
722 self.assertRaises(KeyError, self.loads, b'g0\np0')
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100723 self.assert_is_copy([(100,), (100,)],
724 self.loads(b'((Kdtp0\nh\x00l.))'))
Jeremy Hylton66426532001-10-15 21:38:56 +0000725
Walter Dörwald9b775532007-06-08 14:30:53 +0000726 def test_unicode(self):
Benjamin Petersond1486302008-12-27 16:58:50 +0000727 endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
Victor Stinner485fb562010-04-13 11:07:24 +0000728 '<\\>', '<\\\U00012345>',
729 # surrogates
730 '<\udc80>']
Walter Dörwald9b775532007-06-08 14:30:53 +0000731 for proto in protocols:
732 for u in endcases:
733 p = self.dumps(u, proto)
734 u2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100735 self.assert_is_copy(u, u2)
Tim Peterse089c682001-04-10 03:41:41 +0000736
Alexandre Vassalotti554d8782008-12-27 07:32:41 +0000737 def test_unicode_high_plane(self):
738 t = '\U00012345'
739 for proto in protocols:
740 p = self.dumps(t, proto)
741 t2 = self.loads(p)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100742 self.assert_is_copy(t, t2)
Alexandre Vassalotti554d8782008-12-27 07:32:41 +0000743
Guido van Rossumf4169812008-03-17 22:56:06 +0000744 def test_bytes(self):
745 for proto in protocols:
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -0500746 for s in b'', b'xyz', b'xyz'*100:
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]) 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))
Alexandre Vassalotti3bfc65a2011-12-13 13:08:09 -0500752 for s in [bytes([i, i]) for i in range(256)]:
Ezio Melottiaaef3442013-03-04 15:17:56 +0200753 p = self.dumps(s, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100754 self.assert_is_copy(s, self.loads(p))
Guido van Rossumf4169812008-03-17 22:56:06 +0000755
Jeremy Hylton66426532001-10-15 21:38:56 +0000756 def test_ints(self):
757 import sys
Tim Petersee1a53c2003-02-02 02:57:53 +0000758 for proto in protocols:
Christian Heimesa37d4c62007-12-04 23:02:19 +0000759 n = sys.maxsize
Tim Petersee1a53c2003-02-02 02:57:53 +0000760 while n:
761 for expected in (-n, n):
762 s = self.dumps(expected, proto)
763 n2 = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100764 self.assert_is_copy(expected, n2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000765 n = n >> 1
Tim Peters19ef62d2001-08-28 22:21:18 +0000766
Jeremy Hylton66426532001-10-15 21:38:56 +0000767 def test_maxint64(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000768 maxint64 = (1 << 63) - 1
Guido van Rossum39478e82007-08-27 17:23:59 +0000769 data = b'I' + str(maxint64).encode("ascii") + b'\n.'
Jeremy Hylton66426532001-10-15 21:38:56 +0000770 got = self.loads(data)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100771 self.assert_is_copy(maxint64, got)
Jeremy Hylton66426532001-10-15 21:38:56 +0000772
773 # Try too with a bogus literal.
Guido van Rossum39478e82007-08-27 17:23:59 +0000774 data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
Jeremy Hylton66426532001-10-15 21:38:56 +0000775 self.assertRaises(ValueError, self.loads, data)
776
Tim Petersee1a53c2003-02-02 02:57:53 +0000777 def test_long(self):
778 for proto in protocols:
Tim Petersbf2674b2003-02-02 07:51:32 +0000779 # 256 bytes is where LONG4 begins.
Tim Petersee1a53c2003-02-02 02:57:53 +0000780 for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000781 nbase = 1 << nbits
Tim Petersee1a53c2003-02-02 02:57:53 +0000782 for npos in nbase-1, nbase, nbase+1:
783 for n in npos, -npos:
784 pickle = self.dumps(n, proto)
785 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100786 self.assert_is_copy(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +0000787 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
788 # bother with those.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000789 nbase = int("deadbeeffeedface", 16)
Tim Petersee1a53c2003-02-02 02:57:53 +0000790 nbase += nbase << 1000000
791 for n in nbase, -nbase:
Tim Petersee1a53c2003-02-02 02:57:53 +0000792 p = self.dumps(n, 2)
Tim Petersee1a53c2003-02-02 02:57:53 +0000793 got = self.loads(p)
Antoine Pitroud5df1942013-11-23 21:20:49 +0100794 # assert_is_copy is very expensive here as it precomputes
795 # a failure message by computing the repr() of n and got,
796 # we just do the check ourselves.
797 self.assertIs(type(got), int)
798 self.assertEqual(n, got)
Tim Petersee1a53c2003-02-02 02:57:53 +0000799
Mark Dickinsoncddcf442009-01-24 21:46:33 +0000800 def test_float(self):
801 test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
802 3.14, 263.44582062374053, 6.022e23, 1e30]
803 test_values = test_values + [-x for x in test_values]
804 for proto in protocols:
805 for value in test_values:
806 pickle = self.dumps(value, proto)
807 got = self.loads(pickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100808 self.assert_is_copy(value, got)
Mark Dickinsoncddcf442009-01-24 21:46:33 +0000809
Thomas Wouters477c8d52006-05-27 19:21:47 +0000810 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
811 def test_float_format(self):
Guido van Rossumf4169812008-03-17 22:56:06 +0000812 # make sure that floats are formatted locale independent with proto 0
813 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000814
Jeremy Hylton66426532001-10-15 21:38:56 +0000815 def test_reduce(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +0100816 for proto in protocols:
817 inst = AAA()
818 dumped = self.dumps(inst, proto)
819 loaded = self.loads(dumped)
820 self.assertEqual(loaded, REDUCE_A)
Jeremy Hylton66426532001-10-15 21:38:56 +0000821
822 def test_getinitargs(self):
Antoine Pitrouc1764dd2013-12-28 16:57:37 +0100823 for proto in protocols:
824 inst = initarg(1, 2)
825 dumped = self.dumps(inst, proto)
826 loaded = self.loads(dumped)
827 self.assert_is_copy(inst, loaded)
Jeremy Hylton66426532001-10-15 21:38:56 +0000828
Antoine Pitrou79035bd2012-06-26 23:04:48 +0200829 def test_pop_empty_stack(self):
830 # Test issue7455
831 s = b'0'
832 self.assertRaises((pickle.UnpicklingError, IndexError), self.loads, s)
833
Guido van Rossum04a86612001-12-19 16:58:54 +0000834 def test_metaclass(self):
835 a = use_metaclass()
Tim Peters70b02d72003-02-02 17:26:40 +0000836 for proto in protocols:
837 s = self.dumps(a, proto)
838 b = self.loads(s)
839 self.assertEqual(a.__class__, b.__class__)
Guido van Rossum04a86612001-12-19 16:58:54 +0000840
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200841 def test_dynamic_class(self):
842 a = create_dynamic_class("my_dynamic_class", (object,))
843 copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
844 for proto in protocols:
845 s = self.dumps(a, proto)
846 b = self.loads(s)
847 self.assertEqual(a, b)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100848 self.assertIs(type(a), type(b))
Antoine Pitrouffd41d92011-10-04 09:23:04 +0200849
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000850 def test_structseq(self):
851 import time
Michael W. Hudson0e025302002-03-06 17:11:18 +0000852 import os
Tim Peters70b02d72003-02-02 17:26:40 +0000853
854 t = time.localtime()
855 for proto in protocols:
856 s = self.dumps(t, proto)
Michael W. Hudson0e025302002-03-06 17:11:18 +0000857 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100858 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000859 if hasattr(os, "stat"):
860 t = os.stat(os.curdir)
861 s = self.dumps(t, proto)
862 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100863 self.assert_is_copy(t, u)
Tim Peters70b02d72003-02-02 17:26:40 +0000864 if hasattr(os, "statvfs"):
865 t = os.statvfs(os.curdir)
866 s = self.dumps(t, proto)
867 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100868 self.assert_is_copy(t, u)
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000869
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100870 def test_ellipsis(self):
871 for proto in protocols:
872 s = self.dumps(..., proto)
873 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100874 self.assertIs(..., u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100875
876 def test_notimplemented(self):
877 for proto in protocols:
878 s = self.dumps(NotImplemented, proto)
879 u = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100880 self.assertIs(NotImplemented, u)
Łukasz Langaf3078fb2012-03-12 19:46:12 +0100881
Alexandre Vassalotti19b6fa62013-11-30 16:06:39 -0800882 def test_singleton_types(self):
883 # Issue #6477: Test that types of built-in singletons can be pickled.
884 singletons = [None, ..., NotImplemented]
885 for singleton in singletons:
886 for proto in protocols:
887 s = self.dumps(type(singleton), proto)
888 u = self.loads(s)
889 self.assertIs(type(singleton), u)
890
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000891 # Tests for protocol 2
892
Tim Peters4190fb82003-02-02 16:09:05 +0000893 def test_proto(self):
Tim Peters4190fb82003-02-02 16:09:05 +0000894 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100895 pickled = self.dumps(None, proto)
Tim Peters4190fb82003-02-02 16:09:05 +0000896 if proto >= 2:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100897 proto_header = pickle.PROTO + bytes([proto])
898 self.assertTrue(pickled.startswith(proto_header))
899 else:
900 self.assertEqual(count_opcode(pickle.PROTO, pickled), 0)
Tim Peters4190fb82003-02-02 16:09:05 +0000901
902 oob = protocols[-1] + 1 # a future protocol
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100903 build_none = pickle.NONE + pickle.STOP
Guido van Rossumcfe5f202007-05-08 21:26:54 +0000904 badpickle = pickle.PROTO + bytes([oob]) + build_none
Tim Peters4190fb82003-02-02 16:09:05 +0000905 try:
906 self.loads(badpickle)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100907 except ValueError as err:
908 self.assertIn("unsupported pickle protocol", str(err))
Tim Peters4190fb82003-02-02 16:09:05 +0000909 else:
910 self.fail("expected bad protocol number to raise ValueError")
911
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000912 def test_long1(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000913 x = 12345678910111213141516178920
Tim Peters61bf2572003-02-03 21:31:22 +0000914 for proto in protocols:
915 s = self.dumps(x, proto)
916 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100917 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000918 self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000919
920 def test_long4(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000921 x = 12345678910111213141516178920 << (256*8)
Tim Peters61bf2572003-02-03 21:31:22 +0000922 for proto in protocols:
923 s = self.dumps(x, proto)
924 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100925 self.assert_is_copy(x, y)
Tim Peters22e71712003-02-03 22:27:38 +0000926 self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
Guido van Rossumd6c9e632003-01-28 03:49:52 +0000927
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000928 def test_short_tuples(self):
Tim Peters1d63c9f2003-02-02 20:29:39 +0000929 # Map (proto, len(tuple)) to expected opcode.
930 expected_opcode = {(0, 0): pickle.TUPLE,
931 (0, 1): pickle.TUPLE,
932 (0, 2): pickle.TUPLE,
933 (0, 3): pickle.TUPLE,
934 (0, 4): pickle.TUPLE,
935
936 (1, 0): pickle.EMPTY_TUPLE,
937 (1, 1): pickle.TUPLE,
938 (1, 2): pickle.TUPLE,
939 (1, 3): pickle.TUPLE,
940 (1, 4): pickle.TUPLE,
941
942 (2, 0): pickle.EMPTY_TUPLE,
943 (2, 1): pickle.TUPLE1,
944 (2, 2): pickle.TUPLE2,
945 (2, 3): pickle.TUPLE3,
946 (2, 4): pickle.TUPLE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000947
948 (3, 0): pickle.EMPTY_TUPLE,
949 (3, 1): pickle.TUPLE1,
950 (3, 2): pickle.TUPLE2,
951 (3, 3): pickle.TUPLE3,
952 (3, 4): pickle.TUPLE,
Tim Peters1d63c9f2003-02-02 20:29:39 +0000953 }
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000954 a = ()
Guido van Rossum025bc2f2003-01-28 04:20:02 +0000955 b = (1,)
956 c = (1, 2)
957 d = (1, 2, 3)
958 e = (1, 2, 3, 4)
Tim Peters4190fb82003-02-02 16:09:05 +0000959 for proto in protocols:
Guido van Rossum44f0ea52003-01-28 04:14:51 +0000960 for x in a, b, c, d, e:
961 s = self.dumps(x, proto)
962 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100963 self.assert_is_copy(x, y)
964 expected = expected_opcode[min(proto, 3), len(x)]
965 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters1d63c9f2003-02-02 20:29:39 +0000966
Guido van Rossum7d97d312003-01-28 04:25:27 +0000967 def test_singletons(self):
Tim Peters61bf2572003-02-03 21:31:22 +0000968 # Map (proto, singleton) to expected opcode.
969 expected_opcode = {(0, None): pickle.NONE,
970 (1, None): pickle.NONE,
971 (2, None): pickle.NONE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000972 (3, None): pickle.NONE,
Tim Peters61bf2572003-02-03 21:31:22 +0000973
974 (0, True): pickle.INT,
975 (1, True): pickle.INT,
976 (2, True): pickle.NEWTRUE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000977 (3, True): pickle.NEWTRUE,
Tim Peters61bf2572003-02-03 21:31:22 +0000978
979 (0, False): pickle.INT,
980 (1, False): pickle.INT,
981 (2, False): pickle.NEWFALSE,
Guido van Rossumf4169812008-03-17 22:56:06 +0000982 (3, False): pickle.NEWFALSE,
Tim Peters61bf2572003-02-03 21:31:22 +0000983 }
Tim Peters4190fb82003-02-02 16:09:05 +0000984 for proto in protocols:
Guido van Rossum7d97d312003-01-28 04:25:27 +0000985 for x in None, False, True:
986 s = self.dumps(x, proto)
987 y = self.loads(s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000988 self.assertTrue(x is y, (proto, x, s, y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100989 expected = expected_opcode[min(proto, 3), x]
990 self.assertTrue(opcode_in_pickle(expected, s))
Tim Peters3c67d792003-02-02 17:59:11 +0000991
Guido van Rossum533dbcf2003-01-28 17:55:05 +0000992 def test_newobj_tuple(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +0000993 x = MyTuple([1, 2, 3])
994 x.foo = 42
995 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +0000996 for proto in protocols:
997 s = self.dumps(x, proto)
998 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100999 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001000
1001 def test_newobj_list(self):
Guido van Rossum3d8c01b2003-01-28 19:48:18 +00001002 x = MyList([1, 2, 3])
1003 x.foo = 42
1004 x.bar = "hello"
Tim Peters894453a2003-02-03 22:32:18 +00001005 for proto in protocols:
1006 s = self.dumps(x, proto)
1007 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001008 self.assert_is_copy(x, y)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001009
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001010 def test_newobj_generic(self):
Tim Peters5013bd92003-02-03 22:28:41 +00001011 for proto in protocols:
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001012 for C in myclasses:
1013 B = C.__base__
1014 x = C(C.sample)
1015 x.foo = 42
1016 s = self.dumps(x, proto)
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001017 y = self.loads(s)
1018 detail = (proto, C, B, x, y, type(y))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001019 self.assert_is_copy(x, y) # XXX revisit
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001020 self.assertEqual(B(x), B(y), detail)
1021 self.assertEqual(x.__dict__, y.__dict__, detail)
1022
Antoine Pitrou16c4ce12011-03-11 21:30:43 +01001023 def test_newobj_proxies(self):
1024 # NEWOBJ should use the __class__ rather than the raw type
1025 classes = myclasses[:]
1026 # Cannot create weakproxies to these classes
1027 for c in (MyInt, MyTuple):
1028 classes.remove(c)
1029 for proto in protocols:
1030 for C in classes:
1031 B = C.__base__
1032 x = C(C.sample)
1033 x.foo = 42
1034 p = weakref.proxy(x)
1035 s = self.dumps(p, proto)
1036 y = self.loads(s)
1037 self.assertEqual(type(y), type(x)) # rather than type(p)
1038 detail = (proto, C, B, x, y, type(y))
1039 self.assertEqual(B(x), B(y), detail)
1040 self.assertEqual(x.__dict__, y.__dict__, detail)
1041
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001042 def test_newobj_not_class(self):
1043 # Issue 24552
1044 global SimpleNewObj
1045 save = SimpleNewObj
Benjamin Petersond3a2a952015-07-02 16:58:22 -05001046 o = SimpleNewObj.__new__(SimpleNewObj)
Benjamin Peterson80f78a32015-07-02 16:18:38 -05001047 b = self.dumps(o, 4)
1048 try:
1049 SimpleNewObj = 42
1050 self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b)
1051 finally:
1052 SimpleNewObj = save
1053
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001054 # Register a type with copyreg, with extension code extcode. Pickle
Tim Peters22e71712003-02-03 22:27:38 +00001055 # an object of that type. Check that the resulting pickle uses opcode
1056 # (EXT[124]) under proto 2, and not in proto 1.
Tim Peters3e667d52003-02-04 21:47:44 +00001057
Tim Peters22e71712003-02-03 22:27:38 +00001058 def produce_global_ext(self, extcode, opcode):
Tim Peters3e667d52003-02-04 21:47:44 +00001059 e = ExtensionSaver(extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001060 try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +00001061 copyreg.add_extension(__name__, "MyList", extcode)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001062 x = MyList([1, 2, 3])
1063 x.foo = 42
1064 x.bar = "hello"
1065
Tim Peters22e71712003-02-03 22:27:38 +00001066 # Dump using protocol 1 for comparison.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001067 s1 = self.dumps(x, 1)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001068 self.assertIn(__name__.encode("utf-8"), s1)
1069 self.assertIn(b"MyList", s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001070 self.assertFalse(opcode_in_pickle(opcode, s1))
Tim Peters3e667d52003-02-04 21:47:44 +00001071
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001072 y = self.loads(s1)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001073 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001074
Tim Peters22e71712003-02-03 22:27:38 +00001075 # Dump using protocol 2 for test.
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001076 s2 = self.dumps(x, 2)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001077 self.assertNotIn(__name__.encode("utf-8"), s2)
1078 self.assertNotIn(b"MyList", s2)
Guido van Rossumcfe5f202007-05-08 21:26:54 +00001079 self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
Tim Peters3e667d52003-02-04 21:47:44 +00001080
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001081 y = self.loads(s2)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001082 self.assert_is_copy(x, y)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001083 finally:
Tim Peters3e667d52003-02-04 21:47:44 +00001084 e.restore()
Tim Peters22e71712003-02-03 22:27:38 +00001085
1086 def test_global_ext1(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001087 self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
1088 self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001089
1090 def test_global_ext2(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001091 self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
1092 self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
1093 self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001094
1095 def test_global_ext4(self):
Tim Peters3e667d52003-02-04 21:47:44 +00001096 self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
1097 self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
1098 self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
1099
Tim Peters8d2613a2003-02-11 16:40:16 +00001100 def test_list_chunking(self):
1101 n = 10 # too small to chunk
Guido van Rossum805365e2007-05-07 22:24:25 +00001102 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001103 for proto in protocols:
1104 s = self.dumps(x, proto)
1105 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001106 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001107 num_appends = count_opcode(pickle.APPENDS, s)
1108 self.assertEqual(num_appends, proto > 0)
1109
1110 n = 2500 # expect at least two chunks when proto > 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001111 x = list(range(n))
Tim Peters8d2613a2003-02-11 16:40:16 +00001112 for proto in protocols:
1113 s = self.dumps(x, proto)
1114 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001115 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001116 num_appends = count_opcode(pickle.APPENDS, s)
1117 if proto == 0:
1118 self.assertEqual(num_appends, 0)
1119 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001120 self.assertTrue(num_appends >= 2)
Tim Peters8d2613a2003-02-11 16:40:16 +00001121
1122 def test_dict_chunking(self):
1123 n = 10 # too small to chunk
1124 x = dict.fromkeys(range(n))
1125 for proto in protocols:
1126 s = self.dumps(x, proto)
Ezio Melottie9615932010-01-24 19:26:24 +00001127 self.assertIsInstance(s, bytes_types)
Tim Peters8d2613a2003-02-11 16:40:16 +00001128 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001129 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001130 num_setitems = count_opcode(pickle.SETITEMS, s)
1131 self.assertEqual(num_setitems, proto > 0)
1132
1133 n = 2500 # expect at least two chunks when proto > 0
1134 x = dict.fromkeys(range(n))
1135 for proto in protocols:
1136 s = self.dumps(x, proto)
1137 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001138 self.assert_is_copy(x, y)
Tim Peters8d2613a2003-02-11 16:40:16 +00001139 num_setitems = count_opcode(pickle.SETITEMS, s)
1140 if proto == 0:
1141 self.assertEqual(num_setitems, 0)
1142 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001143 self.assertTrue(num_setitems >= 2)
Guido van Rossum0322d0f2003-01-29 06:12:46 +00001144
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001145 def test_set_chunking(self):
1146 n = 10 # too small to chunk
1147 x = set(range(n))
1148 for proto in protocols:
1149 s = self.dumps(x, proto)
1150 y = self.loads(s)
1151 self.assert_is_copy(x, y)
1152 num_additems = count_opcode(pickle.ADDITEMS, s)
1153 if proto < 4:
1154 self.assertEqual(num_additems, 0)
1155 else:
1156 self.assertEqual(num_additems, 1)
1157
1158 n = 2500 # expect at least two chunks when proto >= 4
1159 x = set(range(n))
1160 for proto in protocols:
1161 s = self.dumps(x, proto)
1162 y = self.loads(s)
1163 self.assert_is_copy(x, y)
1164 num_additems = count_opcode(pickle.ADDITEMS, s)
1165 if proto < 4:
1166 self.assertEqual(num_additems, 0)
1167 else:
1168 self.assertGreaterEqual(num_additems, 2)
1169
Tim Peterse9ef2032003-02-13 18:42:00 +00001170 def test_simple_newobj(self):
1171 x = object.__new__(SimpleNewObj) # avoid __init__
1172 x.abc = 666
1173 for proto in protocols:
1174 s = self.dumps(x, proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001175 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s),
1176 2 <= proto < 4)
1177 self.assertEqual(opcode_in_pickle(pickle.NEWOBJ_EX, s),
1178 proto >= 4)
Tim Peterse9ef2032003-02-13 18:42:00 +00001179 y = self.loads(s) # will raise TypeError if __init__ called
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001180 self.assert_is_copy(x, y)
Tim Peterse9ef2032003-02-13 18:42:00 +00001181
Tim Peters42f08ac2003-02-11 22:43:24 +00001182 def test_newobj_list_slots(self):
1183 x = SlotList([1, 2, 3])
1184 x.foo = 42
1185 x.bar = "hello"
1186 s = self.dumps(x, 2)
1187 y = self.loads(s)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001188 self.assert_is_copy(x, y)
Tim Peters42f08ac2003-02-11 22:43:24 +00001189
Guido van Rossum2a30b212003-02-18 22:41:24 +00001190 def test_reduce_overrides_default_reduce_ex(self):
Collin Winter771d8342009-04-16 03:18:06 +00001191 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001192 x = REX_one()
1193 self.assertEqual(x._reduce_called, 0)
1194 s = self.dumps(x, proto)
1195 self.assertEqual(x._reduce_called, 1)
1196 y = self.loads(s)
1197 self.assertEqual(y._reduce_called, 0)
1198
1199 def test_reduce_ex_called(self):
Collin Winter771d8342009-04-16 03:18:06 +00001200 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001201 x = REX_two()
1202 self.assertEqual(x._proto, None)
1203 s = self.dumps(x, proto)
1204 self.assertEqual(x._proto, proto)
1205 y = self.loads(s)
1206 self.assertEqual(y._proto, None)
1207
1208 def test_reduce_ex_overrides_reduce(self):
Collin Winter771d8342009-04-16 03:18:06 +00001209 for proto in protocols:
Guido van Rossum2a30b212003-02-18 22:41:24 +00001210 x = REX_three()
1211 self.assertEqual(x._proto, None)
1212 s = self.dumps(x, proto)
1213 self.assertEqual(x._proto, proto)
1214 y = self.loads(s)
1215 self.assertEqual(y._proto, None)
1216
Guido van Rossumd8faa362007-04-27 19:54:29 +00001217 def test_reduce_ex_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00001218 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001219 x = REX_four()
1220 self.assertEqual(x._proto, None)
1221 s = self.dumps(x, proto)
1222 self.assertEqual(x._proto, proto)
1223 y = self.loads(s)
1224 self.assertEqual(y._proto, proto)
1225
1226 def test_reduce_calls_base(self):
Collin Winter771d8342009-04-16 03:18:06 +00001227 for proto in protocols:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001228 x = REX_five()
1229 self.assertEqual(x._reduce_called, 0)
1230 s = self.dumps(x, proto)
1231 self.assertEqual(x._reduce_called, 1)
1232 y = self.loads(s)
1233 self.assertEqual(y._reduce_called, 1)
1234
Brett Cannon31f59292011-02-21 19:29:56 +00001235 @no_tracing
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001236 def test_bad_getattr(self):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001237 # Issue #3514: crash when there is an infinite loop in __getattr__
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001238 x = BadGetattr()
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001239 for proto in protocols:
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001240 self.assertRaises(RuntimeError, self.dumps, x, proto)
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001241
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001242 def test_reduce_bad_iterator(self):
1243 # Issue4176: crash when 4th and 5th items of __reduce__()
1244 # are not iterators
1245 class C(object):
1246 def __reduce__(self):
1247 # 4th item is not an iterator
1248 return list, (), None, [], None
1249 class D(object):
1250 def __reduce__(self):
1251 # 5th item is not an iterator
1252 return dict, (), None, None, []
1253
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00001254 # Protocol 0 is less strict and also accept iterables.
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001255 for proto in protocols:
Amaury Forgeot d'Arc6285ffd2008-10-31 17:52:47 +00001256 try:
1257 self.dumps(C(), proto)
1258 except (pickle.PickleError):
1259 pass
1260 try:
1261 self.dumps(D(), proto)
1262 except (pickle.PickleError):
1263 pass
Amaury Forgeot d'Arc424b4812008-10-30 22:25:31 +00001264
Collin Winter771d8342009-04-16 03:18:06 +00001265 def test_many_puts_and_gets(self):
1266 # Test that internal data structures correctly deal with lots of
1267 # puts/gets.
1268 keys = ("aaa" + str(i) for i in range(100))
1269 large_dict = dict((k, [4, 5, 6]) for k in keys)
1270 obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
1271
1272 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001273 with self.subTest(proto=proto):
1274 dumped = self.dumps(obj, proto)
1275 loaded = self.loads(dumped)
1276 self.assert_is_copy(obj, loaded)
Collin Winter771d8342009-04-16 03:18:06 +00001277
Antoine Pitroua9f48a02009-05-02 21:41:14 +00001278 def test_attribute_name_interning(self):
1279 # Test that attribute names of pickled objects are interned when
1280 # unpickling.
1281 for proto in protocols:
1282 x = C()
1283 x.foo = 42
1284 x.bar = "hello"
1285 s = self.dumps(x, proto)
1286 y = self.loads(s)
1287 x_keys = sorted(x.__dict__)
1288 y_keys = sorted(y.__dict__)
1289 for x_key, y_key in zip(x_keys, y_keys):
1290 self.assertIs(x_key, y_key)
1291
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001292 def test_unpickle_from_2x(self):
1293 # Unpickle non-trivial data from Python 2.x.
1294 loaded = self.loads(DATA3)
1295 self.assertEqual(loaded, set([1, 2]))
1296 loaded = self.loads(DATA4)
1297 self.assertEqual(type(loaded), type(range(0)))
1298 self.assertEqual(list(loaded), list(range(5)))
1299 loaded = self.loads(DATA5)
1300 self.assertEqual(type(loaded), SimpleCookie)
1301 self.assertEqual(list(loaded.keys()), ["key"])
Serhiy Storchaka8cf7c1c2014-11-02 22:18:25 +02001302 self.assertEqual(loaded["key"].value, "value")
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001303
Walter Doerwald9d1dbca2013-12-02 11:41:01 +01001304 for (exc, data) in DATA7.items():
1305 loaded = self.loads(data)
1306 self.assertIs(type(loaded), exc)
1307
1308 loaded = self.loads(DATA8)
1309 self.assertIs(type(loaded), Exception)
1310
1311 loaded = self.loads(DATA9)
1312 self.assertIs(type(loaded), UnicodeEncodeError)
1313 self.assertEqual(loaded.object, "foo")
1314 self.assertEqual(loaded.encoding, "ascii")
1315 self.assertEqual(loaded.start, 0)
1316 self.assertEqual(loaded.end, 1)
1317 self.assertEqual(loaded.reason, "bad")
1318
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001319 def test_pickle_to_2x(self):
1320 # Pickle non-trivial data with protocol 2, expecting that it yields
1321 # the same result as Python 2.x did.
1322 # NOTE: this test is a bit too strong since we can produce different
1323 # bytecode that 2.x will still understand.
1324 dumped = self.dumps(range(5), 2)
1325 self.assertEqual(dumped, DATA4)
1326 dumped = self.dumps(set([3]), 2)
1327 self.assertEqual(dumped, DATA6)
1328
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -08001329 def test_load_python2_str_as_bytes(self):
1330 # From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
1331 self.assertEqual(self.loads(b"S'a\\x00\\xa0'\n.",
1332 encoding="bytes"), b'a\x00\xa0')
1333 # From Python 2: pickle.dumps('a\x00\xa0', protocol=1)
1334 self.assertEqual(self.loads(b'U\x03a\x00\xa0.',
1335 encoding="bytes"), b'a\x00\xa0')
1336 # From Python 2: pickle.dumps('a\x00\xa0', protocol=2)
1337 self.assertEqual(self.loads(b'\x80\x02U\x03a\x00\xa0.',
1338 encoding="bytes"), b'a\x00\xa0')
1339
1340 def test_load_python2_unicode_as_str(self):
1341 # From Python 2: pickle.dumps(u'π', protocol=0)
1342 self.assertEqual(self.loads(b'V\\u03c0\n.',
1343 encoding='bytes'), 'π')
1344 # From Python 2: pickle.dumps(u'π', protocol=1)
1345 self.assertEqual(self.loads(b'X\x02\x00\x00\x00\xcf\x80.',
1346 encoding="bytes"), 'π')
1347 # From Python 2: pickle.dumps(u'π', protocol=2)
1348 self.assertEqual(self.loads(b'\x80\x02X\x02\x00\x00\x00\xcf\x80.',
1349 encoding="bytes"), 'π')
1350
1351 def test_load_long_python2_str_as_bytes(self):
1352 # From Python 2: pickle.dumps('x' * 300, protocol=1)
1353 self.assertEqual(self.loads(pickle.BINSTRING +
1354 struct.pack("<I", 300) +
1355 b'x' * 300 + pickle.STOP,
1356 encoding='bytes'), b'x' * 300)
1357
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001358 def test_large_pickles(self):
1359 # Test the correctness of internal buffering routines when handling
1360 # large data.
1361 for proto in protocols:
Antoine Pitrou04248a82010-10-12 20:51:21 +00001362 data = (1, min, b'xy' * (30 * 1024), len)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001363 dumped = self.dumps(data, proto)
1364 loaded = self.loads(dumped)
Antoine Pitrou04248a82010-10-12 20:51:21 +00001365 self.assertEqual(len(loaded), len(data))
Antoine Pitrouea99c5c2010-09-09 18:33:21 +00001366 self.assertEqual(loaded, data)
1367
Alexander Belopolsky1ce92dc2011-02-24 19:40:09 +00001368 def test_empty_bytestring(self):
1369 # issue 11286
1370 empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
1371 self.assertEqual(empty, '')
Antoine Pitroud9dfaa92009-06-04 20:32:06 +00001372
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001373 def test_int_pickling_efficiency(self):
1374 # Test compacity of int representation (see issue #12744)
1375 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001376 with self.subTest(proto=proto):
1377 pickles = [self.dumps(2**n, proto) for n in range(70)]
1378 sizes = list(map(len, pickles))
1379 # the size function is monotonic
1380 self.assertEqual(sorted(sizes), sizes)
1381 if proto >= 2:
1382 for p in pickles:
1383 self.assertFalse(opcode_in_pickle(pickle.LONG, p))
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001384
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001385 def check_negative_32b_binXXX(self, dumped):
1386 if sys.maxsize > 2**32:
1387 self.skipTest("test is only meaningful on 32-bit builds")
1388 # XXX Pure Python pickle reads lengths as signed and passes
1389 # them directly to read() (hence the EOFError)
1390 with self.assertRaises((pickle.UnpicklingError, EOFError,
1391 ValueError, OverflowError)):
1392 self.loads(dumped)
1393
1394 def test_negative_32b_binbytes(self):
1395 # On 32-bit builds, a BINBYTES of 2**31 or more is refused
1396 self.check_negative_32b_binXXX(b'\x80\x03B\xff\xff\xff\xffxyzq\x00.')
1397
1398 def test_negative_32b_binunicode(self):
1399 # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
1400 self.check_negative_32b_binXXX(b'\x80\x03X\xff\xff\xff\xffxyzq\x00.')
1401
Antoine Pitrou55549ec2011-08-30 00:27:10 +02001402 def test_negative_put(self):
1403 # Issue #12847
1404 dumped = b'Va\np-1\n.'
1405 self.assertRaises(ValueError, self.loads, dumped)
1406
1407 def test_negative_32b_binput(self):
1408 # Issue #12847
1409 if sys.maxsize > 2**32:
1410 self.skipTest("test is only meaningful on 32-bit builds")
1411 dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
1412 self.assertRaises(ValueError, self.loads, dumped)
1413
Alexandre Vassalotti7c5e0942013-04-15 23:14:55 -07001414 def test_badly_escaped_string(self):
1415 self.assertRaises(ValueError, self.loads, b"S'\\'\n.")
1416
1417 def test_badly_quoted_string(self):
1418 # Issue #17710
1419 badpickles = [b"S'\n.",
1420 b'S"\n.',
1421 b'S\' \n.',
1422 b'S" \n.',
1423 b'S\'"\n.',
1424 b'S"\'\n.',
1425 b"S' ' \n.",
1426 b'S" " \n.',
1427 b"S ''\n.",
1428 b'S ""\n.',
1429 b'S \n.',
1430 b'S\n.',
1431 b'S.']
1432 for p in badpickles:
1433 self.assertRaises(pickle.UnpicklingError, self.loads, p)
1434
1435 def test_correctly_quoted_string(self):
1436 goodpickles = [(b"S''\n.", ''),
1437 (b'S""\n.', ''),
1438 (b'S"\\n"\n.', '\n'),
1439 (b"S'\\n'\n.", '\n')]
1440 for p, expected in goodpickles:
1441 self.assertEqual(self.loads(p), expected)
1442
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001443 def _check_pickling_with_opcode(self, obj, opcode, proto):
1444 pickled = self.dumps(obj, proto)
1445 self.assertTrue(opcode_in_pickle(opcode, pickled))
1446 unpickled = self.loads(pickled)
1447 self.assertEqual(obj, unpickled)
1448
1449 def test_appends_on_non_lists(self):
1450 # Issue #17720
1451 obj = REX_six([1, 2, 3])
1452 for proto in protocols:
1453 if proto == 0:
1454 self._check_pickling_with_opcode(obj, pickle.APPEND, proto)
1455 else:
1456 self._check_pickling_with_opcode(obj, pickle.APPENDS, proto)
1457
1458 def test_setitems_on_non_dicts(self):
1459 obj = REX_seven({1: -1, 2: -2, 3: -3})
1460 for proto in protocols:
1461 if proto == 0:
1462 self._check_pickling_with_opcode(obj, pickle.SETITEM, proto)
1463 else:
1464 self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)
1465
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001466 # Exercise framing (proto >= 4) for significant workloads
1467
1468 FRAME_SIZE_TARGET = 64 * 1024
1469
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001470 def check_frame_opcodes(self, pickled):
1471 """
1472 Check the arguments of FRAME opcodes in a protocol 4+ pickle.
1473 """
1474 frame_opcode_size = 9
1475 last_arg = last_pos = None
1476 for op, arg, pos in pickletools.genops(pickled):
1477 if op.name != 'FRAME':
1478 continue
1479 if last_pos is not None:
1480 # The previous frame's size should be equal to the number
1481 # of bytes up to the current frame.
1482 frame_size = pos - last_pos - frame_opcode_size
1483 self.assertEqual(frame_size, last_arg)
1484 last_arg, last_pos = arg, pos
1485 # The last frame's size should be equal to the number of bytes up
1486 # to the pickle's end.
1487 frame_size = len(pickled) - last_pos - frame_opcode_size
1488 self.assertEqual(frame_size, last_arg)
1489
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001490 def test_framing_many_objects(self):
1491 obj = list(range(10**5))
1492 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1493 with self.subTest(proto=proto):
1494 pickled = self.dumps(obj, proto)
1495 unpickled = self.loads(pickled)
1496 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01001497 bytes_per_frame = (len(pickled) /
1498 count_opcode(pickle.FRAME, pickled))
1499 self.assertGreater(bytes_per_frame,
1500 self.FRAME_SIZE_TARGET / 2)
1501 self.assertLessEqual(bytes_per_frame,
1502 self.FRAME_SIZE_TARGET * 1)
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001503 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001504
1505 def test_framing_large_objects(self):
1506 N = 1024 * 1024
1507 obj = [b'x' * N, b'y' * N, b'z' * N]
1508 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1509 with self.subTest(proto=proto):
1510 pickled = self.dumps(obj, proto)
1511 unpickled = self.loads(pickled)
1512 self.assertEqual(obj, unpickled)
Antoine Pitrou3ab9cfc2013-11-24 14:33:37 +01001513 n_frames = count_opcode(pickle.FRAME, pickled)
Alexandre Vassalotti28d271e2013-12-01 16:27:46 -08001514 self.assertGreaterEqual(n_frames, len(obj))
Antoine Pitrou6e8bc502013-12-03 09:51:40 +01001515 self.check_frame_opcodes(pickled)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001516
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001517 def test_optional_frames(self):
1518 if pickle.HIGHEST_PROTOCOL < 4:
1519 return
1520
1521 def remove_frames(pickled, keep_frame=None):
1522 """Remove frame opcodes from the given pickle."""
1523 frame_starts = []
1524 # 1 byte for the opcode and 8 for the argument
1525 frame_opcode_size = 9
1526 for opcode, _, pos in pickletools.genops(pickled):
1527 if opcode.name == 'FRAME':
1528 frame_starts.append(pos)
1529
1530 newpickle = bytearray()
1531 last_frame_end = 0
1532 for i, pos in enumerate(frame_starts):
1533 if keep_frame and keep_frame(i):
1534 continue
1535 newpickle += pickled[last_frame_end:pos]
1536 last_frame_end = pos + frame_opcode_size
1537 newpickle += pickled[last_frame_end:]
1538 return newpickle
1539
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001540 frame_size = self.FRAME_SIZE_TARGET
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001541 num_frames = 20
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001542 obj = [bytes([i]) * frame_size for i in range(num_frames)]
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001543
1544 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1545 pickled = self.dumps(obj, proto)
1546
1547 frameless_pickle = remove_frames(pickled)
1548 self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
1549 self.assertEqual(obj, self.loads(frameless_pickle))
1550
Alexandre Vassalotti5e411b72013-11-23 20:58:24 -08001551 some_frames_pickle = remove_frames(pickled, lambda i: i % 2)
Alexandre Vassalottib6a2f2a2013-11-23 20:30:03 -08001552 self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
1553 count_opcode(pickle.FRAME, pickled))
1554 self.assertEqual(obj, self.loads(some_frames_pickle))
1555
Serhiy Storchaka21d75332015-01-26 10:37:01 +02001556 def test_frame_readline(self):
1557 pickled = b'\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00I42\n.'
1558 # 0: \x80 PROTO 4
1559 # 2: \x95 FRAME 5
1560 # 11: I INT 42
1561 # 15: . STOP
1562 self.assertEqual(self.loads(pickled), 42)
1563
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001564 def test_nested_names(self):
1565 global Nested
1566 class Nested:
1567 class A:
1568 class B:
1569 class C:
1570 pass
1571
1572 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1573 for obj in [Nested.A, Nested.A.B, Nested.A.B.C]:
1574 with self.subTest(proto=proto, obj=obj):
1575 unpickled = self.loads(self.dumps(obj, proto))
1576 self.assertIs(obj, unpickled)
1577
1578 def test_py_methods(self):
1579 global PyMethodsTest
1580 class PyMethodsTest:
1581 @staticmethod
1582 def cheese():
1583 return "cheese"
1584 @classmethod
1585 def wine(cls):
1586 assert cls is PyMethodsTest
1587 return "wine"
1588 def biscuits(self):
1589 assert isinstance(self, PyMethodsTest)
1590 return "biscuits"
1591 class Nested:
1592 "Nested class"
1593 @staticmethod
1594 def ketchup():
1595 return "ketchup"
1596 @classmethod
1597 def maple(cls):
1598 assert cls is PyMethodsTest.Nested
1599 return "maple"
1600 def pie(self):
1601 assert isinstance(self, PyMethodsTest.Nested)
1602 return "pie"
1603
1604 py_methods = (
1605 PyMethodsTest.cheese,
1606 PyMethodsTest.wine,
1607 PyMethodsTest().biscuits,
1608 PyMethodsTest.Nested.ketchup,
1609 PyMethodsTest.Nested.maple,
1610 PyMethodsTest.Nested().pie
1611 )
1612 py_unbound_methods = (
1613 (PyMethodsTest.biscuits, PyMethodsTest),
1614 (PyMethodsTest.Nested.pie, PyMethodsTest.Nested)
1615 )
1616 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1617 for method in py_methods:
1618 with self.subTest(proto=proto, method=method):
1619 unpickled = self.loads(self.dumps(method, proto))
1620 self.assertEqual(method(), unpickled())
1621 for method, cls in py_unbound_methods:
1622 obj = cls()
1623 with self.subTest(proto=proto, method=method):
1624 unpickled = self.loads(self.dumps(method, proto))
1625 self.assertEqual(method(obj), unpickled(obj))
1626
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001627 def test_c_methods(self):
1628 global Subclass
1629 class Subclass(tuple):
1630 class Nested(str):
1631 pass
1632
1633 c_methods = (
1634 # bound built-in method
1635 ("abcd".index, ("c",)),
1636 # unbound built-in method
1637 (str.index, ("abcd", "c")),
1638 # bound "slot" method
1639 ([1, 2, 3].__len__, ()),
1640 # unbound "slot" method
1641 (list.__len__, ([1, 2, 3],)),
1642 # bound "coexist" method
1643 ({1, 2}.__contains__, (2,)),
1644 # unbound "coexist" method
1645 (set.__contains__, ({1, 2}, 2)),
1646 # built-in class method
1647 (dict.fromkeys, (("a", 1), ("b", 2))),
1648 # built-in static method
1649 (bytearray.maketrans, (b"abc", b"xyz")),
1650 # subclass methods
1651 (Subclass([1,2,2]).count, (2,)),
1652 (Subclass.count, (Subclass([1,2,2]), 2)),
1653 (Subclass.Nested("sweet").count, ("e",)),
1654 (Subclass.Nested.count, (Subclass.Nested("sweet"), "e")),
1655 )
1656 for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
1657 for method, args in c_methods:
1658 with self.subTest(proto=proto, method=method):
1659 unpickled = self.loads(self.dumps(method, proto))
1660 self.assertEqual(method(*args), unpickled(*args))
1661
Serhiy Storchakabfe18242015-03-31 13:12:37 +03001662 def test_compat_pickle(self):
1663 tests = [
1664 (range(1, 7), '__builtin__', 'xrange'),
1665 (map(int, '123'), 'itertools', 'imap'),
1666 (functools.reduce, '__builtin__', 'reduce'),
1667 (dbm.whichdb, 'whichdb', 'whichdb'),
1668 (Exception(), 'exceptions', 'Exception'),
1669 (collections.UserDict(), 'UserDict', 'IterableUserDict'),
1670 (collections.UserList(), 'UserList', 'UserList'),
1671 (collections.defaultdict(), 'collections', 'defaultdict'),
1672 ]
1673 for val, mod, name in tests:
1674 for proto in range(3):
1675 with self.subTest(type=type(val), proto=proto):
1676 pickled = self.dumps(val, proto)
1677 self.assertIn(('c%s\n%s' % (mod, name)).encode(), pickled)
1678 self.assertIs(type(self.loads(pickled)), type(val))
1679
1680 def test_compat_unpickle(self):
1681 # xrange(1, 7)
1682 pickled = b'\x80\x02c__builtin__\nxrange\nK\x01K\x07K\x01\x87R.'
1683 unpickled = self.loads(pickled)
1684 self.assertIs(type(unpickled), range)
1685 self.assertEqual(unpickled, range(1, 7))
1686 self.assertEqual(list(unpickled), [1, 2, 3, 4, 5, 6])
1687 # reduce
1688 pickled = b'\x80\x02c__builtin__\nreduce\n.'
1689 self.assertIs(self.loads(pickled), functools.reduce)
1690 # whichdb.whichdb
1691 pickled = b'\x80\x02cwhichdb\nwhichdb\n.'
1692 self.assertIs(self.loads(pickled), dbm.whichdb)
1693 # Exception(), StandardError()
1694 for name in (b'Exception', b'StandardError'):
1695 pickled = (b'\x80\x02cexceptions\n' + name + b'\nU\x03ugh\x85R.')
1696 unpickled = self.loads(pickled)
1697 self.assertIs(type(unpickled), Exception)
1698 self.assertEqual(str(unpickled), 'ugh')
1699 # UserDict.UserDict({1: 2}), UserDict.IterableUserDict({1: 2})
1700 for name in (b'UserDict', b'IterableUserDict'):
1701 pickled = (b'\x80\x02(cUserDict\n' + name +
1702 b'\no}U\x04data}K\x01K\x02ssb.')
1703 unpickled = self.loads(pickled)
1704 self.assertIs(type(unpickled), collections.UserDict)
1705 self.assertEqual(unpickled, collections.UserDict({1: 2}))
1706
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001707
1708class BigmemPickleTests(unittest.TestCase):
1709
1710 # Binary protocols can serialize longs of up to 2GB-1
1711
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001712 @bigmemtest(size=_2G, memuse=3.6, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001713 def test_huge_long_32b(self, size):
1714 data = 1 << (8 * size)
1715 try:
1716 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001717 if proto < 2:
1718 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001719 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001720 with self.assertRaises((ValueError, OverflowError)):
1721 self.dumps(data, protocol=proto)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001722 finally:
1723 data = None
1724
1725 # Protocol 3 can serialize up to 4GB-1 as a bytes object
1726 # (older protocols don't have a dedicated opcode for bytes and are
1727 # too inefficient)
1728
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001729 @bigmemtest(size=_2G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001730 def test_huge_bytes_32b(self, size):
1731 data = b"abcd" * (size // 4)
1732 try:
1733 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001734 if proto < 3:
1735 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001736 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001737 try:
1738 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001739 header = (pickle.BINBYTES +
1740 struct.pack("<I", len(data)))
1741 data_start = pickled.index(data)
1742 self.assertEqual(
1743 header,
1744 pickled[data_start-len(header):data_start])
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001745 finally:
1746 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001747 finally:
1748 data = None
1749
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001750 @bigmemtest(size=_4G, memuse=2.5, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001751 def test_huge_bytes_64b(self, size):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001752 data = b"acbd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001753 try:
1754 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001755 if proto < 3:
1756 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001757 with self.subTest(proto=proto):
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001758 if proto == 3:
1759 # Protocol 3 does not support large bytes objects.
1760 # Verify that we do not crash when processing one.
1761 with self.assertRaises((ValueError, OverflowError)):
1762 self.dumps(data, protocol=proto)
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001763 continue
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001764 try:
1765 pickled = self.dumps(data, protocol=proto)
1766 header = (pickle.BINBYTES8 +
1767 struct.pack("<Q", len(data)))
1768 data_start = pickled.index(data)
1769 self.assertEqual(
1770 header,
1771 pickled[data_start-len(header):data_start])
1772 finally:
1773 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001774 finally:
1775 data = None
1776
1777 # All protocols use 1-byte per printable ASCII character; we add another
1778 # byte because the encoded form has to be copied into the internal buffer.
1779
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001780 @bigmemtest(size=_2G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001781 def test_huge_str_32b(self, size):
1782 data = "abcd" * (size // 4)
1783 try:
1784 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001785 if proto == 0:
1786 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001787 with self.subTest(proto=proto):
1788 try:
1789 pickled = self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001790 header = (pickle.BINUNICODE +
1791 struct.pack("<I", len(data)))
1792 data_start = pickled.index(b'abcd')
1793 self.assertEqual(
1794 header,
1795 pickled[data_start-len(header):data_start])
1796 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
1797 pickled.index(b"abcd")), len(data))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001798 finally:
1799 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001800 finally:
1801 data = None
1802
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001803 # BINUNICODE (protocols 1, 2 and 3) cannot carry more than 2**32 - 1 bytes
1804 # of utf-8 encoded unicode. BINUNICODE8 (protocol 4) supports these huge
1805 # unicode strings however.
Antoine Pitroue897e952011-08-30 23:39:34 +02001806
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +02001807 @bigmemtest(size=_4G, memuse=8, dry_run=False)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001808 def test_huge_str_64b(self, size):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001809 data = "abcd" * (size // 4)
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001810 try:
1811 for proto in protocols:
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001812 if proto == 0:
1813 continue
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001814 with self.subTest(proto=proto):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001815 if proto < 4:
1816 with self.assertRaises((ValueError, OverflowError)):
1817 self.dumps(data, protocol=proto)
Alexandre Vassalotti6e73ff12013-12-05 19:29:32 -08001818 continue
1819 try:
1820 pickled = self.dumps(data, protocol=proto)
1821 header = (pickle.BINUNICODE8 +
1822 struct.pack("<Q", len(data)))
1823 data_start = pickled.index(b'abcd')
1824 self.assertEqual(
1825 header,
1826 pickled[data_start-len(header):data_start])
1827 self.assertEqual((pickled.rindex(b"abcd") + len(b"abcd") -
1828 pickled.index(b"abcd")), len(data))
1829 finally:
1830 pickled = None
Antoine Pitrou82be19f2011-08-29 23:09:33 +02001831 finally:
1832 data = None
1833
Antoine Pitrou3c7e9282011-08-13 20:15:19 +02001834
Guido van Rossum2a30b212003-02-18 22:41:24 +00001835# Test classes for reduce_ex
1836
1837class REX_one(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001838 """No __reduce_ex__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00001839 _reduce_called = 0
1840 def __reduce__(self):
1841 self._reduce_called = 1
1842 return REX_one, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00001843
1844class REX_two(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001845 """No __reduce__ here, but inheriting it from object"""
Guido van Rossum2a30b212003-02-18 22:41:24 +00001846 _proto = None
1847 def __reduce_ex__(self, proto):
1848 self._proto = proto
1849 return REX_two, ()
Guido van Rossum2a30b212003-02-18 22:41:24 +00001850
1851class REX_three(object):
1852 _proto = None
1853 def __reduce_ex__(self, proto):
1854 self._proto = proto
1855 return REX_two, ()
1856 def __reduce__(self):
Collin Winter3add4d72007-08-29 23:37:32 +00001857 raise TestFailed("This __reduce__ shouldn't be called")
Guido van Rossum2a30b212003-02-18 22:41:24 +00001858
Guido van Rossumd8faa362007-04-27 19:54:29 +00001859class REX_four(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001860 """Calling base class method should succeed"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001861 _proto = None
1862 def __reduce_ex__(self, proto):
1863 self._proto = proto
1864 return object.__reduce_ex__(self, proto)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001865
1866class REX_five(object):
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001867 """This one used to fail with infinite recursion"""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001868 _reduce_called = 0
1869 def __reduce__(self):
1870 self._reduce_called = 1
1871 return object.__reduce__(self)
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001872
1873class REX_six(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001874 """This class is used to check the 4th argument (list iterator) of
1875 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001876 """
1877 def __init__(self, items=None):
1878 self.items = items if items is not None else []
1879 def __eq__(self, other):
1880 return type(self) is type(other) and self.items == self.items
1881 def append(self, item):
1882 self.items.append(item)
1883 def __reduce__(self):
1884 return type(self), (), None, iter(self.items), None
1885
1886class REX_seven(object):
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001887 """This class is used to check the 5th argument (dict iterator) of
1888 the reduce protocol.
Alexandre Vassalotti1f7492c2013-04-20 13:19:46 -07001889 """
1890 def __init__(self, table=None):
1891 self.table = table if table is not None else {}
1892 def __eq__(self, other):
1893 return type(self) is type(other) and self.table == self.table
1894 def __setitem__(self, key, value):
1895 self.table[key] = value
1896 def __reduce__(self):
1897 return type(self), (), None, None, iter(self.table.items())
1898
Guido van Rossumd8faa362007-04-27 19:54:29 +00001899
Guido van Rossum2a30b212003-02-18 22:41:24 +00001900# Test classes for newobj
Tim Peters080c88b2003-02-15 03:01:11 +00001901
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001902class MyInt(int):
1903 sample = 1
1904
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001905class MyFloat(float):
1906 sample = 1.0
1907
1908class MyComplex(complex):
1909 sample = 1.0 + 0.0j
1910
1911class MyStr(str):
1912 sample = "hello"
1913
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001914class MyUnicode(str):
1915 sample = "hello \u1234"
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001916
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001917class MyTuple(tuple):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001918 sample = (1, 2, 3)
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001919
1920class MyList(list):
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001921 sample = [1, 2, 3]
1922
1923class MyDict(dict):
1924 sample = {"a": 1, "b": 2}
1925
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001926class MySet(set):
1927 sample = {"a", "b"}
1928
1929class MyFrozenSet(frozenset):
1930 sample = frozenset({"a", "b"})
1931
Mark Dickinson5c2db372009-12-05 20:28:34 +00001932myclasses = [MyInt, MyFloat,
Guido van Rossum206b9a72003-03-02 13:53:18 +00001933 MyComplex,
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001934 MyStr, MyUnicode,
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001935 MyTuple, MyList, MyDict, MySet, MyFrozenSet]
Guido van Rossum5d9113d2003-01-29 17:58:45 +00001936
Guido van Rossum533dbcf2003-01-28 17:55:05 +00001937
Guido van Rossumc8d6ef52003-01-28 22:02:31 +00001938class SlotList(MyList):
1939 __slots__ = ["foo"]
1940
Tim Peterse9ef2032003-02-13 18:42:00 +00001941class SimpleNewObj(object):
1942 def __init__(self, a, b, c):
1943 # raise an error, to make sure this isn't called
1944 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001945 def __eq__(self, other):
1946 return self.__dict__ == other.__dict__
Tim Peterse9ef2032003-02-13 18:42:00 +00001947
Alexandre Vassalotti1f9d9072008-08-15 03:07:47 +00001948class BadGetattr:
1949 def __getattr__(self, key):
1950 self.foo
1951
Collin Winter771d8342009-04-16 03:18:06 +00001952
Jeremy Hylton66426532001-10-15 21:38:56 +00001953class AbstractPickleModuleTests(unittest.TestCase):
1954
1955 def test_dump_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001956 import os
Walter Dörwald11b41f62007-06-20 12:46:31 +00001957 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001958 try:
1959 f.close()
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00001960 self.assertRaises(ValueError, pickle.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001961 finally:
1962 os.remove(TESTFN)
Jeremy Hylton66426532001-10-15 21:38:56 +00001963
1964 def test_load_closed_file(self):
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001965 import os
Walter Dörwald11b41f62007-06-20 12:46:31 +00001966 f = open(TESTFN, "wb")
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001967 try:
1968 f.close()
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00001969 self.assertRaises(ValueError, pickle.dump, 123, f)
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001970 finally:
1971 os.remove(TESTFN)
Jeremy Hylton4c8be852002-11-13 22:10:47 +00001972
Collin Winter771d8342009-04-16 03:18:06 +00001973 def test_load_from_and_dump_to_file(self):
1974 stream = io.BytesIO()
1975 data = [123, {}, 124]
1976 pickle.dump(data, stream)
1977 stream.seek(0)
1978 unpickled = pickle.load(stream)
1979 self.assertEqual(unpickled, data)
1980
Tim Petersc0c93702003-02-13 19:30:57 +00001981 def test_highest_protocol(self):
1982 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001983 self.assertEqual(pickle.HIGHEST_PROTOCOL, 4)
Tim Petersc0c93702003-02-13 19:30:57 +00001984
Martin v. Löwis544f1192004-07-27 05:22:33 +00001985 def test_callapi(self):
Collin Winter771d8342009-04-16 03:18:06 +00001986 f = io.BytesIO()
Martin v. Löwis544f1192004-07-27 05:22:33 +00001987 # With and without keyword arguments
Alexandre Vassalottica2d6102008-06-12 18:26:05 +00001988 pickle.dump(123, f, -1)
1989 pickle.dump(123, file=f, protocol=-1)
1990 pickle.dumps(123, -1)
1991 pickle.dumps(123, protocol=-1)
1992 pickle.Pickler(f, -1)
1993 pickle.Pickler(f, protocol=-1)
Tim Petersc0c93702003-02-13 19:30:57 +00001994
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00001995 def test_bad_init(self):
1996 # Test issue3664 (pickle can segfault from a badly initialized Pickler).
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00001997 # Override initialization without calling __init__() of the superclass.
1998 class BadPickler(pickle.Pickler):
1999 def __init__(self): pass
2000
2001 class BadUnpickler(pickle.Unpickler):
2002 def __init__(self): pass
2003
2004 self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
2005 self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
2006
Amaury Forgeot d'Arc3e4e72f2008-11-11 20:05:06 +00002007 def test_bad_input(self):
2008 # Test issue4298
2009 s = bytes([0x58, 0, 0, 0, 0x54])
2010 self.assertRaises(EOFError, pickle.loads, s)
2011
Amaury Forgeot d'Arc87eee632008-10-17 20:15:53 +00002012
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002013class AbstractPersistentPicklerTests(unittest.TestCase):
2014
2015 # This class defines persistent_id() and persistent_load()
2016 # functions that should be used by the pickler. All even integers
2017 # are pickled using persistent ids.
2018
2019 def persistent_id(self, object):
2020 if isinstance(object, int) and object % 2 == 0:
2021 self.id_count += 1
2022 return str(object)
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002023 elif object == "test_false_value":
2024 self.false_count += 1
2025 return ""
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002026 else:
2027 return None
2028
2029 def persistent_load(self, oid):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002030 if not oid:
2031 self.load_false_count += 1
2032 return "test_false_value"
2033 else:
2034 self.load_count += 1
2035 object = int(oid)
2036 assert object % 2 == 0
2037 return object
Jeremy Hylton4c8be852002-11-13 22:10:47 +00002038
2039 def test_persistence(self):
Alexandre Vassalotti896414f2013-11-30 13:52:35 -08002040 L = list(range(10)) + ["test_false_value"]
2041 for proto in protocols:
2042 self.id_count = 0
2043 self.false_count = 0
2044 self.load_false_count = 0
2045 self.load_count = 0
2046 self.assertEqual(self.loads(self.dumps(L, proto)), L)
2047 self.assertEqual(self.id_count, 5)
2048 self.assertEqual(self.false_count, 1)
2049 self.assertEqual(self.load_count, 5)
2050 self.assertEqual(self.load_false_count, 1)
Guido van Rossum98297ee2007-11-06 21:34:58 +00002051
Collin Winter771d8342009-04-16 03:18:06 +00002052
2053class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
2054
2055 pickler_class = None
2056 unpickler_class = None
2057
2058 def setUp(self):
2059 assert self.pickler_class
2060 assert self.unpickler_class
2061
2062 def test_clear_pickler_memo(self):
2063 # To test whether clear_memo() has any effect, we pickle an object,
2064 # then pickle it again without clearing the memo; the two serialized
2065 # forms should be different. If we clear_memo() and then pickle the
2066 # object again, the third serialized form should be identical to the
2067 # first one we obtained.
2068 data = ["abcdefg", "abcdefg", 44]
2069 f = io.BytesIO()
2070 pickler = self.pickler_class(f)
2071
2072 pickler.dump(data)
2073 first_pickled = f.getvalue()
2074
Serhiy Storchaka50254c52013-08-29 11:35:43 +03002075 # Reset BytesIO object.
Collin Winter771d8342009-04-16 03:18:06 +00002076 f.seek(0)
2077 f.truncate()
2078
2079 pickler.dump(data)
2080 second_pickled = f.getvalue()
2081
Serhiy Storchaka50254c52013-08-29 11:35:43 +03002082 # Reset the Pickler and BytesIO objects.
Collin Winter771d8342009-04-16 03:18:06 +00002083 pickler.clear_memo()
2084 f.seek(0)
2085 f.truncate()
2086
2087 pickler.dump(data)
2088 third_pickled = f.getvalue()
2089
2090 self.assertNotEqual(first_pickled, second_pickled)
2091 self.assertEqual(first_pickled, third_pickled)
2092
2093 def test_priming_pickler_memo(self):
2094 # Verify that we can set the Pickler's memo attribute.
2095 data = ["abcdefg", "abcdefg", 44]
2096 f = io.BytesIO()
2097 pickler = self.pickler_class(f)
2098
2099 pickler.dump(data)
2100 first_pickled = f.getvalue()
2101
2102 f = io.BytesIO()
2103 primed = self.pickler_class(f)
2104 primed.memo = pickler.memo
2105
2106 primed.dump(data)
2107 primed_pickled = f.getvalue()
2108
2109 self.assertNotEqual(first_pickled, primed_pickled)
2110
2111 def test_priming_unpickler_memo(self):
2112 # Verify that we can set the Unpickler's memo attribute.
2113 data = ["abcdefg", "abcdefg", 44]
2114 f = io.BytesIO()
2115 pickler = self.pickler_class(f)
2116
2117 pickler.dump(data)
2118 first_pickled = f.getvalue()
2119
2120 f = io.BytesIO()
2121 primed = self.pickler_class(f)
2122 primed.memo = pickler.memo
2123
2124 primed.dump(data)
2125 primed_pickled = f.getvalue()
2126
2127 unpickler = self.unpickler_class(io.BytesIO(first_pickled))
2128 unpickled_data1 = unpickler.load()
2129
2130 self.assertEqual(unpickled_data1, data)
2131
2132 primed = self.unpickler_class(io.BytesIO(primed_pickled))
2133 primed.memo = unpickler.memo
2134 unpickled_data2 = primed.load()
2135
2136 primed.memo.clear()
2137
2138 self.assertEqual(unpickled_data2, data)
2139 self.assertTrue(unpickled_data2 is unpickled_data1)
2140
2141 def test_reusing_unpickler_objects(self):
2142 data1 = ["abcdefg", "abcdefg", 44]
2143 f = io.BytesIO()
2144 pickler = self.pickler_class(f)
2145 pickler.dump(data1)
2146 pickled1 = f.getvalue()
2147
2148 data2 = ["abcdefg", 44, 44]
2149 f = io.BytesIO()
2150 pickler = self.pickler_class(f)
2151 pickler.dump(data2)
2152 pickled2 = f.getvalue()
2153
2154 f = io.BytesIO()
2155 f.write(pickled1)
2156 f.seek(0)
2157 unpickler = self.unpickler_class(f)
2158 self.assertEqual(unpickler.load(), data1)
2159
2160 f.seek(0)
2161 f.truncate()
2162 f.write(pickled2)
2163 f.seek(0)
2164 self.assertEqual(unpickler.load(), data2)
2165
Antoine Pitrou04248a82010-10-12 20:51:21 +00002166 def _check_multiple_unpicklings(self, ioclass):
2167 for proto in protocols:
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002168 with self.subTest(proto=proto):
2169 data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
2170 f = ioclass()
2171 pickler = self.pickler_class(f, protocol=proto)
2172 pickler.dump(data1)
2173 pickled = f.getvalue()
Antoine Pitrou04248a82010-10-12 20:51:21 +00002174
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01002175 N = 5
2176 f = ioclass(pickled * N)
2177 unpickler = self.unpickler_class(f)
2178 for i in range(N):
2179 if f.seekable():
2180 pos = f.tell()
2181 self.assertEqual(unpickler.load(), data1)
2182 if f.seekable():
2183 self.assertEqual(f.tell(), pos + len(pickled))
2184 self.assertRaises(EOFError, unpickler.load)
Antoine Pitrou04248a82010-10-12 20:51:21 +00002185
2186 def test_multiple_unpicklings_seekable(self):
2187 self._check_multiple_unpicklings(io.BytesIO)
2188
2189 def test_multiple_unpicklings_unseekable(self):
2190 self._check_multiple_unpicklings(UnseekableIO)
2191
Antoine Pitrouf6c7a852011-08-11 21:04:02 +02002192 def test_unpickling_buffering_readline(self):
2193 # Issue #12687: the unpickler's buffering logic could fail with
2194 # text mode opcodes.
2195 data = list(range(10))
2196 for proto in protocols:
2197 for buf_size in range(1, 11):
2198 f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
2199 pickler = self.pickler_class(f, protocol=proto)
2200 pickler.dump(data)
2201 f.seek(0)
2202 unpickler = self.unpickler_class(f)
2203 self.assertEqual(unpickler.load(), data)
2204
Collin Winter771d8342009-04-16 03:18:06 +00002205
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01002206# Tests for dispatch_table attribute
2207
2208REDUCE_A = 'reduce_A'
2209
2210class AAA(object):
2211 def __reduce__(self):
2212 return str, (REDUCE_A,)
2213
2214class BBB(object):
2215 pass
2216
2217class AbstractDispatchTableTests(unittest.TestCase):
2218
2219 def test_default_dispatch_table(self):
2220 # No dispatch_table attribute by default
2221 f = io.BytesIO()
2222 p = self.pickler_class(f, 0)
2223 with self.assertRaises(AttributeError):
2224 p.dispatch_table
2225 self.assertFalse(hasattr(p, 'dispatch_table'))
2226
2227 def test_class_dispatch_table(self):
2228 # A dispatch_table attribute can be specified class-wide
2229 dt = self.get_dispatch_table()
2230
2231 class MyPickler(self.pickler_class):
2232 dispatch_table = dt
2233
2234 def dumps(obj, protocol=None):
2235 f = io.BytesIO()
2236 p = MyPickler(f, protocol)
2237 self.assertEqual(p.dispatch_table, dt)
2238 p.dump(obj)
2239 return f.getvalue()
2240
2241 self._test_dispatch_table(dumps, dt)
2242
2243 def test_instance_dispatch_table(self):
2244 # A dispatch_table attribute can also be specified instance-wide
2245 dt = self.get_dispatch_table()
2246
2247 def dumps(obj, protocol=None):
2248 f = io.BytesIO()
2249 p = self.pickler_class(f, protocol)
2250 p.dispatch_table = dt
2251 self.assertEqual(p.dispatch_table, dt)
2252 p.dump(obj)
2253 return f.getvalue()
2254
2255 self._test_dispatch_table(dumps, dt)
2256
2257 def _test_dispatch_table(self, dumps, dispatch_table):
2258 def custom_load_dump(obj):
2259 return pickle.loads(dumps(obj, 0))
2260
2261 def default_load_dump(obj):
2262 return pickle.loads(pickle.dumps(obj, 0))
2263
2264 # pickling complex numbers using protocol 0 relies on copyreg
2265 # so check pickling a complex number still works
2266 z = 1 + 2j
2267 self.assertEqual(custom_load_dump(z), z)
2268 self.assertEqual(default_load_dump(z), z)
2269
2270 # modify pickling of complex
2271 REDUCE_1 = 'reduce_1'
2272 def reduce_1(obj):
2273 return str, (REDUCE_1,)
2274 dispatch_table[complex] = reduce_1
2275 self.assertEqual(custom_load_dump(z), REDUCE_1)
2276 self.assertEqual(default_load_dump(z), z)
2277
2278 # check picklability of AAA and BBB
2279 a = AAA()
2280 b = BBB()
2281 self.assertEqual(custom_load_dump(a), REDUCE_A)
2282 self.assertIsInstance(custom_load_dump(b), BBB)
2283 self.assertEqual(default_load_dump(a), REDUCE_A)
2284 self.assertIsInstance(default_load_dump(b), BBB)
2285
2286 # modify pickling of BBB
2287 dispatch_table[BBB] = reduce_1
2288 self.assertEqual(custom_load_dump(a), REDUCE_A)
2289 self.assertEqual(custom_load_dump(b), REDUCE_1)
2290 self.assertEqual(default_load_dump(a), REDUCE_A)
2291 self.assertIsInstance(default_load_dump(b), BBB)
2292
2293 # revert pickling of BBB and modify pickling of AAA
2294 REDUCE_2 = 'reduce_2'
2295 def reduce_2(obj):
2296 return str, (REDUCE_2,)
2297 dispatch_table[AAA] = reduce_2
2298 del dispatch_table[BBB]
2299 self.assertEqual(custom_load_dump(a), REDUCE_2)
2300 self.assertIsInstance(custom_load_dump(b), BBB)
2301 self.assertEqual(default_load_dump(a), REDUCE_A)
2302 self.assertIsInstance(default_load_dump(b), BBB)
2303
2304
Guido van Rossum98297ee2007-11-06 21:34:58 +00002305if __name__ == "__main__":
2306 # Print some stuff that can be used to rewrite DATA{0,1,2}
2307 from pickletools import dis
2308 x = create_data()
2309 for i in range(3):
2310 p = pickle.dumps(x, i)
2311 print("DATA{0} = (".format(i))
2312 for j in range(0, len(p), 20):
2313 b = bytes(p[j:j+20])
2314 print(" {0!r}".format(b))
2315 print(")")
2316 print()
2317 print("# Disassembly of DATA{0}".format(i))
2318 print("DATA{0}_DIS = \"\"\"\\".format(i))
2319 dis(p)
2320 print("\"\"\"")
2321 print()